diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 5ef7d3fc98..01b3ed14bd 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -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(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(bottom_coord) + .5f) * rcp_efb_height; + uniforms.clamp_bottom = (uniforms.src_top + uniforms.src_height); + uniforms.clamp_bottom -= (static_cast(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 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(g_framebuffer_manager->GetEFBWidth()); const u32 efb_height = g_framebuffer_manager->GetEFBHeight(); const float rcp_efb_height = 1.0f / static_cast(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(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(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(bottom_coord) + .5f) * rcp_efb_height; + encoder_params.clamp_bottom = (encoder_params.src_top + encoder_params.src_height); + encoder_params.clamp_bottom -= (static_cast(bottom_coord) + .5f) * rcp_efb_height; encoder_params.filter_coefficients = filter_coefficients; g_vertex_manager->UploadUtilityUniforms(&encoder_params, sizeof(encoder_params)); diff --git a/Source/Core/VideoCommon/TextureConversionShader.cpp b/Source/Core/VideoCommon/TextureConversionShader.cpp index 6962daa29b..1cebfa68a5 100644 --- a/Source/Core/VideoCommon/TextureConversionShader.cpp +++ b/Source/Core/VideoCommon/TextureConversionShader.cpp @@ -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? diff --git a/Source/Core/VideoCommon/TextureConverterShaderGen.cpp b/Source/Core/VideoCommon/TextureConverterShaderGen.cpp index da2e247a7f..73ca7ff35d 100644 --- a/Source/Core/VideoCommon/TextureConverterShaderGen.cpp +++ b/Source/Core/VideoCommon/TextureConverterShaderGen.cpp @@ -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)