Reorganize depth-stencil

This commit is contained in:
Henrik Rydgard 2017-01-30 12:02:14 +01:00 committed by Henrik Rydgård
parent d581a96d79
commit cffb1d7014
4 changed files with 369 additions and 363 deletions

View file

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

View file

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

View file

@ -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();
}

View file

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