Skip to content

Commit 7d894b8

Browse files
authored
Merge pull request #18813 from hrydgard/ufc-crash-work
Mali: Turn off any depth writes in the shader if depth test == NEVER
2 parents e226ef6 + b4eecf3 commit 7d894b8

File tree

9 files changed

+36
-16
lines changed

9 files changed

+36
-16
lines changed

Common/GPU/Vulkan/thin3d_vulkan.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -973,7 +973,7 @@ VKContext::VKContext(VulkanContext *vulkan, bool useRenderThread)
973973
// See: https://github.com/hrydgard/ppsspp/pull/11684
974974
if (deviceProps.deviceID >= 0x05000000 && deviceProps.deviceID < 0x06000000) {
975975
if (deviceProps.driverVersion < 0x80180000) {
976-
bugs_.Infest(Bugs::NO_DEPTH_CANNOT_DISCARD_STENCIL);
976+
bugs_.Infest(Bugs::NO_DEPTH_CANNOT_DISCARD_STENCIL_ADRENO);
977977
}
978978
}
979979
// Color write mask not masking write in certain scenarios with a depth test, see #10421.
@@ -1006,8 +1006,9 @@ VKContext::VKContext(VulkanContext *vulkan, bool useRenderThread)
10061006
bugs_.Infest(Bugs::EQUAL_WZ_CORRUPTS_DEPTH);
10071007

10081008
// Nearly identical to the the Adreno bug, see #13833 (Midnight Club map broken) and other issues.
1009+
// It has the additional caveat that combining depth writes with NEVER depth tests crashes the driver.
10091010
// Reported fixed in major version 40 - let's add a check once confirmed.
1010-
bugs_.Infest(Bugs::NO_DEPTH_CANNOT_DISCARD_STENCIL);
1011+
bugs_.Infest(Bugs::NO_DEPTH_CANNOT_DISCARD_STENCIL_MALI);
10111012

10121013
// This started in driver 31 or 32, fixed in 40 - let's add a check once confirmed.
10131014
if (majorVersion >= 32) {
@@ -1042,6 +1043,8 @@ VKContext::VKContext(VulkanContext *vulkan, bool useRenderThread)
10421043
INFO_LOG(G3D, "KHR_depth_stencil_resolve not supported, disabling multisampling");
10431044
}
10441045

