Reverse Clamping in OpenGL + Make Relative

This reverses the clamping since it is an issue in OpenGL where the clamping for the top was clamping the bottom and vice versa.

clamp_tb (ie clamp_top and clamp_bottom) now store the clamping amount relative to the top and bottom rather than absolute values.
This commit is contained in:
Patrick Ferry 2024-08-11 15:02:30 +01:00
parent 6cc2133f27
commit 77a1b5c865
3 changed files with 38 additions and 11 deletions

View File

@ -2925,8 +2925,10 @@ void TextureCacheBase::CopyEFBToCacheEntry(RcTcacheEntry& entry, bool is_depth_c
// Statistically, that could happen.
const u32 top_coord = clamp_top ? framebuffer_rect.top : 0;
uniforms.clamp_top = (static_cast<float>(top_coord) + .5f) * rcp_efb_height;
uniforms.clamp_top -= uniforms.src_top;
const u32 bottom_coord = (clamp_bottom ? framebuffer_rect.bottom : efb_height) - 1;
uniforms.clamp_bottom = (static_cast<float>(bottom_coord) + .5f) * rcp_efb_height;
uniforms.clamp_bottom = (uniforms.src_top + uniforms.src_height);
uniforms.clamp_bottom -= (static_cast<float>(bottom_coord) + .5f) * rcp_efb_height;
uniforms.pixel_height = g_ActiveConfig.bCopyEFBScaled ? rcp_efb_height : 1.0f / EFB_HEIGHT;
uniforms.padding = 0;
g_vertex_manager->UploadUtilityUniforms(&uniforms, sizeof(uniforms));
@ -2974,6 +2976,7 @@ void TextureCacheBase::CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams&
// Fill uniform buffer.
struct Uniforms
{
float src_left, src_top, src_width, src_height;
std::array<s32, 4> position_uniform;
float y_scale;
float gamma_rcp;
@ -2983,8 +2986,13 @@ void TextureCacheBase::CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams&
u32 padding;
};
Uniforms encoder_params;
const float rcp_efb_width = 1.0f / static_cast<float>(g_framebuffer_manager->GetEFBWidth());
const u32 efb_height = g_framebuffer_manager->GetEFBHeight();
const float rcp_efb_height = 1.0f / static_cast<float>(efb_height);
encoder_params.src_left = framebuffer_rect.left * rcp_efb_width;
encoder_params.src_top = framebuffer_rect.top * rcp_efb_height;
encoder_params.src_width = framebuffer_rect.GetWidth() * rcp_efb_width;
encoder_params.src_height = framebuffer_rect.GetHeight() * rcp_efb_height;
encoder_params.position_uniform[0] = src_rect.left;
encoder_params.position_uniform[1] = src_rect.top;
encoder_params.position_uniform[2] = static_cast<s32>(native_width);
@ -2998,8 +3006,10 @@ void TextureCacheBase::CopyEFB(AbstractStagingTexture* dst, const EFBCopyParams&
// Statistically, that could happen.
const u32 top_coord = clamp_top ? framebuffer_rect.top : 0;
encoder_params.clamp_top = (static_cast<float>(top_coord) + .5f) * rcp_efb_height;
encoder_params.clamp_top -= encoder_params.src_top;
const u32 bottom_coord = (clamp_bottom ? framebuffer_rect.bottom : efb_height) - 1;
encoder_params.clamp_bottom = (static_cast<float>(bottom_coord) + .5f) * rcp_efb_height;
encoder_params.clamp_bottom = (encoder_params.src_top + encoder_params.src_height);
encoder_params.clamp_bottom -= (static_cast<float>(bottom_coord) + .5f) * rcp_efb_height;
encoder_params.filter_coefficients = filter_coefficients;
g_vertex_manager->UploadUtilityUniforms(&encoder_params, sizeof(encoder_params));

View File

@ -56,6 +56,7 @@ static void WriteHeader(ShaderCode& code, APIType api_type)
// left, top, of source rectangle within source texture
// width of the destination rectangle, scale_factor (1 or 2)
code.Write("UBO_BINDING(std140, 1) uniform PSBlock {{\n"
" float2 src_offset, src_size;\n"
" int4 position;\n"
" float y_scale;\n"
" float gamma_rcp;\n"
@ -102,16 +103,20 @@ static void WriteHeader(ShaderCode& code, APIType api_type)
static void WriteSampleFunction(ShaderCode& code, const EFBCopyParams& params, APIType api_type)
{
code.Write("uint4 SampleEFB0(float2 uv, float2 pixel_size, float x_offset, float y_offset) {{\n"
" float4 tex_sample = texture(samp0, float3(uv.x + x_offset * pixel_size.x, ");
" float clamp_top = src_offset.y + clamp_tb.x;\n"
" float clamp_bottom = (src_offset.y + src_size.y) - clamp_tb.y;\n");
// Reverse the direction for OpenGL, since positive numbers are distance from the bottom row.
// TODO: This isn't done on TextureConverterShaderGen - maybe it handles that via pixel_size?
// Reverse the direction for OpenGL
if (api_type == APIType::OpenGL)
code.Write("clamp(uv.y - y_offset * pixel_size.y, clamp_tb.x, clamp_tb.y)");
else
code.Write("clamp(uv.y + y_offset * pixel_size.y, clamp_tb.x, clamp_tb.y)");
{
code.Write(" clamp_top = src_offset.y + clamp_tb.y;\n"
" clamp_bottom = (src_offset.y + src_size.y) - clamp_tb.x;\n"
" y_offset = -y_offset;\n");
}
code.Write(", 0.0));\n");
code.Write(" float clamp_y = clamp(uv.y + (y_offset * pixel_size.y), clamp_top, clamp_bottom);\n"
" float4 tex_sample = texture(samp0, float3(uv.x + (x_offset * pixel_size.x)"
", clamp_y, 0.0));\n");
// TODO: Is this really needed? Doesn't the EFB only store appropriate values? Or is this for
// EFB2Ram having consistent output with force 32-bit color?

View File

@ -105,9 +105,21 @@ ShaderCode GeneratePixelShader(APIType api_type, const UidData* uid_data)
out.Write("SAMPLER_BINDING(0) uniform sampler2DArray samp0;\n");
out.Write("uint4 SampleEFB(float3 uv, float y_offset) {{\n"
" float4 tex_sample = texture(samp0, float3(uv.x, clamp(uv.y + (y_offset * "
"pixel_height), clamp_tb.x, clamp_tb.y), {}));\n",
" float clamp_top = src_offset.y + clamp_tb.x;\n"
" float clamp_bottom = (src_offset.y + src_size.y) - clamp_tb.y;\n");
// Reverse the direction for OpenGL
if (api_type == APIType::OpenGL)
{
out.Write(" clamp_top = src_offset.y + clamp_tb.y;\n"
" clamp_bottom = (src_offset.y + src_size.y) - clamp_tb.x;\n"
" y_offset = -y_offset;\n");
}
out.Write(" float clamp_y = clamp(uv.y + (y_offset * pixel_height), clamp_top, clamp_bottom);\n"
" float4 tex_sample = texture(samp0, float3(uv.x, clamp_y, {}));\n",
mono_depth ? "0.0" : "uv.z");
if (uid_data->is_depth_copy)
{
if (!g_ActiveConfig.backend_info.bSupportsReversedDepthRange)