From 1c9d8aa470b8056f552a8670ec54bb9596bb14d6 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 19 Jun 2023 11:21:35 +0200 Subject: [PATCH] Add `GPUContext::SetStencilRef` to stencil reference value --- Source/Engine/Graphics/GPUContext.h | 6 ++++++ .../GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp | 9 ++++++++- .../GraphicsDevice/DirectX/DX11/GPUContextDX11.h | 2 ++ .../GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp | 10 ++++++++++ .../GraphicsDevice/DirectX/DX12/GPUContextDX12.h | 2 ++ Source/Engine/GraphicsDevice/Null/GPUContextNull.h | 4 ++++ .../Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp | 11 +++++++++++ .../Engine/GraphicsDevice/Vulkan/GPUContextVulkan.h | 2 ++ .../GraphicsDevice/Vulkan/GPUPipelineStateVulkan.cpp | 2 +- 9 files changed, 46 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Graphics/GPUContext.h b/Source/Engine/Graphics/GPUContext.h index 99a226193..3ff7ec256 100644 --- a/Source/Engine/Graphics/GPUContext.h +++ b/Source/Engine/Graphics/GPUContext.h @@ -321,6 +321,12 @@ public: /// Blend factors, one for each RGBA component. API_FUNCTION() virtual void SetBlendFactor(const Float4& value) = 0; + /// + /// Sets the reference value for depth stencil tests. + /// + /// Reference value to perform against when doing a depth-stencil test. + API_FUNCTION() virtual void SetStencilRef(uint32 value) = 0; + public: /// /// Unbinds all shader resource slots and flushes the change with the driver (used to prevent driver detection of resource hazards, eg. when down-scaling the texture). diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp index 10d85c179..6b6ebd6bc 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp @@ -103,6 +103,7 @@ void GPUContextDX11::FrameBegin() CurrentPS = nullptr; CurrentCS = nullptr; CurrentPrimitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; + CurrentStencilRef = 0; CurrentBlendFactor = Float4::One; // Bind static samplers @@ -275,6 +276,12 @@ void GPUContextDX11::SetBlendFactor(const Float4& value) _context->OMSetBlendState(CurrentBlendState, CurrentBlendFactor.Raw, D3D11_DEFAULT_SAMPLE_MASK); } +void GPUContextDX11::SetStencilRef(uint32 value) +{ + if (CurrentStencilRef != value) + _context->OMSetDepthStencilState(CurrentDepthStencilState, CurrentStencilRef); +} + void GPUContextDX11::ResetSR() { _srDirtyFlag = false; @@ -559,7 +566,7 @@ void GPUContextDX11::SetState(GPUPipelineState* state) if (CurrentDepthStencilState != depthStencilState) { CurrentDepthStencilState = depthStencilState; - _context->OMSetDepthStencilState(depthStencilState, 0); + _context->OMSetDepthStencilState(depthStencilState, CurrentStencilRef); } if (CurrentRasterizerState != rasterizerState) { diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.h b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.h index b623cba3b..4e47c2f11 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.h +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.h @@ -61,6 +61,7 @@ private: GPUShaderProgramPSDX11* CurrentPS; GPUShaderProgramCSDX11* CurrentCS; D3D11_PRIMITIVE_TOPOLOGY CurrentPrimitiveTopology; + uint32 CurrentStencilRef; Float4 CurrentBlendFactor; public: @@ -117,6 +118,7 @@ public: void SetRenderTarget(GPUTextureView* depthBuffer, GPUTextureView* rt) override; void SetRenderTarget(GPUTextureView* depthBuffer, const Span& rts) override; void SetBlendFactor(const Float4& value) override; + void SetStencilRef(uint32 value) override; void ResetSR() override; void ResetUA() override; void ResetCB() override; diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp index 54f1a4290..107895cf5 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp @@ -222,6 +222,7 @@ void GPUContextDX12::Reset() _rtDepth = nullptr; _srMaskDirtyGraphics = 0; _srMaskDirtyCompute = 0; + _stencilRef = 0; _psDirtyFlag = false; _isCompute = false; _currentCompute = nullptr; @@ -850,6 +851,15 @@ void GPUContextDX12::SetBlendFactor(const Float4& value) _commandList->OMSetBlendFactor(value.Raw); } +void GPUContextDX12::SetStencilRef(uint32 value) +{ + if (_stencilRef != value) + { + _stencilRef = value; + _commandList->OMSetStencilRef(value); + } +} + void GPUContextDX12::ResetSR() { for (int32 slot = 0; slot < GPU_MAX_SR_BINDED; slot++) diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.h b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.h index c870cf71e..45dfa8162 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.h +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.h @@ -47,6 +47,7 @@ private: uint32 _srMaskDirtyGraphics; uint32 _srMaskDirtyCompute; + uint32 _stencilRef; int32 _isCompute : 1; int32 _rtDirtyFlag : 1; @@ -167,6 +168,7 @@ public: void SetRenderTarget(GPUTextureView* depthBuffer, GPUTextureView* rt) override; void SetRenderTarget(GPUTextureView* depthBuffer, const Span& rts) override; void SetBlendFactor(const Float4& value) override; + void SetStencilRef(uint32 value) override; void ResetSR() override; void ResetUA() override; void ResetCB() override; diff --git a/Source/Engine/GraphicsDevice/Null/GPUContextNull.h b/Source/Engine/GraphicsDevice/Null/GPUContextNull.h index 7568bb60c..e22c4b147 100644 --- a/Source/Engine/GraphicsDevice/Null/GPUContextNull.h +++ b/Source/Engine/GraphicsDevice/Null/GPUContextNull.h @@ -88,6 +88,10 @@ public: { } + void SetStencilRef(uint32 value) override + { + } + void ResetSR() override { } diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp index d52b446e3..64d8bfb67 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp @@ -727,6 +727,7 @@ void GPUContextVulkan::FrameBegin() _cbDirtyFlag = 0; _rtCount = 0; _vbCount = 0; + _stencilRef = 0; _renderPass = nullptr; _currentState = nullptr; _rtDepth = nullptr; @@ -972,6 +973,16 @@ void GPUContextVulkan::SetBlendFactor(const Float4& value) vkCmdSetBlendConstants(cmdBuffer->GetHandle(), value.Raw); } +void GPUContextVulkan::SetStencilRef(uint32 value) +{ + if (_stencilRef != value) + { + _stencilRef = value; + const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer(); + vkCmdSetStencilReference(cmdBuffer->GetHandle(), VK_STENCIL_FRONT_AND_BACK, _stencilRef); + } +} + void GPUContextVulkan::ResetSR() { Platform::MemoryClear(_srHandles, sizeof(_srHandles)); diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.h index 63224b2d0..08b5c1d6a 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.h +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.h @@ -97,6 +97,7 @@ private: int32 _rtCount; int32 _vbCount; + uint32 _stencilRef; RenderPassVulkan* _renderPass; GPUPipelineStateVulkan* _currentState; @@ -185,6 +186,7 @@ public: void SetRenderTarget(GPUTextureView* depthBuffer, GPUTextureView* rt) override; void SetRenderTarget(GPUTextureView* depthBuffer, const Span& rts) override; void SetBlendFactor(const Float4& value) override; + void SetStencilRef(uint32 value) override; void ResetSR() override; void ResetUA() override; void ResetCB() override; diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUPipelineStateVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUPipelineStateVulkan.cpp index 935f37873..d2ccf7da1 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUPipelineStateVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUPipelineStateVulkan.cpp @@ -274,7 +274,7 @@ bool GPUPipelineStateVulkan::Init(const Description& desc) _descDynamic.pDynamicStates = _dynamicStates; _dynamicStates[_descDynamic.dynamicStateCount++] = VK_DYNAMIC_STATE_VIEWPORT; _dynamicStates[_descDynamic.dynamicStateCount++] = VK_DYNAMIC_STATE_SCISSOR; - //_dynamicStates[_descDynamic.dynamicStateCount++] = VK_DYNAMIC_STATE_STENCIL_REFERENCE; + _dynamicStates[_descDynamic.dynamicStateCount++] = VK_DYNAMIC_STATE_STENCIL_REFERENCE; static_assert(ARRAY_COUNT(_dynamicStates) <= 3, "Invalid dynamic states array."); _desc.pDynamicState = &_descDynamic;