From 762a74624c33c92fe6b549b0dfcb2cfbad82aaff Mon Sep 17 00:00:00 2001 From: Orkuncakilkaya Date: Tue, 15 Sep 2026 19:40:23 +0300 Subject: [PATCH] fix(render3d): the chunked grass draws its blades on Vulkan again grass_flush uploaded u_tiles (vec4[256]) with u_fv(4n floats). On Vulkan an array element is copied at the size given and placed at the array's stride, so each tile got one float: nonsense corners and zero blades a cell. The meadow had no grass on the Vulkan renderer since cdfffa6 while the draw counts looked right. u_f4v uploads n vec4s; OpenGL was never affected. PC camp: chunked path matches R3D_GRASS_TILES=1, validation 0. Co-Authored-By: Claude Opus 5 --- packages/ludic.render3d/gpu.ludic | 4 ++++ packages/ludic.render3d/grass.ludic | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/ludic.render3d/gpu.ludic b/packages/ludic.render3d/gpu.ludic index 3e907d2e..caed494d 100644 --- a/packages/ludic.render3d/gpu.ludic +++ b/packages/ludic.render3d/gpu.ludic @@ -247,6 +247,10 @@ function u_f3(loc: int, x: int, y: int, z: int) -> void { if gpu_kind == GPU_VK function u_f4(loc: int, x: int, y: int, z: int, w: int) -> void { if gpu_kind == GPU_VK { let t = gpu_tmp(); t[0] = x; t[1] = y; t[2] = z; t[3] = w; gvk_u_set(loc, t, 16, 1); return }; let t = gpu_tmp(); t[0] = x; t[1] = y; t[2] = z; t[3] = w; gl_uniform4fv(loc, 1, t) } function u_v3(loc: int, v: words) -> void { if gpu_kind == GPU_VK { gvk_u_set(loc, v, 12, 1); return }; gl_uniform3fv(loc, 1, v) } function u_fv(loc: int, n: int, v: words) -> void { if gpu_kind == GPU_VK { gvk_u_set(loc, v, 4, n); return }; gl_uniform1fv(loc, n, v) } +# n vec4s from 4n float bits. Not u_fv with 4n: on Vulkan an array element is copied at the size +# given and placed at the array's stride, so a vec4 array fed floats got one float per element - +# which drew the chunked grass with every tile at a nonsense corner and zero blades a cell. +function u_f4v(loc: int, n: int, v: words) -> void { if gpu_kind == GPU_VK { gvk_u_set(loc, v, 16, n); return }; gl_uniform4fv(loc, n, v) } function u_mat4(loc: int, m: words) -> void { if gpu_kind == GPU_VK { gvk_u_set(loc, m, 64, 1); return }; gl_uniform_matrix4fv(loc, 1, 0, m) } function u_mat4n(loc: int, n: int, m: words) -> void { if gpu_kind == GPU_VK { gvk_u_set(loc, m, 64, n); return }; gl_uniform_matrix4fv(loc, n, 0, m) } function u_i(loc: int, v: int) -> void { if gpu_kind == GPU_VK { let t = gpu_tmp(); t[0] = v; gvk_u_set(loc, t, 4, 1); return }; gl_uniform1i(loc, v) } diff --git a/packages/ludic.render3d/grass.ludic b/packages/ludic.render3d/grass.ludic index 86efe7d6..d4104447 100644 --- a/packages/ludic.render3d/grass.ludic +++ b/packages/ludic.render3d/grass.ludic @@ -215,7 +215,7 @@ function grass_flush() -> void { var m = e - k if m > GRASS_CHUNK { m = GRASS_CHUNK } for q in 0 .. m * 4 { grass_chunk_tv[q] = grass_tv[k * 4 + q] } - u_fv(gpu_uniform(p, "u_tiles"), m * 4, grass_chunk_tv) + u_f4v(gpu_uniform(p, "u_tiles"), m, grass_chunk_tv) gpu_draw_mesh_indirect(grass_mesh, grass_cmds, k * 20, m, 0, 0) grass_draws += 1 k += m