#version 430 core // Campaign V slice V6c — the Vulkan RHI verification shader. // // Plan §4.11 asks the active capability probe to "build one real pipeline from // the committed .spv and render an offscreen triangle sampling a table slot", // and slice V5 recorded that as its one deliberate deviation because the .spv // toolchain did not exist yet. This is that shader, and it does rather more: it // is what the V6 backend draws its verification scene with, so one pipeline // exercises the vertex layout, both storage bindings, the shared push-constant // block, gl_DrawID under multi-draw-indirect, and the set-2 texture table. // // VULKAN-DIALECT ONLY. Unlike the eight production pairs this is not compiled by // the GL backend: it reads the push-constant block and the descriptor array that // tools/compile-shaders.ps1 injects, neither of which GL has. It is not a fork of // anything — no GL renderer draws with it — and it retires when the ported world // renderers become the backend's own proof. layout(location = 0) in vec3 aPosition; layout(location = 1) in vec3 aNormal; layout(location = 2) in vec2 aTexCoord; // set 0 binding 0 — per-instance transforms, exactly as GpuBindingModel pins it. struct InstanceData { mat4 transform; }; layout(std430, binding = 0) readonly buffer InstanceBuffer { InstanceData Instances[]; }; // set 0 binding 1 — per-draw batch metadata at the pinned 16-byte std430 stride. // The first word is the texture-table slot: since slice V2 a batch carries an // index, not a 64-bit bindless handle, which is what makes this data model // backend-neutral. struct BatchData { uint textureIndex; uint textureLayer; uint tint; uint pad; }; layout(std430, binding = 1) readonly buffer BatchBuffer { BatchData Batches[]; }; layout(location = 0) out vec3 vNormal; layout(location = 1) out vec2 vTexCoord; layout(location = 2) out flat uint vTextureIndex; layout(location = 3) out flat uint vTextureLayer; layout(location = 4) out flat uint vTint; void main() { // gl_BaseInstanceARB + gl_InstanceID is the GL idiom mesh_modern uses; the // injected preamble maps it onto Vulkan's gl_InstanceIndex, which already // includes firstInstance. int instanceIndex = gl_BaseInstanceARB + gl_InstanceID; mat4 model = Instances[instanceIndex].transform; // gl_DrawID resets to 0 at the start of each indirect dispatch on both APIs, // so a pass beginning partway into the batch array offsets its lookup — // issue #52's uDrawIDOffset pattern, carried over unchanged. BatchData b = Batches[uDrawIDOffset + gl_DrawIDARB]; vTextureIndex = b.textureIndex; vTextureLayer = b.textureLayer; vTint = b.tint; vec4 world = model * vec4(aPosition, 1.0); gl_Position = uViewProjection * world; vNormal = mat3(model) * aNormal; vTexCoord = aTexCoord; }