From 9a7ee411918846d00bc1a6f9c22c983c6af6b793 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 1 Dec 2018 14:10:47 -0800 Subject: [PATCH] Vulkan: Avoid OpKill workaround with no stencil. It seems like depth gets messed up either way on discard, but behaves sorta better without the write to depth. --- GPU/Common/ShaderId.cpp | 7 ++++++- GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp | 5 +++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/GPU/Common/ShaderId.cpp b/GPU/Common/ShaderId.cpp index e7ed0b4e87..c0cb1a171e 100644 --- a/GPU/Common/ShaderId.cpp +++ b/GPU/Common/ShaderId.cpp @@ -201,8 +201,10 @@ std::string FragmentShaderDesc(const ShaderID &id) { case STENCIL_VALUE_INCR_8: desc << "StenIncr8 "; break; case STENCIL_VALUE_DECR_4: desc << "StenDecr4 "; break; case STENCIL_VALUE_DECR_8: desc << "StenDecr4 "; break; - default: desc << "StenUnknown"; break; + default: desc << "StenUnknown "; break; } + } else if (id.Bit(FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE)) { + desc << "StenOff "; } if (id.Bit(FS_BIT_DO_TEXTURE)) { switch (id.Bits(FS_BIT_TEXFUNC, 3)) { @@ -292,6 +294,9 @@ void ComputeFragmentShaderID(ShaderID *id_out) { if (stencilToAlpha != REPLACE_ALPHA_NO) { // 4 bits id.SetBits(FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE, 4, ReplaceAlphaWithStencilType()); + } else { + // Use those bits instead for whether stencil output is disabled. + id.SetBit(FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE, IsStencilTestOutputDisabled()); } // 2 bits. diff --git a/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp b/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp index 77695e881e..1a880efc8f 100644 --- a/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp +++ b/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp @@ -84,12 +84,13 @@ bool GenerateVulkanGLSLFragmentShader(const FShaderID &id, char *buffer, uint32_ const char *shading = doFlatShading ? "flat" : ""; bool earlyFragmentTests = ((!enableAlphaTest && !enableColorTest) || testForceToZero) && !gstate_c.Supports(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT); + bool hasStencilOutput = stencilToAlpha != REPLACE_ALPHA_NO || id.Bit(FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE) == 0; bool isAdreno = vulkanVendorId == VULKAN_VENDOR_QUALCOMM; if (earlyFragmentTests) { WRITE(p, "layout (early_fragment_tests) in;\n"); - } else if (isAdreno) { + } else if (isAdreno && hasStencilOutput && !gstate_c.Supports(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT)) { WRITE(p, "layout (depth_unchanged) out float gl_FragDepth;\n"); } @@ -585,7 +586,7 @@ bool GenerateVulkanGLSLFragmentShader(const FShaderID &id, char *buffer, uint32_ WRITE(p, " z = (1.0/65535.0) * floor(z * 65535.0);\n"); } WRITE(p, " gl_FragDepth = z;\n"); - } else if (!earlyFragmentTests && isAdreno) { + } else if (!earlyFragmentTests && isAdreno && hasStencilOutput) { // Adreno (and possibly MESA/others) apply early frag tests even with discard in the shader. // Writing depth prevents the bug, even with depth_unchanged specified. WRITE(p, " gl_FragDepth = gl_FragCoord.z;\n");