Files
renderdoc/util/test/demos/d3d12/d3d12_helpers.cpp
T
Dan Hawson 7619414b8a Add multi-queue wait-before-signal test
This tests submitting commands, signals, and waits to graphics and
multiple compute queues where the entire frame's submission for each
queue depends on the other queues and the submission order is not the
order in which the GPU (and replay) need to be processed.  This is to
ensure any capture or replaying deserialises adequately.
2023-11-03 10:46:42 +00:00

1288 lines
38 KiB
C++

/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2019-2023 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include "d3d12_test.h"
static const UINT formatStrides[] = {
0, // DXGI_FORMAT_UNKNOWN
4 * 4, // DXGI_FORMAT_R32G32B32A32_TYPELESS
4 * 4, // DXGI_FORMAT_R32G32B32A32_FLOAT
4 * 4, // DXGI_FORMAT_R32G32B32A32_UINT
4 * 4, // DXGI_FORMAT_R32G32B32A32_SINT
4 * 3, // DXGI_FORMAT_R32G32B32_TYPELESS
4 * 3, // DXGI_FORMAT_R32G32B32_FLOAT
4 * 3, // DXGI_FORMAT_R32G32B32_UINT
4 * 3, // DXGI_FORMAT_R32G32B32_SINT
2 * 4, // DXGI_FORMAT_R16G16B16A16_TYPELESS
2 * 4, // DXGI_FORMAT_R16G16B16A16_FLOAT
2 * 4, // DXGI_FORMAT_R16G16B16A16_UNORM
2 * 4, // DXGI_FORMAT_R16G16B16A16_UINT
2 * 4, // DXGI_FORMAT_R16G16B16A16_SNORM
2 * 4, // DXGI_FORMAT_R16G16B16A16_SINT
4 * 2, // DXGI_FORMAT_R32G32_TYPELESS
4 * 2, // DXGI_FORMAT_R32G32_FLOAT
4 * 2, // DXGI_FORMAT_R32G32_UINT
4 * 2, // DXGI_FORMAT_R32G32_SINT
4 * 2, // DXGI_FORMAT_R32G8X24_TYPELESS
5, // DXGI_FORMAT_D32_FLOAT_S8X24_UINT
5, // DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS
5, // DXGI_FORMAT_X32_TYPELESS_G8X24_UINT
4, // DXGI_FORMAT_R10G10B10A2_TYPELESS
4, // DXGI_FORMAT_R10G10B10A2_UNORM
4, // DXGI_FORMAT_R10G10B10A2_UINT
4, // DXGI_FORMAT_R11G11B10_FLOAT
1 * 4, // DXGI_FORMAT_R8G8B8A8_TYPELESS
1 * 4, // DXGI_FORMAT_R8G8B8A8_UNORM
1 * 4, // DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
1 * 4, // DXGI_FORMAT_R8G8B8A8_UINT
1 * 4, // DXGI_FORMAT_R8G8B8A8_SNORM
1 * 4, // DXGI_FORMAT_R8G8B8A8_SINT
2 * 2, // DXGI_FORMAT_R16G16_TYPELESS
2 * 2, // DXGI_FORMAT_R16G16_FLOAT
2 * 2, // DXGI_FORMAT_R16G16_UNORM
2 * 2, // DXGI_FORMAT_R16G16_UINT
2 * 2, // DXGI_FORMAT_R16G16_SNORM
2 * 2, // DXGI_FORMAT_R16G16_SINT
4 * 1, // DXGI_FORMAT_R32_TYPELESS
4 * 1, // DXGI_FORMAT_D32_FLOAT
4 * 1, // DXGI_FORMAT_R32_FLOAT
4 * 1, // DXGI_FORMAT_R32_UINT
4 * 1, // DXGI_FORMAT_R32_SINT
4, // DXGI_FORMAT_R24G8_TYPELESS
4, // DXGI_FORMAT_D24_UNORM_S8_UINT
4, // DXGI_FORMAT_R24_UNORM_X8_TYPELESS
4, // DXGI_FORMAT_X24_TYPELESS_G8_UINT
1 * 2, // DXGI_FORMAT_R8G8_TYPELESS
1 * 2, // DXGI_FORMAT_R8G8_UNORM
1 * 2, // DXGI_FORMAT_R8G8_UINT
1 * 2, // DXGI_FORMAT_R8G8_SNORM
1 * 2, // DXGI_FORMAT_R8G8_SINT
2 * 1, // DXGI_FORMAT_R16_TYPELESS
2 * 1, // DXGI_FORMAT_R16_FLOAT
2, // DXGI_FORMAT_D16_UNORM
2 * 1, // DXGI_FORMAT_R16_UNORM
2 * 1, // DXGI_FORMAT_R16_UINT
2 * 1, // DXGI_FORMAT_R16_SNORM
2 * 1, // DXGI_FORMAT_R16_SINT
1 * 1, // DXGI_FORMAT_R8_TYPELESS
1 * 1, // DXGI_FORMAT_R8_UNORM
1 * 1, // DXGI_FORMAT_R8_UINT
1 * 1, // DXGI_FORMAT_R8_SNORM
1 * 1, // DXGI_FORMAT_R8_SINT
1, // DXGI_FORMAT_A8_UNORM
1, // DXGI_FORMAT_R1_UNORM
4, // DXGI_FORMAT_R9G9B9E5_SHAREDEXP
1 * 3, // DXGI_FORMAT_R8G8_B8G8_UNORM
1 * 3, // DXGI_FORMAT_G8R8_G8B8_UNORM
0, // DXGI_FORMAT_BC1_TYPELESS
0, // DXGI_FORMAT_BC1_UNORM
0, // DXGI_FORMAT_BC1_UNORM_SRGB
0, // DXGI_FORMAT_BC2_TYPELESS
0, // DXGI_FORMAT_BC2_UNORM
0, // DXGI_FORMAT_BC2_UNORM_SRGB
0, // DXGI_FORMAT_BC3_TYPELESS
0, // DXGI_FORMAT_BC3_UNORM
0, // DXGI_FORMAT_BC3_UNORM_SRGB
0, // DXGI_FORMAT_BC4_TYPELESS
0, // DXGI_FORMAT_BC4_UNORM
0, // DXGI_FORMAT_BC4_SNORM
0, // DXGI_FORMAT_BC5_TYPELESS
0, // DXGI_FORMAT_BC5_UNORM
0, // DXGI_FORMAT_BC5_SNORM
0, // DXGI_FORMAT_B5G6R5_UNORM
0, // DXGI_FORMAT_B5G5R5A1_UNORM
1 * 4, // DXGI_FORMAT_B8G8R8A8_UNORM
1 * 3, // DXGI_FORMAT_B8G8R8X8_UNORM
4, // DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
1 * 4, // DXGI_FORMAT_B8G8R8A8_TYPELESS
1 * 4, // DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
1 * 3, // DXGI_FORMAT_B8G8R8X8_TYPELESS
1 * 3, // DXGI_FORMAT_B8G8R8X8_UNORM_SRGB
0, // DXGI_FORMAT_BC6H_TYPELESS
0, // DXGI_FORMAT_BC6H_UF16
0, // DXGI_FORMAT_BC6H_SF16
0, // DXGI_FORMAT_BC7_TYPELESS
0, // DXGI_FORMAT_BC7_UNORM
0, // DXGI_FORMAT_BC7_UNORM_SRGB
0, // DXGI_FORMAT_AYUV
0, // DXGI_FORMAT_Y410
0, // DXGI_FORMAT_Y416
0, // DXGI_FORMAT_NV12
0, // DXGI_FORMAT_P010
0, // DXGI_FORMAT_P016
0, // DXGI_FORMAT_420_OPAQUE
0, // DXGI_FORMAT_YUY2
0, // DXGI_FORMAT_Y210
0, // DXGI_FORMAT_Y216
0, // DXGI_FORMAT_NV11
0, // DXGI_FORMAT_AI44
0, // DXGI_FORMAT_IA44
0, // DXGI_FORMAT_P8
0, // DXGI_FORMAT_A8P8
0, // DXGI_FORMAT_B4G4R4A4_UNORM
};
D3D12_ROOT_PARAMETER1 cbvParam(D3D12_SHADER_VISIBILITY vis, UINT space, UINT reg)
{
D3D12_ROOT_PARAMETER1 ret;
ret.ShaderVisibility = vis;
ret.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
ret.Descriptor.RegisterSpace = space;
ret.Descriptor.ShaderRegister = reg;
ret.Descriptor.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE;
return ret;
}
D3D12_ROOT_PARAMETER1 srvParam(D3D12_SHADER_VISIBILITY vis, UINT space, UINT reg)
{
D3D12_ROOT_PARAMETER1 ret;
ret.ShaderVisibility = vis;
ret.ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;
ret.Descriptor.RegisterSpace = space;
ret.Descriptor.ShaderRegister = reg;
ret.Descriptor.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE;
return ret;
}
D3D12_ROOT_PARAMETER1 uavParam(D3D12_SHADER_VISIBILITY vis, UINT space, UINT reg)
{
D3D12_ROOT_PARAMETER1 ret;
ret.ShaderVisibility = vis;
ret.ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV;
ret.Descriptor.RegisterSpace = space;
ret.Descriptor.ShaderRegister = reg;
ret.Descriptor.Flags = D3D12_ROOT_DESCRIPTOR_FLAG_NONE;
return ret;
}
D3D12_ROOT_PARAMETER1 constParam(D3D12_SHADER_VISIBILITY vis, UINT space, UINT reg, UINT num)
{
D3D12_ROOT_PARAMETER1 ret;
ret.ShaderVisibility = vis;
ret.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
ret.Constants.RegisterSpace = space;
ret.Constants.ShaderRegister = reg;
ret.Constants.Num32BitValues = num;
return ret;
}
D3D12_ROOT_PARAMETER1 tableParam(D3D12_SHADER_VISIBILITY vis, D3D12_DESCRIPTOR_RANGE_TYPE type,
UINT space, UINT basereg, UINT numreg, UINT descOffset,
D3D12_DESCRIPTOR_RANGE_FLAGS flags)
{
// this is a super hack but avoids the need to be clumsy with allocation of these structs
static D3D12_DESCRIPTOR_RANGE1 ranges[32] = {};
static int rangeIdx = 0;
if(type == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER)
{
flags &= ~D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE;
}
D3D12_DESCRIPTOR_RANGE1 &range = ranges[rangeIdx];
rangeIdx = (rangeIdx + 1) % ARRAY_COUNT(ranges);
D3D12_ROOT_PARAMETER1 ret;
ret.ShaderVisibility = vis;
ret.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
ret.DescriptorTable.NumDescriptorRanges = 1;
ret.DescriptorTable.pDescriptorRanges = ⦥
memset(&range, 0, sizeof(range));
range.RangeType = type;
range.RegisterSpace = space;
range.BaseShaderRegister = basereg;
range.NumDescriptors = numreg;
range.OffsetInDescriptorsFromTableStart = descOffset;
range.Flags = flags;
return ret;
}
D3D12BufferCreator::D3D12BufferCreator(ID3D12DevicePtr dev, D3D12GraphicsTest *test)
: m_Dev(dev), m_Test(test)
{
m_BufDesc.Alignment = 0;
m_BufDesc.DepthOrArraySize = 1;
m_BufDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
m_BufDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
m_BufDesc.Format = DXGI_FORMAT_UNKNOWN;
m_BufDesc.Height = 1;
m_BufDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
m_BufDesc.Width = 64;
m_BufDesc.MipLevels = 1;
m_BufDesc.SampleDesc.Count = 1;
m_BufDesc.SampleDesc.Quality = 0;
m_HeapDesc.Type = D3D12_HEAP_TYPE_DEFAULT;
m_HeapDesc.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
m_HeapDesc.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
m_HeapDesc.CreationNodeMask = 1;
m_HeapDesc.VisibleNodeMask = 1;
m_InitialState = D3D12_RESOURCE_STATE_COMMON;
}
D3D12BufferCreator &D3D12BufferCreator::UAV()
{
m_BufDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
return *this;
}
D3D12BufferCreator &D3D12BufferCreator::Upload()
{
m_HeapDesc.Type = D3D12_HEAP_TYPE_UPLOAD;
m_InitialState = D3D12_RESOURCE_STATE_GENERIC_READ;
return *this;
}
D3D12BufferCreator &D3D12BufferCreator::Readback()
{
m_HeapDesc.Type = D3D12_HEAP_TYPE_READBACK;
m_InitialState = D3D12_RESOURCE_STATE_COPY_DEST;
return *this;
}
D3D12BufferCreator &D3D12BufferCreator::Data(const void *data)
{
m_Initdata = data;
return *this;
}
D3D12BufferCreator &D3D12BufferCreator::Size(UINT size)
{
m_BufDesc.Width = size;
return *this;
}
D3D12BufferCreator &D3D12BufferCreator::InitialState(D3D12_RESOURCE_STATES initialState)
{
m_InitialState = initialState;
return *this;
}
D3D12BufferCreator::operator ID3D12ResourcePtr() const
{
ID3D12ResourcePtr buf;
CHECK_HR(m_Dev->CreateCommittedResource(&m_HeapDesc, D3D12_HEAP_FLAG_NONE, &m_BufDesc,
m_InitialState, NULL, __uuidof(ID3D12Resource),
(void **)&buf));
if(m_Initdata && m_Test)
m_Test->SetBufferData(buf, D3D12_RESOURCE_STATE_COMMON, (const byte *)m_Initdata,
m_BufDesc.Width);
return buf;
}
D3D12TextureCreator::D3D12TextureCreator(ID3D12DevicePtr dev, DXGI_FORMAT format, UINT width,
UINT height, UINT depth)
: m_Dev(dev)
{
m_InitialState = D3D12_RESOURCE_STATE_COMMON;
m_TexDesc.Alignment = 0;
m_TexDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE1D;
if(height > 1)
m_TexDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
if(depth > 1)
m_TexDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE3D;
m_TexDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
m_TexDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
m_TexDesc.Format = format;
m_TexDesc.Width = width;
m_TexDesc.Height = height;
m_TexDesc.DepthOrArraySize = (UINT16)depth;
m_TexDesc.MipLevels = 1;
m_TexDesc.SampleDesc.Count = 1;
m_TexDesc.SampleDesc.Quality = 0;
m_HeapDesc.Type = D3D12_HEAP_TYPE_DEFAULT;
m_HeapDesc.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
m_HeapDesc.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
m_HeapDesc.CreationNodeMask = 1;
m_HeapDesc.VisibleNodeMask = 1;
m_ClearVal.Format = DXGI_FORMAT_UNKNOWN;
}
D3D12TextureCreator &D3D12TextureCreator::Mips(UINT mips)
{
m_TexDesc.MipLevels = (UINT16)mips;
return *this;
}
D3D12TextureCreator &D3D12TextureCreator::Array(UINT size)
{
m_TexDesc.DepthOrArraySize = (UINT16)size;
return *this;
}
D3D12TextureCreator &D3D12TextureCreator::Multisampled(UINT count, UINT quality)
{
m_TexDesc.SampleDesc.Count = count;
m_TexDesc.SampleDesc.Quality = quality;
return *this;
}
D3D12TextureCreator &D3D12TextureCreator::UAV()
{
m_TexDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
return *this;
}
D3D12TextureCreator &D3D12TextureCreator::RTV()
{
m_TexDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
return *this;
}
D3D12TextureCreator &D3D12TextureCreator::DSV()
{
m_TexDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
return *this;
}
D3D12TextureCreator &D3D12TextureCreator::NoSRV()
{
m_TexDesc.Flags |= D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
return *this;
}
D3D12TextureCreator &D3D12TextureCreator::Upload()
{
m_HeapDesc.Type = D3D12_HEAP_TYPE_UPLOAD;
return *this;
}
D3D12TextureCreator &D3D12TextureCreator::Readback()
{
m_HeapDesc.Type = D3D12_HEAP_TYPE_READBACK;
return *this;
}
D3D12TextureCreator &D3D12TextureCreator::CustomHeap(D3D12_HEAP_PROPERTIES heap)
{
m_HeapDesc = heap;
return *this;
}
D3D12TextureCreator &D3D12TextureCreator::Shared()
{
m_HeapFlags = D3D12_HEAP_FLAG_SHARED;
m_TexDesc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS;
return *this;
}
D3D12TextureCreator &D3D12TextureCreator::InitialState(D3D12_RESOURCE_STATES state)
{
m_InitialState = state;
return *this;
}
D3D12TextureCreator &D3D12TextureCreator::ClearVal(const D3D12_CLEAR_VALUE &clearVal)
{
m_ClearVal = clearVal;
return *this;
}
D3D12TextureCreator::operator ID3D12ResourcePtr() const
{
ID3D12ResourcePtr tex;
CHECK_HR(m_Dev->CreateCommittedResource(
&m_HeapDesc, m_HeapFlags, &m_TexDesc, m_InitialState,
(m_ClearVal.Format == DXGI_FORMAT_UNKNOWN) ? NULL : &m_ClearVal, __uuidof(ID3D12Resource),
(void **)&tex));
return tex;
}
D3D12ViewCreator::D3D12ViewCreator(ID3D12DevicePtr dev, ID3D12DescriptorHeap *heap,
ID3D12DescriptorHeap *clearHeap, ViewType viewType,
ID3D12Resource *res)
: m_Dev(dev), m_Type(viewType), m_Heap(heap), m_ClearHeap(clearHeap), m_Res(res)
{
D3D12_RESOURCE_DESC resdesc = res->GetDesc();
D3D12_RESOURCE_DIMENSION dim = resdesc.Dimension;
Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
if(m_Type == ViewType::CBV)
{
desc.cbv.BufferLocation = m_Res->GetGPUVirtualAddress();
desc.cbv.SizeInBytes = 0;
}
else if(dim == D3D12_RESOURCE_DIMENSION_BUFFER)
{
SetupDescriptors(viewType, ResourceType::Buffer);
}
else if(dim == D3D12_RESOURCE_DIMENSION_TEXTURE1D)
{
ResourceType resType = ResourceType::Texture1D;
if(resdesc.DepthOrArraySize > 1)
resType = ResourceType::Texture1DArray;
SetupDescriptors(viewType, resType);
}
else if(dim == D3D12_RESOURCE_DIMENSION_TEXTURE2D)
{
ResourceType resType;
if(resdesc.SampleDesc.Count > 1)
{
resType = ResourceType::Texture2DMS;
if(resdesc.DepthOrArraySize > 1)
resType = ResourceType::Texture2DMSArray;
}
else
{
resType = ResourceType::Texture2D;
if(resdesc.DepthOrArraySize > 1)
resType = ResourceType::Texture2DArray;
}
SetupDescriptors(viewType, resType);
}
else if(dim == D3D12_RESOURCE_DIMENSION_TEXTURE3D)
{
SetupDescriptors(viewType, ResourceType::Texture3D);
}
if(dim != D3D12_RESOURCE_DIMENSION_BUFFER)
Format(resdesc.Format);
}
void D3D12ViewCreator::SetupDescriptors(ViewType viewType, ResourceType resType)
{
memset(&desc, 0, sizeof(desc));
constexpr D3D12_SRV_DIMENSION srvDim[] = {
D3D12_SRV_DIMENSION_BUFFER, // Buffer
D3D12_SRV_DIMENSION_TEXTURE1D, // Texture1D
D3D12_SRV_DIMENSION_TEXTURE1DARRAY, // Texture1DArray
D3D12_SRV_DIMENSION_TEXTURE2D, // Texture2D
D3D12_SRV_DIMENSION_TEXTURE2DARRAY, // Texture2DArray
D3D12_SRV_DIMENSION_TEXTURE2DMS, // Texture2DMS
D3D12_SRV_DIMENSION_TEXTURE2DMSARRAY, // Texture2DMSArray
D3D12_SRV_DIMENSION_TEXTURE3D, // Texture3D
};
constexpr D3D12_RTV_DIMENSION rtvDim[] = {
D3D12_RTV_DIMENSION_BUFFER, // Buffer
D3D12_RTV_DIMENSION_TEXTURE1D, // Texture1D
D3D12_RTV_DIMENSION_TEXTURE1DARRAY, // Texture1DArray
D3D12_RTV_DIMENSION_TEXTURE2D, // Texture2D
D3D12_RTV_DIMENSION_TEXTURE2DARRAY, // Texture2DArray
D3D12_RTV_DIMENSION_TEXTURE2DMS, // Texture2DMS
D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY, // Texture2DMSArray
D3D12_RTV_DIMENSION_TEXTURE3D, // Texture3D
};
constexpr D3D12_DSV_DIMENSION dsvDim[] = {
D3D12_DSV_DIMENSION_UNKNOWN, // Buffer
D3D12_DSV_DIMENSION_TEXTURE1D, // Texture1D
D3D12_DSV_DIMENSION_TEXTURE1DARRAY, // Texture1DArray
D3D12_DSV_DIMENSION_TEXTURE2D, // Texture2D
D3D12_DSV_DIMENSION_TEXTURE2DARRAY, // Texture2DArray
D3D12_DSV_DIMENSION_TEXTURE2DMS, // Texture2DMS
D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY, // Texture2DMSArray
D3D12_DSV_DIMENSION_UNKNOWN, // Texture3D
};
constexpr D3D12_UAV_DIMENSION uavDim[] = {
D3D12_UAV_DIMENSION_BUFFER, // Buffer
D3D12_UAV_DIMENSION_TEXTURE1D, // Texture1D
D3D12_UAV_DIMENSION_TEXTURE1DARRAY, // Texture1DArray
D3D12_UAV_DIMENSION_TEXTURE2D, // Texture2D
D3D12_UAV_DIMENSION_TEXTURE2DARRAY, // Texture2DArray
D3D12_UAV_DIMENSION_UNKNOWN, // Texture2DMS
D3D12_UAV_DIMENSION_UNKNOWN, // Texture2DMSArray
D3D12_UAV_DIMENSION_TEXTURE3D, // Texture3D
};
if(viewType == ViewType::SRV)
{
desc.srv.ViewDimension = srvDim[(int)resType];
if(resType == ResourceType::Buffer)
{
firstElement = &desc.srv.Buffer.FirstElement;
numElements = &desc.srv.Buffer.NumElements;
}
}
else if(viewType == ViewType::RTV)
{
desc.rtv.ViewDimension = rtvDim[(int)resType];
if(resType == ResourceType::Buffer)
{
firstElement = &desc.rtv.Buffer.FirstElement;
numElements = &desc.rtv.Buffer.NumElements;
}
}
else if(viewType == ViewType::DSV)
{
desc.dsv.ViewDimension = dsvDim[(int)resType];
if(desc.dsv.ViewDimension == D3D12_DSV_DIMENSION_UNKNOWN)
TEST_FATAL("Unsupported resource for DSV");
}
else if(viewType == ViewType::UAV)
{
desc.uav.ViewDimension = uavDim[(int)resType];
if(desc.uav.ViewDimension == D3D12_UAV_DIMENSION_UNKNOWN)
TEST_FATAL("Unsupported resource for UAV");
if(resType == ResourceType::Buffer)
{
firstElement = &desc.uav.Buffer.FirstElement;
numElements = &desc.uav.Buffer.NumElements;
}
}
UINT *pointers[4][8][5] = {
// SRV
{
// &firstMip, &numMips, &firstSlice, &numSlices, &planeSlice
{NULL, NULL, NULL, NULL, NULL},
{
&desc.srv.Texture1D.MostDetailedMip,
&desc.srv.Texture1D.MipLevels,
NULL,
NULL,
NULL,
},
{
&desc.srv.Texture1DArray.MostDetailedMip,
&desc.srv.Texture1DArray.MipLevels,
&desc.srv.Texture1DArray.FirstArraySlice,
&desc.srv.Texture1DArray.ArraySize,
NULL,
},
{
&desc.srv.Texture2D.MostDetailedMip,
&desc.srv.Texture2D.MipLevels,
NULL,
NULL,
&desc.srv.Texture2D.PlaneSlice,
},
{
&desc.srv.Texture2DArray.MostDetailedMip,
&desc.srv.Texture2DArray.MipLevels,
&desc.srv.Texture2DArray.FirstArraySlice,
&desc.srv.Texture2DArray.ArraySize,
&desc.srv.Texture2DArray.PlaneSlice,
},
{
NULL,
NULL,
NULL,
NULL,
NULL,
},
{
NULL,
NULL,
&desc.srv.Texture2DMSArray.FirstArraySlice,
&desc.srv.Texture2DMSArray.ArraySize,
NULL,
},
{
&desc.srv.Texture3D.MostDetailedMip,
&desc.srv.Texture2D.MipLevels,
NULL,
NULL,
NULL,
},
},
// RTV
{
// &firstMip, &numMips, &firstSlice, &numSlices
{
NULL,
NULL,
NULL,
NULL,
NULL,
},
{
&desc.rtv.Texture1D.MipSlice,
NULL,
NULL,
NULL,
NULL,
},
{
&desc.rtv.Texture1DArray.MipSlice,
NULL,
&desc.rtv.Texture1DArray.FirstArraySlice,
&desc.rtv.Texture1DArray.ArraySize,
NULL,
},
{
&desc.rtv.Texture2D.MipSlice,
NULL,
NULL,
NULL,
&desc.rtv.Texture2D.PlaneSlice,
},
{
&desc.rtv.Texture2DArray.MipSlice,
NULL,
&desc.rtv.Texture2DArray.FirstArraySlice,
&desc.rtv.Texture2DArray.ArraySize,
&desc.rtv.Texture2DArray.PlaneSlice,
},
{
NULL,
NULL,
NULL,
NULL,
NULL,
},
{
NULL,
NULL,
&desc.rtv.Texture2DMSArray.FirstArraySlice,
&desc.rtv.Texture2DMSArray.ArraySize,
NULL,
},
{
&desc.rtv.Texture3D.MipSlice,
NULL,
&desc.rtv.Texture3D.FirstWSlice,
&desc.rtv.Texture3D.WSize,
NULL,
},
},
// DSV
{
// &firstMip, &numMips, &firstSlice, &numSlices
{
NULL,
NULL,
NULL,
NULL,
NULL,
},
{
&desc.dsv.Texture1D.MipSlice,
NULL,
NULL,
NULL,
NULL,
},
{
&desc.dsv.Texture1DArray.MipSlice,
NULL,
&desc.dsv.Texture1DArray.FirstArraySlice,
&desc.dsv.Texture1DArray.ArraySize,
NULL,
},
{
&desc.dsv.Texture2D.MipSlice,
NULL,
NULL,
NULL,
NULL,
},
{
&desc.dsv.Texture2DArray.MipSlice,
NULL,
&desc.dsv.Texture2DArray.FirstArraySlice,
&desc.dsv.Texture2DArray.ArraySize,
NULL,
},
{
NULL,
NULL,
NULL,
NULL,
NULL,
},
{
NULL,
NULL,
&desc.dsv.Texture2DMSArray.FirstArraySlice,
&desc.dsv.Texture2DMSArray.ArraySize,
NULL,
},
{
NULL,
NULL,
NULL,
NULL,
NULL,
},
},
// UAV
{
// &firstMip, &numMips, &firstSlice, &numSlices
{
NULL,
NULL,
NULL,
NULL,
NULL,
},
{
&desc.uav.Texture1D.MipSlice,
NULL,
NULL,
NULL,
NULL,
},
{
&desc.uav.Texture1DArray.MipSlice,
NULL,
&desc.uav.Texture1DArray.FirstArraySlice,
&desc.uav.Texture1DArray.ArraySize,
NULL,
},
{
&desc.uav.Texture2D.MipSlice,
NULL,
NULL,
NULL,
&desc.uav.Texture2D.PlaneSlice,
},
{
&desc.uav.Texture2DArray.MipSlice,
NULL,
&desc.uav.Texture2DArray.FirstArraySlice,
&desc.uav.Texture2DArray.ArraySize,
&desc.uav.Texture2DArray.PlaneSlice,
},
{
NULL,
NULL,
NULL,
NULL,
NULL,
},
{
NULL,
NULL,
NULL,
NULL,
NULL,
},
{
&desc.uav.Texture3D.MipSlice,
NULL,
&desc.uav.Texture3D.FirstWSlice,
&desc.uav.Texture3D.WSize,
NULL,
},
},
};
if(resType != ResourceType::Buffer)
{
firstMip = pointers[(int)viewType][(int)resType][0];
numMips = pointers[(int)viewType][(int)resType][1];
firstSlice = pointers[(int)viewType][(int)resType][2];
numSlices = pointers[(int)viewType][(int)resType][3];
planeSlice = pointers[(int)viewType][(int)resType][4];
if(numMips)
*numMips = ~0U;
if(numSlices)
*numSlices = ~0U;
}
}
D3D12ViewCreator &D3D12ViewCreator::Format(DXGI_FORMAT f)
{
// this is always in the same place, just write it once
desc.srv.Format = f;
return *this;
}
D3D12ViewCreator &D3D12ViewCreator::Offset(UINT offset)
{
if(m_Type == ViewType::CBV)
desc.cbv.BufferLocation += offset;
else
TEST_ERROR("This view & resource doesn't support SizeBytes");
return *this;
}
D3D12ViewCreator &D3D12ViewCreator::SizeBytes(UINT size)
{
if(m_Type == ViewType::CBV)
desc.cbv.SizeInBytes = size;
else
TEST_ERROR("This view & resource doesn't support SizeBytes");
return *this;
}
D3D12ViewCreator &D3D12ViewCreator::FirstElement(UINT el)
{
if(firstElement)
*firstElement = el;
return *this;
}
D3D12ViewCreator &D3D12ViewCreator::NumElements(UINT num)
{
if(numElements)
*numElements = num;
else
TEST_ERROR("This view & resource doesn't support NumElements");
return *this;
}
D3D12ViewCreator &D3D12ViewCreator::StructureStride(UINT stride)
{
if(m_Type == ViewType::UAV)
desc.uav.Buffer.StructureByteStride = stride;
else if(m_Type == ViewType::SRV)
desc.srv.Buffer.StructureByteStride = stride;
else
TEST_ERROR("This view & resource doesn't support StructureStride");
return *this;
}
D3D12ViewCreator &D3D12ViewCreator::ByteAddressed()
{
if(m_Type == ViewType::UAV)
desc.uav.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW;
else if(m_Type == ViewType::SRV)
desc.srv.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW;
else
TEST_ERROR("This view & resource doesn't support ByteAddressed");
return *this;
}
D3D12ViewCreator &D3D12ViewCreator::FirstMip(UINT mip)
{
if(firstMip)
*firstMip = mip;
return *this;
}
D3D12ViewCreator &D3D12ViewCreator::NumMips(UINT num)
{
if(numMips)
*numMips = num;
return *this;
}
D3D12ViewCreator &D3D12ViewCreator::FirstSlice(UINT mip)
{
if(firstSlice)
*firstSlice = mip;
return *this;
}
D3D12ViewCreator &D3D12ViewCreator::NumSlices(UINT num)
{
if(numSlices)
*numSlices = num;
return *this;
}
D3D12ViewCreator &D3D12ViewCreator::Swizzle(UINT swizzle)
{
Shader4ComponentMapping = swizzle;
return *this;
}
D3D12ViewCreator &D3D12ViewCreator::PlaneSlice(UINT plane)
{
if(planeSlice)
*planeSlice = plane;
return *this;
}
D3D12ViewCreator &D3D12ViewCreator::ReadOnlyDepth()
{
desc.dsv.Flags |= D3D12_DSV_FLAG_READ_ONLY_DEPTH;
return *this;
}
D3D12ViewCreator &D3D12ViewCreator::ReadOnlyStencil()
{
desc.dsv.Flags |= D3D12_DSV_FLAG_READ_ONLY_STENCIL;
return *this;
}
D3D12_CPU_DESCRIPTOR_HANDLE D3D12ViewCreator::CreateCPU(ID3D12DescriptorHeap *heap,
uint32_t descriptor)
{
static UINT increment[] = {
m_Dev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV),
0, // D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER
m_Dev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV),
m_Dev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV),
};
D3D12_CPU_DESCRIPTOR_HANDLE cpu = heap->GetCPUDescriptorHandleForHeapStart();
TEST_ASSERT(m_Res, "Must have resource");
if(m_Type == ViewType::DSV)
{
cpu.ptr += increment[D3D12_DESCRIPTOR_HEAP_TYPE_DSV] * descriptor;
m_Dev->CreateDepthStencilView(m_Res, &desc.dsv, cpu);
}
else if(m_Type == ViewType::RTV)
{
cpu.ptr += increment[D3D12_DESCRIPTOR_HEAP_TYPE_RTV] * descriptor;
m_Dev->CreateRenderTargetView(m_Res, &desc.rtv, cpu);
}
else if(m_Type == ViewType::CBV)
{
cpu.ptr += increment[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] * descriptor;
m_Dev->CreateConstantBufferView(&desc.cbv, cpu);
}
else if(m_Type == ViewType::SRV)
{
if(desc.uav.ViewDimension == D3D12_SRV_DIMENSION_BUFFER)
{
D3D12_RESOURCE_DESC bufdesc = m_Res->GetDesc();
UINT elementStride = desc.srv.Buffer.StructureByteStride;
if(desc.srv.Buffer.StructureByteStride == 0 && desc.srv.Format == DXGI_FORMAT_UNKNOWN)
TEST_FATAL("Can't create srv on non-structured buffer with no format");
if(desc.srv.Format != DXGI_FORMAT_UNKNOWN)
elementStride = formatStrides[desc.srv.Format];
if(desc.srv.Buffer.NumElements == 0)
desc.srv.Buffer.NumElements = UINT(bufdesc.Width / std::max(elementStride, 1U));
}
desc.srv.Shader4ComponentMapping = Shader4ComponentMapping;
cpu.ptr += increment[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] * descriptor;
m_Dev->CreateShaderResourceView(m_Res, &desc.srv, cpu);
}
else if(m_Type == ViewType::UAV)
{
if(desc.uav.ViewDimension == D3D12_UAV_DIMENSION_BUFFER)
{
D3D12_RESOURCE_DESC bufdesc = m_Res->GetDesc();
UINT elementStride = desc.uav.Buffer.StructureByteStride;
if(desc.uav.Buffer.StructureByteStride == 0 && desc.uav.Format == DXGI_FORMAT_UNKNOWN)
TEST_FATAL("Can't create uav on non-structured buffer with no format");
if(desc.uav.Format != DXGI_FORMAT_UNKNOWN)
elementStride = formatStrides[desc.uav.Format];
if(desc.uav.Buffer.NumElements == 0)
desc.uav.Buffer.NumElements = UINT(bufdesc.Width / std::max(elementStride, 1U));
}
cpu.ptr += increment[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] * descriptor;
m_Dev->CreateUnorderedAccessView(m_Res, NULL, &desc.uav, cpu);
}
return cpu;
}
D3D12_GPU_DESCRIPTOR_HANDLE D3D12ViewCreator::CreateGPU(ID3D12DescriptorHeap *heap,
uint32_t descriptor)
{
CreateCPU(heap, descriptor);
static UINT increment[] = {
m_Dev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV),
0, // D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER
m_Dev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV),
m_Dev->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV),
};
D3D12_GPU_DESCRIPTOR_HANDLE gpu = heap->GetGPUDescriptorHandleForHeapStart();
if(m_Type == ViewType::DSV)
gpu.ptr += increment[D3D12_DESCRIPTOR_HEAP_TYPE_DSV] * descriptor;
else if(m_Type == ViewType::RTV)
gpu.ptr += increment[D3D12_DESCRIPTOR_HEAP_TYPE_RTV] * descriptor;
else
gpu.ptr += increment[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] * descriptor;
return gpu;
}
D3D12PSOCreator::D3D12PSOCreator(ID3D12DevicePtr dev) : m_Dev(dev)
{
GraphicsDesc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
GraphicsDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
GraphicsDesc.SampleMask = 0xFFFFFFFF;
GraphicsDesc.SampleDesc.Count = 1;
GraphicsDesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED;
GraphicsDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
GraphicsDesc.NumRenderTargets = 1;
GraphicsDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
GraphicsDesc.DSVFormat = DXGI_FORMAT_UNKNOWN;
GraphicsDesc.BlendState.RenderTarget[0].BlendEnable = FALSE;
GraphicsDesc.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;
GraphicsDesc.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
GraphicsDesc.BlendState.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD;
GraphicsDesc.BlendState.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_SRC_ALPHA;
GraphicsDesc.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;
GraphicsDesc.BlendState.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD;
GraphicsDesc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
GraphicsDesc.DepthStencilState.DepthEnable = FALSE;
GraphicsDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
GraphicsDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
GraphicsDesc.DepthStencilState.StencilReadMask = 0xff;
GraphicsDesc.DepthStencilState.StencilWriteMask = 0xff;
GraphicsDesc.DepthStencilState.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_EQUAL;
GraphicsDesc.DepthStencilState.FrontFace.StencilFailOp = D3D12_STENCIL_OP_KEEP;
GraphicsDesc.DepthStencilState.FrontFace.StencilDepthFailOp = D3D12_STENCIL_OP_KEEP;
GraphicsDesc.DepthStencilState.FrontFace.StencilPassOp = D3D12_STENCIL_OP_REPLACE;
GraphicsDesc.DepthStencilState.BackFace = GraphicsDesc.DepthStencilState.FrontFace;
}
D3D12PSOCreator &D3D12PSOCreator::VS(ID3DBlobPtr blob)
{
if(blob)
{
GraphicsDesc.VS.pShaderBytecode = blob->GetBufferPointer();
GraphicsDesc.VS.BytecodeLength = blob->GetBufferSize();
}
else
{
GraphicsDesc.VS.pShaderBytecode = NULL;
GraphicsDesc.VS.BytecodeLength = 0;
}
return *this;
}
D3D12PSOCreator &D3D12PSOCreator::HS(ID3DBlobPtr blob)
{
if(blob)
{
GraphicsDesc.HS.pShaderBytecode = blob->GetBufferPointer();
GraphicsDesc.HS.BytecodeLength = blob->GetBufferSize();
}
else
{
GraphicsDesc.HS.pShaderBytecode = NULL;
GraphicsDesc.HS.BytecodeLength = 0;
}
return *this;
}
D3D12PSOCreator &D3D12PSOCreator::DS(ID3DBlobPtr blob)
{
if(blob)
{
GraphicsDesc.DS.pShaderBytecode = blob->GetBufferPointer();
GraphicsDesc.DS.BytecodeLength = blob->GetBufferSize();
}
else
{
GraphicsDesc.DS.pShaderBytecode = NULL;
GraphicsDesc.DS.BytecodeLength = 0;
}
return *this;
}
D3D12PSOCreator &D3D12PSOCreator::GS(ID3DBlobPtr blob)
{
if(blob)
{
GraphicsDesc.GS.pShaderBytecode = blob->GetBufferPointer();
GraphicsDesc.GS.BytecodeLength = blob->GetBufferSize();
}
else
{
GraphicsDesc.GS.pShaderBytecode = NULL;
GraphicsDesc.GS.BytecodeLength = 0;
}
return *this;
}
D3D12PSOCreator &D3D12PSOCreator::PS(ID3DBlobPtr blob)
{
if(blob)
{
GraphicsDesc.PS.pShaderBytecode = blob->GetBufferPointer();
GraphicsDesc.PS.BytecodeLength = blob->GetBufferSize();
}
else
{
GraphicsDesc.PS.pShaderBytecode = NULL;
GraphicsDesc.PS.BytecodeLength = 0;
}
return *this;
}
D3D12PSOCreator &D3D12PSOCreator::CS(ID3DBlobPtr blob)
{
if(blob)
{
ComputeDesc.CS.pShaderBytecode = blob->GetBufferPointer();
ComputeDesc.CS.BytecodeLength = blob->GetBufferSize();
}
else
{
ComputeDesc.CS.pShaderBytecode = NULL;
ComputeDesc.CS.BytecodeLength = 0;
}
return *this;
}
D3D12PSOCreator &D3D12PSOCreator::InputLayout(const std::vector<D3D12_INPUT_ELEMENT_DESC> &elements)
{
GraphicsDesc.InputLayout.NumElements = (UINT)elements.size();
GraphicsDesc.InputLayout.pInputElementDescs = elements.data();
return *this;
}
D3D12PSOCreator &D3D12PSOCreator::InputLayout()
{
const D3D12_INPUT_CLASSIFICATION vertex = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
static const std::vector<D3D12_INPUT_ELEMENT_DESC> defaultLayout = {
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, vertex, 0},
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, vertex, 0},
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 28, vertex, 0},
};
return InputLayout(defaultLayout);
}
D3D12PSOCreator &D3D12PSOCreator::StripRestart(D3D12_INDEX_BUFFER_STRIP_CUT_VALUE stripCut)
{
GraphicsDesc.IBStripCutValue = stripCut;
return *this;
}
D3D12PSOCreator &D3D12PSOCreator::Topology(D3D12_PRIMITIVE_TOPOLOGY_TYPE topo)
{
GraphicsDesc.PrimitiveTopologyType = topo;
return *this;
}
D3D12PSOCreator &D3D12PSOCreator::RootSig(ID3D12RootSignaturePtr rootSig)
{
GraphicsDesc.pRootSignature = rootSig;
ComputeDesc.pRootSignature = rootSig;
return *this;
}
D3D12PSOCreator &D3D12PSOCreator::RTVs(const std::vector<DXGI_FORMAT> &fmts)
{
memset(GraphicsDesc.RTVFormats, 0, sizeof(GraphicsDesc.RTVFormats));
GraphicsDesc.NumRenderTargets = (UINT)fmts.size();
for(size_t i = 0; i < 8 && i < fmts.size(); i++)
GraphicsDesc.RTVFormats[i] = fmts[i];
return *this;
}
D3D12PSOCreator &D3D12PSOCreator::DSV(DXGI_FORMAT fmt)
{
GraphicsDesc.DSVFormat = fmt;
return *this;
}
D3D12PSOCreator &D3D12PSOCreator::SampleCount(UINT Samples)
{
GraphicsDesc.SampleDesc.Count = Samples;
return *this;
}
D3D12PSOCreator::operator ID3D12PipelineStatePtr() const
{
ID3D12PipelineStatePtr pso;
if(ComputeDesc.CS.BytecodeLength > 0)
{
CHECK_HR(m_Dev->CreateComputePipelineState(&ComputeDesc, __uuidof(ID3D12PipelineState),
(void **)&pso));
}
else
{
CHECK_HR(m_Dev->CreateGraphicsPipelineState(&GraphicsDesc, __uuidof(ID3D12PipelineState),
(void **)&pso));
}
return pso;
}
D3D12_INDIRECT_ARGUMENT_DESC vbArg(UINT slot)
{
return {D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW, slot};
}
D3D12_INDIRECT_ARGUMENT_DESC ibArg()
{
return {D3D12_INDIRECT_ARGUMENT_TYPE_INDEX_BUFFER_VIEW};
}
D3D12_INDIRECT_ARGUMENT_DESC uavArg(UINT root)
{
return {D3D12_INDIRECT_ARGUMENT_TYPE_UNORDERED_ACCESS_VIEW, root};
}
D3D12_INDIRECT_ARGUMENT_DESC srvArg(UINT root)
{
return {D3D12_INDIRECT_ARGUMENT_TYPE_SHADER_RESOURCE_VIEW, root};
}
D3D12_INDIRECT_ARGUMENT_DESC cbvArg(UINT root)
{
return {D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT_BUFFER_VIEW, root};
}
D3D12_INDIRECT_ARGUMENT_DESC constArg(UINT root, UINT wordOffset, UINT wordCount)
{
D3D12_INDIRECT_ARGUMENT_DESC ret;
ret.Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;
ret.Constant.RootParameterIndex = root;
ret.Constant.DestOffsetIn32BitValues = wordOffset;
ret.Constant.Num32BitValuesToSet = wordCount;
return ret;
}
D3D12_INDIRECT_ARGUMENT_DESC drawArg()
{
return {D3D12_INDIRECT_ARGUMENT_TYPE_DRAW};
}
D3D12_INDIRECT_ARGUMENT_DESC drawIndexedArg()
{
return {D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED};
}
D3D12_INDIRECT_ARGUMENT_DESC dispatchArg()
{
return {D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH};
}