// BVLE Voxels - Shared shader definitions // Root signature, common structures, and constant buffers for voxel shaders. #ifndef VOXEL_COMMON_HLSLI #define VOXEL_COMMON_HLSLI // Wicked Engine DX12 root signature (HLSL 6.6+ bindless model) // b999: push constants (12 x uint32 = 48 bytes) // b0-b2: root CBV descriptors // t0-t15, u0-u15: SRV/UAV descriptor table // s0-s7: dynamic samplers // s100+: static samplers #define VOXEL_ROOTSIG \ "RootFlags(CBV_SRV_UAV_HEAP_DIRECTLY_INDEXED | SAMPLER_HEAP_DIRECTLY_INDEXED), " \ "RootConstants(num32BitConstants=12, b999), " \ "CBV(b0), " \ "CBV(b1), " \ "CBV(b2), " \ "DescriptorTable( " \ "CBV(b3, numDescriptors = 11, flags = DATA_STATIC_WHILE_SET_AT_EXECUTE)," \ "SRV(t0, numDescriptors = 16, flags = DESCRIPTORS_VOLATILE | DATA_STATIC_WHILE_SET_AT_EXECUTE)," \ "UAV(u0, numDescriptors = 16, flags = DESCRIPTORS_VOLATILE | DATA_STATIC_WHILE_SET_AT_EXECUTE)" \ ")," \ "DescriptorTable( " \ "Sampler(s0, offset = 0, numDescriptors = 8, flags = DESCRIPTORS_VOLATILE)" \ ")," \ "StaticSampler(s100, addressU = TEXTURE_ADDRESS_CLAMP, addressV = TEXTURE_ADDRESS_CLAMP, addressW = TEXTURE_ADDRESS_CLAMP, filter = FILTER_MIN_MAG_MIP_LINEAR)," \ "StaticSampler(s101, addressU = TEXTURE_ADDRESS_WRAP, addressV = TEXTURE_ADDRESS_WRAP, addressW = TEXTURE_ADDRESS_WRAP, filter = FILTER_MIN_MAG_MIP_LINEAR)," \ "StaticSampler(s102, addressU = TEXTURE_ADDRESS_MIRROR, addressV = TEXTURE_ADDRESS_MIRROR, addressW = TEXTURE_ADDRESS_MIRROR, filter = FILTER_MIN_MAG_MIP_LINEAR)," \ "StaticSampler(s103, addressU = TEXTURE_ADDRESS_CLAMP, addressV = TEXTURE_ADDRESS_CLAMP, addressW = TEXTURE_ADDRESS_CLAMP, filter = FILTER_MIN_MAG_MIP_POINT)," \ "StaticSampler(s104, addressU = TEXTURE_ADDRESS_WRAP, addressV = TEXTURE_ADDRESS_WRAP, addressW = TEXTURE_ADDRESS_WRAP, filter = FILTER_MIN_MAG_MIP_POINT)," \ "StaticSampler(s105, addressU = TEXTURE_ADDRESS_MIRROR, addressV = TEXTURE_ADDRESS_MIRROR, addressW = TEXTURE_ADDRESS_MIRROR, filter = FILTER_MIN_MAG_MIP_POINT)," \ "StaticSampler(s106, addressU = TEXTURE_ADDRESS_CLAMP, addressV = TEXTURE_ADDRESS_CLAMP, addressW = TEXTURE_ADDRESS_CLAMP, filter = FILTER_ANISOTROPIC, maxAnisotropy = 16)," \ "StaticSampler(s107, addressU = TEXTURE_ADDRESS_WRAP, addressV = TEXTURE_ADDRESS_WRAP, addressW = TEXTURE_ADDRESS_WRAP, filter = FILTER_ANISOTROPIC, maxAnisotropy = 16)," \ "StaticSampler(s108, addressU = TEXTURE_ADDRESS_MIRROR, addressV = TEXTURE_ADDRESS_MIRROR, addressW = TEXTURE_ADDRESS_MIRROR, filter = FILTER_ANISOTROPIC, maxAnisotropy = 16)," \ "StaticSampler(s109, addressU = TEXTURE_ADDRESS_CLAMP, addressV = TEXTURE_ADDRESS_CLAMP, addressW = TEXTURE_ADDRESS_CLAMP, filter = FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT, comparisonFunc = COMPARISON_GREATER_EQUAL)," // ── Per-frame constant buffer (b0) ────────────────────────────── cbuffer VoxelCB : register(b0) { float4x4 viewProjection; float4 cameraPosition; float4 sunDirection; float4 sunColor; float chunkSize; float textureTiling; float2 _pad; // Frustum culling data (used by cull compute shader) float4 frustumPlanes[6]; // ax+by+cz+d=0, xyz=normal, w=distance uint chunkCount; uint _cullPad0; uint _cullPad1; uint _cullPad2; }; // ── Indirect draw args (must match C++ IndirectDrawArgs, 20 bytes) ── // Wicked Engine's DrawInstancedIndirectCount command signature includes a push // constant (1 × uint32 at b999[0]) BEFORE each D3D12_DRAW_ARGUMENTS. // Total stride = 4 + 16 = 20 bytes per draw entry. struct IndirectDrawArgsInstanced { uint pushConstant; // written to b999[0] by ExecuteIndirect uint vertexCountPerInstance; uint instanceCount; uint startVertexLocation; uint startInstanceLocation; }; // ── GPU chunk info (must match C++ GPUChunkInfo, 80 bytes) ────── // NOTE: No arrays — scalar-only to guarantee C-style packing in StructuredBuffer. struct GPUChunkInfo { float4 worldPos; // xyz = chunk origin in world space, w = debug flag uint quadOffset; // offset into mega quad buffer (in quads) uint quadCount; // number of quads for this chunk uint _pad0; uint _pad1; // Per-face data (6 faces: +X -X +Y -Y +Z -Z) uint faceOff0, faceOff1, faceOff2, faceOff3, faceOff4, faceOff5; uint faceCnt0, faceCnt1, faceCnt2, faceCnt3, faceCnt4, faceCnt5; }; // Helper functions to access scalar face fields by index uint getFaceOffset(GPUChunkInfo info, uint f) { switch (f) { case 0: return info.faceOff0; case 1: return info.faceOff1; case 2: return info.faceOff2; case 3: return info.faceOff3; case 4: return info.faceOff4; default: return info.faceOff5; } } uint getFaceCount(GPUChunkInfo info, uint f) { switch (f) { case 0: return info.faceCnt0; case 1: return info.faceCnt1; case 2: return info.faceCnt2; case 3: return info.faceCnt3; case 4: return info.faceCnt4; default: return info.faceCnt5; } } #endif // VOXEL_COMMON_HLSLI