From 3a5ddb27f1ac56fd1512f7468abd00d8f49ba840 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 22 Mar 2025 15:31:10 +0100 Subject: [PATCH] [dxvk,d3d9,d3d11] Refactor depth-stencil state object No reason to pass 72 bytes around when we can do with 10. --- src/d3d11/d3d11_context.cpp | 37 +++----- src/d3d11/d3d11_context.h | 3 +- src/d3d11/d3d11_depth_stencil.cpp | 42 ++++----- src/d3d11/d3d11_depth_stencil.h | 12 +-- src/d3d9/d3d9_device.cpp | 47 +++++----- src/dxvk/dxvk_constant_state.h | 143 +++++++++++++++++++++++++++--- src/dxvk/dxvk_context.cpp | 33 +++++-- src/dxvk/dxvk_graphics_state.h | 20 +++-- 8 files changed, 229 insertions(+), 108 deletions(-) diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 6d2f0adc7..075c47685 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -3410,16 +3410,13 @@ namespace dxvk { void D3D11CommonContext::ApplyDepthStencilState() { if (m_state.om.dsState != nullptr) { EmitCs([ - cDepthStencilState = m_state.om.dsState + cState = m_state.om.dsState->GetState() ] (DxvkContext* ctx) { - cDepthStencilState->BindToContext(ctx); + ctx->setDepthStencilState(cState); }); } else { EmitCs([] (DxvkContext* ctx) { - DxvkDepthStencilState dsState; - InitDefaultDepthStencilState(&dsState); - - ctx->setDepthStencilState(dsState); + ctx->setDepthStencilState(InitDefaultDepthStencilState()); }); } } @@ -4728,9 +4725,6 @@ namespace dxvk { DxvkInputAssemblyState iaState; InitDefaultPrimitiveTopology(&iaState); - DxvkDepthStencilState dsState; - InitDefaultDepthStencilState(&dsState); - DxvkRasterizerState rsState; InitDefaultRasterizerState(&rsState); @@ -4740,7 +4734,7 @@ namespace dxvk { InitDefaultBlendState(&cbState, &loState, &msState, D3D11_DEFAULT_SAMPLE_MASK); ctx->setInputAssemblyState(iaState); - ctx->setDepthStencilState(dsState); + ctx->setDepthStencilState(InitDefaultDepthStencilState()); ctx->setRasterizerState(rsState); ctx->setLogicOpState(loState); ctx->setMultisampleState(msState); @@ -5809,23 +5803,12 @@ namespace dxvk { template - void D3D11CommonContext::InitDefaultDepthStencilState( - DxvkDepthStencilState* pDsState) { - VkStencilOpState stencilOp; - stencilOp.failOp = VK_STENCIL_OP_KEEP; - stencilOp.passOp = VK_STENCIL_OP_KEEP; - stencilOp.depthFailOp = VK_STENCIL_OP_KEEP; - stencilOp.compareOp = VK_COMPARE_OP_ALWAYS; - stencilOp.compareMask = D3D11_DEFAULT_STENCIL_READ_MASK; - stencilOp.writeMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; - stencilOp.reference = 0; - - pDsState->enableDepthTest = VK_TRUE; - pDsState->enableDepthWrite = VK_TRUE; - pDsState->enableStencilTest = VK_FALSE; - pDsState->depthCompareOp = VK_COMPARE_OP_LESS; - pDsState->stencilOpFront = stencilOp; - pDsState->stencilOpBack = stencilOp; + DxvkDepthStencilState D3D11CommonContext::InitDefaultDepthStencilState() { + DxvkDepthStencilState dsState = { }; + dsState.setDepthTest(true); + dsState.setDepthWrite(true); + dsState.setDepthCompareOp(VK_COMPARE_OP_LESS); + return dsState; } diff --git a/src/d3d11/d3d11_context.h b/src/d3d11/d3d11_context.h index 6fe65a019..2de436de0 100644 --- a/src/d3d11/d3d11_context.h +++ b/src/d3d11/d3d11_context.h @@ -1149,8 +1149,7 @@ namespace dxvk { static void InitDefaultRasterizerState( DxvkRasterizerState* pRsState); - static void InitDefaultDepthStencilState( - DxvkDepthStencilState* pDsState); + static DxvkDepthStencilState InitDefaultDepthStencilState(); static void InitDefaultBlendState( DxvkBlendMode* pCbState, diff --git a/src/d3d11/d3d11_depth_stencil.cpp b/src/d3d11/d3d11_depth_stencil.cpp index 69efe593e..abbd5cc2a 100644 --- a/src/d3d11/d3d11_depth_stencil.cpp +++ b/src/d3d11/d3d11_depth_stencil.cpp @@ -8,12 +8,12 @@ namespace dxvk { const D3D11_DEPTH_STENCIL_DESC& desc) : D3D11StateObject(device), m_desc(desc), m_d3d10(this) { - m_state.enableDepthTest = desc.DepthEnable; - m_state.enableDepthWrite = desc.DepthWriteMask == D3D11_DEPTH_WRITE_MASK_ALL; - m_state.enableStencilTest = desc.StencilEnable; - m_state.depthCompareOp = DecodeCompareOp(desc.DepthFunc); - m_state.stencilOpFront = DecodeStencilOpState(desc.FrontFace, desc); - m_state.stencilOpBack = DecodeStencilOpState(desc.BackFace, desc); + m_state.setDepthTest(desc.DepthEnable); + m_state.setDepthWrite(desc.DepthWriteMask == D3D11_DEPTH_WRITE_MASK_ALL); + m_state.setStencilTest(desc.StencilEnable); + m_state.setDepthCompareOp(DecodeCompareOp(desc.DepthFunc)); + m_state.setStencilOpFront(DecodeStencilOpState(desc.FrontFace, desc)); + m_state.setStencilOpBack(DecodeStencilOpState(desc.BackFace, desc)); } @@ -55,11 +55,6 @@ namespace dxvk { } - void D3D11DepthStencilState::BindToContext(DxvkContext* ctx) { - ctx->setDepthStencilState(m_state); - } - - HRESULT D3D11DepthStencilState::NormalizeDesc(D3D11_DEPTH_STENCIL_DESC* pDesc) { if (pDesc->DepthEnable) { pDesc->DepthEnable = TRUE; @@ -105,25 +100,20 @@ namespace dxvk { } - VkStencilOpState D3D11DepthStencilState::DecodeStencilOpState( + DxvkStencilOp D3D11DepthStencilState::DecodeStencilOpState( const D3D11_DEPTH_STENCILOP_DESC& StencilDesc, const D3D11_DEPTH_STENCIL_DESC& Desc) const { - VkStencilOpState result; - result.failOp = VK_STENCIL_OP_KEEP; - result.passOp = VK_STENCIL_OP_KEEP; - result.depthFailOp = VK_STENCIL_OP_KEEP; - result.compareOp = VK_COMPARE_OP_ALWAYS; - result.compareMask = Desc.StencilReadMask; - result.writeMask = Desc.StencilWriteMask; - result.reference = 0; - + DxvkStencilOp result = { }; + if (Desc.StencilEnable) { - result.failOp = DecodeStencilOp(StencilDesc.StencilFailOp); - result.passOp = DecodeStencilOp(StencilDesc.StencilPassOp); - result.depthFailOp = DecodeStencilOp(StencilDesc.StencilDepthFailOp); - result.compareOp = DecodeCompareOp(StencilDesc.StencilFunc); + result.setFailOp(DecodeStencilOp(StencilDesc.StencilFailOp)); + result.setPassOp(DecodeStencilOp(StencilDesc.StencilPassOp)); + result.setDepthFailOp(DecodeStencilOp(StencilDesc.StencilDepthFailOp)); + result.setCompareOp(DecodeCompareOp(StencilDesc.StencilFunc)); + result.setCompareMask(Desc.StencilReadMask); + result.setWriteMask(Desc.StencilWriteMask); } - + return result; } diff --git a/src/d3d11/d3d11_depth_stencil.h b/src/d3d11/d3d11_depth_stencil.h index 5cc1dba86..4ddacda28 100644 --- a/src/d3d11/d3d11_depth_stencil.h +++ b/src/d3d11/d3d11_depth_stencil.h @@ -28,9 +28,11 @@ namespace dxvk { void STDMETHODCALLTYPE GetDesc( D3D11_DEPTH_STENCIL_DESC* pDesc) final; - - void BindToContext(DxvkContext* ctx); - + + DxvkDepthStencilState GetState() const { + return m_state; + } + D3D10DepthStencilState* GetD3D10Iface() { return &m_d3d10; } @@ -41,10 +43,10 @@ namespace dxvk { private: D3D11_DEPTH_STENCIL_DESC m_desc; - DxvkDepthStencilState m_state; + DxvkDepthStencilState m_state = { }; D3D10DepthStencilState m_d3d10; - VkStencilOpState DecodeStencilOpState( + DxvkStencilOp DecodeStencilOpState( const D3D11_DEPTH_STENCILOP_DESC& StencilDesc, const D3D11_DEPTH_STENCIL_DESC& Desc) const; diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index cfd970fdc..f0ca0c0d1 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -6917,35 +6917,36 @@ namespace dxvk { bool stencil = rs[D3DRS_STENCILENABLE]; bool twoSidedStencil = stencil && rs[D3DRS_TWOSIDEDSTENCILMODE]; - DxvkDepthStencilState state; - state.enableDepthTest = rs[D3DRS_ZENABLE] != FALSE; - state.enableDepthWrite = rs[D3DRS_ZWRITEENABLE] != FALSE; - state.enableStencilTest = stencil; - state.depthCompareOp = DecodeCompareOp(D3DCMPFUNC(rs[D3DRS_ZFUNC])); + DxvkDepthStencilState state = { }; + state.setDepthTest(rs[D3DRS_ZENABLE]); + state.setDepthWrite(rs[D3DRS_ZWRITEENABLE]); + state.setStencilTest(stencil); + state.setDepthCompareOp(DecodeCompareOp(D3DCMPFUNC(rs[D3DRS_ZFUNC]))); + + DxvkStencilOp frontOp = { }; if (stencil) { - state.stencilOpFront.failOp = DecodeStencilOp(D3DSTENCILOP(rs[D3DRS_STENCILFAIL])); - state.stencilOpFront.passOp = DecodeStencilOp(D3DSTENCILOP(rs[D3DRS_STENCILPASS])); - state.stencilOpFront.depthFailOp = DecodeStencilOp(D3DSTENCILOP(rs[D3DRS_STENCILZFAIL])); - state.stencilOpFront.compareOp = DecodeCompareOp(D3DCMPFUNC (rs[D3DRS_STENCILFUNC])); - state.stencilOpFront.compareMask = uint32_t(rs[D3DRS_STENCILMASK]); - state.stencilOpFront.writeMask = uint32_t(rs[D3DRS_STENCILWRITEMASK]); - state.stencilOpFront.reference = 0; + frontOp.setFailOp(DecodeStencilOp(D3DSTENCILOP(rs[D3DRS_STENCILFAIL]))); + frontOp.setPassOp(DecodeStencilOp(D3DSTENCILOP(rs[D3DRS_STENCILPASS]))); + frontOp.setDepthFailOp(DecodeStencilOp(D3DSTENCILOP(rs[D3DRS_STENCILZFAIL]))); + frontOp.setCompareOp(DecodeCompareOp(D3DCMPFUNC(rs[D3DRS_STENCILFUNC]))); + frontOp.setCompareMask(rs[D3DRS_STENCILMASK]); + frontOp.setWriteMask(rs[D3DRS_STENCILWRITEMASK]); } - else - state.stencilOpFront = VkStencilOpState(); + + DxvkStencilOp backOp = frontOp; if (twoSidedStencil) { - state.stencilOpBack.failOp = DecodeStencilOp(D3DSTENCILOP(rs[D3DRS_CCW_STENCILFAIL])); - state.stencilOpBack.passOp = DecodeStencilOp(D3DSTENCILOP(rs[D3DRS_CCW_STENCILPASS])); - state.stencilOpBack.depthFailOp = DecodeStencilOp(D3DSTENCILOP(rs[D3DRS_CCW_STENCILZFAIL])); - state.stencilOpBack.compareOp = DecodeCompareOp(D3DCMPFUNC (rs[D3DRS_CCW_STENCILFUNC])); - state.stencilOpBack.compareMask = state.stencilOpFront.compareMask; - state.stencilOpBack.writeMask = state.stencilOpFront.writeMask; - state.stencilOpBack.reference = 0; + backOp.setFailOp(DecodeStencilOp(D3DSTENCILOP(rs[D3DRS_CCW_STENCILFAIL]))); + backOp.setPassOp(DecodeStencilOp(D3DSTENCILOP(rs[D3DRS_CCW_STENCILPASS]))); + backOp.setDepthFailOp(DecodeStencilOp(D3DSTENCILOP(rs[D3DRS_CCW_STENCILZFAIL]))); + backOp.setCompareOp(DecodeCompareOp(D3DCMPFUNC(rs[D3DRS_CCW_STENCILFUNC]))); + backOp.setCompareMask(rs[D3DRS_STENCILMASK]); + backOp.setWriteMask(rs[D3DRS_STENCILWRITEMASK]); } - else - state.stencilOpBack = state.stencilOpFront; + + state.setStencilOpFront(frontOp); + state.setStencilOpBack(backOp); EmitCs([ cState = state diff --git a/src/dxvk/dxvk_constant_state.h b/src/dxvk/dxvk_constant_state.h index 19db7b88f..9d46d10e0 100644 --- a/src/dxvk/dxvk_constant_state.h +++ b/src/dxvk/dxvk_constant_state.h @@ -141,20 +141,143 @@ namespace dxvk { VkBool32 enableAlphaToCoverage; }; - + + /** + * \brief Stencil operation + */ + class DxvkStencilOp { + + public: + + VkStencilOp failOp() const { + return VkStencilOp(m_failOp); + } + + VkStencilOp passOp() const { + return VkStencilOp(m_passOp); + } + + VkStencilOp depthFailOp() const { + return VkStencilOp(m_depthFailOp); + } + + VkCompareOp compareOp() const { + return VkCompareOp(m_compareOp); + } + + uint8_t compareMask() const { + return m_compareMask; + } + + uint8_t writeMask() const { + return m_writeMask; + } + + void setFailOp(VkStencilOp op) { + m_failOp = uint16_t(op); + } + + void setPassOp(VkStencilOp op) { + m_passOp = uint16_t(op); + } + + void setDepthFailOp(VkStencilOp op) { + m_depthFailOp = uint16_t(op); + } + + void setCompareOp(VkCompareOp op) { + m_compareOp = uint16_t(op); + } + + void setCompareMask(uint8_t mask) { + m_compareMask = mask; + } + + void setWriteMask(uint8_t mask) { + m_writeMask = mask; + } + + private: + + uint16_t m_failOp : 3; + uint16_t m_passOp : 3; + uint16_t m_depthFailOp : 3; + uint16_t m_compareOp : 3; + uint16_t m_reserved : 4; + uint8_t m_compareMask; + uint8_t m_writeMask; + + }; + + /** * \brief Depth-stencil state * * Defines the depth test and stencil * operations for the graphics pipeline. */ - struct DxvkDepthStencilState { - VkBool32 enableDepthTest; - VkBool32 enableDepthWrite; - VkBool32 enableStencilTest; - VkCompareOp depthCompareOp; - VkStencilOpState stencilOpFront; - VkStencilOpState stencilOpBack; + class DxvkDepthStencilState { + + public: + + bool depthTest() const { + return m_enableDepthTest; + } + + bool depthWrite() const { + return m_enableDepthWrite; + } + + bool stencilTest() const { + return m_enableStencilTest; + } + + VkCompareOp depthCompareOp() const { + return VkCompareOp(m_depthCompareOp); + } + + DxvkStencilOp stencilOpFront() const { + return m_stencilOpFront; + } + + DxvkStencilOp stencilOpBack() const { + return m_stencilOpBack; + } + + void setDepthTest(bool depthTest) { + m_enableDepthTest = depthTest; + } + + void setDepthWrite(bool depthWrite) { + m_enableDepthWrite = depthWrite; + } + + void setStencilTest(bool stencilTest) { + m_enableStencilTest = stencilTest; + } + + void setDepthCompareOp(VkCompareOp compareOp) { + m_depthCompareOp = uint16_t(compareOp); + } + + void setStencilOpFront(DxvkStencilOp op) { + m_stencilOpFront = op; + } + + void setStencilOpBack(DxvkStencilOp op) { + m_stencilOpBack = op; + } + + private: + + uint16_t m_enableDepthTest : 1; + uint16_t m_enableDepthWrite : 1; + uint16_t m_enableStencilTest : 1; + uint16_t m_depthCompareOp : 3; + uint16_t m_reserved : 10; + DxvkStencilOp m_stencilOpFront; + DxvkStencilOp m_stencilOpBack; + }; @@ -227,5 +350,5 @@ namespace dxvk { std::array attributes; std::array bindings; }; - -} \ No newline at end of file + +} diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 55a1efc89..cc2fb1ca8 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -2891,15 +2891,32 @@ namespace dxvk { void DxvkContext::setDepthStencilState(const DxvkDepthStencilState& ds) { m_state.gp.state.ds = DxvkDsInfo( - ds.enableDepthTest, - ds.enableDepthWrite, + ds.depthTest(), + ds.depthWrite(), m_state.gp.state.ds.enableDepthBoundsTest(), - ds.enableStencilTest, - ds.depthCompareOp); - - m_state.gp.state.dsFront = DxvkDsStencilOp(ds.stencilOpFront); - m_state.gp.state.dsBack = DxvkDsStencilOp(ds.stencilOpBack); - + ds.stencilTest(), + ds.depthCompareOp()); + + DxvkStencilOp front = ds.stencilOpFront(); + + m_state.gp.state.dsFront = DxvkDsStencilOp( + front.failOp(), + front.passOp(), + front.depthFailOp(), + front.compareOp(), + front.compareMask(), + front.writeMask()); + + DxvkStencilOp back = ds.stencilOpBack(); + + m_state.gp.state.dsBack = DxvkDsStencilOp( + back.failOp(), + back.passOp(), + back.depthFailOp(), + back.compareOp(), + back.compareMask(), + back.writeMask()); + m_flags.set( DxvkContextFlag::GpDirtyPipelineState, DxvkContextFlag::GpDirtyDepthStencilState); diff --git a/src/dxvk/dxvk_graphics_state.h b/src/dxvk/dxvk_graphics_state.h index 926f7f28d..885a38a79 100644 --- a/src/dxvk/dxvk_graphics_state.h +++ b/src/dxvk/dxvk_graphics_state.h @@ -400,14 +400,20 @@ namespace dxvk { DxvkDsStencilOp() = default; - DxvkDsStencilOp(VkStencilOpState state) - : m_failOp (uint32_t(state.failOp)), - m_passOp (uint32_t(state.passOp)), - m_depthFailOp (uint32_t(state.depthFailOp)), - m_compareOp (uint32_t(state.compareOp)), + DxvkDsStencilOp( + VkStencilOp failOp, + VkStencilOp passOp, + VkStencilOp depthFailOp, + VkCompareOp compareOp, + uint8_t compareMask, + uint8_t writeMask) + : m_failOp (uint32_t(failOp)), + m_passOp (uint32_t(passOp)), + m_depthFailOp (uint32_t(depthFailOp)), + m_compareOp (uint32_t(compareOp)), m_reserved (0), - m_compareMask (uint32_t(state.compareMask)), - m_writeMask (uint32_t(state.writeMask)) { } + m_compareMask (uint32_t(compareMask)), + m_writeMask (uint32_t(writeMask)) { } VkStencilOpState state(bool write) const { VkStencilOpState result;