fix(shaders): varyings meet by name on Vulkan, so the meadow's flowers draw

OpenGL links a vertex output to a fragment input by name; SPIR-V links them by location, and
glslang's --auto-map-locations numbered each stage in its own declaration order. The foliage
prepass's depth.frag declares v_wpos then v_uv where model.vert writes v_wpos, v_nrm, v_uv, so
the prepass read a normal as its texture coordinate, its alpha test cut every flower head and
leaf, and the lit pass (depth EQUAL) drew nothing over them. `ludic-dev shaders` now gives both
stages explicit locations: the vertex stage's out order numbers them and the fragment stage looks
each in up by name. All 45 variants checked: every fragment input sits on its vertex output.

Also:
- A clear still waiting for its pass when the framebuffer changes now runs on that framebuffer,
  instead of becoming the load op of whichever pass began next.
- R3D_DUMP_ATLAS writes every impostor and card atlas a run bakes (build/atlas_<n>_*.ppm); the
  40 baked on Vulkan match OpenGL's.

The PC's Vulkan frame now shows the flowers as OpenGL does, validation-clean. ludic-dev test 140
passed; OpenGL frames byte-identical at the five viewpoints; 59 self-tests pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-15 12:50:54 +03:00
parent a674c9b372
commit 66940f9c0a
8 changed files with 81 additions and 4 deletions

View file

@ -960,6 +960,14 @@ function gvk_clear_color(r: int, g: int, b: int, a: int) -> void {
gvk_clear_rgba[0] = r; gvk_clear_rgba[1] = g; gvk_clear_rgba[2] = b; gvk_clear_rgba[3] = a
}
function gvk_fb_colors(fb: int, n: int) -> void { if gvk_fb_ncolor != null and fb >= 0 and fb < 4096 { gvk_fb_ncolor[fb] = n } }
# The framebuffer changes: a clear still waiting for this one's pass runs now, on this target,
# rather than becoming the load op of whichever pass begins next.
function gvk_rebind(fb: int) -> void {
if fb == gvk_fb_cur { return }
if not gvk_in_pass and gvk_clear_bits != 0 { gvk_pass_begin(gpu_fb, gpu_fb_at(gvk_fb_cur)) }
gvk_pass_end()
gvk_fb_cur = fb
}
function gvk_fb_forget(fb: int) -> void {
if fb == gvk_fb_cur { gvk_pass_end() }
gvk_fb_colors(fb, 1)