Files
psxrecomp/runtime/shaders/present.frag
Martin Penkava 7ad8519128 vulkan: present through an opaque shader pass instead of a blit
The plain present path copied the VRAM image into the swapchain with
vkCmdBlitImage, alpha included. VRAM alpha is the PSX mask/STP bit, 0 on
most pixels, and AMD's compositor honours it even with an OPAQUE
compositeAlpha: parts of the window went see-through (8x8 black/white
blocks of whatever sat behind it). Reported in #411.

vk_renderer_present_vram/_wide now draw the displayed rect with a
fullscreen triangle whose fragment shader writes alpha = 1 (new
present.vert/.frag). The pass is self-contained and created lazily; if
any of it fails to build, presents fall back to the old blit. Its render
pass ends in TRANSFER_DST_OPTIMAL so finish_present (OSD + present
barrier) is unchanged. Wide surfaces gain SAMPLED usage for it.

Checked on an RX 7900 XT: intro/logo screens render correctly, no new
validation-layer messages.

Most of this was written by Claude Opus 5.5; I reviewed and tested it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 13:41:03 +02:00

15 lines
677 B
GLSL

#version 450
/* Swapchain present: sample the displayed VRAM rect and write it OPAQUE.
* VRAM alpha carries the PSX mask/STP bit (0 on most pixels); copying it into
* the swapchain with a transfer blit let AMD's compositor treat the window as
* partly transparent (desktop showing through as black/white blocks). */
layout(location = 0) in vec2 v_uv;
layout(location = 0) out vec4 o_col;
layout(set = 0, binding = 0) uniform sampler2D u_src;
layout(push_constant) uniform PC {
vec4 u_src_rect; /* displayed region in normalized src coords: x0,y0,x1,y1 */
} pc;
void main() {
o_col = vec4(texture(u_src, mix(pc.u_src_rect.xy, pc.u_src_rect.zw, v_uv)).rgb, 1.0);
}