mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-14 15:00:30 +02:00
Depth readback: Scale by 65536, and decode in full precision
The vertex shader stores depth as z / 65536, so reading it back with 65535 came out one too low whenever z's fraction was below z / 65536. Both the CPU conversion and the shader path (used on GLES and at higher render resolutions) had it. The shader also ran at the fragment shader's default lowp, which mobile GPUs honor; 24 bits of depth need highp, sampler included on GLES. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c2ce8d1f2e
commit
bcfb4daa78
1 file changed
+11
-4
@@ -54,11 +54,17 @@ static const VaryingDef varyings[] = {
|
||||
};
|
||||
|
||||
void GenerateDepthDownloadFs(ShaderWriter &writer) {
|
||||
// 24 bits of depth need full precision, through the sampler too (GLES samplers default to lowp).
|
||||
writer.HighPrecisionFloat();
|
||||
if (ShaderLanguageIsOpenGL(writer.Lang().shaderLanguage) && writer.Lang().gles) {
|
||||
writer.C("precision highp sampler2D;\n");
|
||||
}
|
||||
writer.DeclareSamplers(samplers);
|
||||
writer.BeginFSMain(depthUniforms, varyings);
|
||||
writer.C(" float depth = ").SampleTexture2D("tex", "v_texcoord").C(".r;\n");
|
||||
// At this point, clamped maps [0, 1] to [0, 65535].
|
||||
writer.C(" float clamped = clamp(depth, 0.0, 1.0);\n");
|
||||
// Depth is stored as z / 65536 (clears as z / 65535), so the PSP's z is the top 16 of 24 bits of
|
||||
// depth * 2^24. Clamp just below 1.0 so a cleared 65535 doesn't wrap to 0.
|
||||
writer.C(" float clamped = clamp(depth, 0.0, 16777215.0 / 16777216.0);\n");
|
||||
writer.C(" vec4 enc = u_depthShift * clamped;\n");
|
||||
writer.C(" enc = floor(mod(enc, 256.0)) * u_depthTo8;\n");
|
||||
writer.C(" vec4 outColor = enc.yzww;\n"); // Let's ignore the bits outside 16 bit precision.
|
||||
@@ -214,7 +220,7 @@ bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x
|
||||
DepthUB ub{};
|
||||
|
||||
// These are for packing a float in u8x4 colors. We should support more suitable readback formats on APIs that can do it.
|
||||
static constexpr float shifts[] = { 16777215.0f, 16777215.0f / 256.0f, 16777215.0f / 65536.0f, 16777215.0f / 16777216.0f };
|
||||
static constexpr float shifts[] = { 16777216.0f, 65536.0f, 256.0f, 1.0f };
|
||||
memcpy(ub.u_depthShift, shifts, sizeof(shifts));
|
||||
static constexpr float to8[] = { 1.0f / 255.0f, 1.0f / 255.0f, 1.0f / 255.0f, 1.0f / 255.0f };
|
||||
memcpy(ub.u_depthTo8, to8, sizeof(to8));
|
||||
@@ -261,7 +267,8 @@ bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x
|
||||
const float *packedf = (float *)convBuf_;
|
||||
for (int yp = 0; yp < destH; ++yp) {
|
||||
for (int xp = 0; xp < destW; ++xp) {
|
||||
dest[xp] = (u16)std::clamp(65535.0f * packedf[xp], 0.0f, 65535.0f);
|
||||
// Depth is stored as z / 65536 (clears as z / 65535), and the PSP truncates.
|
||||
dest[xp] = (u16)std::clamp(65536.0f * packedf[xp], 0.0f, 65535.0f);
|
||||
}
|
||||
dest += pixelsStride;
|
||||
packedf += destW;
|
||||
|
||||
Reference in new issue
Block a user