mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 13:30:02 +00:00
Depth scale functions: Clean up the naming, add a failing test
This commit is contained in:
parent
d426ce5118
commit
d65dae7185
@ -55,9 +55,9 @@ void GenerateDepalShader300(ShaderWriter &writer, const DepalConfig &config) {
|
|||||||
// NOTE: This swizzle can be made to work with any power-of-2 resolution scaleFactor by shifting
|
// NOTE: This swizzle can be made to work with any power-of-2 resolution scaleFactor by shifting
|
||||||
// the bits around, but not sure how to handle 3x scaling. For now this is 1x-only (rough edges at higher resolutions).
|
// the bits around, but not sure how to handle 3x scaling. For now this is 1x-only (rough edges at higher resolutions).
|
||||||
if (config.bufferFormat == GE_FORMAT_DEPTH16) {
|
if (config.bufferFormat == GE_FORMAT_DEPTH16) {
|
||||||
DepthScaleFactors factors = GetDepthScaleFactors();
|
DepthScaleFactors factors = GetDepthScaleFactors(gstate_c.UseFlags());
|
||||||
writer.ConstFloat("z_scale", factors.scale);
|
writer.ConstFloat("z_scale", factors.ScaleU16());
|
||||||
writer.ConstFloat("z_offset", factors.offset);
|
writer.ConstFloat("z_offset", factors.Offset());
|
||||||
if (config.depthUpperBits == 0x2) {
|
if (config.depthUpperBits == 0x2) {
|
||||||
writer.C(R"(
|
writer.C(R"(
|
||||||
int x = int((texcoord.x / scaleFactor) * texSize.x);
|
int x = int((texcoord.x / scaleFactor) * texSize.x);
|
||||||
@ -116,7 +116,7 @@ void GenerateDepalShader300(ShaderWriter &writer, const DepalConfig &config) {
|
|||||||
writer.C(" int index = (a << 15) | (b << 10) | (g << 5) | (r);\n");
|
writer.C(" int index = (a << 15) | (b << 10) | (g << 5) | (r);\n");
|
||||||
break;
|
break;
|
||||||
case GE_FORMAT_DEPTH16:
|
case GE_FORMAT_DEPTH16:
|
||||||
// Remap depth buffer.
|
// Decode depth buffer.
|
||||||
writer.C(" float depth = (color.x - z_offset) * z_scale;\n");
|
writer.C(" float depth = (color.x - z_offset) * z_scale;\n");
|
||||||
|
|
||||||
if (config.bufferFormat == GE_FORMAT_DEPTH16 && config.textureFormat == GE_TFMT_5650) {
|
if (config.bufferFormat == GE_FORMAT_DEPTH16 && config.textureFormat == GE_TFMT_5650) {
|
||||||
@ -161,9 +161,9 @@ void GenerateDepalShaderFloat(ShaderWriter &writer, const DepalConfig &config) {
|
|||||||
const int mask = config.mask;
|
const int mask = config.mask;
|
||||||
|
|
||||||
if (config.bufferFormat == GE_FORMAT_DEPTH16) {
|
if (config.bufferFormat == GE_FORMAT_DEPTH16) {
|
||||||
DepthScaleFactors factors = GetDepthScaleFactors();
|
DepthScaleFactors factors = GetDepthScaleFactors(gstate_c.UseFlags());
|
||||||
writer.ConstFloat("z_scale", factors.scale);
|
writer.ConstFloat("z_scale", factors.ScaleU16());
|
||||||
writer.ConstFloat("z_offset", factors.offset);
|
writer.ConstFloat("z_offset", factors.Offset());
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.C(" vec4 index = ").SampleTexture2D("tex", "v_texcoord").C(";\n");
|
writer.C(" vec4 index = ").SampleTexture2D("tex", "v_texcoord").C(";\n");
|
||||||
|
@ -227,7 +227,7 @@ bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x
|
|||||||
ub.u_depthFactor[0] = 0.0f;
|
ub.u_depthFactor[0] = 0.0f;
|
||||||
ub.u_depthFactor[1] = fudgeFactor;
|
ub.u_depthFactor[1] = fudgeFactor;
|
||||||
} else {
|
} else {
|
||||||
const float factor = DepthSliceFactor();
|
const float factor = DepthSliceFactor(gstate_c.UseFlags());
|
||||||
ub.u_depthFactor[0] = -0.5f * (factor - 1.0f) * (1.0f / factor);
|
ub.u_depthFactor[0] = -0.5f * (factor - 1.0f) * (1.0f / factor);
|
||||||
ub.u_depthFactor[1] = factor * fudgeFactor;
|
ub.u_depthFactor[1] = factor * fudgeFactor;
|
||||||
}
|
}
|
||||||
@ -276,10 +276,10 @@ bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x
|
|||||||
// We downloaded float values directly in this case.
|
// We downloaded float values directly in this case.
|
||||||
uint16_t *dest = pixels;
|
uint16_t *dest = pixels;
|
||||||
const float *packedf = (float *)convBuf_;
|
const float *packedf = (float *)convBuf_;
|
||||||
DepthScaleFactors depthScale = GetDepthScaleFactors();
|
DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags());
|
||||||
for (int yp = 0; yp < destH; ++yp) {
|
for (int yp = 0; yp < destH; ++yp) {
|
||||||
for (int xp = 0; xp < destW; ++xp) {
|
for (int xp = 0; xp < destW; ++xp) {
|
||||||
float scaled = depthScale.Apply(packedf[xp]);
|
float scaled = depthScale.DecodeToU16(packedf[xp]);
|
||||||
if (scaled <= 0.0f) {
|
if (scaled <= 0.0f) {
|
||||||
dest[xp] = 0;
|
dest[xp] = 0;
|
||||||
} else if (scaled >= 65535.0f) {
|
} else if (scaled >= 65535.0f) {
|
||||||
|
1
GPU/Common/DepthBufferCommon.h
Normal file
1
GPU/Common/DepthBufferCommon.h
Normal file
@ -0,0 +1 @@
|
|||||||
|
#pragma once
|
@ -108,10 +108,10 @@ Draw2DPipelineInfo GenerateDraw2D565ToDepthFs(ShaderWriter &writer) {
|
|||||||
writer.C(" vec4 outColor = vec4(0.0, 0.0, 0.0, 0.0);\n");
|
writer.C(" vec4 outColor = vec4(0.0, 0.0, 0.0, 0.0);\n");
|
||||||
// Unlike when just copying a depth buffer, here we're generating new depth values so we'll
|
// Unlike when just copying a depth buffer, here we're generating new depth values so we'll
|
||||||
// have to apply the scaling.
|
// have to apply the scaling.
|
||||||
DepthScaleFactors factors = GetDepthScaleFactors();
|
DepthScaleFactors factors = GetDepthScaleFactors(gstate_c.UseFlags());
|
||||||
writer.C(" vec3 rgb = ").SampleTexture2D("tex", "v_texcoord.xy").C(".xyz;\n");
|
writer.C(" vec3 rgb = ").SampleTexture2D("tex", "v_texcoord.xy").C(".xyz;\n");
|
||||||
writer.F(" highp float depthValue = (floor(rgb.x * 31.99) + floor(rgb.y * 63.99) * 32.0 + floor(rgb.z * 31.99) * 2048.0); \n");
|
writer.F(" highp float depthValue = (floor(rgb.x * 31.99) + floor(rgb.y * 63.99) * 32.0 + floor(rgb.z * 31.99) * 2048.0); \n");
|
||||||
writer.F(" gl_FragDepth = (depthValue / %f) + %f;\n", factors.scale, factors.offset);
|
writer.F(" gl_FragDepth = (depthValue / %f) + %f;\n", factors.ScaleU16(), factors.Offset());
|
||||||
writer.EndFSMain("outColor");
|
writer.EndFSMain("outColor");
|
||||||
|
|
||||||
return Draw2DPipelineInfo{
|
return Draw2DPipelineInfo{
|
||||||
@ -128,7 +128,7 @@ Draw2DPipelineInfo GenerateDraw2D565ToDepthDeswizzleFs(ShaderWriter &writer) {
|
|||||||
writer.C(" vec4 outColor = vec4(0.0, 0.0, 0.0, 0.0);\n");
|
writer.C(" vec4 outColor = vec4(0.0, 0.0, 0.0, 0.0);\n");
|
||||||
// Unlike when just copying a depth buffer, here we're generating new depth values so we'll
|
// Unlike when just copying a depth buffer, here we're generating new depth values so we'll
|
||||||
// have to apply the scaling.
|
// have to apply the scaling.
|
||||||
DepthScaleFactors factors = GetDepthScaleFactors();
|
DepthScaleFactors factors = GetDepthScaleFactors(gstate_c.UseFlags());
|
||||||
writer.C(" vec2 tsize = texSize;\n");
|
writer.C(" vec2 tsize = texSize;\n");
|
||||||
writer.C(" vec2 coord = v_texcoord * tsize;\n");
|
writer.C(" vec2 coord = v_texcoord * tsize;\n");
|
||||||
writer.F(" float strip = 4.0 * scaleFactor;\n");
|
writer.F(" float strip = 4.0 * scaleFactor;\n");
|
||||||
@ -137,7 +137,7 @@ Draw2DPipelineInfo GenerateDraw2D565ToDepthDeswizzleFs(ShaderWriter &writer) {
|
|||||||
writer.C(" coord /= tsize;\n");
|
writer.C(" coord /= tsize;\n");
|
||||||
writer.C(" vec3 rgb = ").SampleTexture2D("tex", "coord").C(".xyz;\n");
|
writer.C(" vec3 rgb = ").SampleTexture2D("tex", "coord").C(".xyz;\n");
|
||||||
writer.F(" highp float depthValue = (floor(rgb.x * 31.99) + floor(rgb.y * 63.99) * 32.0 + floor(rgb.z * 31.99) * 2048.0); \n");
|
writer.F(" highp float depthValue = (floor(rgb.x * 31.99) + floor(rgb.y * 63.99) * 32.0 + floor(rgb.z * 31.99) * 2048.0); \n");
|
||||||
writer.F(" gl_FragDepth = (depthValue / %f) + %f;\n", factors.scale, factors.offset);
|
writer.F(" gl_FragDepth = (depthValue / %f) + %f;\n", factors.ScaleU16(), factors.Offset());
|
||||||
writer.EndFSMain("outColor");
|
writer.EndFSMain("outColor");
|
||||||
|
|
||||||
return Draw2DPipelineInfo{
|
return Draw2DPipelineInfo{
|
||||||
|
@ -1185,13 +1185,13 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (gstate_c.Use(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT)) {
|
if (gstate_c.Use(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT)) {
|
||||||
const double scale = DepthSliceFactor() * 65535.0;
|
const double scale = DepthSliceFactor(gstate_c.UseFlags()) * 65535.0;
|
||||||
|
|
||||||
WRITE(p, " highp float z = gl_FragCoord.z;\n");
|
WRITE(p, " highp float z = gl_FragCoord.z;\n");
|
||||||
if (gstate_c.Use(GPU_USE_ACCURATE_DEPTH)) {
|
if (gstate_c.Use(GPU_USE_ACCURATE_DEPTH)) {
|
||||||
// We center the depth with an offset, but only its fraction matters.
|
// We center the depth with an offset, but only its fraction matters.
|
||||||
// When (DepthSliceFactor() - 1) is odd, it will be 0.5, otherwise 0.
|
// When (DepthSliceFactor() - 1) is odd, it will be 0.5, otherwise 0.
|
||||||
if (((int)(DepthSliceFactor() - 1.0f) & 1) == 1) {
|
if (((int)(DepthSliceFactor(gstate_c.UseFlags()) - 1.0f) & 1) == 1) {
|
||||||
WRITE(p, " z = (floor((z * %f) - (1.0 / 2.0)) + (1.0 / 2.0)) * (1.0 / %f);\n", scale, scale);
|
WRITE(p, " z = (floor((z * %f) - (1.0 / 2.0)) + (1.0 / 2.0)) * (1.0 / %f);\n", scale, scale);
|
||||||
} else {
|
} else {
|
||||||
WRITE(p, " z = floor(z * %f) * (1.0 / %f);\n", scale, scale);
|
WRITE(p, " z = floor(z * %f) * (1.0 / %f);\n", scale, scale);
|
||||||
|
@ -1063,7 +1063,7 @@ void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffe
|
|||||||
float clearDepth = 0.0f;
|
float clearDepth = 0.0f;
|
||||||
if (vfb->usageFlags & FB_USAGE_INVALIDATE_DEPTH) {
|
if (vfb->usageFlags & FB_USAGE_INVALIDATE_DEPTH) {
|
||||||
depthAction = Draw::RPAction::CLEAR;
|
depthAction = Draw::RPAction::CLEAR;
|
||||||
clearDepth = GetDepthScaleFactors().offset;
|
clearDepth = GetDepthScaleFactors(gstate_c.UseFlags()).Offset();
|
||||||
vfb->usageFlags &= ~FB_USAGE_INVALIDATE_DEPTH;
|
vfb->usageFlags &= ~FB_USAGE_INVALIDATE_DEPTH;
|
||||||
}
|
}
|
||||||
draw_->BindFramebufferAsRenderTarget(vfb->fbo, {Draw::RPAction::KEEP, depthAction, Draw::RPAction::KEEP, 0, clearDepth}, "FBSwitch");
|
draw_->BindFramebufferAsRenderTarget(vfb->fbo, {Draw::RPAction::KEEP, depthAction, Draw::RPAction::KEEP, 0, clearDepth}, "FBSwitch");
|
||||||
|
@ -502,25 +502,28 @@ ReplaceBlendType ReplaceBlendWithShader(GEBufferFormat bufferFormat) {
|
|||||||
static const float DEPTH_SLICE_FACTOR_HIGH = 4.0f;
|
static const float DEPTH_SLICE_FACTOR_HIGH = 4.0f;
|
||||||
static const float DEPTH_SLICE_FACTOR_16BIT = 256.0f;
|
static const float DEPTH_SLICE_FACTOR_16BIT = 256.0f;
|
||||||
|
|
||||||
float DepthSliceFactor() {
|
float DepthSliceFactor(u32 useFlags) {
|
||||||
if (gstate_c.Use(GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT)) {
|
if (!(useFlags & GPU_USE_ACCURATE_DEPTH)) {
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
if (useFlags & GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT) {
|
||||||
return DEPTH_SLICE_FACTOR_16BIT;
|
return DEPTH_SLICE_FACTOR_16BIT;
|
||||||
}
|
}
|
||||||
if (gstate_c.Use(GPU_USE_DEPTH_CLAMP)) {
|
if (useFlags & GPU_USE_DEPTH_CLAMP) {
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
return DEPTH_SLICE_FACTOR_HIGH;
|
return DEPTH_SLICE_FACTOR_HIGH;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is used for float values which might not be integers, but are in the integer scale of 65535.
|
// This is used for float values which might not be integers, but are in the integer scale of 0-65535.
|
||||||
float ToScaledDepthFromIntegerScale(float z) {
|
float ToScaledDepthFromIntegerScale(u32 useFlags, float z) {
|
||||||
if (!gstate_c.Use(GPU_USE_ACCURATE_DEPTH)) {
|
if (!(useFlags & GPU_USE_ACCURATE_DEPTH)) {
|
||||||
return z * (1.0f / 65535.0f);
|
return z * (1.0f / 65535.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
const float depthSliceFactor = DepthSliceFactor();
|
const float depthSliceFactor = DepthSliceFactor(useFlags);
|
||||||
if (gstate_c.Use(GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT)) {
|
|
||||||
const double doffset = 0.5 * (depthSliceFactor - 1.0) * (1.0 / depthSliceFactor);
|
const double doffset = 0.5 * (depthSliceFactor - 1.0) * (1.0 / depthSliceFactor);
|
||||||
|
if (useFlags & GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT) {
|
||||||
// Use one bit for each value, rather than 1.0 / (65535.0 * 256.0).
|
// Use one bit for each value, rather than 1.0 / (65535.0 * 256.0).
|
||||||
return (float)((double)z * (1.0 / 16777215.0) + doffset);
|
return (float)((double)z * (1.0 / 16777215.0) + doffset);
|
||||||
} else {
|
} else {
|
||||||
@ -529,20 +532,15 @@ float ToScaledDepthFromIntegerScale(float z) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// See struct DepthScaleFactors for how to apply.
|
// See class DepthScaleFactors for how to apply.
|
||||||
DepthScaleFactors GetDepthScaleFactors() {
|
DepthScaleFactors GetDepthScaleFactors(u32 useFlags) {
|
||||||
DepthScaleFactors factors;
|
if (!(useFlags & GPU_USE_ACCURATE_DEPTH)) {
|
||||||
if (!gstate_c.Use(GPU_USE_ACCURATE_DEPTH)) {
|
return DepthScaleFactors(0.0f, 65535.0f);
|
||||||
factors.offset = 0;
|
|
||||||
factors.scale = 65535.0f;
|
|
||||||
return factors;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const float depthSliceFactor = DepthSliceFactor();
|
const float depthSliceFactor = DepthSliceFactor(useFlags);
|
||||||
const float offset = 0.5f * (depthSliceFactor - 1.0f) * (1.0f / depthSliceFactor);
|
const float offset = 0.5f * (depthSliceFactor - 1.0f) * (1.0f / depthSliceFactor);
|
||||||
factors.scale = depthSliceFactor * 65535.0f;
|
return DepthScaleFactors(offset, depthSliceFactor * 65535.0f);
|
||||||
factors.offset = offset;
|
|
||||||
return factors;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out) {
|
void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out) {
|
||||||
@ -608,8 +606,8 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
|
|||||||
out.viewportY = renderY * renderHeightFactor + displayOffsetY;
|
out.viewportY = renderY * renderHeightFactor + displayOffsetY;
|
||||||
out.viewportW = curRTWidth * renderWidthFactor;
|
out.viewportW = curRTWidth * renderWidthFactor;
|
||||||
out.viewportH = curRTHeight * renderHeightFactor;
|
out.viewportH = curRTHeight * renderHeightFactor;
|
||||||
out.depthRangeMin = ToScaledDepthFromIntegerScale(0);
|
out.depthRangeMin = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), 0.0f);
|
||||||
out.depthRangeMax = ToScaledDepthFromIntegerScale(65536);
|
out.depthRangeMax = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), 65536.0f);
|
||||||
} else {
|
} else {
|
||||||
// These we can turn into a glViewport call, offset by offsetX and offsetY. Math after.
|
// These we can turn into a glViewport call, offset by offsetX and offsetY. Math after.
|
||||||
float vpXScale = gstate.getViewportXScale();
|
float vpXScale = gstate.getViewportXScale();
|
||||||
@ -723,7 +721,7 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
|
|||||||
// Here, we should "clamp." But clamping per fragment would be slow.
|
// Here, we should "clamp." But clamping per fragment would be slow.
|
||||||
// So, instead, we just increase the available range and hope.
|
// So, instead, we just increase the available range and hope.
|
||||||
// If depthSliceFactor is 4, it means (75% / 2) of the depth lies in each direction.
|
// If depthSliceFactor is 4, it means (75% / 2) of the depth lies in each direction.
|
||||||
float fullDepthRange = 65535.0f * (DepthSliceFactor() - 1.0f) * (1.0f / 2.0f);
|
float fullDepthRange = 65535.0f * (DepthSliceFactor(gstate_c.UseFlags()) - 1.0f) * (1.0f / 2.0f);
|
||||||
if (minz == 0) {
|
if (minz == 0) {
|
||||||
minz -= fullDepthRange;
|
minz -= fullDepthRange;
|
||||||
}
|
}
|
||||||
@ -734,7 +732,7 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
|
|||||||
// This means clamp isn't enabled, but we still want to allow values up to 65535.99.
|
// This means clamp isn't enabled, but we still want to allow values up to 65535.99.
|
||||||
// If DepthSliceFactor() is 1.0, though, this would make out.depthRangeMax exceed 1.
|
// If DepthSliceFactor() is 1.0, though, this would make out.depthRangeMax exceed 1.
|
||||||
// Since that would clamp, it would make Z=1234 not match between draws when maxz changes.
|
// Since that would clamp, it would make Z=1234 not match between draws when maxz changes.
|
||||||
if (DepthSliceFactor() > 1.0f)
|
if (DepthSliceFactor(gstate_c.UseFlags()) > 1.0f)
|
||||||
maxz = 65535.99f;
|
maxz = 65535.99f;
|
||||||
}
|
}
|
||||||
// Okay. So, in our shader, -1 will map to minz, and +1 will map to maxz.
|
// Okay. So, in our shader, -1 will map to minz, and +1 will map to maxz.
|
||||||
@ -746,11 +744,11 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
|
|||||||
if (!gstate_c.Use(GPU_USE_ACCURATE_DEPTH)) {
|
if (!gstate_c.Use(GPU_USE_ACCURATE_DEPTH)) {
|
||||||
out.depthScale = 1.0f;
|
out.depthScale = 1.0f;
|
||||||
out.zOffset = 0.0f;
|
out.zOffset = 0.0f;
|
||||||
out.depthRangeMin = ToScaledDepthFromIntegerScale(vpZCenter - vpZScale);
|
out.depthRangeMin = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), vpZCenter - vpZScale);
|
||||||
out.depthRangeMax = ToScaledDepthFromIntegerScale(vpZCenter + vpZScale);
|
out.depthRangeMax = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), vpZCenter + vpZScale);
|
||||||
} else {
|
} else {
|
||||||
out.depthRangeMin = ToScaledDepthFromIntegerScale(minz);
|
out.depthRangeMin = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), minz);
|
||||||
out.depthRangeMax = ToScaledDepthFromIntegerScale(maxz);
|
out.depthRangeMax = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), maxz);
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenGL will clamp these for us anyway, and Direct3D will error if not clamped.
|
// OpenGL will clamp these for us anyway, and Direct3D will error if not clamped.
|
||||||
|
@ -86,25 +86,38 @@ struct ViewportAndScissor {
|
|||||||
float zOffset;
|
float zOffset;
|
||||||
bool throughMode;
|
bool throughMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out);
|
void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out);
|
||||||
void UpdateCachedViewportState(const ViewportAndScissor &vpAndScissor);
|
void UpdateCachedViewportState(const ViewportAndScissor &vpAndScissor);
|
||||||
float ToScaledDepthFromIntegerScale(float z);
|
|
||||||
|
|
||||||
struct DepthScaleFactors {
|
class DepthScaleFactors {
|
||||||
float offset;
|
public:
|
||||||
float scale;
|
// This should only be used from GetDepthScaleFactors.
|
||||||
|
DepthScaleFactors(float offset, float scale) : offset_(offset), scale_(scale) {}
|
||||||
|
|
||||||
float Apply(float z) const {
|
// Decodes a value from a depth buffer to a value of range 0..65536
|
||||||
return (z - offset) * scale;
|
float DecodeToU16(float z) const {
|
||||||
|
return (z - offset_) * scale_;
|
||||||
}
|
}
|
||||||
|
|
||||||
float ApplyInverse(float z) const {
|
// Encodes a value from the range 0..65536 to a normalized depth value (0-1), in the
|
||||||
return (z / scale) + offset;
|
// range that we write to the depth buffer.
|
||||||
|
float EncodeFromU16(float z_u16) const {
|
||||||
|
return (z_u16 / scale_) + offset_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Offset() const { return offset_; }
|
||||||
|
float ScaleU16() const { return scale_; }
|
||||||
|
// float Scale() const { return scale_ / 65535.0f; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
float offset_;
|
||||||
|
float scale_;
|
||||||
};
|
};
|
||||||
DepthScaleFactors GetDepthScaleFactors();
|
|
||||||
|
|
||||||
float DepthSliceFactor();
|
DepthScaleFactors GetDepthScaleFactors(u32 useFlags);
|
||||||
|
float ToScaledDepthFromIntegerScale(u32 useFlags, float z);
|
||||||
|
float DepthSliceFactor(u32 useFlags);
|
||||||
|
|
||||||
// These are common to all modern APIs and can be easily converted with a lookup table.
|
// These are common to all modern APIs and can be easily converted with a lookup table.
|
||||||
enum class BlendFactor : uint8_t {
|
enum class BlendFactor : uint8_t {
|
||||||
|
@ -255,7 +255,7 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView
|
|||||||
float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange;
|
float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange;
|
||||||
float viewZScale = halfActualZRange * 2.0f;
|
float viewZScale = halfActualZRange * 2.0f;
|
||||||
// Account for the half pixel offset.
|
// Account for the half pixel offset.
|
||||||
float viewZCenter = minz + (DepthSliceFactor() / 256.0f) * 0.5f;
|
float viewZCenter = minz + (DepthSliceFactor(gstate_c.UseFlags()) / 256.0f) * 0.5f;
|
||||||
|
|
||||||
ub->depthRange[0] = viewZScale;
|
ub->depthRange[0] = viewZScale;
|
||||||
ub->depthRange[1] = viewZCenter;
|
ub->depthRange[1] = viewZCenter;
|
||||||
|
@ -454,7 +454,7 @@ void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVt
|
|||||||
if (matchingComponents && stencilNotMasked) {
|
if (matchingComponents && stencilNotMasked) {
|
||||||
result->color = transformed[1].color0_32;
|
result->color = transformed[1].color0_32;
|
||||||
// Need to rescale from a [0, 1] float. This is the final transformed value.
|
// Need to rescale from a [0, 1] float. This is the final transformed value.
|
||||||
result->depth = ToScaledDepthFromIntegerScale((int)(transformed[1].z * 65535.0f));
|
result->depth = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), (int)(transformed[1].z * 65535.0f));
|
||||||
result->action = SW_CLEAR;
|
result->action = SW_CLEAR;
|
||||||
gpuStats.numClears++;
|
gpuStats.numClears++;
|
||||||
return;
|
return;
|
||||||
|
@ -74,13 +74,13 @@ bool FramebufferManagerDX9::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x, i
|
|||||||
const u32 *packed = (const u32 *)locked.pBits;
|
const u32 *packed = (const u32 *)locked.pBits;
|
||||||
u16 *depth = (u16 *)pixels;
|
u16 *depth = (u16 *)pixels;
|
||||||
|
|
||||||
DepthScaleFactors depthScale = GetDepthScaleFactors();
|
DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags());
|
||||||
// TODO: Optimize.
|
// TODO: Optimize.
|
||||||
for (int yp = 0; yp < h; ++yp) {
|
for (int yp = 0; yp < h; ++yp) {
|
||||||
for (int xp = 0; xp < w; ++xp) {
|
for (int xp = 0; xp < w; ++xp) {
|
||||||
const int offset = (yp + y) * pixelsStride + x + xp;
|
const int offset = (yp + y) * pixelsStride + x + xp;
|
||||||
|
|
||||||
float scaled = depthScale.Apply((packed[offset] & 0x00FFFFFF) * (1.0f / 16777215.0f));
|
float scaled = depthScale.DecodeToU16((packed[offset] & 0x00FFFFFF) * (1.0f / 16777215.0f));
|
||||||
if (scaled <= 0.0f) {
|
if (scaled <= 0.0f) {
|
||||||
depth[offset] = 0;
|
depth[offset] = 0;
|
||||||
} else if (scaled >= 65535.0f) {
|
} else if (scaled >= 65535.0f) {
|
||||||
|
@ -466,7 +466,7 @@ void ShaderManagerDX9::VSUpdateUniforms(u64 dirtyUniforms) {
|
|||||||
float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange;
|
float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange;
|
||||||
float viewZScale = halfActualZRange * 2.0f;
|
float viewZScale = halfActualZRange * 2.0f;
|
||||||
// Account for the half pixel offset.
|
// Account for the half pixel offset.
|
||||||
float viewZCenter = minz + (DepthSliceFactor() / 256.0f) * 0.5f;
|
float viewZCenter = minz + (DepthSliceFactor(gstate_c.UseFlags()) / 256.0f) * 0.5f;
|
||||||
float reverseScale = 2.0f * (1.0f / gstate_c.vpDepthScale);
|
float reverseScale = 2.0f * (1.0f / gstate_c.vpDepthScale);
|
||||||
float reverseTranslate = gstate_c.vpZOffset * 0.5f + 0.5f;
|
float reverseTranslate = gstate_c.vpZOffset * 0.5f + 0.5f;
|
||||||
|
|
||||||
|
@ -524,8 +524,10 @@ enum class SubmitType {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct GPUStateCache {
|
struct GPUStateCache {
|
||||||
bool Use(u32 flags) { return (useFlags_ & flags) != 0; } // Return true if ANY of flags are true.
|
bool Use(u32 flags) const { return (useFlags_ & flags) != 0; } // Return true if ANY of flags are true.
|
||||||
bool UseAll(u32 flags) { return (useFlags_ & flags) == flags; } // Return true if ALL flags are true.
|
bool UseAll(u32 flags) const { return (useFlags_ & flags) == flags; } // Return true if ALL flags are true.
|
||||||
|
|
||||||
|
u32 UseFlags() const { return useFlags_; }
|
||||||
|
|
||||||
uint64_t GetDirtyUniforms() { return dirty & DIRTY_ALL_UNIFORMS; }
|
uint64_t GetDirtyUniforms() { return dirty & DIRTY_ALL_UNIFORMS; }
|
||||||
void Dirty(u64 what) {
|
void Dirty(u64 what) {
|
||||||
|
@ -839,9 +839,9 @@ void CGEDebugger::DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y,
|
|||||||
|
|
||||||
case GPU_DBG_FORMAT_24BIT_8X:
|
case GPU_DBG_FORMAT_24BIT_8X:
|
||||||
{
|
{
|
||||||
DepthScaleFactors depthScale = GetDepthScaleFactors();
|
DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags());
|
||||||
// These are only ever going to be depth values, so let's also show scaled to 16 bit.
|
// These are only ever going to be depth values, so let's also show scaled to 16 bit.
|
||||||
snprintf(desc, 256, "%d,%d: %d / %f / %f", x, y, pix & 0x00FFFFFF, (pix & 0x00FFFFFF) * (1.0f / 16777215.0f), depthScale.Apply((pix & 0x00FFFFFF) * (1.0f / 16777215.0f)));
|
snprintf(desc, 256, "%d,%d: %d / %f / %f", x, y, pix & 0x00FFFFFF, (pix & 0x00FFFFFF) * (1.0f / 16777215.0f), depthScale.DecodeToU16((pix & 0x00FFFFFF) * (1.0f / 16777215.0f)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -860,8 +860,8 @@ void CGEDebugger::DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y,
|
|||||||
|
|
||||||
case GPU_DBG_FORMAT_FLOAT: {
|
case GPU_DBG_FORMAT_FLOAT: {
|
||||||
float pixf = *(float *)&pix;
|
float pixf = *(float *)&pix;
|
||||||
DepthScaleFactors depthScale = GetDepthScaleFactors();
|
DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags());
|
||||||
snprintf(desc, 256, "%d,%d: %f / %f", x, y, pixf, depthScale.Apply(pixf));
|
snprintf(desc, 256, "%d,%d: %f / %f", x, y, pixf, depthScale.DecodeToU16(pixf));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -870,11 +870,11 @@ void CGEDebugger::DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y,
|
|||||||
double z = *(float *)&pix;
|
double z = *(float *)&pix;
|
||||||
int z24 = (int)(z * 16777215.0);
|
int z24 = (int)(z * 16777215.0);
|
||||||
|
|
||||||
DepthScaleFactors factors = GetDepthScaleFactors();
|
DepthScaleFactors factors = GetDepthScaleFactors(gstate_c.UseFlags());
|
||||||
// TODO: Use GetDepthScaleFactors here too, verify it's the same.
|
// TODO: Use GetDepthScaleFactors here too, verify it's the same.
|
||||||
int z16 = z24 - 0x800000 + 0x8000;
|
int z16 = z24 - 0x800000 + 0x8000;
|
||||||
|
|
||||||
int z16_2 = factors.Apply(z);
|
int z16_2 = factors.DecodeToU16(z);
|
||||||
|
|
||||||
snprintf(desc, 256, "%d,%d: %d / %f", x, y, z16, (z - 0.5 + (1.0 / 512.0)) * 256.0);
|
snprintf(desc, 256, "%d,%d: %d / %f", x, y, z16, (z - 0.5 + (1.0 / 512.0)) * 256.0);
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 7bd1ec93d4586985ba1ef420b43b5e620f68695e
|
Subproject commit 6719edebaae03330ee5441d9b28280672edf00d5
|
@ -61,6 +61,7 @@
|
|||||||
#include "Core/MemMap.h"
|
#include "Core/MemMap.h"
|
||||||
#include "Core/MIPS/MIPSVFPUUtils.h"
|
#include "Core/MIPS/MIPSVFPUUtils.h"
|
||||||
#include "GPU/Common/TextureDecoder.h"
|
#include "GPU/Common/TextureDecoder.h"
|
||||||
|
#include "GPU/Common/GPUStateUtils.h"
|
||||||
|
|
||||||
#include "android/jni/AndroidContentURI.h"
|
#include "android/jni/AndroidContentURI.h"
|
||||||
|
|
||||||
@ -795,6 +796,44 @@ static bool TestSmallDataConvert() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool TestDepthMath() {
|
||||||
|
// Flag combinations that can happen:
|
||||||
|
// 0
|
||||||
|
// GPU_USE_ACCURATE_DEPTH
|
||||||
|
// GPU_USE_ACCURATE_DEPTH | GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT
|
||||||
|
// What about GPU_USE_DEPTH_CLAMP? It basically overrides GPU_USE_ACCURATE_DEPTH?
|
||||||
|
|
||||||
|
// These are in normalized space.
|
||||||
|
static const float testValues[] = { 0.0f * 65535.0f, 0.1f * 65535.0f, 0.9f * 65535.0f, 1.0f * 65535.0f };
|
||||||
|
|
||||||
|
static const u32 useFlagsArray[] = {
|
||||||
|
0,
|
||||||
|
GPU_USE_ACCURATE_DEPTH,
|
||||||
|
GPU_USE_ACCURATE_DEPTH | GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT,
|
||||||
|
};
|
||||||
|
static const float expectedScale[] = { 65535.0f, 262140.0f, -1.0f };
|
||||||
|
static const float expectedOffset[] = { 0.0f, 0.375f, -2.0f };
|
||||||
|
|
||||||
|
for (int j = 0; j < ARRAY_SIZE(useFlagsArray); j++) {
|
||||||
|
u32 useFlags = useFlagsArray[j];
|
||||||
|
printf("j: %d useflags: %d\n", j, useFlags);
|
||||||
|
DepthScaleFactors factors = GetDepthScaleFactors(useFlags);
|
||||||
|
|
||||||
|
EXPECT_EQ_FLOAT(factors.ScaleU16(), expectedScale[j]);
|
||||||
|
EXPECT_EQ_FLOAT(factors.Offset(), expectedOffset[j]);
|
||||||
|
EXPECT_EQ_FLOAT(factors.ScaleU16(), DepthSliceFactor(useFlags) * 65535.0f);
|
||||||
|
|
||||||
|
for (int i = 0; i < ARRAY_SIZE(testValues); i++) {
|
||||||
|
float encoded = factors.EncodeFromU16(testValues[i]);
|
||||||
|
float decodedU16 = factors.DecodeToU16(encoded);
|
||||||
|
EXPECT_EQ_FLOAT(decodedU16, testValues[i]);
|
||||||
|
EXPECT_EQ_FLOAT(encoded, ToScaledDepthFromIntegerScale(useFlags, testValues[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
typedef bool (*TestFunc)();
|
typedef bool (*TestFunc)();
|
||||||
struct TestItem {
|
struct TestItem {
|
||||||
const char *name;
|
const char *name;
|
||||||
@ -846,6 +885,7 @@ TestItem availableTests[] = {
|
|||||||
TEST_ITEM(WrapText),
|
TEST_ITEM(WrapText),
|
||||||
TEST_ITEM(TinySet),
|
TEST_ITEM(TinySet),
|
||||||
TEST_ITEM(SmallDataConvert),
|
TEST_ITEM(SmallDataConvert),
|
||||||
|
TEST_ITEM(DepthMath),
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, const char *argv[]) {
|
int main(int argc, const char *argv[]) {
|
||||||
|
Loading…
Reference in New Issue
Block a user