diff --git a/GPU/D3D11/StateMappingD3D11.cpp b/GPU/D3D11/StateMappingD3D11.cpp index 0ec3b01b32..f3be8cb4bb 100644 --- a/GPU/D3D11/StateMappingD3D11.cpp +++ b/GPU/D3D11/StateMappingD3D11.cpp @@ -148,8 +148,7 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { bool alphaMask = gstate.isClearModeAlphaMask(); bool colorMask = gstate.isClearModeColorMask(); keys_.blend.colorWriteMask = (colorMask ? (1 | 2 | 4) : 0) | (alphaMask ? 8 : 0); - } - else { + } else { // Set blend - unless we need to do it in the shader. GenericBlendState blendState; ConvertBlendState(blendState, gstate_c.allowShaderBlend); @@ -158,14 +157,12 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { if (ApplyShaderBlending()) { // We may still want to do something about stencil -> alpha. ApplyStencilReplaceAndLogicOp(blendState.replaceAlphaWithStencil, blendState); - } - else { + } else { // Until next time, force it off. ResetShaderBlending(); gstate_c.allowShaderBlend = false; } - } - else if (blendState.resetShaderBlending) { + } else if (blendState.resetShaderBlending) { ResetShaderBlending(); } @@ -185,8 +182,7 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { if (blendState.useBlendColor) { dynState_.blendColor = blendState.blendColor; } - } - else { + } else { keys_.blend.blendEnable = false; dynState_.useBlendColor = false; } @@ -197,8 +193,7 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { keys_.blend.blendEnable = false; // Can't have both blend & logic op - although I think the PSP can! keys_.blend.logicOpEnable = true; keys_.blend.logicOp = logicOps[gstate.getLogicOp()]; - } - else { + } else { keys_.blend.logicOpEnable = false; } } @@ -240,120 +235,120 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { dynState_.useStencil = false; - // Set ColorMask/Stencil/Depth - if (gstate.isModeClear()) { - keys_.raster.cullMode = D3D11_CULL_NONE; + { + // Set ColorMask/Stencil/Depth + if (gstate.isModeClear()) { + keys_.raster.cullMode = D3D11_CULL_NONE; - keys_.depthStencil.depthTestEnable = true; - keys_.depthStencil.depthCompareOp = D3D11_COMPARISON_ALWAYS; - keys_.depthStencil.depthWriteEnable = gstate.isClearModeDepthMask(); - if (gstate.isClearModeDepthMask()) { - framebufferManager_->SetDepthUpdated(); - } - - // Stencil Test - bool alphaMask = gstate.isClearModeAlphaMask(); - if (alphaMask) { - keys_.depthStencil.stencilTestEnable = true; - keys_.depthStencil.stencilCompareFunc = D3D11_COMPARISON_ALWAYS; - keys_.depthStencil.stencilPassOp = D3D11_STENCIL_OP_REPLACE; - keys_.depthStencil.stencilFailOp = D3D11_STENCIL_OP_REPLACE; - keys_.depthStencil.stencilDepthFailOp = D3D11_STENCIL_OP_REPLACE; - dynState_.useStencil = true; - // In clear mode, the stencil value is set to the alpha value of the vertex. - // A normal clear will be 2 points, the second point has the color. - // We override this value in the pipeline from software transform for clear rectangles. - dynState_.stencilRef = 0xFF; - keys_.depthStencil.stencilWriteMask = 0xFF; - } - else { - keys_.depthStencil.stencilTestEnable = false; - dynState_.useStencil = false; - } - - } - else { - // Set cull - bool wantCull = !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES && gstate.isCullEnabled(); - keys_.raster.cullMode = wantCull ? (gstate.getCullMode() ? D3D11_CULL_FRONT : D3D11_CULL_BACK) : D3D11_CULL_NONE; - - // Depth Test - if (gstate.isDepthTestEnabled()) { keys_.depthStencil.depthTestEnable = true; - keys_.depthStencil.depthCompareOp = compareOps[gstate.getDepthTestFunction()]; - keys_.depthStencil.depthWriteEnable = gstate.isDepthWriteEnabled(); - if (gstate.isDepthWriteEnabled()) { + keys_.depthStencil.depthCompareOp = D3D11_COMPARISON_ALWAYS; + keys_.depthStencil.depthWriteEnable = gstate.isClearModeDepthMask(); + if (gstate.isClearModeDepthMask()) { framebufferManager_->SetDepthUpdated(); } - } - else { - keys_.depthStencil.depthTestEnable = false; - keys_.depthStencil.depthWriteEnable = false; - keys_.depthStencil.depthCompareOp = D3D11_COMPARISON_ALWAYS; - } - GenericStencilFuncState stencilState; - ConvertStencilFuncState(stencilState); + // Stencil Test + bool alphaMask = gstate.isClearModeAlphaMask(); + if (alphaMask) { + keys_.depthStencil.stencilTestEnable = true; + keys_.depthStencil.stencilCompareFunc = D3D11_COMPARISON_ALWAYS; + keys_.depthStencil.stencilPassOp = D3D11_STENCIL_OP_REPLACE; + keys_.depthStencil.stencilFailOp = D3D11_STENCIL_OP_REPLACE; + keys_.depthStencil.stencilDepthFailOp = D3D11_STENCIL_OP_REPLACE; + dynState_.useStencil = true; + // In clear mode, the stencil value is set to the alpha value of the vertex. + // A normal clear will be 2 points, the second point has the color. + // We override this value in the pipeline from software transform for clear rectangles. + dynState_.stencilRef = 0xFF; + keys_.depthStencil.stencilWriteMask = 0xFF; + } else { + keys_.depthStencil.stencilTestEnable = false; + dynState_.useStencil = false; + } - // Stencil Test - if (stencilState.enabled) { - keys_.depthStencil.stencilTestEnable = true; - keys_.depthStencil.stencilCompareFunc = compareOps[stencilState.testFunc]; - keys_.depthStencil.stencilPassOp = stencilOps[stencilState.zPass]; - keys_.depthStencil.stencilFailOp = stencilOps[stencilState.sFail]; - keys_.depthStencil.stencilDepthFailOp = stencilOps[stencilState.zFail]; - keys_.depthStencil.stencilCompareMask = stencilState.testMask; - keys_.depthStencil.stencilWriteMask = stencilState.writeMask; - dynState_.useStencil = true; - dynState_.stencilRef = stencilState.testRef; } else { - keys_.depthStencil.stencilTestEnable = false; - dynState_.useStencil = false; + // Set cull + bool wantCull = !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES && gstate.isCullEnabled(); + keys_.raster.cullMode = wantCull ? (gstate.getCullMode() ? D3D11_CULL_FRONT : D3D11_CULL_BACK) : D3D11_CULL_NONE; + + // Depth Test + if (gstate.isDepthTestEnabled()) { + keys_.depthStencil.depthTestEnable = true; + keys_.depthStencil.depthCompareOp = compareOps[gstate.getDepthTestFunction()]; + keys_.depthStencil.depthWriteEnable = gstate.isDepthWriteEnabled(); + if (gstate.isDepthWriteEnabled()) { + framebufferManager_->SetDepthUpdated(); + } + } else { + keys_.depthStencil.depthTestEnable = false; + keys_.depthStencil.depthWriteEnable = false; + keys_.depthStencil.depthCompareOp = D3D11_COMPARISON_ALWAYS; + } + + GenericStencilFuncState stencilState; + ConvertStencilFuncState(stencilState); + + // Stencil Test + if (stencilState.enabled) { + keys_.depthStencil.stencilTestEnable = true; + keys_.depthStencil.stencilCompareFunc = compareOps[stencilState.testFunc]; + keys_.depthStencil.stencilPassOp = stencilOps[stencilState.zPass]; + keys_.depthStencil.stencilFailOp = stencilOps[stencilState.sFail]; + keys_.depthStencil.stencilDepthFailOp = stencilOps[stencilState.zFail]; + keys_.depthStencil.stencilCompareMask = stencilState.testMask; + keys_.depthStencil.stencilWriteMask = stencilState.writeMask; + dynState_.useStencil = true; + dynState_.stencilRef = stencilState.testRef; + } else { + keys_.depthStencil.stencilTestEnable = false; + dynState_.useStencil = false; + } + } + } + + { + ViewportAndScissor vpAndScissor; + ConvertViewportAndScissor(useBufferedRendering, + framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), + framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), + vpAndScissor); + + float depthMin = vpAndScissor.depthRangeMin; + float depthMax = vpAndScissor.depthRangeMax; + + if (depthMin < 0.0f) depthMin = 0.0f; + if (depthMax > 1.0f) depthMax = 1.0f; + if (vpAndScissor.dirtyDepth) { + gstate_c.Dirty(DIRTY_DEPTHRANGE); + } + + Draw::Viewport &vp = dynState_.viewport; + vp.TopLeftX = vpAndScissor.viewportX; + vp.TopLeftY = vpAndScissor.viewportY; + vp.Width = vpAndScissor.viewportW; + vp.Height = vpAndScissor.viewportH; + vp.MinDepth = depthMin; + vp.MaxDepth = depthMax; + if (vpAndScissor.dirtyProj) { + gstate_c.Dirty(DIRTY_PROJMATRIX); + } + + D3D11_RECT &scissor = dynState_.scissor; + if (vpAndScissor.scissorEnable) { + scissor.left = vpAndScissor.scissorX; + scissor.top = vpAndScissor.scissorY; + scissor.right = vpAndScissor.scissorX + std::max(0, vpAndScissor.scissorW); + scissor.bottom = vpAndScissor.scissorY + std::max(0, vpAndScissor.scissorH); + } else { + scissor.left = 0; + scissor.top = 0; + scissor.right = framebufferManager_->GetRenderWidth(); + scissor.bottom = framebufferManager_->GetRenderHeight(); } } dynState_.topology = primToD3D11[prim]; - ViewportAndScissor vpAndScissor; - ConvertViewportAndScissor(useBufferedRendering, - framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), - framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), - vpAndScissor); - - float depthMin = vpAndScissor.depthRangeMin; - float depthMax = vpAndScissor.depthRangeMax; - - if (depthMin < 0.0f) depthMin = 0.0f; - if (depthMax > 1.0f) depthMax = 1.0f; - if (vpAndScissor.dirtyDepth) { - gstate_c.Dirty(DIRTY_DEPTHRANGE); - } - - Draw::Viewport &vp = dynState_.viewport; - vp.TopLeftX = vpAndScissor.viewportX; - vp.TopLeftY = vpAndScissor.viewportY; - vp.Width = vpAndScissor.viewportW; - vp.Height = vpAndScissor.viewportH; - vp.MinDepth = depthMin; - vp.MaxDepth = depthMax; - if (vpAndScissor.dirtyProj) { - gstate_c.Dirty(DIRTY_PROJMATRIX); - } - - D3D11_RECT &scissor = dynState_.scissor; - if (vpAndScissor.scissorEnable) { - scissor.left = vpAndScissor.scissorX; - scissor.top = vpAndScissor.scissorY; - scissor.right = vpAndScissor.scissorX + std::max(0, vpAndScissor.scissorW); - scissor.bottom = vpAndScissor.scissorY + std::max(0, vpAndScissor.scissorH); - } - else { - scissor.left = 0; - scissor.top = 0; - scissor.right = framebufferManager_->GetRenderWidth(); - scissor.bottom = framebufferManager_->GetRenderHeight(); - } - if (gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS) && !gstate.isModeClear() && gstate.isTextureMapEnabled()) { textureCache_->SetTexture(); gstate_c.Clean(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS); diff --git a/GPU/Directx9/StateMappingDX9.cpp b/GPU/Directx9/StateMappingDX9.cpp index f896a89ff8..078e90a078 100644 --- a/GPU/Directx9/StateMappingDX9.cpp +++ b/GPU/Directx9/StateMappingDX9.cpp @@ -205,83 +205,87 @@ void DrawEngineDX9::ApplyDrawState(int prim) { dxstate.dither.disable(); } - // Set ColorMask/Stencil/Depth - if (gstate.isModeClear()) { - // Set Cull - dxstate.cullMode.set(false, false); - - // Depth Test - dxstate.depthTest.enable(); - dxstate.depthFunc.set(D3DCMP_ALWAYS); - dxstate.depthWrite.set(gstate.isClearModeDepthMask()); - if (gstate.isClearModeDepthMask() || alwaysDepthWrite) { - framebufferManager_->SetDepthUpdated(); - } + { + // Set Stencil/Depth + if (gstate.isModeClear()) { + // Set Cull + dxstate.cullMode.set(false, false); - // Stencil Test - bool alphaMask = gstate.isClearModeAlphaMask(); - if (alphaMask && enableStencilTest) { - dxstate.stencilTest.enable(); - dxstate.stencilOp.set(D3DSTENCILOP_REPLACE, D3DSTENCILOP_REPLACE, D3DSTENCILOP_REPLACE); - dxstate.stencilFunc.set(D3DCMP_ALWAYS, 255, 0xFF); - dxstate.stencilMask.set(0xFF); - } else { - dxstate.stencilTest.disable(); - } - - } else { - // Set cull - bool wantCull = !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES && gstate.isCullEnabled(); - dxstate.cullMode.set(wantCull, gstate.getCullMode()); - - // Depth Test - if (gstate.isDepthTestEnabled()) { + // Depth Test dxstate.depthTest.enable(); - dxstate.depthFunc.set(ztests[gstate.getDepthTestFunction()]); - dxstate.depthWrite.set(gstate.isDepthWriteEnabled()); - if (gstate.isDepthWriteEnabled()) { + dxstate.depthFunc.set(D3DCMP_ALWAYS); + dxstate.depthWrite.set(gstate.isClearModeDepthMask()); + if (gstate.isClearModeDepthMask() || alwaysDepthWrite) { framebufferManager_->SetDepthUpdated(); } - } else { - dxstate.depthTest.disable(); - } - GenericStencilFuncState stencilState; - ConvertStencilFuncState(stencilState); + // Stencil Test + bool alphaMask = gstate.isClearModeAlphaMask(); + if (alphaMask && enableStencilTest) { + dxstate.stencilTest.enable(); + dxstate.stencilOp.set(D3DSTENCILOP_REPLACE, D3DSTENCILOP_REPLACE, D3DSTENCILOP_REPLACE); + dxstate.stencilFunc.set(D3DCMP_ALWAYS, 255, 0xFF); + dxstate.stencilMask.set(0xFF); + } else { + dxstate.stencilTest.disable(); + } - // Stencil Test - if (stencilState.enabled) { - dxstate.stencilTest.enable(); - dxstate.stencilFunc.set(ztests[stencilState.testFunc], stencilState.testRef, stencilState.testMask); - dxstate.stencilOp.set(stencilOps[stencilState.sFail], stencilOps[stencilState.zFail], stencilOps[stencilState.zPass]); - dxstate.stencilMask.set(stencilState.writeMask); } else { - dxstate.stencilTest.disable(); + // Set cull + bool wantCull = !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES && gstate.isCullEnabled(); + dxstate.cullMode.set(wantCull, gstate.getCullMode()); + + // Depth Test + if (gstate.isDepthTestEnabled()) { + dxstate.depthTest.enable(); + dxstate.depthFunc.set(ztests[gstate.getDepthTestFunction()]); + dxstate.depthWrite.set(gstate.isDepthWriteEnabled()); + if (gstate.isDepthWriteEnabled()) { + framebufferManager_->SetDepthUpdated(); + } + } else { + dxstate.depthTest.disable(); + } + + GenericStencilFuncState stencilState; + ConvertStencilFuncState(stencilState); + + // Stencil Test + if (stencilState.enabled) { + dxstate.stencilTest.enable(); + dxstate.stencilFunc.set(ztests[stencilState.testFunc], stencilState.testRef, stencilState.testMask); + dxstate.stencilOp.set(stencilOps[stencilState.sFail], stencilOps[stencilState.zFail], stencilOps[stencilState.zPass]); + dxstate.stencilMask.set(stencilState.writeMask); + } else { + dxstate.stencilTest.disable(); + } } } - ViewportAndScissor vpAndScissor; - ConvertViewportAndScissor(useBufferedRendering, - framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), - framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), - vpAndScissor); + { + ViewportAndScissor vpAndScissor; + ConvertViewportAndScissor(useBufferedRendering, + framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), + framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), + vpAndScissor); - if (vpAndScissor.scissorEnable) { - dxstate.scissorTest.enable(); - dxstate.scissorRect.set(vpAndScissor.scissorX, vpAndScissor.scissorY, vpAndScissor.scissorX + vpAndScissor.scissorW, vpAndScissor.scissorY + vpAndScissor.scissorH); - } else { - dxstate.scissorTest.disable(); - } + if (vpAndScissor.scissorEnable) { + dxstate.scissorTest.enable(); + dxstate.scissorRect.set(vpAndScissor.scissorX, vpAndScissor.scissorY, vpAndScissor.scissorX + vpAndScissor.scissorW, vpAndScissor.scissorY + vpAndScissor.scissorH); + } else { + dxstate.scissorTest.disable(); + } - float depthMin = vpAndScissor.depthRangeMin; - float depthMax = vpAndScissor.depthRangeMax; + float depthMin = vpAndScissor.depthRangeMin; + float depthMax = vpAndScissor.depthRangeMax; - dxstate.viewport.set(vpAndScissor.viewportX, vpAndScissor.viewportY, vpAndScissor.viewportW, vpAndScissor.viewportH, depthMin, depthMax); - if (vpAndScissor.dirtyProj) { - gstate_c.Dirty(DIRTY_PROJMATRIX); - } - if (vpAndScissor.dirtyDepth) { - gstate_c.Dirty(DIRTY_DEPTHRANGE); + dxstate.viewport.set(vpAndScissor.viewportX, vpAndScissor.viewportY, vpAndScissor.viewportW, vpAndScissor.viewportH, depthMin, depthMax); + if (vpAndScissor.dirtyProj) { + gstate_c.Dirty(DIRTY_PROJMATRIX); + } + if (vpAndScissor.dirtyDepth) { + gstate_c.Dirty(DIRTY_DEPTHRANGE); + } } } diff --git a/GPU/GLES/StateMappingGLES.cpp b/GPU/GLES/StateMappingGLES.cpp index e18e8631b3..3dc6f007d9 100644 --- a/GPU/GLES/StateMappingGLES.cpp +++ b/GPU/GLES/StateMappingGLES.cpp @@ -167,6 +167,12 @@ void DrawEngineGLES::ApplyDrawState(int prim) { bool colorMask = gstate.isClearModeColorMask(); bool alphaMask = gstate.isClearModeAlphaMask(); glstate.colorMask.set(colorMask, colorMask, colorMask, alphaMask); +#ifndef USING_GLES2 + if (gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP)) { + // Logic Ops + glstate.colorLogicOp.disable(); + } +#endif } else { // Do the large chunks of state conversion. We might be able to hide these two behind a dirty-flag each, // to avoid recomputing heavy stuff unnecessarily every draw call. @@ -230,12 +236,22 @@ void DrawEngineGLES::ApplyDrawState(int prim) { #endif glstate.colorMask.set(rmask, gmask, bmask, amask); + +#ifndef USING_GLES2 + if (gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP)) { + // TODO: Make this dynamic + // Logic Ops + if (gstate.isLogicOpEnabled() && gstate.getLogicOp() != GE_LOGIC_COPY) { + glstate.colorLogicOp.enable(); + glstate.logicOp.set(logicOps[gstate.getLogicOp()]); + } else { + glstate.colorLogicOp.disable(); + } + } +#endif } } - bool alwaysDepthWrite = g_Config.bAlwaysDepthWrite; - bool enableStencilTest = !g_Config.bDisableStencilTest; - // Dither if (gstate.isDitherEnabled()) { glstate.dither.enable(); @@ -245,49 +261,9 @@ void DrawEngineGLES::ApplyDrawState(int prim) { } if (gstate.isModeClear()) { -#ifndef USING_GLES2 - if (gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP)) { - // Logic Ops - glstate.colorLogicOp.disable(); - } -#endif // Culling glstate.cullFace.disable(); - - // Depth Test - glstate.depthTest.enable(); - glstate.depthFunc.set(GL_ALWAYS); - glstate.depthWrite.set(gstate.isClearModeDepthMask() || alwaysDepthWrite ? GL_TRUE : GL_FALSE); - if (gstate.isClearModeDepthMask() || alwaysDepthWrite) { - framebufferManager_->SetDepthUpdated(); - } - - // Stencil Test - if (gstate.isClearModeAlphaMask() && enableStencilTest) { - glstate.stencilTest.enable(); - glstate.stencilOp.set(GL_REPLACE, GL_REPLACE, GL_REPLACE); - // TODO: In clear mode, the stencil value is set to the alpha value of the vertex. - // A normal clear will be 2 points, the second point has the color. - // We should set "ref" to that value instead of 0. - // In case of clear rectangles, we set it again once we know what the color is. - glstate.stencilFunc.set(GL_ALWAYS, 255, 0xFF); - glstate.stencilMask.set(0xFF); - } else { - glstate.stencilTest.disable(); - } } else { -#ifndef USING_GLES2 - if (gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP)) { - // TODO: Make this dynamic - // Logic Ops - if (gstate.isLogicOpEnabled() && gstate.getLogicOp() != GE_LOGIC_COPY) { - glstate.colorLogicOp.enable(); - glstate.logicOp.set(logicOps[gstate.getLogicOp()]); - } else { - glstate.colorLogicOp.disable(); - } - } -#endif // Set cull bool cullEnabled = !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES && gstate.isCullEnabled(); if (cullEnabled) { @@ -296,60 +272,90 @@ void DrawEngineGLES::ApplyDrawState(int prim) { } else { glstate.cullFace.disable(); } + } - // Depth Test - if (gstate.isDepthTestEnabled()) { + { + bool alwaysDepthWrite = g_Config.bAlwaysDepthWrite; + bool enableStencilTest = !g_Config.bDisableStencilTest; + if (gstate.isModeClear()) { + // Depth Test glstate.depthTest.enable(); - glstate.depthFunc.set(compareOps[gstate.getDepthTestFunction()]); - glstate.depthWrite.set(gstate.isDepthWriteEnabled() || alwaysDepthWrite ? GL_TRUE : GL_FALSE); - if (gstate.isDepthWriteEnabled() || alwaysDepthWrite) { + glstate.depthFunc.set(GL_ALWAYS); + glstate.depthWrite.set(gstate.isClearModeDepthMask() || alwaysDepthWrite ? GL_TRUE : GL_FALSE); + if (gstate.isClearModeDepthMask() || alwaysDepthWrite) { framebufferManager_->SetDepthUpdated(); } - } else { - glstate.depthTest.disable(); - } - GenericStencilFuncState stencilState; - ConvertStencilFuncState(stencilState); - - // Stencil Test - if (stencilState.enabled) { - glstate.stencilTest.enable(); - glstate.stencilFunc.set(compareOps[stencilState.testFunc], stencilState.testRef, stencilState.testMask); - glstate.stencilOp.set(stencilOps[stencilState.sFail], stencilOps[stencilState.zFail], stencilOps[stencilState.zPass]); - glstate.stencilMask.set(stencilState.writeMask); + // Stencil Test + if (gstate.isClearModeAlphaMask() && enableStencilTest) { + glstate.stencilTest.enable(); + glstate.stencilOp.set(GL_REPLACE, GL_REPLACE, GL_REPLACE); + // TODO: In clear mode, the stencil value is set to the alpha value of the vertex. + // A normal clear will be 2 points, the second point has the color. + // We should set "ref" to that value instead of 0. + // In case of clear rectangles, we set it again once we know what the color is. + glstate.stencilFunc.set(GL_ALWAYS, 255, 0xFF); + glstate.stencilMask.set(0xFF); + } else { + glstate.stencilTest.disable(); + } } else { - glstate.stencilTest.disable(); + // Depth Test + if (gstate.isDepthTestEnabled()) { + glstate.depthTest.enable(); + glstate.depthFunc.set(compareOps[gstate.getDepthTestFunction()]); + glstate.depthWrite.set(gstate.isDepthWriteEnabled() || alwaysDepthWrite ? GL_TRUE : GL_FALSE); + if (gstate.isDepthWriteEnabled() || alwaysDepthWrite) { + framebufferManager_->SetDepthUpdated(); + } + } else { + glstate.depthTest.disable(); + } + + GenericStencilFuncState stencilState; + ConvertStencilFuncState(stencilState); + + // Stencil Test + if (stencilState.enabled) { + glstate.stencilTest.enable(); + glstate.stencilFunc.set(compareOps[stencilState.testFunc], stencilState.testRef, stencilState.testMask); + glstate.stencilOp.set(stencilOps[stencilState.sFail], stencilOps[stencilState.zFail], stencilOps[stencilState.zPass]); + glstate.stencilMask.set(stencilState.writeMask); + } else { + glstate.stencilTest.disable(); + } } } - ViewportAndScissor vpAndScissor; - ConvertViewportAndScissor(useBufferedRendering, - framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), - framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), - vpAndScissor); + { + ViewportAndScissor vpAndScissor; + ConvertViewportAndScissor(useBufferedRendering, + framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), + framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), + vpAndScissor); + + if (vpAndScissor.scissorEnable) { + glstate.scissorTest.enable(); + if (!useBufferedRendering) { + vpAndScissor.scissorY = PSP_CoreParameter().pixelHeight - vpAndScissor.scissorH - vpAndScissor.scissorY; + } + glstate.scissorRect.set(vpAndScissor.scissorX, vpAndScissor.scissorY, vpAndScissor.scissorW, vpAndScissor.scissorH); + } else { + glstate.scissorTest.disable(); + } - if (vpAndScissor.scissorEnable) { - glstate.scissorTest.enable(); if (!useBufferedRendering) { - vpAndScissor.scissorY = PSP_CoreParameter().pixelHeight - vpAndScissor.scissorH - vpAndScissor.scissorY; + vpAndScissor.viewportY = PSP_CoreParameter().pixelHeight - vpAndScissor.viewportH - vpAndScissor.viewportY; } - glstate.scissorRect.set(vpAndScissor.scissorX, vpAndScissor.scissorY, vpAndScissor.scissorW, vpAndScissor.scissorH); - } else { - glstate.scissorTest.disable(); - } + glstate.viewport.set(vpAndScissor.viewportX, vpAndScissor.viewportY, vpAndScissor.viewportW, vpAndScissor.viewportH); + glstate.depthRange.set(vpAndScissor.depthRangeMin, vpAndScissor.depthRangeMax); - if (!useBufferedRendering) { - vpAndScissor.viewportY = PSP_CoreParameter().pixelHeight - vpAndScissor.viewportH - vpAndScissor.viewportY; - } - glstate.viewport.set(vpAndScissor.viewportX, vpAndScissor.viewportY, vpAndScissor.viewportW, vpAndScissor.viewportH); - glstate.depthRange.set(vpAndScissor.depthRangeMin, vpAndScissor.depthRangeMax); - - if (vpAndScissor.dirtyProj) { - gstate_c.Dirty(DIRTY_PROJMATRIX); - } - if (vpAndScissor.dirtyDepth) { - gstate_c.Dirty(DIRTY_DEPTHRANGE); + if (vpAndScissor.dirtyProj) { + gstate_c.Dirty(DIRTY_PROJMATRIX); + } + if (vpAndScissor.dirtyDepth) { + gstate_c.Dirty(DIRTY_DEPTHRANGE); + } } CHECK_GL_ERROR_IF_DEBUG(); } diff --git a/GPU/Vulkan/StateMappingVulkan.cpp b/GPU/Vulkan/StateMappingVulkan.cpp index 7e855d01eb..dc9ef50d9e 100644 --- a/GPU/Vulkan/StateMappingVulkan.cpp +++ b/GPU/Vulkan/StateMappingVulkan.cpp @@ -220,117 +220,118 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag } } - dynState.useStencil = false; + { + // Set Stencil/Depth + if (gstate.isModeClear()) { + key.cullMode = VK_CULL_MODE_NONE; - // Set Stencil/Depth - if (gstate.isModeClear()) { - key.cullMode = VK_CULL_MODE_NONE; - - key.depthTestEnable = true; - key.depthCompareOp = VK_COMPARE_OP_ALWAYS; - key.depthWriteEnable = gstate.isClearModeDepthMask(); - if (gstate.isClearModeDepthMask()) { - fbManager.SetDepthUpdated(); - } - - // Stencil Test - bool alphaMask = gstate.isClearModeAlphaMask(); - if (alphaMask) { - key.stencilTestEnable = true; - key.stencilCompareOp = VK_COMPARE_OP_ALWAYS; - key.stencilPassOp = VK_STENCIL_OP_REPLACE; - key.stencilFailOp = VK_STENCIL_OP_REPLACE; - key.stencilDepthFailOp = VK_STENCIL_OP_REPLACE; - dynState.useStencil = true; - // In clear mode, the stencil value is set to the alpha value of the vertex. - // A normal clear will be 2 points, the second point has the color. - // We override this value in the pipeline from software transform for clear rectangles. - dynState.stencilRef = 0xFF; - dynState.stencilWriteMask = 0xFF; - } else { - key.stencilTestEnable = false; - dynState.useStencil = false; - } - } else { - if (gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP)) { - // Logic Ops - if (gstate.isLogicOpEnabled() && gstate.getLogicOp() != GE_LOGIC_COPY) { - key.logicOpEnable = true; - key.logicOp = logicOps[gstate.getLogicOp()]; - } else { - key.logicOpEnable = false; - } - } - - // Set cull - bool wantCull = !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES && gstate.isCullEnabled(); - key.cullMode = wantCull ? (gstate.getCullMode() ? VK_CULL_MODE_FRONT_BIT : VK_CULL_MODE_BACK_BIT) : VK_CULL_MODE_NONE; - - // Depth Test - if (gstate.isDepthTestEnabled()) { key.depthTestEnable = true; - key.depthCompareOp = compareOps[gstate.getDepthTestFunction()]; - key.depthWriteEnable = gstate.isDepthWriteEnabled(); - if (gstate.isDepthWriteEnabled()) { + key.depthCompareOp = VK_COMPARE_OP_ALWAYS; + key.depthWriteEnable = gstate.isClearModeDepthMask(); + if (gstate.isClearModeDepthMask()) { fbManager.SetDepthUpdated(); } - } else { - key.depthTestEnable = false; - key.depthWriteEnable = false; - key.depthCompareOp = VK_COMPARE_OP_ALWAYS; - } - GenericStencilFuncState stencilState; - ConvertStencilFuncState(stencilState); - - // Stencil Test - if (stencilState.enabled) { - key.stencilTestEnable = true; - key.stencilCompareOp = compareOps[stencilState.testFunc]; - key.stencilPassOp = stencilOps[stencilState.zPass]; - key.stencilFailOp = stencilOps[stencilState.sFail]; - key.stencilDepthFailOp = stencilOps[stencilState.zFail]; - dynState.useStencil = true; - dynState.stencilRef = stencilState.testRef; - dynState.stencilCompareMask = stencilState.testMask; - dynState.stencilWriteMask = stencilState.writeMask; + // Stencil Test + bool alphaMask = gstate.isClearModeAlphaMask(); + if (alphaMask) { + key.stencilTestEnable = true; + key.stencilCompareOp = VK_COMPARE_OP_ALWAYS; + key.stencilPassOp = VK_STENCIL_OP_REPLACE; + key.stencilFailOp = VK_STENCIL_OP_REPLACE; + key.stencilDepthFailOp = VK_STENCIL_OP_REPLACE; + dynState.useStencil = true; + // In clear mode, the stencil value is set to the alpha value of the vertex. + // A normal clear will be 2 points, the second point has the color. + // We override this value in the pipeline from software transform for clear rectangles. + dynState.stencilRef = 0xFF; + dynState.stencilWriteMask = 0xFF; + } else { + key.stencilTestEnable = false; + dynState.useStencil = false; + } } else { - key.stencilTestEnable = false; - dynState.useStencil = false; + if (gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP)) { + // Logic Ops + if (gstate.isLogicOpEnabled() && gstate.getLogicOp() != GE_LOGIC_COPY) { + key.logicOpEnable = true; + key.logicOp = logicOps[gstate.getLogicOp()]; + } else { + key.logicOpEnable = false; + } + } + + // Set cull + bool wantCull = !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES && gstate.isCullEnabled(); + key.cullMode = wantCull ? (gstate.getCullMode() ? VK_CULL_MODE_FRONT_BIT : VK_CULL_MODE_BACK_BIT) : VK_CULL_MODE_NONE; + + // Depth Test + if (gstate.isDepthTestEnabled()) { + key.depthTestEnable = true; + key.depthCompareOp = compareOps[gstate.getDepthTestFunction()]; + key.depthWriteEnable = gstate.isDepthWriteEnabled(); + if (gstate.isDepthWriteEnabled()) { + fbManager.SetDepthUpdated(); + } + } else { + key.depthTestEnable = false; + key.depthWriteEnable = false; + key.depthCompareOp = VK_COMPARE_OP_ALWAYS; + } + + GenericStencilFuncState stencilState; + ConvertStencilFuncState(stencilState); + + // Stencil Test + if (stencilState.enabled) { + key.stencilTestEnable = true; + key.stencilCompareOp = compareOps[stencilState.testFunc]; + key.stencilPassOp = stencilOps[stencilState.zPass]; + key.stencilFailOp = stencilOps[stencilState.sFail]; + key.stencilDepthFailOp = stencilOps[stencilState.zFail]; + dynState.useStencil = true; + dynState.stencilRef = stencilState.testRef; + dynState.stencilCompareMask = stencilState.testMask; + dynState.stencilWriteMask = stencilState.writeMask; + } else { + key.stencilTestEnable = false; + dynState.useStencil = false; + } } } + { + ViewportAndScissor vpAndScissor; + ConvertViewportAndScissor(useBufferedRendering, + fbManager.GetRenderWidth(), fbManager.GetRenderHeight(), + fbManager.GetTargetBufferWidth(), fbManager.GetTargetBufferHeight(), + vpAndScissor); + + VkViewport &vp = dynState.viewport; + vp.x = vpAndScissor.viewportX; + vp.y = vpAndScissor.viewportY; + vp.width = vpAndScissor.viewportW; + vp.height = vpAndScissor.viewportH; + vp.minDepth = vpAndScissor.depthRangeMin; + vp.maxDepth = vpAndScissor.depthRangeMax; + if (vpAndScissor.dirtyProj) { + gstate_c.Dirty(DIRTY_PROJMATRIX); + } + + VkRect2D &scissor = dynState.scissor; + scissor.offset.x = vpAndScissor.scissorX; + scissor.offset.y = vpAndScissor.scissorY; + scissor.extent.width = vpAndScissor.scissorW; + scissor.extent.height = vpAndScissor.scissorH; + + float depthMin = vpAndScissor.depthRangeMin; + float depthMax = vpAndScissor.depthRangeMax; + + if (depthMin < 0.0f) depthMin = 0.0f; + if (depthMax > 1.0f) depthMax = 1.0f; + if (vpAndScissor.dirtyDepth) { + gstate_c.Dirty(DIRTY_DEPTHRANGE); + } + } key.topology = primToVulkan[prim]; - - ViewportAndScissor vpAndScissor; - ConvertViewportAndScissor(useBufferedRendering, - fbManager.GetRenderWidth(), fbManager.GetRenderHeight(), - fbManager.GetTargetBufferWidth(), fbManager.GetTargetBufferHeight(), - vpAndScissor); - - VkViewport &vp = dynState.viewport; - vp.x = vpAndScissor.viewportX; - vp.y = vpAndScissor.viewportY; - vp.width = vpAndScissor.viewportW; - vp.height = vpAndScissor.viewportH; - vp.minDepth = vpAndScissor.depthRangeMin; - vp.maxDepth = vpAndScissor.depthRangeMax; - if (vpAndScissor.dirtyProj) { - gstate_c.Dirty(DIRTY_PROJMATRIX); - } - - VkRect2D &scissor = dynState.scissor; - scissor.offset.x = vpAndScissor.scissorX; - scissor.offset.y = vpAndScissor.scissorY; - scissor.extent.width = vpAndScissor.scissorW; - scissor.extent.height = vpAndScissor.scissorH; - - float depthMin = vpAndScissor.depthRangeMin; - float depthMax = vpAndScissor.depthRangeMax; - - if (depthMin < 0.0f) depthMin = 0.0f; - if (depthMax > 1.0f) depthMax = 1.0f; - if (vpAndScissor.dirtyDepth) { - gstate_c.Dirty(DIRTY_DEPTHRANGE); - } }