namespace AcDream.App.Rendering.Gpu;
///
/// Campaign V (V0): the PINNED binding model shared by the CPU renderers, the
/// GLSL sources, and both RHI backends. Every number here appears in a shader
/// file; changing one is a contract change that must land in the same commit as
/// the matching shader edit.
///
/// The model is deliberately Vulkan-shaped and dual-legal:
///
/// set 0 — storage buffers, bindings 0..9. GLSL omits the set qualifier, and
/// GL_KHR_vulkan_glsl defines an omitted set as set 0, so one source
/// file compiles for both backends.
/// set 1 — uniform buffers. Vulkan has ONE binding namespace per set, while
/// GL keeps GL_SHADER_STORAGE_BUFFER and GL_UNIFORM_BUFFER tables
/// separate. Today mesh_modern.vert exploits that: the BatchBuffer
/// SSBO and the SceneLighting UBO both sit at binding=1. Moving UBOs
/// to their own set preserves both numbers and removes the collision.
/// set 2 — the global sampled-texture table that replaces ARB_bindless_texture.
/// Vulkan binds it as one variable-count, partially-bound,
/// update-after-bind descriptor array. GL used to emulate it with a
/// storage buffer of uvec2 handles at set 0 binding 9
/// (StorageTextureTable); Campaign V slice V11 deleted that
/// binding along with the rest of the raw-GL arm, so set 2 is the
/// only texture table left.
///
/// A batch no longer carries a 64-bit bindless handle; it carries a
/// index into the table. That single change is what
/// makes the CPU-side data model backend-neutral (Campaign V slice V2), and it
/// lands on GL — pixel-gated — long before any Vulkan code exists.
///
internal static class GpuBindingModel
{
// ---- set 0: storage buffers (identical numbering to today's SSBO bindings) ----
/// Per-instance transforms. std430 InstanceData { mat4 transform; }.
public const uint StorageInstances = 0;
/// Per-draw batch metadata. std430 BatchData (see ).
public const uint StorageBatches = 1;
/// Phase U.3 shared per-frame clip regions (CellClip, 144 B/slot). Slot 0 = no-clip.
public const uint StorageClipRegions = 2;
/// Phase U.3 per-instance clip-slot index, parallel to .
public const uint StorageClipSlots = 3;
/// A7 Fix B global point/spot light array.
public const uint StorageGlobalLights = 4;
/// A7 Fix B per-instance light set: 8 indices into the global light array, -1 = unused.
public const uint StorageInstanceLightSets = 5;
/// #142 per-instance indoor flag (1 = parented to an EnvCell, skip the sun).
public const uint StorageInstanceIndoor = 6;
/// #188 per-instance opacity multiplier for TransparentPartHook fades.
public const uint StorageInstanceAlpha = 7;
/// Retail SmartBox selection lighting: one vec2 (luminosity, diffuse) per instance.
public const uint StorageInstanceSelectionLighting = 8;
// Campaign V slice V11 deleted StorageTextureTable (binding 9): the GL-only
// emulation of the Vulkan texture table via a storage buffer of uvec2
// bindless handles indexed by GpuTextureSlot.Index. The Vulkan backend
// always bound TextureTableSet instead and never used this binding — every
// Vulkan descriptor set layout declared it anyway (seeded with a dummy
// buffer, like every other unused-by-a-given-shader binding), purely
// because it counted toward StorageBindingCount.
/// One past the highest storage binding — the count the backend must support.
public const uint StorageBindingCount = 9;
// ---- set 1: uniform buffers ----
///
/// SceneLighting std140 block. Keeps binding=1 so the existing shader source
/// and SceneLightingUboBinding layout are untouched; the set index is
/// what disambiguates it from under Vulkan.
///
public const uint UniformSceneLighting = 1;
///
/// Terrain per-layer texture tiling factors — 36 floats.
///
/// Added at slice V4d. These live in a uniform float[36] today, which
/// is 144 bytes: too large for the 96-byte push-constant block (and for
/// Vulkan's guaranteed 128-byte ceiling), and there is no RHI verb for setting
/// a uniform array. A small uniform buffer is the Vulkan-legal home. Binding 2
/// is taken by the terrain clip block, so this is 3.
///
public const uint UniformTerrainTiling = 3;
///
/// Sky per-draw parameters — the sky/model transforms, the keyframe's
/// ambient/sun colours and sun direction, the UV scroll, and the
/// per-surface emissive/diffuse/opacity/fog scalars.
///
/// Added at slice V6e for the same reason as
/// : Vulkan GLSL has no default uniform
/// block, so a loose uniform mat4 uSkyView; is unspellable, and this
/// set is 256 bytes in std140 — three matrices alone are twice the entire
/// 96-byte push-constant block. A uniform buffer is the only legal home.
/// Bindings 1, 2 and 3 are taken by SceneLighting, the terrain clip block
/// and terrain tiling, so this is 4.
///
public const uint UniformSkyParams = 4;
/// Set index carrying every uniform buffer.
public const uint UniformSet = 1;
// ---- set 2: the global texture table ----
/// Set index of the sampled-texture descriptor array (Vulkan) / logical table (GL).
public const uint TextureTableSet = 2;
/// Binding of the descriptor array within .
public const uint TextureTableBinding = 0;
///
/// Upper bound on simultaneously registered textures. Vulkan requires
/// maxDescriptorSetUpdateAfterBindSampledImages to reach this; the
/// capability probe asserts it rather than discovering it at draw time.
///
public const uint TextureTableCapacity = 16384;
// ---- push constants ----
///
/// Bytes actually written by . Vulkan guarantees
/// at least , so 32 bytes of headroom remain
/// for later slices; any growth updates this constant and the shader block in
/// the same commit.
///
public const int PushConstantBytes = 96;
/// The Vulkan-guaranteed minimum push-constant budget. A hard ceiling for us.
public const int MaxPushConstantBytes = 128;
// ---- shared layout facts the CPU writers and the shaders must agree on ----
///
/// std430 stride of BatchData. The bindless uvec2 textureHandle
/// becomes uint textureIndex plus one pad word at slice V2, so the
/// stride is unchanged and every existing CPU writer keeps its offsets.
///
public const int GpuBatchDataStrideBytes = 16;
/// Clip planes per CellClip slot; also the required gl_ClipDistance size.
public const int ClipPlanesPerSlot = 8;
/// std430 stride of one CellClip slot: 16 B header + 8 × vec4.
public const int ClipRegionStrideBytes = 16 + (ClipPlanesPerSlot * 16);
/// Lights selected per object by retail's minimize_object_lighting.
public const int MaxLightsPerObject = 8;
}