From def22eb53cf72d90d3bc11a340bef67bfaf88d77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 31 Aug 2026 15:46:00 +0200 Subject: [PATCH] Fix two unreachable-guard style bugs in GPU state and shader gen ReplaceAlphaWithStencil's blue-to-alpha check sat after a branch that already catches every replaceBlend except NO and READ_FRAMEBUFFER - so it was dead, and blue-to-alpha draws could come back REPLACE_ALPHA_YES or DUALSOURCE and pick up stencil-to-alpha on top of the blue-to-alpha setup. Moved it above. The D3D11 fragment shader applied nointerpolation to v_color0 but not v_color1, and in HLSL it's the PS input declaration that decides - so flat shading was lost for the specular term. The vertex shader already marks both. --- GPU/Common/FragmentShaderGenerator.cpp | 5 ++++- GPU/Common/GPUStateUtils.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/GPU/Common/FragmentShaderGenerator.cpp b/GPU/Common/FragmentShaderGenerator.cpp index ab51b2a213..d9b45a210a 100644 --- a/GPU/Common/FragmentShaderGenerator.cpp +++ b/GPU/Common/FragmentShaderGenerator.cpp @@ -286,7 +286,10 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu const char *colorInterpolation = doFlatShading && compat.shaderLanguage == HLSL_D3D11 ? "nointerpolation " : ""; WRITE(p, " %svec4 v_color0: COLOR0;\n", colorInterpolation); if (lmode) { - WRITE(p, " vec3 v_color1: COLOR1;\n"); + // Needs the same nointerpolation as v_color0 - in HLSL it's the PS input declaration + // that decides, so without it the specular term keeps interpolating when flat shading + // is on. Both GLSL paths already mark both. + WRITE(p, " %svec3 v_color1: COLOR1;\n", colorInterpolation); } WRITE(p, " float v_fogdepth: TEXCOORD1;\n"); if (needFragCoord) { diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index ddedde12d5..027b6e3cd0 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -185,6 +185,10 @@ ReplaceAlphaType ReplaceAlphaWithStencil(ReplaceBlendType replaceBlend) { return REPLACE_ALPHA_NO; } + if (replaceBlend == ReplaceBlendType::REPLACE_BLEND_BLUE_TO_ALPHA) { + return REPLACE_ALPHA_NO; // irrelevant + } + if (replaceBlend != REPLACE_BLEND_NO && replaceBlend != REPLACE_BLEND_READ_FRAMEBUFFER) { if (nonAlphaSrcFactors[gstate.getBlendFuncA()] && nonAlphaDestFactors[gstate.getBlendFuncB()]) { return REPLACE_ALPHA_YES; @@ -197,10 +201,6 @@ ReplaceAlphaType ReplaceAlphaWithStencil(ReplaceBlendType replaceBlend) { } } - if (replaceBlend == ReplaceBlendType::REPLACE_BLEND_BLUE_TO_ALPHA) { - return REPLACE_ALPHA_NO; // irrelevant - } - return REPLACE_ALPHA_YES; }