From 1915e1e7f4d2795876ad174b152aa3f62d6fe2b1 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 9 Aug 2025 23:58:15 +0200 Subject: [PATCH] Optimize compute shader pipeline binding on D3D12 and Vulkan when unchanged --- .../DirectX/DX12/GPUContextDX12.cpp | 20 ++++++++++++------- .../Vulkan/GPUContextVulkan.cpp | 18 +++++++++++++---- .../GraphicsDevice/Vulkan/GPUContextVulkan.h | 2 ++ 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp index 88afc5cfb..c132c7343 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp @@ -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; diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp index 430ce5b70..34ad63a66 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp @@ -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(); diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.h index d3dd1c528..bba79c498 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.h +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.h @@ -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];