From 149915c15c93493a8c8de1c4fca2ae201c323f84 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 1 Jul 2026 08:56:29 +0530 Subject: [PATCH] Use gather for texture sampling --- kitty/shaders/screenshot.slang | 34 +++++++++++++++++++++++++++------- kitty/shaders/slang.py | 3 ++- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/kitty/shaders/screenshot.slang b/kitty/shaders/screenshot.slang index 34c9985da..340b24c1e 100644 --- a/kitty/shaders/screenshot.slang +++ b/kitty/shaders/screenshot.slang @@ -33,15 +33,35 @@ float3 safe_unpremult_to_linear(float4 s) { } [shader("fragment")] -float4 fragment_main(float2 tc : TEXCOORD, uniform float2 src_size) : SV_Target { - // Calculate the texel size +float4 fragment_main(float2 texcoord : TEXCOORD, uniform float2 src_size) : SV_Target { + float4 s00, s10, s01, s11; float2 texel_size = 1.0 / src_size; - // Sample a 2x2 grid for better quality downscaling - float4 s00 = image.Sample(tc + float2(-0.25, -0.25) * texel_size); - float4 s10 = image.Sample(tc + float2( 0.25, -0.25) * texel_size); - float4 s01 = image.Sample(tc + float2(-0.25, 0.25) * texel_size); - float4 s11 = image.Sample(tc + float2( 0.25, 0.25) * texel_size); + // Use Slang target switches to dynamically compile for specific backend features + __target_switch + { + // Modern backends with full texture gathering capabilities + case spirv: case hlsl: case metal: { + float2 gather_coord = texcoord - (0.5 * texel_size); + + float4 r_gather = image.GatherRed(gather_coord); + float4 g_gather = image.GatherGreen(gather_coord); + float4 b_gather = image.GatherBlue(gather_coord); + float4 a_gather = image.GatherAlpha(gather_coord); + + s00 = float4(r_gather.w, g_gather.w, b_gather.w, a_gather.w); // Bottom-Left + s10 = float4(r_gather.z, g_gather.z, b_gather.z, a_gather.z); // Bottom-Right + s01 = float4(r_gather.x, g_gather.x, b_gather.x, a_gather.x); // Top-Left + s11 = float4(r_gather.y, g_gather.y, b_gather.y, a_gather.y); // Top-Right + } + // Fallback for older targets or legacy GLSL versions + default: { + s00 = image.Sample(texcoord + float2(-0.25, -0.25) * texel_size); + s10 = image.Sample(texcoord + float2( 0.25, -0.25) * texel_size); + s01 = image.Sample(texcoord + float2(-0.25, 0.25) * texel_size); + s11 = image.Sample(texcoord + float2( 0.25, 0.25) * texel_size); + } + } // Unpremultiply and convert to linear for each sample float3 linear00 = safe_unpremult_to_linear(s00); diff --git a/kitty/shaders/slang.py b/kitty/shaders/slang.py index 13e5c6de3..6463612b0 100644 --- a/kitty/shaders/slang.py +++ b/kitty/shaders/slang.py @@ -268,7 +268,8 @@ def iter_entry_point_shaders(sources: dict[str, SlangFile], build_dir: str, dest def commands_to_compile_to_spirv(sources: dict[str, SlangFile], build_dir: str, dest_dir: str, built_files: list[str]) -> Iterator[Command]: - base_cmd = ['-target', 'spirv', '-capability', 'vk_mem_model', '-fvk-use-entrypoint-name'] + # glsl 450 is vulkan 1.1 and spirv 1.3 released 2008 + base_cmd = ['-target', 'spirv', '-profile', 'glsl_450', '-capability', 'vk_mem_model', '-fvk-use-entrypoint-name'] for base_dest, slang_module, scmd, sfile in iter_entry_point_shaders(sources, build_dir, dest_dir): for x in sfile.specializations: cmd = list(scmd)