Improve documentation.

This commit is contained in:
Jules Blok 2016-08-15 15:25:50 +02:00
parent 8c1c7fc2da
commit 7078216b61
7 changed files with 44 additions and 26 deletions

View File

@ -578,7 +578,10 @@ void Renderer::SetViewport()
Wd = (X + Wd <= GetTargetWidth()) ? Wd : (GetTargetWidth() - X);
Ht = (Y + Ht <= GetTargetHeight()) ? Ht : (GetTargetHeight() - Y);
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(X, Y, Wd, Ht, D3D11_MIN_DEPTH, 16777215.0f / 16777216.0f);
// We do depth clipping and depth range in the vertex shader instead of relying
// on the graphics API. However we still need to ensure depth values don't exceed
// the maximum value supported by the console GPU.
D3D11_VIEWPORT vp = CD3D11_VIEWPORT(X, Y, Wd, Ht, D3D11_MIN_DEPTH, GX_MAX_DEPTH);
D3D::context->RSSetViewports(1, &vp);
}

View File

@ -482,8 +482,10 @@ void Renderer::SetViewport()
width = (x + width <= GetTargetWidth()) ? width : (GetTargetWidth() - x);
height = (y + height <= GetTargetHeight()) ? height : (GetTargetHeight() - y);
D3D12_VIEWPORT vp = {x, y, width, height, D3D12_MIN_DEPTH, 16777215.0f / 16777216.0f};
// We do depth clipping and depth range in the vertex shader instead of relying
// on the graphics API. However we still need to ensure depth values don't exceed
// the maximum value supported by the console GPU.
D3D12_VIEWPORT vp = {x, y, width, height, D3D12_MIN_DEPTH, GX_MAX_DEPTH};
D3D::current_command_list->RSSetViewports(1, &vp);
}

View File

@ -1159,8 +1159,12 @@ void Renderer::SetViewport()
glViewport(iceilf(X), iceilf(Y), iceilf(Width), iceilf(Height));
}
// Set the reversed depth range. If we do depth clipping and depth range in the
// vertex shader we only need to ensure depth values don't exceed the maximum
// value supported by the console GPU. If not, we simply clamp the near/far values
// themselves to the maximum value as done above.
if (g_ActiveConfig.backend_info.bSupportsDepthClamp)
glDepthRangef(16777215.0f / 16777216.0f, 0.0f);
glDepthRangef(GX_MAX_DEPTH, 0.0f);
else
glDepthRangef(GLFar, GLNear);
}

View File

@ -86,6 +86,12 @@ unsigned int Renderer::efb_scale_numeratorY = 1;
unsigned int Renderer::efb_scale_denominatorX = 1;
unsigned int Renderer::efb_scale_denominatorY = 1;
// The maximum depth that is written to the depth buffer should never exceed this value.
// This is necessary because we use a 2^24 divisor for all our depth values to prevent
// floating-point round-trip errors. However the console GPU doesn't ever write a value
// to the depth buffer that exceeds 2^24 - 1.
const float Renderer::GX_MAX_DEPTH = 16777215.0f / 16777216.0f;
static float AspectToWidescreen(float aspect)
{
return aspect * ((16.0f / 9.0f) / (4.0f / 3.0f));

View File

@ -176,6 +176,8 @@ protected:
static std::unique_ptr<PostProcessingShaderImplementation> m_post_processor;
static const float GX_MAX_DEPTH;
private:
static PEControl::PixelFormat prev_efb_format;
static unsigned int efb_scale_numeratorX;

View File

@ -399,43 +399,43 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da
out.Write("o.colors_1 = color1;\n");
}
// Write the true depth value. If the game uses depth textures, then the pixel shader will
// override it with the correct values if not then early z culling will improve speed.
if (g_ActiveConfig.backend_info.bSupportsDepthClamp)
{
// If we can disable the incorrect depth clipping planes using depth clamping, then we can do
// our own depth clipping and calculate the depth range before the perspective divide.
// Since we're adjusting z for the depth range before the perspective divide, we have to do our
// own clipping. We want to clip so that -w <= z <= 0.
// own clipping. We want to clip so that -w <= z <= 0, which matches the console -1..0 range.
out.Write("o.clipDist0 = o.pos.z + o.pos.w;\n"); // Near: z < -w
out.Write("o.clipDist1 = -o.pos.z;\n"); // Far: z > 0
// We have to handle the depth range in the vertex shader, because some games will use a depth
// range beyond the normal depth range of 0..1.
// Adjust z for the depth range. We're using an equation which incorperates a depth inversion,
// so we can map the console -1..0 range to the 0..1 range used in the depth buffer.
// We have to handle the depth range in the vertex shader instead of after the perspective
// divide, because some games will use a depth range larger than what is allowed by the
// graphics API. These large depth ranges will still be clipped to the 0..1 range, so these
// games effectively add a depth bias to the values written to the depth buffer.
out.Write("o.pos.z = o.pos.w * " I_PIXELCENTERCORRECTION ".w - "
"o.pos.z * " I_PIXELCENTERCORRECTION ".z;\n");
}
else
{
// User-defined clipping is not supported, thus we rely on the API to handle the depth range.
// We still need to take care of the reversed depth, so we do that here.
// If we can't disable the incorrect depth clipping planes, then we need to rely on the
// graphics API to handle the depth range after the perspective divide. This can result in
// inaccurate depth values due to the missing depth bias, but that can be least corrected by
// overriding depth values in the pixel shader. We still need to take care of the reversed depth
// though, so we do that here.
out.Write("o.pos.z = -o.pos.z;\n");
}
// write the true depth value, if the game uses depth textures pixel shaders will override with
// the correct values
// if not early z culling will improve speed
if (!g_ActiveConfig.backend_info.bSupportsClipControl)
{
// this results in a scale from -1..0 to -1..1 after perspective
// divide
// If the graphics API doesn't support a depth range of 0..1, then we need to map z to
// the -1..1 range. Unfortunately we have to use a substraction, which is a lossy floating-point
// operation that can introduce a round-trip error.
out.Write("o.pos.z = o.pos.z * 2.0 - o.pos.w;\n");
// the next steps of the OGL pipeline are:
// (x_c,y_c,z_c,w_c) = o.pos //switch to OGL spec terminology
// clipping to -w_c <= (x_c,y_c,z_c) <= w_c
// (x_d,y_d,z_d) = (x_c,y_c,z_c)/w_c//perspective divide
// z_w = (f-n)/2*z_d + (n+f)/2
// z_w now contains the value to go to the 0..1 depth buffer
// trying to get the correct semantic while not using glDepthRange
// seems to get rather complicated
}
// The console GPU places the pixel center at 7/12 in screen space unless

View File

@ -389,8 +389,9 @@ void VertexShaderManager::SetConstants()
// The depth range is handled in the vertex shader. We need to reverse
// the far value to get a reversed depth range mapping. This is necessary
// because we have the most precision at the near plane, while the console
// has the most percision at the far plane.
// because the standard depth range equation pushes all depth values towards
// the back of the depth buffer where conventionally depth buffers have the
// least precision.
constants.pixelcentercorrection[2] = xfmem.viewport.zRange / 16777215.0f;
constants.pixelcentercorrection[3] = 1.0f - xfmem.viewport.farZ / 16777215.0f;