diff --git a/examples/rendering/vk_resources.ludic b/examples/rendering/vk_resources.ludic index 1b0dc12a..6e2a7849 100644 --- a/examples/rendering/vk_resources.ludic +++ b/examples/rendering/vk_resources.ludic @@ -61,6 +61,19 @@ program VkResources { check("RGB16F from floats (halved)", gvk_tex_storage(t4, false, GL_RGB16F, w, h, 1, true) and gvk_tex_upload(t4, GL_RGB16F, w, h, 1, GL_RGB, GL_FLOAT, fl)) check("half of 1.5 is 0x3E00", gvk_half(0x3FC00000) == 0x3E00) + # a 16-bit RGB PNG (a normal map): big-endian samples, swapped on upload, alpha filled opaque + let n16 = bytes(w * h * 6) + for i in 0 .. w * h * 3 { n16[i * 2] = (i >> 8) & 255; n16[i * 2 + 1] = i & 255 } + let t7 = gvk_tex_new() + gvk_unpack_swap = true + check("RGB16 swapped upload", gvk_tex_storage(t7, false, GL_RGB16, w, h, 1, true) and gvk_tex_upload(t7, GL_RGB16, w, h, 1, GL_RGB, GL_UNSIGNED_SHORT, n16)) + gvk_unpack_swap = false + let b16 = bytes(w * h * 6) + check("RGB16 read-back call", gvk_tex_read(t7, GL_RGB16, w, h, GL_RGB, GL_UNSIGNED_SHORT, b16)) + var s16 = true + for i in 0 .. w * h * 3 { if b16[i * 2] != (i & 255) or b16[i * 2 + 1] != ((i >> 8) & 255) { s16 = false } } + check("RGB16 samples arrive little-endian", s16) + # the shadow cascades: a depth array, and a render-sized half-float target with no pixels let t5 = gvk_tex_new() check("D32 array of 4", gvk_tex_storage(t5, true, GL_DEPTH_COMPONENT32F, 256, 256, 4, false)) @@ -85,7 +98,7 @@ program VkResources { check("a smaller upload keeps the buffer", gvk_buf_upload(b, 512, data) and gvk_buf[b] == first) check("a larger upload grows it", gvk_buf_upload(b, 4096, data) and gvk_buf_size[b] >= 4096) - for t in 1 .. 7 { gvk_tex_release(t) } + for t in 1 .. 8 { gvk_tex_release(t) } gvk_buf_release(b) for i in 0 .. len(gvk_smp) { Vk.destroy_sampler(gvk_dev, gvk_smp[i], null) } print(`vulkan: {gvk_n_allocs} allocations left after freeing`) diff --git a/packages/ludic.render3d/gpu_vk_draw.ludic b/packages/ludic.render3d/gpu_vk_draw.ludic index 8b15f999..d1a25479 100644 --- a/packages/ludic.render3d/gpu_vk_draw.ludic +++ b/packages/ludic.render3d/gpu_vk_draw.ludic @@ -290,7 +290,9 @@ function gvk_pipeline(p: int, m: Mesh, st: GvkState, n_color: int, color_fmt: in Vk.zero(ms, VkPipelineMultisampleStateCreateInfo_sizeof) Vk.put_i32(ms, VkPipelineMultisampleStateCreateInfo_sType, VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO) Vk.put_i32(ms, VkPipelineMultisampleStateCreateInfo_rasterizationSamples, samples) - Vk.put_i32(ms, VkPipelineMultisampleStateCreateInfo_alphaToCoverageEnable, st.a2c) + # OpenGL ignores alpha to coverage without a multisampled target; Vulkan with one sample would + # instead drop every fragment under half alpha, which erased the meadow's flowers + if samples > 1 { Vk.put_i32(ms, VkPipelineMultisampleStateCreateInfo_alphaToCoverageEnable, st.a2c) } let ds = bytes(VkPipelineDepthStencilStateCreateInfo_sizeof) Vk.zero(ds, VkPipelineDepthStencilStateCreateInfo_sizeof) Vk.put_i32(ds, VkPipelineDepthStencilStateCreateInfo_sType, VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO) @@ -607,10 +609,12 @@ function gvk_frame_cb() -> pointer { return gvk_cb } -# a view of one layer of an array image, for a cascade drawn into on its own +# The view a pass draws into: level 0 only (an attachment view has exactly one level, and a target +# the exposure measure mipmaps has several), and one layer of an array image for a cascade drawn +# on its own. Keyed by the image's generation, so a replaced image never reuses a stale view. function gvk_view_of(tex: int, layer1: int) -> long { - if layer1 == 0 { return gvk_tex_view[tex] } - let key = `{tex}:{layer1}` + if layer1 == 0 and gvk_tex_levels[tex] <= 1 and gvk_tex_layers[tex] <= 1 { return gvk_tex_view[tex] } + let key = `{tex}:{gvk_tex_gen[tex]}:{layer1}` if gvk_layer_views == null { gvk_layer_views = new []string; gvk_layer_view = new []long } for i in 0 .. len(gvk_layer_views) { if gvk_layer_views[i] == key { return gvk_layer_view[i] } } let depth = gvk_tex_vkfmt[tex] == VK_FORMAT_D32_SFLOAT @@ -623,7 +627,7 @@ function gvk_view_of(tex: int, layer1: int) -> long { let sr = VkImageViewCreateInfo_subresourceRange if depth { Vk.put_i32(vci, sr + VkImageSubresourceRange_aspectMask, VK_IMAGE_ASPECT_DEPTH_BIT) } else { Vk.put_i32(vci, sr + VkImageSubresourceRange_aspectMask, VK_IMAGE_ASPECT_COLOR_BIT) } Vk.put_i32(vci, sr + VkImageSubresourceRange_levelCount, 1) - Vk.put_i32(vci, sr + VkImageSubresourceRange_baseArrayLayer, layer1 - 1) + if layer1 > 0 { Vk.put_i32(vci, sr + VkImageSubresourceRange_baseArrayLayer, layer1 - 1) } Vk.put_i32(vci, sr + VkImageSubresourceRange_layerCount, 1) let out = bytes(8) let zero: long = 0 diff --git a/packages/ludic.render3d/gpu_vk_res.ludic b/packages/ludic.render3d/gpu_vk_res.ludic index ea5f92f6..15a41612 100644 --- a/packages/ludic.render3d/gpu_vk_res.ludic +++ b/packages/ludic.render3d/gpu_vk_res.ludic @@ -52,6 +52,9 @@ var gvk_tex_layers: []int = null var gvk_tex_vkfmt: []int = null var gvk_tex_dims_w: []int = null var gvk_tex_dims_h: []int = null +var gvk_tex_glfmt: []int = null # the format the renderer asked for (gpu.ludic's vocabulary) +var gvk_tex_array: []int = null # 1 for an array image +var gvk_tex_gen: []int = null # bumped whenever the image behind a handle is replaced var gvk_unpack_swap: bool = false # GL_UNPACK_SWAP_BYTES: 16-bit PNG samples arrive big-endian function gvk_tex_new() -> int { @@ -60,7 +63,9 @@ function gvk_tex_new() -> int { gvk_tex_image = new []long; gvk_tex_view = new []long; gvk_tex_mem = new []long gvk_tex_levels = new []int; gvk_tex_layers = new []int; gvk_tex_vkfmt = new []int gvk_tex_dims_w = new []int; gvk_tex_dims_h = new []int + gvk_tex_glfmt = new []int; gvk_tex_array = new []int; gvk_tex_gen = new []int push(gvk_tex_dims_w, 0); push(gvk_tex_dims_h, 0) + push(gvk_tex_glfmt, 0); push(gvk_tex_array, 0); push(gvk_tex_gen, 0) # handle 0 is "no texture", as it is on OpenGL push(gvk_tex_image, zero); push(gvk_tex_view, zero); push(gvk_tex_mem, zero) push(gvk_tex_levels, 0); push(gvk_tex_layers, 0); push(gvk_tex_vkfmt, 0) @@ -68,6 +73,7 @@ function gvk_tex_new() -> int { push(gvk_tex_image, zero); push(gvk_tex_view, zero); push(gvk_tex_mem, zero) push(gvk_tex_levels, 0); push(gvk_tex_layers, 0); push(gvk_tex_vkfmt, 0) push(gvk_tex_dims_w, 0); push(gvk_tex_dims_h, 0) + push(gvk_tex_glfmt, 0); push(gvk_tex_array, 0); push(gvk_tex_gen, 0) return len(gvk_tex_image) - 1 } @@ -191,6 +197,8 @@ function gvk_tex_storage(tex: int, array: bool, ifmt: int, w: int, h: int, layer gvk_tex_image[tex] = image; gvk_tex_view[tex] = gvk_handle(out); gvk_tex_mem[tex] = mem gvk_tex_levels[tex] = levels; gvk_tex_layers[tex] = layers; gvk_tex_vkfmt[tex] = vkfmt gvk_tex_dims_w[tex] = w; gvk_tex_dims_h[tex] = h + gvk_tex_glfmt[tex] = ifmt; gvk_tex_gen[tex] = gvk_tex_gen[tex] + 1 + if array { gvk_tex_array[tex] = 1 } else { gvk_tex_array[tex] = 0 } # a target starts cleared-to-nothing but readable: every level in the layout samplers expect let cb = gvk_once_begin() gvk_barrier(cb, image, depth, 0, levels, layers, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) @@ -285,7 +293,42 @@ function gvk_tex_upload(tex: int, ifmt: int, w: int, h: int, layers: int, fmt: i } # The mip chain from level 0, each level blitted down from the one above it +# A target made without pixels has one level; the renderer asking it for mipmaps (the exposure +# measure reads the HDR scene's smallest level every frame) grows it a full chain, level 0 kept. +function gvk_tex_grow_mips(tex: int, w: int, h: int) -> bool { + let old_image = gvk_tex_image[tex] + let old_view = gvk_tex_view[tex] + let old_mem = gvk_tex_mem[tex] + let layers = gvk_tex_layers[tex] + let zero: long = 0 + gvk_tex_image[tex] = zero + if not gvk_tex_storage(tex, gvk_tex_array[tex] == 1, gvk_tex_glfmt[tex], w, h, layers, true) { return false } + let cb = gvk_once_begin() + gvk_barrier(cb, old_image, false, 0, 1, layers, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) + gvk_barrier(cb, gvk_tex_image[tex], false, 0, 1, layers, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) + let ic = bytes(VkImageCopy_sizeof) + Vk.zero(ic, VkImageCopy_sizeof) + Vk.put_i32(ic, VkImageCopy_srcSubresource + VkImageSubresourceLayers_aspectMask, VK_IMAGE_ASPECT_COLOR_BIT) + Vk.put_i32(ic, VkImageCopy_srcSubresource + VkImageSubresourceLayers_layerCount, layers) + Vk.put_i32(ic, VkImageCopy_dstSubresource + VkImageSubresourceLayers_aspectMask, VK_IMAGE_ASPECT_COLOR_BIT) + Vk.put_i32(ic, VkImageCopy_dstSubresource + VkImageSubresourceLayers_layerCount, layers) + Vk.put_i32(ic, VkImageCopy_extent + VkExtent3D_width, w) + Vk.put_i32(ic, VkImageCopy_extent + VkExtent3D_height, h) + Vk.put_i32(ic, VkImageCopy_extent + VkExtent3D_depth, 1) + Vk.cmd_copy_image(cb, old_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, gvk_tex_image[tex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ic) + gvk_barrier(cb, gvk_tex_image[tex], false, 0, 1, layers, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) + let ok = gvk_once_end(cb) + Vk.destroy_image_view(gvk_dev, old_view, null) + Vk.destroy_image(gvk_dev, old_image, null) + Vk.free_memory(gvk_dev, old_mem, null) + gvk_n_allocs -= 1 + return ok +} + function gvk_tex_mips(tex: int, w: int, h: int) -> bool { + if gvk_tex_levels[tex] <= 1 and (w > 1 or h > 1) and not gvk_is_depth(gvk_tex_glfmt[tex]) { + if not gvk_tex_grow_mips(tex, w, h) { return false } + } let levels = gvk_tex_levels[tex] if levels <= 1 { return true } let image = gvk_tex_image[tex] @@ -372,6 +415,7 @@ function gvk_tex_release(tex: int) -> void { gvk_n_allocs -= 1 gvk_tex_image[tex] = zero; gvk_tex_view[tex] = zero; gvk_tex_mem[tex] = zero gvk_tex_levels[tex] = 0; gvk_tex_layers[tex] = 0; gvk_tex_vkfmt[tex] = 0 + gvk_tex_gen[tex] = gvk_tex_gen[tex] + 1 } # ---- samplers ----------------------------------------------------------------------------- diff --git a/packages/ludic.render3d/shaders/spv/1b654972.vert.spv b/packages/ludic.render3d/shaders/spv/1b654972.vert.spv index 5e3e3f83..2259b608 100644 Binary files a/packages/ludic.render3d/shaders/spv/1b654972.vert.spv and b/packages/ludic.render3d/shaders/spv/1b654972.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/1f95f31b.vert.spv b/packages/ludic.render3d/shaders/spv/1f95f31b.vert.spv index 5fb95e1f..7051758f 100644 Binary files a/packages/ludic.render3d/shaders/spv/1f95f31b.vert.spv and b/packages/ludic.render3d/shaders/spv/1f95f31b.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/1fde9cd2.vert.spv b/packages/ludic.render3d/shaders/spv/1fde9cd2.vert.spv index 7a5330a2..fb69f940 100644 Binary files a/packages/ludic.render3d/shaders/spv/1fde9cd2.vert.spv and b/packages/ludic.render3d/shaders/spv/1fde9cd2.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/2e2908c8.vert.spv b/packages/ludic.render3d/shaders/spv/2e2908c8.vert.spv index 5fb95e1f..7051758f 100644 Binary files a/packages/ludic.render3d/shaders/spv/2e2908c8.vert.spv and b/packages/ludic.render3d/shaders/spv/2e2908c8.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/2ee6d2e3.vert.spv b/packages/ludic.render3d/shaders/spv/2ee6d2e3.vert.spv index 51406087..55a54733 100644 Binary files a/packages/ludic.render3d/shaders/spv/2ee6d2e3.vert.spv and b/packages/ludic.render3d/shaders/spv/2ee6d2e3.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/3733fc38.vert.spv b/packages/ludic.render3d/shaders/spv/3733fc38.vert.spv index 1bd92780..04572eba 100644 Binary files a/packages/ludic.render3d/shaders/spv/3733fc38.vert.spv and b/packages/ludic.render3d/shaders/spv/3733fc38.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/3e4b62f9.vert.spv b/packages/ludic.render3d/shaders/spv/3e4b62f9.vert.spv index 51406087..55a54733 100644 Binary files a/packages/ludic.render3d/shaders/spv/3e4b62f9.vert.spv and b/packages/ludic.render3d/shaders/spv/3e4b62f9.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/428caa3a.vert.spv b/packages/ludic.render3d/shaders/spv/428caa3a.vert.spv index 51406087..55a54733 100644 Binary files a/packages/ludic.render3d/shaders/spv/428caa3a.vert.spv and b/packages/ludic.render3d/shaders/spv/428caa3a.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/46e2325c.vert.spv b/packages/ludic.render3d/shaders/spv/46e2325c.vert.spv index 35027170..fc73f668 100644 Binary files a/packages/ludic.render3d/shaders/spv/46e2325c.vert.spv and b/packages/ludic.render3d/shaders/spv/46e2325c.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/4a8e9f28.vert.spv b/packages/ludic.render3d/shaders/spv/4a8e9f28.vert.spv index 51406087..55a54733 100644 Binary files a/packages/ludic.render3d/shaders/spv/4a8e9f28.vert.spv and b/packages/ludic.render3d/shaders/spv/4a8e9f28.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/4be7acd9.vert.spv b/packages/ludic.render3d/shaders/spv/4be7acd9.vert.spv index 51406087..55a54733 100644 Binary files a/packages/ludic.render3d/shaders/spv/4be7acd9.vert.spv and b/packages/ludic.render3d/shaders/spv/4be7acd9.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/4cf96468.vert.spv b/packages/ludic.render3d/shaders/spv/4cf96468.vert.spv index 51406087..55a54733 100644 Binary files a/packages/ludic.render3d/shaders/spv/4cf96468.vert.spv and b/packages/ludic.render3d/shaders/spv/4cf96468.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/4d4fa91b.vert.spv b/packages/ludic.render3d/shaders/spv/4d4fa91b.vert.spv index f17706c7..aaff3b9e 100644 Binary files a/packages/ludic.render3d/shaders/spv/4d4fa91b.vert.spv and b/packages/ludic.render3d/shaders/spv/4d4fa91b.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/638623c2.vert.spv b/packages/ludic.render3d/shaders/spv/638623c2.vert.spv index 51406087..55a54733 100644 Binary files a/packages/ludic.render3d/shaders/spv/638623c2.vert.spv and b/packages/ludic.render3d/shaders/spv/638623c2.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/676965ab.vert.spv b/packages/ludic.render3d/shaders/spv/676965ab.vert.spv index 51406087..55a54733 100644 Binary files a/packages/ludic.render3d/shaders/spv/676965ab.vert.spv and b/packages/ludic.render3d/shaders/spv/676965ab.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/725523d9.vert.spv b/packages/ludic.render3d/shaders/spv/725523d9.vert.spv index 51406087..55a54733 100644 Binary files a/packages/ludic.render3d/shaders/spv/725523d9.vert.spv and b/packages/ludic.render3d/shaders/spv/725523d9.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/7ed7de52.vert.spv b/packages/ludic.render3d/shaders/spv/7ed7de52.vert.spv index 2128ef9e..d9a792db 100644 Binary files a/packages/ludic.render3d/shaders/spv/7ed7de52.vert.spv and b/packages/ludic.render3d/shaders/spv/7ed7de52.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/858f5089.vert.spv b/packages/ludic.render3d/shaders/spv/858f5089.vert.spv index 51406087..55a54733 100644 Binary files a/packages/ludic.render3d/shaders/spv/858f5089.vert.spv and b/packages/ludic.render3d/shaders/spv/858f5089.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/9068df1c.vert.spv b/packages/ludic.render3d/shaders/spv/9068df1c.vert.spv index a0730921..17d7ba64 100644 Binary files a/packages/ludic.render3d/shaders/spv/9068df1c.vert.spv and b/packages/ludic.render3d/shaders/spv/9068df1c.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/9d3e2ddd.vert.spv b/packages/ludic.render3d/shaders/spv/9d3e2ddd.vert.spv index 51406087..55a54733 100644 Binary files a/packages/ludic.render3d/shaders/spv/9d3e2ddd.vert.spv and b/packages/ludic.render3d/shaders/spv/9d3e2ddd.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/a45356c7.vert.spv b/packages/ludic.render3d/shaders/spv/a45356c7.vert.spv index 51406087..55a54733 100644 Binary files a/packages/ludic.render3d/shaders/spv/a45356c7.vert.spv and b/packages/ludic.render3d/shaders/spv/a45356c7.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/a5ad521e.vert.spv b/packages/ludic.render3d/shaders/spv/a5ad521e.vert.spv index 7a5330a2..fb69f940 100644 Binary files a/packages/ludic.render3d/shaders/spv/a5ad521e.vert.spv and b/packages/ludic.render3d/shaders/spv/a5ad521e.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/a64015f2.vert.spv b/packages/ludic.render3d/shaders/spv/a64015f2.vert.spv index 69cda115..fce8b982 100644 Binary files a/packages/ludic.render3d/shaders/spv/a64015f2.vert.spv and b/packages/ludic.render3d/shaders/spv/a64015f2.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/b79a1f4e.vert.spv b/packages/ludic.render3d/shaders/spv/b79a1f4e.vert.spv index 69cda115..fce8b982 100644 Binary files a/packages/ludic.render3d/shaders/spv/b79a1f4e.vert.spv and b/packages/ludic.render3d/shaders/spv/b79a1f4e.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/bf3151c8.vert.spv b/packages/ludic.render3d/shaders/spv/bf3151c8.vert.spv index 647e7ad6..4f89b741 100644 Binary files a/packages/ludic.render3d/shaders/spv/bf3151c8.vert.spv and b/packages/ludic.render3d/shaders/spv/bf3151c8.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/c57b4f14.vert.spv b/packages/ludic.render3d/shaders/spv/c57b4f14.vert.spv index 51406087..55a54733 100644 Binary files a/packages/ludic.render3d/shaders/spv/c57b4f14.vert.spv and b/packages/ludic.render3d/shaders/spv/c57b4f14.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/e18e40c9.vert.spv b/packages/ludic.render3d/shaders/spv/e18e40c9.vert.spv index 51406087..55a54733 100644 Binary files a/packages/ludic.render3d/shaders/spv/e18e40c9.vert.spv and b/packages/ludic.render3d/shaders/spv/e18e40c9.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/e9b6300c.vert.spv b/packages/ludic.render3d/shaders/spv/e9b6300c.vert.spv index a0730921..17d7ba64 100644 Binary files a/packages/ludic.render3d/shaders/spv/e9b6300c.vert.spv and b/packages/ludic.render3d/shaders/spv/e9b6300c.vert.spv differ diff --git a/packages/ludic.render3d/shaders/spv/f4382918.vert.spv b/packages/ludic.render3d/shaders/spv/f4382918.vert.spv index 5fb95e1f..7051758f 100644 Binary files a/packages/ludic.render3d/shaders/spv/f4382918.vert.spv and b/packages/ludic.render3d/shaders/spv/f4382918.vert.spv differ diff --git a/tools/ludic-cli/shaders.ludic b/tools/ludic-cli/shaders.ludic index b287520c..de75c8bf 100644 --- a/tools/ludic-cli/shaders.ludic +++ b/tools/ludic-cli/shaders.ludic @@ -173,7 +173,9 @@ function cmd_shaders() -> int { # is untouched. No y flip: a Vulkan target's row 0 is where OpenGL's is (NDC y = -1), so render # to texture, sampling and gl_FragCoord agree; only the present and the screenshot flip. let depth_remap = "\n#undef main\nvoid main() {\n ludic_gl_main();\n gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n}\n" - let vsrc = "#version 460\n" + defines + "#define main ludic_gl_main\n" + shd_file(parts[0]) + depth_remap + # invariant: the foliage's depth prepass and its lit pass (depth EQUAL) are different variants, + # and without it the compiler may compute their positions a hair apart and fail the test + let vsrc = "#version 460\n" + defines + "invariant gl_Position;\n#define main ludic_gl_main\n" + shd_file(parts[0]) + depth_remap let fsrc = "#version 460\n" + defines + shd_noise + shd_lighting + shd_file(parts[1]) # one binding table for both stages shd_names = new []pointer