From 851e96f83ab5d23a0b33d73fbb957b3d54eb6886 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 8 Mar 2025 22:09:04 +0100 Subject: [PATCH] [dxvk] Improve swapchain scaling --- src/dxvk/shaders/dxvk_present_frag_blit.frag | 24 +++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/dxvk/shaders/dxvk_present_frag_blit.frag b/src/dxvk/shaders/dxvk_present_frag_blit.frag index 4ebd5c8b3..ac07d05e6 100644 --- a/src/dxvk/shaders/dxvk_present_frag_blit.frag +++ b/src/dxvk/shaders/dxvk_present_frag_blit.frag @@ -9,7 +9,29 @@ layout(location = 0) out vec4 o_color; void main() { vec2 coord = vec2(src_offset) + vec2(src_extent) * i_coord; - o_color = input_to_sc_rgb(textureLod(s_image, coord, 0.0f)); + vec2 delta = vec2(dFdx(coord.x), dFdy(coord.y)); + + ivec2 i_coord = ivec2(coord); + vec2 f_coord = fract(coord); + + if (all(lessThan(delta, vec2(1.0f)))) { + // Map pixel rectangle to source image. If it is entirely contained within one + // source pixel, just sample that pixel, otherwise do a linear interpolation. + // For even scaling factors, this is essentially integer scaling. + vec2 lo = max(coord - 0.5f * delta, vec2(src_offset)); + vec2 hi = min(coord + 0.5f * delta, vec2(src_offset + src_extent - 1)); + + i_coord = ivec2(lo); + f_coord = mix((hi - floor(hi)) / delta, vec2(0.0), equal(floor(lo), floor(hi))); + } + + // Manually interpolate in the correct color space + o_color = mix(mix(input_to_sc_rgb(texelFetch(s_image, i_coord + ivec2(0, 0), 0)), + input_to_sc_rgb(texelFetch(s_image, i_coord + ivec2(1, 0), 0)), f_coord.x), + mix(input_to_sc_rgb(texelFetch(s_image, i_coord + ivec2(0, 1), 0)), + input_to_sc_rgb(texelFetch(s_image, i_coord + ivec2(1, 1), 0)), f_coord.x), + f_coord.y); + o_color = composite_image(o_color); o_color = sc_rgb_to_output(o_color); }