mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-28 10:59:16 -04:00
0ac63b655c
Vulkan backend alongside software + OpenGL: geometry/textured-prim pipelines, GPU-authoritative VRAM image, deferred-submit + drain-at-present perf model, GPU-direct present (vk_renderer_present_vram), and a full-VRAM-pack readback path (ensure_cpu rect_adds the whole VRAM rect before pack_flush so screenshots/guest VRAM reads reflect live content, not just the incremental pack-dirty rect — readback-only, no per-frame cost). Runtime plumbing: --debug-port / --renderer / --window-title CLI overrides (multi-instance fleet), latency_ring, SPIR-V shaders + embed_spirv.py, config_loader renderer selection, debug_server screenshot wiring. All on feat/vulkan-renderer; snapshot in backup/vulkan-wip-20260617. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
89 lines
4.0 KiB
GLSL
89 lines
4.0 KiB
GLSL
#version 450
|
|
/* Textured fragment: sample raw 1555 VRAM (integer), CLUT-decode per depth,
|
|
* texture window, optional bilinear, texel-0 cutout discard, STP-split discard,
|
|
* PS1 *2-around-0x80 colour modulation. Output alpha = bit15 of the written
|
|
* pixel. Ported verbatim from the GL backend's TEX_FS (usampler2D u_vram = the
|
|
* native R16_UINT raw VRAM mirror). */
|
|
layout(location = 0) noperspective in vec2 v_uv;
|
|
layout(location = 1) noperspective in vec4 v_col;
|
|
layout(location = 2) flat in ivec2 v_tpage; /* texture page base, VRAM px */
|
|
layout(location = 3) flat in ivec2 v_clut; /* CLUT base, VRAM px */
|
|
layout(location = 4) flat in int v_depth; /* 0=4bit 1=8bit 2=15bit */
|
|
layout(location = 5) flat in int v_raw; /* 1 = no colour modulation */
|
|
layout(location = 6) flat in ivec4 v_limits; /* prim uv bounds (inclusive) */
|
|
|
|
layout(set = 0, binding = 0) uniform usampler2D u_vram;
|
|
|
|
layout(push_constant) uniform PC {
|
|
float u_shift;
|
|
float u_xoff;
|
|
float u_xhalf;
|
|
int u_semipass; /* 0=all texels, 1=STP=0 only, 2=STP=1 only */
|
|
int u_maskset; /* GP0(E6h) set-mask: OR bit15 into output */
|
|
int u_filter; /* 1 = bilinear */
|
|
ivec4 u_twin; /* texture window: mask_x, mask_y, off_x, off_y */
|
|
} pc;
|
|
|
|
layout(location = 0) out vec4 frag;
|
|
|
|
int vram_at(int x, int y) {
|
|
return int(texelFetch(u_vram, ivec2(x & 1023, y & 511), 0).r);
|
|
}
|
|
int fetch_texel(int u, int v) {
|
|
u &= 255; v &= 255;
|
|
if ((pc.u_twin.x | pc.u_twin.y) != 0) {
|
|
u = (u & ~(pc.u_twin.x * 8)) | ((pc.u_twin.z & pc.u_twin.x) * 8);
|
|
v = (v & ~(pc.u_twin.y * 8)) | ((pc.u_twin.w & pc.u_twin.y) * 8);
|
|
} else {
|
|
u = clamp(u, v_limits.x, v_limits.z);
|
|
v = clamp(v, v_limits.y, v_limits.w);
|
|
}
|
|
if (v_depth == 0) {
|
|
int px = vram_at(v_tpage.x + (u >> 2), v_tpage.y + v);
|
|
return vram_at(v_clut.x + ((px >> ((u & 3) * 4)) & 0xF), v_clut.y);
|
|
} else if (v_depth == 1) {
|
|
int px = vram_at(v_tpage.x + (u >> 1), v_tpage.y + v);
|
|
return vram_at(v_clut.x + ((px >> ((u & 1) * 8)) & 0xFF), v_clut.y);
|
|
}
|
|
return vram_at(v_tpage.x + u, v_tpage.y + v);
|
|
}
|
|
vec3 col5(int raw) {
|
|
return vec3(float(raw & 31), float((raw >> 5) & 31), float((raw >> 10) & 31)) / 31.0;
|
|
}
|
|
void main() {
|
|
int stp; vec3 rgb;
|
|
if (pc.u_filter == 0) {
|
|
int raw = fetch_texel(int(floor(v_uv.x)), int(floor(v_uv.y)));
|
|
if (raw == 0) discard;
|
|
rgb = col5(raw);
|
|
stp = (raw >> 15) & 1;
|
|
} else {
|
|
/* Bilinear, Beetle-PSX formulation: the NEAREST texel is the base
|
|
* (cutout + STP authority), the neighbours lie toward the sub-texel
|
|
* offset and clamp to v_limits, and each texel's weight is gated by its
|
|
* opacity with the colour renormalised. */
|
|
int iu = int(floor(v_uv.x)), iv = int(floor(v_uv.y));
|
|
float fx = v_uv.x - float(iu) - 0.5, fy = v_uv.y - float(iv) - 0.5;
|
|
int sx = fx < 0.0 ? -1 : 1, sy = fy < 0.0 ? -1 : 1;
|
|
fx = abs(fx); fy = abs(fy);
|
|
int c00 = fetch_texel(iu, iv);
|
|
int c10 = fetch_texel(iu + sx, iv);
|
|
int c01 = fetch_texel(iu, iv + sy);
|
|
int c11 = fetch_texel(iu + sx, iv + sy);
|
|
float w00 = (c00 == 0 ? 0.0 : 1.0) * (1.0 - fx) * (1.0 - fy);
|
|
float w10 = (c10 == 0 ? 0.0 : 1.0) * fx * (1.0 - fy);
|
|
float w01 = (c01 == 0 ? 0.0 : 1.0) * (1.0 - fx) * fy;
|
|
float w11 = (c11 == 0 ? 0.0 : 1.0) * fx * fy;
|
|
float opac = w00 + w10 + w01 + w11;
|
|
if (opac < 0.5) discard;
|
|
rgb = (col5(c00) * w00 + col5(c10) * w10 + col5(c01) * w01 + col5(c11) * w11) / opac;
|
|
float stpf = (float((c00 >> 15) & 1) * w00 + float((c10 >> 15) & 1) * w10
|
|
+ float((c01 >> 15) & 1) * w01 + float((c11 >> 15) & 1) * w11) / opac;
|
|
stp = stpf >= 0.5 ? 1 : 0;
|
|
}
|
|
if (pc.u_semipass == 1 && stp == 1) discard;
|
|
if (pc.u_semipass == 2 && stp == 0) discard;
|
|
if (v_raw == 0) rgb = clamp(rgb * v_col.rgb * 2.0, 0.0, 1.0);
|
|
frag = vec4(rgb, (stp == 1 || pc.u_maskset == 1) ? 1.0 : 0.0);
|
|
}
|