1046+
bugs_.Infest(Draw::Bugs::NO_DEPTH_CANNOT_DISCARD_STENCIL_MALI);
1047+
10451048
// We limit multisampling functionality to reasonably recent and known-good tiling GPUs.
10461049
if (multisampleAllowed) {
10471050
// Check for depth stencil resolve. Without it, depth textures won't work, and we don't want that mess

Common/GPU/thin3d.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,8 @@ void ConvertToD16(uint8_t *dst, const uint8_t *src, uint32_t dstStride, uint32_t
751751

752752
const char *Bugs::GetBugName(uint32_t bug) {
753753
switch (bug) {
754-
case NO_DEPTH_CANNOT_DISCARD_STENCIL: return "NO_DEPTH_CANNOT_DISCARD_STENCIL";
754+
case NO_DEPTH_CANNOT_DISCARD_STENCIL_MALI: return "NO_DEPTH_CANNOT_DISCARD_STENCIL_MALI";
755+
case NO_DEPTH_CANNOT_DISCARD_STENCIL_ADRENO: return "NO_DEPTH_CANNOT_DISCARD_STENCIL_ADRENO";
755756
case DUAL_SOURCE_BLENDING_BROKEN: return "DUAL_SOURCE_BLENDING_BROKEN";
756757
case ANY_MAP_BUFFER_RANGE_SLOW: return "ANY_MAP_BUFFER_RANGE_SLOW";
757758
case PVR_GENMIPMAP_HEIGHT_GREATER: return "PVR_GENMIPMAP_HEIGHT_GREATER";

Common/GPU/thin3d.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ class Bugs {
336336
const char *GetBugName(uint32_t bug);
337337

338338
enum : uint32_t {
339-
NO_DEPTH_CANNOT_DISCARD_STENCIL = 0,
339+
NO_DEPTH_CANNOT_DISCARD_STENCIL_ADRENO = 0,
340340
DUAL_SOURCE_BLENDING_BROKEN = 1,
341341
ANY_MAP_BUFFER_RANGE_SLOW = 2,
342342
PVR_GENMIPMAP_HEIGHT_GREATER = 3,
@@ -351,6 +351,7 @@ class Bugs {
351351
ADRENO_RESOURCE_DEADLOCK = 12,
352352
UNIFORM_INDEXING_BROKEN = 13, // not a properly diagnosed issue, a workaround attempt: #17386
353353
PVR_BAD_16BIT_TEXFORMATS = 14,
354+
NO_DEPTH_CANNOT_DISCARD_STENCIL_MALI = 15,
354355
MAX_BUG,
355356
};
356357

Core/Util/GameManager.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,7 @@ bool GameManager::InstallMemstickGame(struct zip *z, const Path &zipfile, const
625625
g_OSD.SetProgressBar("install", di->T("Installing..."), 0.0f, 1.0f, 0.1f + (i + 1) / (float)info.numFiles * 0.9f, 0.1f);
626626
}
627627

628-
INFO_LOG(HLE, "Extracted %d files from zip (%d bytes / %d).", info.numFiles, (int)bytesCopied, (int)allBytes);
628+
INFO_LOG(HLE, "Unzipped %d files (%d bytes / %d).", info.numFiles, (int)bytesCopied, (int)allBytes);
629629
zip_close(z);
630630
z = nullptr;
631631
installProgress_ = 1.0f;
@@ -733,7 +733,7 @@ bool GameManager::InstallZippedISO(struct zip *z, int isoFileIndex, const Path &
733733
auto di = GetI18NCategory(I18NCat::DIALOG);
734734
g_OSD.SetProgressBar("install", di->T("Installing..."), 0.0f, 0.0f, 0.0f, 0.1f);
735735
if (ExtractFile(z, isoFileIndex, outputISOFilename, &bytesCopied, allBytes)) {
736-
INFO_LOG(IO, "Successfully extracted ISO file to '%s'", outputISOFilename.c_str());
736+
INFO_LOG(IO, "Successfully unzipped ISO file to '%s'", outputISOFilename.c_str());
737737
success = true;
738738
}
739739
zip_close(z);

GPU/Common/FragmentShaderGenerator.cpp

+5-3
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.
@@ -192,7 +194,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
192194
std::vector<SamplerDef> samplers;
193195

194196
if (compat.shaderLanguage == ShaderLanguage::GLSL_VULKAN) {
195-
if (useDiscardStencilBugWorkaround && !gstate_c.Use(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT)) {
197+
if (useDiscardStencilBugWorkaround && !writeDepth) {
196198
WRITE(p, "layout (depth_unchanged) out float gl_FragDepth;\n");
197199
}
198200

GPU/Common/ShaderId.cpp

+16-4
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;
@@ -387,13 +388,24 @@ void ComputeFragmentShaderID(FShaderID *id_out, const ComputedPipelineState &pip
387388
id.SetBit(FS_BIT_STEREO);
388389
}
389390

390-
if (g_Config.bVendorBugChecksEnabled && bugs.Has(Draw::Bugs::NO_DEPTH_CANNOT_DISCARD_STENCIL)) {
391-
bool stencilWithoutDepth = !IsStencilTestOutputDisabled() && (!gstate.isDepthTestEnabled() || !gstate.isDepthWriteEnabled());
392-
if (stencilWithoutDepth) {
393-
id.SetBit(FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL, stencilWithoutDepth);
391+
if (g_Config.bVendorBugChecksEnabled) {
392+
if (bugs.Has(Draw::Bugs::NO_DEPTH_CANNOT_DISCARD_STENCIL_ADRENO) || bugs.Has(Draw::Bugs::NO_DEPTH_CANNOT_DISCARD_STENCIL_MALI)) {
393+
// On Adreno, the workaround is safe, so we do simple checks.
394+
bool stencilWithoutDepth = (!gstate.isDepthTestEnabled() || !gstate.isDepthWriteEnabled()) && !IsStencilTestOutputDisabled();
395+
if (stencilWithoutDepth) {
396+
id.SetBit(FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL, stencilWithoutDepth);
397+
}
394398
}
395399
}
396400

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+
397409
// In case the USE flag changes (for example, in multisampling we might disable input attachments),
398410
// we don't want to accidentally use the wrong cached shader here. So moved it to a bit.
399411
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/Common/StencilCommon.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ void GenerateStencilFs(char *buffer, const ShaderLanguageDesc &lang, const Draw:
119119
writer.HighPrecisionFloat();
120120
writer.DeclareSamplers(samplers);
121121

122-
if (bugs.Has(Draw::Bugs::NO_DEPTH_CANNOT_DISCARD_STENCIL)) {
122+
if (bugs.Has(Draw::Bugs::NO_DEPTH_CANNOT_DISCARD_STENCIL_MALI) || bugs.Has(Draw::Bugs::NO_DEPTH_CANNOT_DISCARD_STENCIL_ADRENO)) {
123123
writer.C("layout (depth_unchanged) out float gl_FragDepth;\n");
124124
}
125125

@@ -137,7 +137,7 @@ void GenerateStencilFs(char *buffer, const ShaderLanguageDesc &lang, const Draw:
137137
writer.C(" if (mod(floor(shifted), 2.0) < 0.99) DISCARD;\n");
138138
}
139139

140-
if (bugs.Has(Draw::Bugs::NO_DEPTH_CANNOT_DISCARD_STENCIL)) {
140+
if (bugs.Has(Draw::Bugs::NO_DEPTH_CANNOT_DISCARD_STENCIL_MALI) || bugs.Has(Draw::Bugs::NO_DEPTH_CANNOT_DISCARD_STENCIL_ADRENO)) {
141141
writer.C(" gl_FragDepth = gl_FragCoord.z;\n");
142142
}
143143

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)