1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-28 02:19:26 +01:00

[dxvk,d3d9,d3d11] Refactor depth-stencil state object

No reason to pass 72 bytes around when we can do with 10.
This commit is contained in:
Philip Rebohle 2025-03-22 15:31:10 +01:00
parent e6ef72b63d
commit 92b3e96ebc
8 changed files with 229 additions and 108 deletions

View File

@ -3420,16 +3420,13 @@ namespace dxvk {
void D3D11CommonContext<ContextType>::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());
});
}
}
@ -4738,9 +4735,6 @@ namespace dxvk {
DxvkInputAssemblyState iaState;
InitDefaultPrimitiveTopology(&iaState);
DxvkDepthStencilState dsState;
InitDefaultDepthStencilState(&dsState);
DxvkRasterizerState rsState;
InitDefaultRasterizerState(&rsState);
@ -4750,7 +4744,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);
@ -5819,23 +5813,12 @@ namespace dxvk {
template<typename ContextType>
void D3D11CommonContext<ContextType>::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<ContextType>::InitDefaultDepthStencilState() {
DxvkDepthStencilState dsState = { };
dsState.setDepthTest(true);
dsState.setDepthWrite(true);
dsState.setDepthCompareOp(VK_COMPARE_OP_LESS);
return dsState;
}

View File

@ -1149,8 +1149,7 @@ namespace dxvk {
static void InitDefaultRasterizerState(
DxvkRasterizerState* pRsState);
static void InitDefaultDepthStencilState(
DxvkDepthStencilState* pDsState);
static DxvkDepthStencilState InitDefaultDepthStencilState();
static void InitDefaultBlendState(
DxvkBlendMode* pCbState,

View File

@ -8,12 +8,12 @@ namespace dxvk {
const D3D11_DEPTH_STENCIL_DESC& desc)
: D3D11StateObject<ID3D11DepthStencilState>(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;
}

View File

@ -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;

View File

@ -6919,35 +6919,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

View File

@ -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<DxvkVertexAttribute, DxvkLimits::MaxNumVertexAttributes> attributes;
std::array<DxvkVertexBinding, DxvkLimits::MaxNumVertexBindings> bindings;
};
}
}

View File

@ -2778,15 +2778,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);

View File

@ -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;