mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
GPU: Avoid clears for non-simple depth values.
Some drivers don't round depth the same way for a clear vs for drawing, which can cause mismatches. We only do this if we see equals-style depth comparison funcs used in drawing.
This commit is contained in:
parent
818849c4b9
commit
3333f2a5aa
9 changed files with 38 additions and 0 deletions
|
@ -145,11 +145,28 @@ protected:
|
|||
return 1;
|
||||
}
|
||||
|
||||
inline void UpdateEverUsedEqualDepth(GEComparison comp) {
|
||||
switch (comp) {
|
||||
case GE_COMP_EQUAL:
|
||||
case GE_COMP_NOTEQUAL:
|
||||
case GE_COMP_LEQUAL:
|
||||
case GE_COMP_GEQUAL:
|
||||
everUsedEqualDepth_ = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool useHWTransform_ = false;
|
||||
bool useHWTessellation_ = false;
|
||||
// Used to prevent unnecessary flushing in softgpu.
|
||||
bool flushOnParams_ = true;
|
||||
|
||||
// Set once a equal depth test is encountered.
|
||||
bool everUsedEqualDepth_ = false;
|
||||
|
||||
// Vertex collector buffers
|
||||
u8 *decoded = nullptr;
|
||||
u16 *decIndex = nullptr;
|
||||
|
|
|
@ -643,6 +643,10 @@ rotateVBO:
|
|||
swTransform.BuildDrawingParams(prim, indexGen.VertexCount(), dec_->VertexType(), inds, maxIndex, &result);
|
||||
if (result.setSafeSize)
|
||||
framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight);
|
||||
// Non-zero depth clears are unusual, but some drivers don't match drawn depth values to cleared values.
|
||||
// Games sometimes expect exact matches (see #12626, for example) for equal comparisons.
|
||||
if (result.action == SW_CLEAR && everUsedEqualDepth_ && gstate.isClearModeDepthMask() && result.depth > 0.0f && result.depth < 1.0f)
|
||||
result.action = SW_DRAW_PRIMITIVES;
|
||||
|
||||
ApplyDrawStateLate(result.setStencil, result.stencilValue);
|
||||
|
||||
|
|
|
@ -274,6 +274,7 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
|
|||
keys_.depthStencil.depthTestEnable = true;
|
||||
keys_.depthStencil.depthCompareOp = compareOps[gstate.getDepthTestFunction()];
|
||||
keys_.depthStencil.depthWriteEnable = gstate.isDepthWriteEnabled();
|
||||
UpdateEverUsedEqualDepth(gstate.getDepthTestFunction());
|
||||
} else {
|
||||
keys_.depthStencil.depthTestEnable = false;
|
||||
keys_.depthStencil.depthWriteEnable = false;
|
||||
|
|
|
@ -611,6 +611,10 @@ rotateVBO:
|
|||
swTransform.BuildDrawingParams(prim, indexGen.VertexCount(), dec_->VertexType(), inds, maxIndex, &result);
|
||||
if (result.setSafeSize)
|
||||
framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight);
|
||||
// Non-zero depth clears are unusual, but some drivers don't match drawn depth values to cleared values.
|
||||
// Games sometimes expect exact matches (see #12626, for example) for equal comparisons.
|
||||
if (result.action == SW_CLEAR && everUsedEqualDepth_ && gstate.isClearModeDepthMask() && result.depth > 0.0f && result.depth < 1.0f)
|
||||
result.action = SW_DRAW_PRIMITIVES;
|
||||
|
||||
ApplyDrawStateLate();
|
||||
|
||||
|
|
|
@ -232,6 +232,7 @@ void DrawEngineDX9::ApplyDrawState(int prim) {
|
|||
dxstate.depthTest.enable();
|
||||
dxstate.depthFunc.set(ztests[gstate.getDepthTestFunction()]);
|
||||
dxstate.depthWrite.set(gstate.isDepthWriteEnabled());
|
||||
UpdateEverUsedEqualDepth(gstate.getDepthTestFunction());
|
||||
} else {
|
||||
dxstate.depthTest.disable();
|
||||
}
|
||||
|
|
|
@ -404,6 +404,10 @@ void DrawEngineGLES::DoFlush() {
|
|||
swTransform.BuildDrawingParams(prim, vertexCount, dec_->VertexType(), inds, maxIndex, &result);
|
||||
if (result.setSafeSize)
|
||||
framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight);
|
||||
// Non-zero depth clears are unusual, but some drivers don't match drawn depth values to cleared values.
|
||||
// Games sometimes expect exact matches (see #12626, for example) for equal comparisons.
|
||||
if (result.action == SW_CLEAR && everUsedEqualDepth_ && gstate.isClearModeDepthMask() && result.depth > 0.0f && result.depth < 1.0f)
|
||||
result.action = SW_DRAW_PRIMITIVES;
|
||||
|
||||
ApplyDrawStateLate(result.setStencil, result.stencilValue);
|
||||
|
||||
|
|
|
@ -254,6 +254,8 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
|
|||
} else {
|
||||
// Depth Test
|
||||
renderManager->SetDepth(gstate.isDepthTestEnabled(), gstate.isDepthWriteEnabled(), compareOps[gstate.getDepthTestFunction()]);
|
||||
if (gstate.isDepthTestEnabled())
|
||||
UpdateEverUsedEqualDepth(gstate.getDepthTestFunction());
|
||||
|
||||
// Stencil Test
|
||||
if (stencilState.enabled) {
|
||||
|
|
|
@ -899,6 +899,10 @@ void DrawEngineVulkan::DoFlush() {
|
|||
|
||||
if (result.setSafeSize)
|
||||
framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight);
|
||||
// Non-zero depth clears are unusual, but some drivers don't match drawn depth values to cleared values.
|
||||
// Games sometimes expect exact matches (see #12626, for example) for equal comparisons.
|
||||
if (result.action == SW_CLEAR && everUsedEqualDepth_ && gstate.isClearModeDepthMask() && result.depth > 0.0f && result.depth < 1.0f)
|
||||
result.action = SW_DRAW_PRIMITIVES;
|
||||
|
||||
// Only here, where we know whether to clear or to draw primitives, should we actually set the current framebuffer! Because that gives use the opportunity
|
||||
// to use a "pre-clear" render pass, for high efficiency on tilers.
|
||||
|
|
|
@ -278,6 +278,7 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag
|
|||
key.depthTestEnable = true;
|
||||
key.depthCompareOp = compareOps[gstate.getDepthTestFunction()];
|
||||
key.depthWriteEnable = gstate.isDepthWriteEnabled();
|
||||
UpdateEverUsedEqualDepth(gstate.getDepthTestFunction());
|
||||
} else {
|
||||
key.depthTestEnable = false;
|
||||
key.depthWriteEnable = false;
|
||||
|
|
Loading…
Add table
Reference in a new issue