Expand description
GPU.2 — Vxl → (occupancy bitmap, colour offsets, packed colour array). Pure CPU; no wgpu deps in this module. Shape:
occupancy[x, y]is 8 contiguous u32 words covering z=0..256, one bit per voxel with z-innermost ordering. Bit position of voxel(x, y, z)isz + (x + y*vsid)*CHUNK_Z; the word index is(x + y*vsid)*8 + z/32and the bit-in-word isz & 31. This packs each column’s 256 z-bits into 8 contiguous u32s so the GPU shader can rank-count solid voxels in O(8 popcount) instead of O(z) sequential bit fetches.color_offsets[x + y*vsid]— u32 = base index intocolorsfor that column’s voxels in ascending z.vsid*vsid + 1entries; trailing sentinel =colors.len().colors[..]— packed u32 per occupied voxel, ordered first by column index then by ascending z within the column.
The voxlap slab format interleaves floor and ceiling colour ranges across slab boundaries, with implicit “bedrock” voxels filling the gap between a slab’s textured floor and the next slab’s air-gap top. Bedrock has no per-voxel colour in the slab data — voxlap stores only textured surfaces.
Bedrock-as-solid (cliff-face fix): each MipUpload carries
two bitmaps — occupancy (textured voxels only, for the colour
rank) and solid_occupancy (textured surfaces plus the
implicit bedrock interior below them). The marcher hit-tests
solid_occupancy, so vertical wall/cliff faces are opaque; a
bedrock hit (solid but uncoloured) inherits the colour of the
textured surface above it. Bedrock is still stored as 1 bit,
not a per-voxel colour, so the colour array stays
O(textured voxels) — storing bedrock colours would balloon a
vsid=128 chunk from ~80 KiB to ~10 MiB. The cost is one extra
occupancy bitmap (occupancy storage doubles; colours unchanged).
(Originally “bedrock-as-air”, GPU.4: bedrock was dropped entirely, which left cliff faces transparent to the sky.)
This is O(textured voxels) work; not on the render hot path.
Structs§
- Chunk
Upload - CPU-decompressed chunk ready to upload to the GPU. Each field maps onto one storage buffer in GPU.3+; for GPU.2 the buffers also serve the read-back validator.
- MipUpload
- GPU.11 — one mip level of a chunk in the GPU upload shape. Mip-N
has
(vsid >> mip)²columns spanning z = 0..CHUNK_Z >> mip.
Constants§
- BEDROCK_
RGB - Historic sentinel BGRA for bedrock voxels — kept exported so callers that want voxlap-CPU bedrock parity can render their own pass. Not used by the default GPU decompressor: the “bedrock-as-air” refactor (GPU.4 prereq) skips bedrock entirely.
- CHUNK_Z
- Z-extent of every voxlap column — matches
roxlap_formats’ privateMAXZDIM(voxlap5.h:10). Re-declared here so this module stays a pure consumer of the publicVxlsurface. - GPU_
MAX_ MIPS - GPU.11 — number of mip levels
decompress_chunkbuilds per chunk (capped by the chunk’s ownvsid/CHUNK_Zhalving). Matches the CPU demo’sOpticastSettings::mip_levels = 6, so the GPU mip ladder reaches the same ray-depth as the CPU path (mip_scan_dist · 2⁵). The per-mip relative-offset tables incrate::scene::GridStaticMetaare sized to this. - OCC_
WORDS_ PER_ COLUMN - Number of u32 words per column in the occupancy bitmap
(
CHUNK_Zbits packed 32-per-word). WithCHUNK_Z = 256this is exactly 8 — the rank-count loop in the GPU shader runs in 8 iterations max.
Functions§
- decompress_
chunk - Decompress a
Vxlchunk into the GPU upload shape, building the full mip ladder (gpu_mip_count(vsid)levels). Caller guaranteesvxlis shaped as a roxlap-scene chunk (vsidsquare). Ifvxlalready carries at least that many mips (the common scene path — the bake generates 6), they are read directly; otherwise the chunk is cloned and re-mipped so the upload always carries a deterministic, vsid-uniform level count. - gpu_
mip_ count - GPU.11 — how many mip levels a chunk of side
vsidactually yields underGPU_MAX_MIPS. Mirrors the stopping rule inVxl::generate_mips(src_vsid > 1 && src_z > 1 && n < max) so the upload, the per-slot stride math incrate::scene, and the shader all agree on the level count for a givenvsid. Always>= 1(mip-0). - occ_
words_ per_ column_ for_ mip - GPU.11 — number of occupancy u32 words per column at a given mip
(
(CHUNK_Z >> mip)bits packed 32-per-word, min 1). Mip-0 isOCC_WORDS_PER_COLUMN(= 8).