bvle-voxels/shaders/voxelCommon.hlsli
Samuel Bouchet 5f346bb14a Phase 2: GPU-driven voxel rendering pipeline
Mega-buffer architecture replacing per-chunk GPU buffers:
- Single StructuredBuffer<PackedQuad> for all chunks (2M quads, 16 MB)
- StructuredBuffer<GPUChunkInfo> with per-chunk metadata (position, quad offsets, face groups)
- VS reads chunk info via push constants (b999) for driver-safe chunk indexing
- CPU frustum culling with wi::primitive::Frustum + AABB per chunk
- Quads sorted by face direction in greedy mesher (faceOffsets/faceCounts)
- GPU frustum + backface cull compute shader (voxelCullCS.hlsl)
- GPU binary mesher compute shader baseline (voxelMeshCS.hlsl)
- Indirect draw buffers and timestamp query infrastructure
- README with build instructions and project architecture
2026-03-25 14:24:05 +01:00

99 lines
4.9 KiB
HLSL

// 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 / DX12 DrawInstanced) ──
struct IndirectDrawArgsInstanced {
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