From 5265422c0e992a080d404f1b201c8f810a2489e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 10 Jun 2026 09:54:52 +0200 Subject: [PATCH] Remove the old "Fragment ubershader" setting. It's been on by default for years and is not really an ubershader. --- Core/Config.cpp | 1 - Core/Config.h | 1 - GPU/Common/FragmentShaderGenerator.cpp | 34 +++++++------------------- GPU/Common/ShaderId.cpp | 13 ---------- GPU/Common/ShaderId.h | 17 ++++++------- GPU/GLES/GPU_GLES.cpp | 5 ---- GPU/GLES/ShaderManagerGLES.cpp | 2 +- GPU/GPUCommonHW.cpp | 12 --------- GPU/GPUState.h | 3 +-- GPU/Vulkan/ShaderManagerVulkan.cpp | 2 +- UI/DeveloperToolsScreen.cpp | 7 ------ 11 files changed, 19 insertions(+), 78 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 26ca47f84a..a29d4971b6 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -792,7 +792,6 @@ static const ConfigSetting graphicsSettings[] = { ConfigSetting("GpuLogProfiler", SETTING(g_Config, bGpuLogProfiler), false, CfgFlag::DEFAULT), ConfigSetting("UberShaderVertex", SETTING(g_Config, bUberShaderVertex), true, CfgFlag::DEFAULT), - ConfigSetting("UberShaderFragment", SETTING(g_Config, bUberShaderFragment), true, CfgFlag::DEFAULT), ConfigSetting("DisplayRefreshRate", SETTING(g_Config, iDisplayRefreshRate), g_Config.iDisplayRefreshRate, CfgFlag::PER_GAME), }; diff --git a/Core/Config.h b/Core/Config.h index b55580d314..6faa70303c 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -365,7 +365,6 @@ public: bool bHardwareTessellation; bool bShaderCache; // Hidden ini-only setting, useful for debugging shader compile times. bool bUberShaderVertex; - bool bUberShaderFragment; int iDefaultTab; int iScreenshotMode; bool bVulkanDisableImplicitLayers; diff --git a/GPU/Common/FragmentShaderGenerator.cpp b/GPU/Common/FragmentShaderGenerator.cpp index 1ed3c003b2..5a860e87f9 100644 --- a/GPU/Common/FragmentShaderGenerator.cpp +++ b/GPU/Common/FragmentShaderGenerator.cpp @@ -110,10 +110,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu bool colorTestAgainstZero = id.Bit(FS_BIT_COLOR_AGAINST_ZERO); bool doTextureProjection = id.Bit(FS_BIT_DO_TEXTURE_PROJ); - bool ubershader = id.Bit(FS_BIT_UBERSHADER); - // ubershader-controlled bits. If ubershader is on, these will not be used below (and will be false). - bool useTexAlpha = id.Bit(FS_BIT_TEXALPHA); - bool enableColorDouble = id.Bit(FS_BIT_DOUBLE_COLOR); + bool ubershader = true; if (texture3D && arrayTexture) { *errorString = "Invalid combination of 3D texture and array texture, shouldn't happen"; @@ -328,9 +325,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu WRITE(p, "uniform sampler2D tex;\n"); } *uniformMask |= DIRTY_TEX_ALPHA_MUL; - if (ubershader) { - WRITE(p, "uniform vec2 u_texNoAlphaMul;\n"); - } + WRITE(p, "uniform vec2 u_texNoAlphaMul;\n"); } if (readFramebufferTex) { @@ -795,11 +790,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu WRITE(p, " vec4 p = v_color0;\n"); if (texFunc != GE_TEXFUNC_REPLACE) { - if (ubershader) { - WRITE(p, " t.a = max(t.a, u_texNoAlphaMul.x);\n"); - } else if (!useTexAlpha) { - WRITE(p, " t.a = 1.0;\n"); - } + WRITE(p, " t.a = max(t.a, u_texNoAlphaMul.x);\n"); } switch (texFunc) { @@ -814,11 +805,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu break; case GE_TEXFUNC_REPLACE: WRITE(p, " vec4 r = t;\n"); - if (ubershader) { - WRITE(p, " r.a = mix(r.a, p.a, u_texNoAlphaMul.x);\n"); - } else if (!useTexAlpha) { - WRITE(p, " r.a = p.a;\n"); - } + WRITE(p, " r.a = mix(r.a, p.a, u_texNoAlphaMul.x);\n"); WRITE(p, " vec4 v = r%s;\n", secondary); break; case GE_TEXFUNC_ADD: @@ -837,14 +824,11 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu *uniformMask |= DIRTY_TEX_ALPHA_MUL; // We only need a clamp if the color will be further processed. Otherwise the hardware color conversion will clamp for us. - if (ubershader) { - if (enableFog || enableColorTest || replaceBlend != REPLACE_BLEND_NO || simulateLogicOpType != LOGICOPTYPE_NORMAL || colorWriteMask || blueToAlpha) { - WRITE(p, " v.rgb = clamp(v.rgb * u_texNoAlphaMul.y, 0.0, 1.0);\n"); - } else { - WRITE(p, " v.rgb *= u_texNoAlphaMul.y;\n"); - } - } else if (enableColorDouble) { - p.C(" v.rgb = clamp(v.rgb * 2.0, 0.0, 1.0);\n"); + // TODO: Clamp is so cheap that this probably is pretty meaningless. + if (enableFog || enableColorTest || replaceBlend != REPLACE_BLEND_NO || simulateLogicOpType != LOGICOPTYPE_NORMAL || colorWriteMask || blueToAlpha) { + WRITE(p, " v.rgb = clamp(v.rgb * u_texNoAlphaMul.y, 0.0, 1.0);\n"); + } else { + WRITE(p, " v.rgb *= u_texNoAlphaMul.y;\n"); } } else { // No texture mapping diff --git a/GPU/Common/ShaderId.cpp b/GPU/Common/ShaderId.cpp index 9236bdcb87..a7aa6bfb01 100644 --- a/GPU/Common/ShaderId.cpp +++ b/GPU/Common/ShaderId.cpp @@ -200,13 +200,9 @@ std::string FragmentShaderDesc(const FShaderID &id) { if (id.Bit(FS_BIT_CLEARMODE)) desc << "Clear "; if (id.Bit(FS_BIT_DO_TEXTURE)) desc << (id.Bit(FS_BIT_3D_TEXTURE) ? "Tex3D " : "Tex "); if (id.Bit(FS_BIT_DO_TEXTURE_PROJ)) desc << "TexProj "; - if (id.Bit(FS_BIT_ENABLE_FOG)) desc << "Fog "; if (id.Bit(FS_BIT_LMODE)) desc << "LM "; - if (id.Bit(FS_BIT_TEXALPHA)) desc << "TexAlpha "; - if (id.Bit(FS_BIT_DOUBLE_COLOR)) desc << "Double "; if (id.Bit(FS_BIT_FLATSHADE)) desc << "Flat "; if (id.Bit(FS_BIT_BGRA_TEXTURE)) desc << "BGRA "; - if (id.Bit(FS_BIT_UBERSHADER)) desc << "FragUber "; if (id.Bit(FS_BIT_DEPTH_TEST_NEVER)) desc << "DepthNever "; switch ((ShaderDepalMode)id.Bits(FS_BIT_SHADER_DEPAL_MODE, 2)) { case ShaderDepalMode::OFF: break; @@ -329,8 +325,6 @@ void ComputeFragmentShaderID(FShaderID *id_out, const ComputedPipelineState &pip bool enableTexAlpha = gstate.isTextureAlphaUsed(); - bool uberShader = gstate_c.Use(GPU_USE_FRAGMENT_UBERSHADER); - ShaderDepalMode shaderDepalMode = gstate_c.shaderDepalMode; bool colorWriteMask = pipelineState.maskState.applyFramebufferRead; @@ -373,13 +367,6 @@ void ComputeFragmentShaderID(FShaderID *id_out, const ComputedPipelineState &pip } id.SetBit(FS_BIT_ENABLE_FOG, enableFog); // TODO: Will be moved back to the ubershader. - - id.SetBit(FS_BIT_UBERSHADER, uberShader); - if (!uberShader) { - id.SetBit(FS_BIT_TEXALPHA, enableTexAlpha); - id.SetBit(FS_BIT_DOUBLE_COLOR, enableColorDouble); - } - id.SetBit(FS_BIT_DO_TEXTURE_PROJ, doTextureProjection); // 2 bits diff --git a/GPU/Common/ShaderId.h b/GPU/Common/ShaderId.h index d91679f374..29affbf6f7 100644 --- a/GPU/Common/ShaderId.h +++ b/GPU/Common/ShaderId.h @@ -85,20 +85,17 @@ enum FShaderBit : uint8_t { FS_BIT_CLEARMODE = 0, FS_BIT_DO_TEXTURE = 1, FS_BIT_TEXFUNC = 2, // 3 bits - FS_BIT_DOUBLE_COLOR = 5, // Not used with FS_BIT_UBERSHADER - FS_BIT_3D_TEXTURE = 6, - FS_BIT_SHADER_TEX_CLAMP = 7, - FS_BIT_CLAMP_S = 8, - FS_BIT_CLAMP_T = 9, - FS_BIT_TEXALPHA = 10, // Not used with FS_BIT_UBERSHADER - FS_BIT_LMODE = 11, + FS_BIT_SHADER_TEX_CLAMP = 5, + FS_BIT_CLAMP_S = 6, + FS_BIT_CLAMP_T = 7, + // Free bits: 8-11 FS_BIT_ALPHA_TEST = 12, FS_BIT_ALPHA_TEST_FUNC = 13, // 3 bits FS_BIT_ALPHA_AGAINST_ZERO = 16, FS_BIT_COLOR_TEST = 17, FS_BIT_COLOR_TEST_FUNC = 18, // 2 bits FS_BIT_COLOR_AGAINST_ZERO = 20, - FS_BIT_ENABLE_FOG = 21, // Not used with FS_BIT_UBERSHADER + FS_BIT_ENABLE_FOG = 21, FS_BIT_DO_TEXTURE_PROJ = 22, FS_BIT_MINMAX_DISCARD = 23, FS_BIT_STENCIL_TO_ALPHA = 24, // 2 bits @@ -118,10 +115,10 @@ enum FShaderBit : uint8_t { FS_BIT_SAMPLE_ARRAY_TEXTURE = 57, // For multiview, framebuffers are array textures and we need to sample the two layers correctly. FS_BIT_STEREO = 58, FS_BIT_USE_FRAMEBUFFER_FETCH = 59, - FS_BIT_UBERSHADER = 60, + FS_BIT_LMODE = 60, 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. FS_BIT_DEPTH_CLAMP = 62, // These both are connected to VS_BIT_MINMAX_DISCARD_OR_DEPTH_CLAMP in the vertex shader. - // Free bit: 63 + FS_BIT_3D_TEXTURE = 63, }; static inline FShaderBit operator +(FShaderBit bit, int i) { diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index ab48b0f2ba..ea1f569fb7 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -167,11 +167,6 @@ u32 GPU_GLES::CheckGPUFeatures() const { features &= ~GPU_USE_VS_RANGE_CULLING; } - if (!gl_extensions.GLES3) { - // Heuristic. - features &= ~GPU_USE_FRAGMENT_UBERSHADER; - } - features = CheckGPUFeaturesLate(features); if (draw_->GetBugs().Has(Draw::Bugs::ADRENO_RESOURCE_DEADLOCK) && g_Config.bVendorBugChecksEnabled) { diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 4ba4cf787c..d1564e2ff5 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -946,7 +946,7 @@ enum class CacheDetectFlags { }; #define CACHE_HEADER_MAGIC 0x83277592 -#define CACHE_VERSION 39 +#define CACHE_VERSION 40 struct CacheHeader { uint32_t magic; diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index b14f62ac6e..fa396b9a84 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -495,13 +495,6 @@ void GPUCommonHW::UpdateCmdInfo() { cmdInfo_[GE_CMD_MATERIALUPDATE].RemoveDirty(DIRTY_LIGHT_CONTROL); cmdInfo_[GE_CMD_MATERIALUPDATE].AddDirty(DIRTY_VERTEXSHADER_STATE); } - - if (gstate_c.Use(GPU_USE_FRAGMENT_UBERSHADER)) { - // Texfunc controls both texalpha and doubling. The rest is not dynamic yet so can't remove fragment shader dirtying. - cmdInfo_[GE_CMD_TEXFUNC].AddDirty(DIRTY_TEX_ALPHA_MUL); - } else { - cmdInfo_[GE_CMD_TEXFUNC].RemoveDirty(DIRTY_TEX_ALPHA_MUL); - } } void GPUCommonHW::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) { @@ -620,11 +613,6 @@ u32 GPUCommonHW::CheckGPUFeatures() const { features |= GPU_USE_CLEAR_RAM_HACK; } - // Some backends will turn this off again in the calling function. - if (g_Config.bUberShaderFragment) { - features |= GPU_USE_FRAGMENT_UBERSHADER; - } - if (!draw_->GetBugs().Has(Draw::Bugs::BROKEN_NAN_IN_CONDITIONAL)) { features |= GPU_USE_VS_RANGE_CULLING; } diff --git a/GPU/GPUState.h b/GPU/GPUState.h index d51b202e81..ff45d0a721 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -472,8 +472,7 @@ enum : u32 { GPU_USE_VS_RANGE_CULLING = FLAG_BIT(3), GPU_USE_BLEND_MINMAX = FLAG_BIT(4), GPU_USE_LOGIC_OP = FLAG_BIT(5), - GPU_USE_FRAGMENT_UBERSHADER = FLAG_BIT(6), - // Free bit: 7 + // Free bits: 6-7 GPU_USE_ANISOTROPY = FLAG_BIT(8), GPU_USE_CLEAR_RAM_HACK = FLAG_BIT(9), GPU_USE_INSTANCE_RENDERING = FLAG_BIT(10), diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index 1dd669a1b1..276895ad8c 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -410,7 +410,7 @@ enum class VulkanCacheDetectFlags { }; #define CACHE_HEADER_MAGIC 0xff51f420 -#define CACHE_VERSION 55 +#define CACHE_VERSION 56 struct VulkanCacheHeader { uint32_t magic; diff --git a/UI/DeveloperToolsScreen.cpp b/UI/DeveloperToolsScreen.cpp index 15118232e8..bbeb4a7756 100644 --- a/UI/DeveloperToolsScreen.cpp +++ b/UI/DeveloperToolsScreen.cpp @@ -545,13 +545,6 @@ void DeveloperToolsScreen::CreateGraphicsTab(UI::LinearLayout *list) { // If the above if fails, the checkbox is redundant since it'll be force disabled anyway. list->Add(new CheckBox(&g_Config.bUberShaderVertex, dev->T("Vertex"))); } -#if !PPSSPP_PLATFORM(UWP) - if (g_Config.iGPUBackend != (int)GPUBackend::OPENGL || gl_extensions.GLES3) { -#else - { -#endif - list->Add(new CheckBox(&g_Config.bUberShaderFragment, dev->T("Fragment"))); - } // Experimental, allow some VR features without OpenXR if (GetGPUBackend() == GPUBackend::OPENGL) {