From e1d45e9ba66d3ba7d6769e36c0fc82ceb5028ecb Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Sun, 18 Apr 2021 19:51:02 -0700 Subject: [PATCH] UberShaderPixel: always run indirect stage logic Hardware testing has confirmed that fb_addprev and wrapping both run even when the indirect stage is disabled. --- .../Core/VideoCommon/PixelShaderManager.cpp | 33 +++++++------------ Source/Core/VideoCommon/UberShaderPixel.cpp | 6 ++++ 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/Source/Core/VideoCommon/PixelShaderManager.cpp b/Source/Core/VideoCommon/PixelShaderManager.cpp index 6d52d8ffc1..0ae1ced1e4 100644 --- a/Source/Core/VideoCommon/PixelShaderManager.cpp +++ b/Source/Core/VideoCommon/PixelShaderManager.cpp @@ -148,29 +148,18 @@ void PixelShaderManager::SetConstants() for (u32 i = 0; i < (bpmem.genMode.numtevstages + 1); ++i) { - u32 stage = bpmem.tevind[i].bt; - if (stage < bpmem.genMode.numindstages) - { - // We set some extra bits so the ubershader can quickly check if these - // features are in use. - if (bpmem.tevind[i].IsActive()) - constants.pack1[stage][3] = - bpmem.tevindref.getTexCoord(stage) | bpmem.tevindref.getTexMap(stage) << 8 | 1 << 16; - // Note: a tevind of zero just happens to be a passthrough, so no need - // to set an extra bit. - constants.pack1[i][2] = bpmem.tevind[i].hex; // TODO: This match shadergen, but videosw - // will always wrap. + // Note: a tevind of zero just happens to be a passthrough, so no need + // to set an extra bit. Furthermore, wrap and add to previous apply even if there is no + // indirect stage. + constants.pack1[i][2] = bpmem.tevind[i].hex; - // The ubershader uses tevind != 0 as a condition whether to calculate texcoords, - // even when texture is disabled, instead of the stage < bpmem.genMode.numindstages. - // We set an unused bit here to indicate that the stage is active, even if it - // is just a pass-through. - constants.pack1[i][2] |= 0x80000000; - } - else - { - constants.pack1[i][2] = 0; - } + u32 stage = bpmem.tevind[i].bt; + + // We use an extra bit (1 << 16) to provide a fast way of testing if this feature is in use. + // Note also that this is indexed by indirect stage, not by TEV stage. + if (bpmem.tevind[i].IsActive() && stage < bpmem.genMode.numindstages) + constants.pack1[stage][3] = + bpmem.tevindref.getTexCoord(stage) | bpmem.tevindref.getTexMap(stage) << 8 | 1 << 16; } dirty = true; diff --git a/Source/Core/VideoCommon/UberShaderPixel.cpp b/Source/Core/VideoCommon/UberShaderPixel.cpp index a029f58812..642896a3dc 100644 --- a/Source/Core/VideoCommon/UberShaderPixel.cpp +++ b/Source/Core/VideoCommon/UberShaderPixel.cpp @@ -287,6 +287,8 @@ ShaderCode GenPixelShader(APIType ApiType, const ShaderHostConfig& host_config, // ====================== const auto LookupIndirectTexture = [&out, stereo](std::string_view out_var_name, std::string_view in_index_name) { + // in_index_name is the indirect stage, not the tev stage + // bpmem_iref is packed differently from RAS1_IREF out.Write("{{\n" " uint iref = bpmem_iref({});\n" " if ( iref != 0u)\n" @@ -304,6 +306,10 @@ ShaderCode GenPixelShader(APIType ApiType, const ShaderHostConfig& host_config, "[texmap].xy, {})).abg;\n", in_index_name, in_index_name, in_index_name, in_index_name, out_var_name, stereo ? "float(layer)" : "0.0"); + // There is always a bit set in bpmem_iref if the data is valid (matrix is not off, and the + // indirect texture stage is enabled). If the matrix is off, the result doesn't matter; if the + // indirect texture stage is disabled, the result is undefined (and produces a glitchy pattern + // on hardware, different from this). out.Write(" }}\n" " else\n" " {{\n"