From 8d00df12a40c8a3db5eec6d70809a257e5f878e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 11 Sep 2022 18:23:57 +0200 Subject: [PATCH] Detect the CLUT8/8888 situation Implement CLUT8 depal from 8888 textures. Hard to tell if working --- GPU/Common/FragmentShaderGenerator.cpp | 22 ++++++++++++++++++++-- GPU/Common/ShaderId.cpp | 2 +- GPU/Common/TextureCacheCommon.cpp | 21 +++++++++++++++++---- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/GPU/Common/FragmentShaderGenerator.cpp b/GPU/Common/FragmentShaderGenerator.cpp index 9586d01b48..74acc84886 100644 --- a/GPU/Common/FragmentShaderGenerator.cpp +++ b/GPU/Common/FragmentShaderGenerator.cpp @@ -734,8 +734,26 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu WRITE(p, " }\n"); break; case ShaderDepalMode::CLUT8_8888: - // Not yet implemented. - WRITE(p, " vec4 t = vec4(0.0, 0.0, 0.0, 0.0);\n"); + if (doTextureProjection) { + // We don't use textureProj because we need better control and it's probably not much of a savings anyway. + // However it is good for precision on older hardware like PowerVR. + p.F(" vec2 uv = %s.xy/%s.z;\n vec2 uv_round;\n", texcoord, texcoord); + } else { + p.F(" vec2 uv = %s.xy;\n vec2 uv_round;\n", texcoord); + } + p.C(" vec2 tsize = vec2(textureSize(tex, 0).xy);\n"); + p.C(" uv_round = floor(uv * tsize);\n"); + p.C(" int component = int(uv_round.x) & 3;\n"); + p.C(" uv_round.x *= 0.25;\n"); + p.C(" vec4 t = ivec4(").LoadTexture2D("tex", "ivec2(uv_round)", 0).C(");\n"); + p.C(" int index;\n"); + p.C(" switch (component) {\n"); + p.C(" case 0: index = int(t.x * 255.99); break;\n"); + p.C(" case 1: index = int(t.y * 255.99); break;\n"); + p.C(" case 2: index = int(t.z * 255.99); break;\n"); + p.C(" case 3: index = int(t.w * 255.99); break;\n"); + p.C(" }\n"); + p.C(" t = ").LoadTexture2D("pal", "ivec2(index, 0)", 0).C(";\n"); break; } diff --git a/GPU/Common/ShaderId.cpp b/GPU/Common/ShaderId.cpp index f873024c39..7ca42ccba6 100644 --- a/GPU/Common/ShaderId.cpp +++ b/GPU/Common/ShaderId.cpp @@ -180,7 +180,7 @@ std::string FragmentShaderDesc(const FShaderID &id) { if (id.Bit(FS_BIT_COLOR_DOUBLE)) desc << "2x "; if (id.Bit(FS_BIT_FLATSHADE)) desc << "Flat "; if (id.Bit(FS_BIT_BGRA_TEXTURE)) desc << "BGRA "; - switch ((ShaderDepalMode)id.Bit(FS_BIT_SHADER_DEPAL_MODE)) { + switch ((ShaderDepalMode)id.Bits(FS_BIT_SHADER_DEPAL_MODE, 2)) { case ShaderDepalMode::OFF: break; case ShaderDepalMode::NORMAL: desc << "Depal "; break; case ShaderDepalMode::SMOOTHED: desc << "SmoothDepal "; break; diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 77b47e8b9e..65869ad428 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -947,12 +947,13 @@ bool TextureCacheCommon::MatchFramebuffer( return false; } - // Check works for D16 too (???) + // Check works for D16 too. const bool matchingClutFormat = (fb_format == GE_FORMAT_DEPTH16 && entry.format == GE_TFMT_CLUT16) || (fb_format == GE_FORMAT_DEPTH16 && entry.format == GE_TFMT_5650) || (fb_format == GE_FORMAT_8888 && entry.format == GE_TFMT_CLUT32) || - (fb_format != GE_FORMAT_8888 && entry.format == GE_TFMT_CLUT16); + (fb_format != GE_FORMAT_8888 && entry.format == GE_TFMT_CLUT16) || + (fb_format == GE_FORMAT_8888 && entry.format == GE_TFMT_CLUT8); const int texBitsPerPixel = std::max(1U, (u32)textureBitsPerPixel[entry.format]); const int byteOffset = texaddr - addr; @@ -991,6 +992,10 @@ bool TextureCacheCommon::MatchFramebuffer( if (fb_stride_in_bytes != tex_stride_in_bytes) { // Probably irrelevant. Although, as we shall see soon, there are exceptions. + // Burnout Dominator lens flare trick special case. + if (fb_format == GE_FORMAT_8888 && entry.format == GE_TFMT_CLUT8 && texWidth == 4 && texHeight == 1) { + return true; + } return false; } @@ -1876,7 +1881,7 @@ static bool CanDepalettize(GETextureFormat texFormat, GEBufferFormat bufferForma } break; case GE_FORMAT_8888: - if (texFormat == GE_TFMT_CLUT32) { + if (texFormat == GE_TFMT_CLUT32 || texFormat == GE_TFMT_CLUT8) { // clut8 takes a special depal mode. return true; } break; @@ -1964,9 +1969,17 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer samplerKey.mipEnable = false; ApplySamplingParams(samplerKey); + ShaderDepalMode mode = ShaderDepalMode::NORMAL; + if (texFormat == GE_TFMT_CLUT8 && framebuffer->fb_format == GE_FORMAT_8888) { + mode = ShaderDepalMode::CLUT8_8888; + smoothedDepal = false; // just in case + } else if (smoothedDepal) { + mode = ShaderDepalMode::SMOOTHED; + } + // Since we started/ended render passes, might need these. gstate_c.Dirty(DIRTY_DEPAL); - gstate_c.SetUseShaderDepal(smoothedDepal ? ShaderDepalMode::SMOOTHED : ShaderDepalMode::NORMAL); + gstate_c.SetUseShaderDepal(mode); gstate_c.depalFramebufferFormat = framebuffer->fb_format; const u32 bytesPerColor = clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16);