Execute Indirect
功能与用法
DX12 有一个函数,叫做ExecuteIndirect,功能是:
(1)将一组由CPU指定的命令
(2)用由GPU指定的参数
(3)执行由GPU指定的次数
这个函数给予GPU定制命令的能力,利用它可以在GPU端实现视锥体剔除。
ID3D12GraphicsCommandList::ExecuteIndirect 的声明如下:
virtual void STDMETHODCALLTYPE ExecuteIndirect(
_In_ ID3D12CommandSignature *pCommandSignature,
_In_ UINT MaxCommandCount,
_In_ ID3D12Resource *pArgumentBuffer,
_In_ UINT64 ArgumentBufferOffset,
_In_opt_ ID3D12Resource *pCountBuffer,
_In_ UINT64 CountBufferOffset
对应上述功能
功能 | 参数 | 参数类型 |
指定一组命令 | pCommandSignature | ID3D12CommandSignature |
指定命令参数 | pArgumentBuffer | ID3D12Resource |
指定次数 | pCountBuffer | ID3D12Resource |
Argument Buffer 和 Count Buffer 都是普通的 buffer。通常的做法是,在compute shader把在视锥体里面的物体挑选出来,把对应的参数写入 argement buffer,物体个数写入 count buffer,再调用ExecuteIndirect一次过画出来。
Command Signature
Command Signature的作用是指定一组待重复执行的命令,其在CPU中创建一次,不能被GPU修改。
创建Command Signature的方法是
m_device->CreateCommandSignature(&commandSignatureDesc, m_rootSignature.Get(), IID_PPV_ARGS(&m_commandSignature))
其中commandSignatureDesc指定它的内部结构,它其实是D3D12_INDIRECT_ARGUMENT_DESC的数组,数组的一个元素表示一条命令。
于是,D3D12_INDIRECT_ARGUMENT_DESC自然就决定了一条命令是怎么指定的。
D3D12_INDIRECT_ARGUMENT_DESC 的数据包括
(1)命令类型
(2)固定参数(可变参数由GPU写入Argument Buffer)
以下是命令类型和对应应该指定的参数
命令(统一有D3D12_INDIRECT_ARGUMENT_TYPE_前缀) | 固定参数 | 可变参数(由Argument Buffer 指定) | 对应CommandList函数 |
DRAW | UINT VertexCountPerInstance, UINT InstanceCount, UINT StartVertexLocation, UINT StartInstanceLocation | void DrawInstanced( UINT VertexCountPerInstance, UINT InstanceCount, UINT StartVertexLocation, UINT StartInstanceLocation); | |
DRAW_INDEXED | UINT IndexCountPerInstance, UINT InstanceCount, UINT StartIndexLocation, INT BaseVertexLocation, UINT StartInstanceLocation | void DrawIndexedInstanced( UINT IndexCountPerInstance, UINT InstanceCount, UINT StartIndexLocation, INT BaseVertexLocation, UINT StartInstanceLocation); | |
DISPATCH | UINT ThreadGroupCountX, UINT ThreadGroupCountY, UINT ThreadGroupCountZ | void Dispatch( UINT ThreadGroupCountX, UINT ThreadGroupCountY, UINT ThreadGroupCountZ); | |
VERTEX_BUFFER_VIEW | UINT Slot; | UINT NumViews, const D3D12_VERTEX_BUFFER_VIEW *pViews | void IASetVertexBuffers( UINT StartSlot, UINT NumViews, const D3D12_VERTEX_BUFFER_VIEW *pViews); |
INDEX_BUFFER_VIEW | const D3D12_INDEX_BUFFER_VIEW *pView | void IASetIndexBuffer( const D3D12_INDEX_BUFFER_VIEW *pView); | |
CONSTANT | UINT RootParameterIndex; UINT DestOffsetIn32BitValues; UINT Num32BitValuesToSet; | void *pSrcData | void SetComputeRoot32BitConstants( UINT RootParameterIndex, UINT Num32BitValuesToSet, const void *pSrcData, UINT DestOffsetIn32BitValues); void SetGraphicsRoot32BitConstants( UINT RootParameterIndex, UINT Num32BitValuesToSet, const void *pSrcData, UINT DestOffsetIn32BitValues); |
CONSTANT_BUFFER_VIEW | UINT RootParameterIndex; | D3D12_GPU_VIRTUAL_ADDRESS BufferLocation | void SetComputeRootConstantBufferView( UINT RootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS BufferLocation); void SetGraphicsRootConstantBufferView( UINT RootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS BufferLocation); |
SHADER_RESOURCE_VIEW | UINT RootParameterIndex; | D3D12_GPU_VIRTUAL_ADDRESS BufferLocation | void SetComputeRootShaderResourceView( UINT RootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS BufferLocation); void SetGraphicsRootShaderResourceView( UINT RootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS BufferLocation); |
UNORDERED_ACCESS_VIEW | UINT RootParameterIndex; | D3D12_GPU_VIRTUAL_ADDRESS BufferLocation | void SetComputeRootUnorderedAccessView( UINT RootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS BufferLocation); void SetGraphicsRootUnorderedAccessView( UINT RootParameterIndex, D3D12_GPU_VIRTUAL_ADDRESS BufferLocation); |