GPU: Respect stencil write mask for 5551 buffers.
If the mask is 0x7F on 5551, that's equivalent to allowing the clear entirely. See #13391.
This commit is contained in:
parent
a88f6b45d2
commit
9857e8d1b1
5 changed files with 28 additions and 22 deletions
|
@ -1303,8 +1303,6 @@ void ConvertBlendState(GenericBlendState &blendState, bool allowFramebufferRead)
|
|||
}
|
||||
|
||||
static void ConvertStencilFunc5551(GenericStencilFuncState &state) {
|
||||
state.writeMask = state.writeMask >= 0x80 ? 0xff : 0x00;
|
||||
|
||||
// Flaws:
|
||||
// - INVERT should convert 1, 5, 0xFF to 0. Currently it won't always.
|
||||
// - INCR twice shouldn't change the value.
|
||||
|
@ -1436,13 +1434,19 @@ static void ConvertStencilFunc5551(GenericStencilFuncState &state) {
|
|||
}
|
||||
}
|
||||
|
||||
void ConvertStencilFuncState(GenericStencilFuncState &state) {
|
||||
state.enabled = gstate.isStencilTestEnabled();
|
||||
if (!state.enabled)
|
||||
return;
|
||||
static void ConvertStencilMask5551(GenericStencilFuncState &state) {
|
||||
state.writeMask = state.writeMask >= 0x80 ? 0xff : 0x00;
|
||||
}
|
||||
|
||||
// The PSP's mask is reversed (bits not to write.)
|
||||
void ConvertStencilFuncState(GenericStencilFuncState &state) {
|
||||
// The PSP's mask is reversed (bits not to write.) Ignore enabled, used for clears too.
|
||||
state.writeMask = (~gstate.getStencilWriteMask()) & 0xFF;
|
||||
state.enabled = gstate.isStencilTestEnabled();
|
||||
if (!state.enabled) {
|
||||
if (gstate.FrameBufFormat() == GE_FORMAT_5551)
|
||||
ConvertStencilMask5551(state);
|
||||
return;
|
||||
}
|
||||
|
||||
state.sFail = gstate.getStencilOpSFail();
|
||||
state.zFail = gstate.getStencilOpZFail();
|
||||
|
@ -1458,6 +1462,7 @@ void ConvertStencilFuncState(GenericStencilFuncState &state) {
|
|||
break;
|
||||
|
||||
case GE_FORMAT_5551:
|
||||
ConvertStencilMask5551(state);
|
||||
ConvertStencilFunc5551(state);
|
||||
break;
|
||||
|
||||
|
|
|
@ -284,6 +284,9 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
|
|||
}
|
||||
|
||||
if (gstate_c.IsDirty(DIRTY_DEPTHSTENCIL_STATE)) {
|
||||
GenericStencilFuncState stencilState;
|
||||
ConvertStencilFuncState(stencilState);
|
||||
|
||||
if (gstate.isModeClear()) {
|
||||
keys_.depthStencil.value = 0;
|
||||
keys_.depthStencil.depthTestEnable = true;
|
||||
|
@ -307,7 +310,7 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
|
|||
// We override this value in the pipeline from software transform for clear rectangles.
|
||||
dynState_.stencilRef = 0xFF;
|
||||
// But we still apply the stencil write mask.
|
||||
keys_.depthStencil.stencilWriteMask = (~gstate.getStencilWriteMask()) & 0xFF;
|
||||
keys_.depthStencil.stencilWriteMask = stencilState.writeMask;
|
||||
} else {
|
||||
keys_.depthStencil.stencilTestEnable = false;
|
||||
dynState_.useStencil = false;
|
||||
|
@ -329,9 +332,6 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
|
|||
keys_.depthStencil.depthCompareOp = D3D11_COMPARISON_ALWAYS;
|
||||
}
|
||||
|
||||
GenericStencilFuncState stencilState;
|
||||
ConvertStencilFuncState(stencilState);
|
||||
|
||||
// Stencil Test
|
||||
if (stencilState.enabled) {
|
||||
keys_.depthStencil.stencilTestEnable = true;
|
||||
|
|
|
@ -187,6 +187,9 @@ void DrawEngineDX9::ApplyDrawState(int prim) {
|
|||
|
||||
if (gstate_c.IsDirty(DIRTY_DEPTHSTENCIL_STATE)) {
|
||||
gstate_c.Clean(DIRTY_DEPTHSTENCIL_STATE);
|
||||
GenericStencilFuncState stencilState;
|
||||
ConvertStencilFuncState(stencilState);
|
||||
|
||||
// Set Stencil/Depth
|
||||
if (gstate.isModeClear()) {
|
||||
// Depth Test
|
||||
|
@ -203,7 +206,7 @@ void DrawEngineDX9::ApplyDrawState(int prim) {
|
|||
dxstate.stencilTest.enable();
|
||||
dxstate.stencilOp.set(D3DSTENCILOP_REPLACE, D3DSTENCILOP_REPLACE, D3DSTENCILOP_REPLACE);
|
||||
dxstate.stencilFunc.set(D3DCMP_ALWAYS, 255, 0xFF);
|
||||
dxstate.stencilMask.set((~gstate.getStencilWriteMask()) & 0xFF);
|
||||
dxstate.stencilMask.set(stencilState.writeMask);
|
||||
} else {
|
||||
dxstate.stencilTest.disable();
|
||||
}
|
||||
|
@ -221,9 +224,6 @@ void DrawEngineDX9::ApplyDrawState(int prim) {
|
|||
dxstate.depthTest.disable();
|
||||
}
|
||||
|
||||
GenericStencilFuncState stencilState;
|
||||
ConvertStencilFuncState(stencilState);
|
||||
|
||||
// Stencil Test
|
||||
if (stencilState.enabled) {
|
||||
dxstate.stencilTest.enable();
|
||||
|
|
|
@ -235,13 +235,16 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
|
|||
|
||||
if (gstate_c.IsDirty(DIRTY_DEPTHSTENCIL_STATE)) {
|
||||
gstate_c.Clean(DIRTY_DEPTHSTENCIL_STATE);
|
||||
GenericStencilFuncState stencilState;
|
||||
ConvertStencilFuncState(stencilState);
|
||||
|
||||
if (gstate.isModeClear()) {
|
||||
// Depth Test
|
||||
if (gstate.isClearModeDepthMask()) {
|
||||
framebufferManager_->SetDepthUpdated();
|
||||
}
|
||||
renderManager->SetStencilFunc(gstate.isClearModeAlphaMask(), GL_ALWAYS, 0xFF, 0xFF);
|
||||
renderManager->SetStencilOp((~gstate.getStencilWriteMask()) & 0xFF, GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
||||
renderManager->SetStencilOp(stencilState.writeMask, GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
||||
renderManager->SetDepth(true, gstate.isClearModeDepthMask() ? true : false, GL_ALWAYS);
|
||||
} else {
|
||||
// Depth Test
|
||||
|
@ -250,8 +253,6 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
|
|||
framebufferManager_->SetDepthUpdated();
|
||||
}
|
||||
|
||||
GenericStencilFuncState stencilState;
|
||||
ConvertStencilFuncState(stencilState);
|
||||
// Stencil Test
|
||||
if (stencilState.enabled) {
|
||||
renderManager->SetStencilFunc(stencilState.enabled, compareOps[stencilState.testFunc], stencilState.testRef, stencilState.testMask);
|
||||
|
|
|
@ -253,6 +253,9 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag
|
|||
}
|
||||
|
||||
if (gstate_c.IsDirty(DIRTY_DEPTHSTENCIL_STATE)) {
|
||||
GenericStencilFuncState stencilState;
|
||||
ConvertStencilFuncState(stencilState);
|
||||
|
||||
if (gstate.isModeClear()) {
|
||||
key.depthTestEnable = true;
|
||||
key.depthCompareOp = VK_COMPARE_OP_ALWAYS;
|
||||
|
@ -275,7 +278,7 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag
|
|||
// We override this value in the pipeline from software transform for clear rectangles.
|
||||
dynState.stencilRef = 0xFF;
|
||||
// But we still apply the stencil write mask.
|
||||
dynState.stencilWriteMask = (~gstate.getStencilWriteMask()) & 0xFF;
|
||||
dynState.stencilWriteMask = stencilState.writeMask;
|
||||
} else {
|
||||
key.stencilTestEnable = false;
|
||||
key.stencilCompareOp = VK_COMPARE_OP_ALWAYS;
|
||||
|
@ -299,9 +302,6 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag
|
|||
key.depthCompareOp = VK_COMPARE_OP_ALWAYS;
|
||||
}
|
||||
|
||||
GenericStencilFuncState stencilState;
|
||||
ConvertStencilFuncState(stencilState);
|
||||
|
||||
// Stencil Test
|
||||
if (stencilState.enabled) {
|
||||
key.stencilTestEnable = true;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue