Optimize compute shader pipeline binding on D3D12 and Vulkan when unchanged

This commit is contained in:
Wojtek Figat
2025-08-09 23:58:15 +02:00
parent b5a431d2f5
commit 1915e1e7f4
3 changed files with 29 additions and 11 deletions

View File

@@ -384,7 +384,7 @@ void GPUContextDX12::flushSRVs()
ASSERT(srCount <= GPU_MAX_SR_BINDED);
// Fill table with source descriptors
DxShaderHeader& header = _currentCompute ? ((GPUShaderProgramCSDX12*)_currentCompute)->Header : _currentState->Header;
DxShaderHeader& header = _isCompute ? ((GPUShaderProgramCSDX12*)_currentCompute)->Header : _currentState->Header;
D3D12_CPU_DESCRIPTOR_HANDLE srcDescriptorRangeStarts[GPU_MAX_SR_BINDED];
for (uint32 i = 0; i < srCount; i++)
{
@@ -1141,6 +1141,7 @@ void GPUContextDX12::UpdateCB(GPUConstantBuffer* cb, const void* data)
void GPUContextDX12::Dispatch(GPUShaderProgramCS* shader, uint32 threadGroupCountX, uint32 threadGroupCountY, uint32 threadGroupCountZ)
{
bool bindPipelineState = _currentCompute != shader;
_isCompute = 1;
_currentCompute = shader;
@@ -1153,14 +1154,16 @@ void GPUContextDX12::Dispatch(GPUShaderProgramCS* shader, uint32 threadGroupCoun
auto shaderDX12 = (GPUShaderProgramCSDX12*)shader;
auto computeState = shaderDX12->GetOrCreateState();
_commandList->SetPipelineState(computeState);
RENDER_STAT_PS_STATE_CHANGE();
if (bindPipelineState)
{
_commandList->SetPipelineState(computeState);
RENDER_STAT_PS_STATE_CHANGE();
}
_commandList->Dispatch(threadGroupCountX, threadGroupCountY, threadGroupCountZ);
RENDER_STAT_DISPATCH_CALL();
_isCompute = 0;
_currentCompute = nullptr;
// Restore previous state on next draw call
_psDirtyFlag = true;
@@ -1172,6 +1175,7 @@ void GPUContextDX12::Dispatch(GPUShaderProgramCS* shader, uint32 threadGroupCoun
void GPUContextDX12::DispatchIndirect(GPUShaderProgramCS* shader, GPUBuffer* bufferForArgs, uint32 offsetForArgs)
{
bool bindPipelineState = _currentCompute != shader;
_isCompute = 1;
_currentCompute = shader;
@@ -1187,15 +1191,17 @@ void GPUContextDX12::DispatchIndirect(GPUShaderProgramCS* shader, GPUBuffer* buf
auto shaderDX12 = (GPUShaderProgramCSDX12*)shader;
auto computeState = shaderDX12->GetOrCreateState();
_commandList->SetPipelineState(computeState);
RENDER_STAT_PS_STATE_CHANGE();
if (bindPipelineState)
{
_commandList->SetPipelineState(computeState);
RENDER_STAT_PS_STATE_CHANGE();
}
auto signature = _device->DispatchIndirectCommandSignature->GetSignature();
_commandList->ExecuteIndirect(signature, 1, bufferForArgsDX12->GetResource(), (UINT64)offsetForArgs, nullptr, 0);
RENDER_STAT_DISPATCH_CALL();
_isCompute = 0;
_currentCompute = nullptr;
// Restore previous state on next draw call
_psDirtyFlag = true;

View File

@@ -746,6 +746,7 @@ void GPUContextVulkan::FrameBegin()
_stencilRef = 0;
_renderPass = nullptr;
_currentState = nullptr;
_currentCompute = nullptr;
_vertexLayout = nullptr;
_rtDepth = nullptr;
Platform::MemoryClear(_rtHandles, sizeof(_rtHandles));
@@ -1157,8 +1158,12 @@ void GPUContextVulkan::Dispatch(GPUShaderProgramCS* shader, uint32 threadGroupCo
FlushBarriers();
// Bind pipeline
vkCmdBindPipeline(cmdBuffer->GetHandle(), VK_PIPELINE_BIND_POINT_COMPUTE, pipelineState->GetHandle());
RENDER_STAT_PS_STATE_CHANGE();
if (_currentCompute != shaderVulkan)
{
_currentCompute = shaderVulkan;
vkCmdBindPipeline(cmdBuffer->GetHandle(), VK_PIPELINE_BIND_POINT_COMPUTE, pipelineState->GetHandle());
RENDER_STAT_PS_STATE_CHANGE();
}
// Bind descriptors sets to the compute pipeline
pipelineState->Bind(cmdBuffer);
@@ -1193,8 +1198,12 @@ void GPUContextVulkan::DispatchIndirect(GPUShaderProgramCS* shader, GPUBuffer* b
FlushBarriers();
// Bind pipeline
vkCmdBindPipeline(cmdBuffer->GetHandle(), VK_PIPELINE_BIND_POINT_COMPUTE, pipelineState->GetHandle());
RENDER_STAT_PS_STATE_CHANGE();
if (_currentCompute != shaderVulkan)
{
_currentCompute = shaderVulkan;
vkCmdBindPipeline(cmdBuffer->GetHandle(), VK_PIPELINE_BIND_POINT_COMPUTE, pipelineState->GetHandle());
RENDER_STAT_PS_STATE_CHANGE();
}
// Bind descriptors sets to the compute pipeline
pipelineState->Bind(cmdBuffer);
@@ -1346,6 +1355,7 @@ void GPUContextVulkan::Flush()
// Flush remaining and buffered commands
FlushState();
_currentState = nullptr;
_currentCompute = nullptr;
// Execute commands
_cmdBufferManager->SubmitActiveCmdBuffer();

View File

@@ -16,6 +16,7 @@ class GPUTextureViewVulkan;
class GPUBufferVulkan;
class GPUVertexLayoutVulkan;
class GPUPipelineStateVulkan;
class GPUShaderProgramCSVulkan;
class ComputePipelineStateVulkan;
class GPUConstantBufferVulkan;
class DescriptorPoolVulkan;
@@ -84,6 +85,7 @@ private:
RenderPassVulkan* _renderPass;
GPUPipelineStateVulkan* _currentState;
GPUShaderProgramCSVulkan* _currentCompute;
GPUVertexLayoutVulkan* _vertexLayout;
GPUTextureViewVulkan* _rtDepth;
GPUTextureViewVulkan* _rtHandles[GPU_MAX_RT_BINDED];