Skip to content

Commit b4eecf3

Browse files
committed
Mali: Turn off any depth writes if depth test is set to NEVER.
1 parent 6ce4933 commit b4eecf3

File tree

4 files changed

+15
-3
lines changed

4 files changed

+15
-3
lines changed

GPU/Common/FragmentShaderGenerator.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,9 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
155155
shading = doFlatShading ? "flat" : "";
156156
}
157157

158-
bool useDiscardStencilBugWorkaround = id.Bit(FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL);
158+
bool forceDepthWritesOff = id.Bit(FS_BIT_DEPTH_TEST_NEVER);
159+
160+
bool useDiscardStencilBugWorkaround = id.Bit(FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL) && !forceDepthWritesOff;
159161

160162
GEBlendSrcFactor replaceBlendFuncA = (GEBlendSrcFactor)id.Bits(FS_BIT_BLENDFUNC_A, 4);
161163
GEBlendDstFactor replaceBlendFuncB = (GEBlendDstFactor)id.Bits(FS_BIT_BLENDFUNC_B, 4);
@@ -177,7 +179,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
177179
}
178180

179181
bool needFragCoord = readFramebufferTex || gstate_c.Use(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT);
180-
bool writeDepth = gstate_c.Use(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT);
182+
bool writeDepth = gstate_c.Use(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT) && !forceDepthWritesOff;
181183

182184
// TODO: We could have a separate mechanism to support more ops using the shader blending mechanism,
183185
// on hardware that can do proper bit math in fragment shaders.

GPU/Common/ShaderId.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ std::string FragmentShaderDesc(const FShaderID &id) {
196196
if (id.Bit(FS_BIT_FLATSHADE)) desc << "Flat ";
197197
if (id.Bit(FS_BIT_BGRA_TEXTURE)) desc << "BGRA ";
198198
if (id.Bit(FS_BIT_UBERSHADER)) desc << "FragUber ";
199+
if (id.Bit(FS_BIT_DEPTH_TEST_NEVER)) desc << "DepthNever ";
199200
switch ((ShaderDepalMode)id.Bits(FS_BIT_SHADER_DEPAL_MODE, 2)) {
200201
case ShaderDepalMode::OFF: break;
201202
case ShaderDepalMode::NORMAL: desc << "Depal "; break;
@@ -397,6 +398,14 @@ void ComputeFragmentShaderID(FShaderID *id_out, const ComputedPipelineState &pip
397398
}
398399
}
399400

401+
// Forcibly disable NEVER + depth-write on Mali.
402+
// TODO: Take this from computed depth test instead of directly from the gstate.
403+
// That will take more refactoring though.
404+
if (bugs.Has(Draw::Bugs::NO_DEPTH_CANNOT_DISCARD_STENCIL_MALI) &&
405+
gstate.getDepthTestFunction() == GE_COMP_NEVER && gstate.isDepthTestEnabled()) {
406+
id.SetBit(FS_BIT_DEPTH_TEST_NEVER);
407+
}
408+
400409
// In case the USE flag changes (for example, in multisampling we might disable input attachments),
401410
// we don't want to accidentally use the wrong cached shader here. So moved it to a bit.
402411
if (FragmentIdNeedsFramebufferRead(id)) {

GPU/Common/ShaderId.h

+1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ enum FShaderBit : uint8_t {
102102
FS_BIT_STEREO = 58,
103103
FS_BIT_USE_FRAMEBUFFER_FETCH = 59,
104104
FS_BIT_UBERSHADER = 60,
105+
FS_BIT_DEPTH_TEST_NEVER = 61, // Only used on Mali. Set when depth == NEVER. We forcibly avoid writing to depth in this case, since it crashes the driver.
105106
};
106107

107108
static inline FShaderBit operator +(FShaderBit bit, int i) {

GPU/GPUCommonHW.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ const CommonCommandTableEntry commonCommandTable[] = {
124124
{ GE_CMD_BLENDFIXEDB, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_FRAGMENTSHADER_STATE },
125125
{ GE_CMD_MASKRGB, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_COLORWRITEMASK },
126126
{ GE_CMD_MASKALPHA, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_COLORWRITEMASK },
127-
{ GE_CMD_ZTEST, FLAG_FLUSHBEFOREONCHANGE, DIRTY_DEPTHSTENCIL_STATE },
127+
{ GE_CMD_ZTEST, FLAG_FLUSHBEFOREONCHANGE, DIRTY_DEPTHSTENCIL_STATE | DIRTY_FRAGMENTSHADER_STATE },
128128
{ GE_CMD_ZTESTENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_DEPTHSTENCIL_STATE | DIRTY_FRAGMENTSHADER_STATE },
129129
{ GE_CMD_ZWRITEDISABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_DEPTHSTENCIL_STATE | DIRTY_FRAGMENTSHADER_STATE },
130130
{ GE_CMD_LOGICOP, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_FRAGMENTSHADER_STATE },

0 commit comments

Comments
 (0)