diff --git a/bin/resources/shaders/dx11/convert.fx b/bin/resources/shaders/dx11/convert.fx index 7ab1cadf6f..ccd9a8277c 100644 --- a/bin/resources/shaders/dx11/convert.fx +++ b/bin/resources/shaders/dx11/convert.fx @@ -237,6 +237,13 @@ float rgb5a1_to_depth16(float4 val) return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f); } +float ps_convert_float32_float24(PS_INPUT input) : SV_Depth +{ + // Truncates depth value to 24bits + uint d = uint(sample_c(input.t).r * exp2(32.0f)) & 0xFFFFFF; + return float(d) * exp2(-32.0f); +} + float ps_convert_rgba8_float32(PS_INPUT input) : SV_Depth { // Convert an RGBA texture into a float depth texture diff --git a/bin/resources/shaders/opengl/convert.glsl b/bin/resources/shaders/opengl/convert.glsl index 982195270a..4b8f551555 100644 --- a/bin/resources/shaders/opengl/convert.glsl +++ b/bin/resources/shaders/opengl/convert.glsl @@ -144,6 +144,15 @@ float rgb5a1_to_depth16(vec4 unorm) return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f); } +#ifdef ps_convert_float32_float24 +void ps_convert_float32_float24() +{ + // Truncates depth value to 24bits + uint d = uint(sample_c().r * exp2(32.0f)) & 0xFFFFFF; + gl_FragDepth = float(d) * exp2(-32.0f); +} +#endif + #ifdef ps_convert_rgba8_float32 void ps_convert_rgba8_float32() { diff --git a/bin/resources/shaders/vulkan/convert.glsl b/bin/resources/shaders/vulkan/convert.glsl index 1142400f2f..fb9e6148e6 100644 --- a/bin/resources/shaders/vulkan/convert.glsl +++ b/bin/resources/shaders/vulkan/convert.glsl @@ -214,6 +214,15 @@ float rgb5a1_to_depth16(vec4 unorm) return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f); } +#ifdef ps_convert_float32_float24 +void ps_convert_float32_float24() +{ + // Truncates depth value to 24bits + uint d = uint(sample_c(v_tex).r * exp2(32.0f)) & 0xFFFFFF; + gl_FragDepth = float(d) * exp2(-32.0f); +} +#endif + #ifdef ps_convert_rgba8_float32 void ps_convert_rgba8_float32() { diff --git a/pcsx2/GS/Renderers/Common/GSDevice.cpp b/pcsx2/GS/Renderers/Common/GSDevice.cpp index 43b0b7c96a..a7981e4bc1 100644 --- a/pcsx2/GS/Renderers/Common/GSDevice.cpp +++ b/pcsx2/GS/Renderers/Common/GSDevice.cpp @@ -64,6 +64,7 @@ const char* shaderName(ShaderConvert value) case ShaderConvert::RGBA8_TO_FLOAT24_BILN: return "ps_convert_rgba8_float24_biln"; case ShaderConvert::RGBA8_TO_FLOAT16_BILN: return "ps_convert_rgba8_float16_biln"; case ShaderConvert::RGB5A1_TO_FLOAT16_BILN: return "ps_convert_rgb5a1_float16_biln"; + case ShaderConvert::FLOAT32_TO_FLOAT24: return "ps_convert_float32_float24"; case ShaderConvert::DEPTH_COPY: return "ps_depth_copy"; case ShaderConvert::DOWNSAMPLE_COPY: return "ps_downsample_copy"; case ShaderConvert::RGBA_TO_8I: return "ps_convert_rgba_8i"; diff --git a/pcsx2/GS/Renderers/Common/GSDevice.h b/pcsx2/GS/Renderers/Common/GSDevice.h index 497134b7ef..e1de43deb3 100644 --- a/pcsx2/GS/Renderers/Common/GSDevice.h +++ b/pcsx2/GS/Renderers/Common/GSDevice.h @@ -39,6 +39,7 @@ enum class ShaderConvert RGBA8_TO_FLOAT24_BILN, RGBA8_TO_FLOAT16_BILN, RGB5A1_TO_FLOAT16_BILN, + FLOAT32_TO_FLOAT24, DEPTH_COPY, DOWNSAMPLE_COPY, RGBA_TO_8I, @@ -78,6 +79,7 @@ static inline bool HasDepthOutput(ShaderConvert shader) case ShaderConvert::RGBA8_TO_FLOAT24_BILN: case ShaderConvert::RGBA8_TO_FLOAT16_BILN: case ShaderConvert::RGB5A1_TO_FLOAT16_BILN: + case ShaderConvert::FLOAT32_TO_FLOAT24: case ShaderConvert::DEPTH_COPY: return true; default: diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 40d24803d1..216b41277d 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -2026,6 +2026,20 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe else if (dst->m_scale != scale) scale = dst->m_scale; + // Game is changing from 32bit deptth to 24bit, meaning any top values in the depth will no longer be valid, I hope no games rely on these values being maintained, else we're screwed. + if (type == DepthStencil && dst->m_type == DepthStencil && GSLocalMemory::m_psm[dst->m_TEX0.PSM].trbpp == 32 && GSLocalMemory::m_psm[TEX0.PSM].trbpp == 24 && dst->m_alpha_max > 0) + { + calcRescale(dst); + GSTexture* tex = g_gs_device->CreateDepthStencil(new_scaled_size.x, new_scaled_size.y, GSTexture::Format::DepthStencil, false); + g_gs_device->StretchRect(dst->m_texture, sRect, tex, dRect, ShaderConvert::FLOAT32_TO_FLOAT24, false); + g_perfmon.Put(GSPerfMon::TextureCopies, 1); + g_gs_device->Recycle(dst->m_texture); + + dst->m_texture = tex; + dst->m_alpha_min = 0; + dst->m_alpha_max = 0; + } + // If our RGB was invalidated, we need to pull it from depth. // Terminator 3 will reuse our dst_matched target with the RGB masked, then later use the full ARGB area, so we need to update the depth. const bool preserve_target = preserve_rgb || preserve_alpha; diff --git a/pcsx2/GS/Renderers/Metal/convert.metal b/pcsx2/GS/Renderers/Metal/convert.metal index e6aaa7bb9c..50daffd0f6 100644 --- a/pcsx2/GS/Renderers/Metal/convert.metal +++ b/pcsx2/GS/Renderers/Metal/convert.metal @@ -249,6 +249,13 @@ struct ConvertToDepthRes } }; +fragment DepthOut ps_convert_float32_float24(ConvertShaderData data [[stage_in]], ConvertPSDepthRes res) +{ + // Truncates depth value to 24bits + uint val = uint(res.sample(data.t) * 0x1p32) & 0xFFFFFF; + return float(val) * 0x1p-32f; +} + fragment DepthOut ps_convert_rgba8_float32(ConvertShaderData data [[stage_in]], ConvertToDepthRes res) { return rgba8_to_depth32(res.sample(data.t));