Expand description
Shared GPU data types used by all rendering backends. Defined here (no #cfg gate) so a future Vulkan backend can import them without pulling in Metal-specific code. metal.rs imports from this module rather than defining its own copies.
Structs§
- Area
Light Data - One rectangular area light’s extent, indexed by
GpuLight.data_index. The centre is the GpuLight’spositionand the emitting direction itsdirection; only the two in-plane edge vectors and the sidedness flag need the extra room. - Cluster
Params - Per-frame uniform for the clustered light-binning compute pass and the forward
pass that reads the per-cluster lists. The compute kernel unprojects each
cluster’s screen tile through
inv_view_projand walks camera rays to the slice’s near/far depth to build a world-space AABB (same convention as the fog froxel kernel), then tests each GpuLight sphere against it. The forward pass reads the grid dims + depth range + screen size to map a fragment to its cluster. 128 bytes; packed_float3 keepscam_pos/view_forwardinside their 16-byte lanes. Must match theClusterParamsstruct in the light-cull and forward shaders. - Composite
Params - Fragment constants for the composite pass: the authored post-process
tunables plus the scene-transition fade the backend owns. Pushed verbatim to
the composite fragment shader, so the layout must stay in sync with the
CompositeUniformsstruct there. 48 bytes. - Directional
Light Data - One directional light entry in LightUniforms. Layout (32 bytes) must match DirectionalLightData in every .metal shader. MSL shaders must declare float3 fields as packed_float3 in constant buffer structs; plain float3 has size=16 in MSL which shifts subsequent fields.
- Draw
Object - One renderable object: vertex/index slice within the shared GPU buffers, a model matrix, albedo and normal-map texture slots, and material parameters.
- FogFroxel
Params - Per-frame uniform consumed by the volumetric-fog froxel compute kernel and
the matching fragment-shader sample path. Carries the view matrix (so the
compute kernel + the fragment sampler can map between world-space froxel
positions and the volume’s Z axis) and the discrete volume dimensions. Used
by the froxel-volume fog path; only worlds that declare a
VolumetricFogbind it. - FogParams
- Per-frame uniform consumed by the volumetric-fog ray-march. Carries the
clamped authored tunables plus the view inputs the shader needs to
reconstruct world positions from depth and integrate sun-aligned
scattering. Pushed verbatim to the fog fragment shader, so the layout must
stay in sync with
FogParamsinmetal/shaders/fog.metal. 176 bytes. - GpuDraw
Args - Per-object draw parameters consumed by the GPU-driven compute cull kernel.
Parallel to
GpuObjectData(one record perDrawObject, same index):GpuObjectDatacarries the cull bounds the kernel tests, this carries the indexed-draw arguments the kernel encodes into the indirect command buffer (MetalMTLIndirectCommandBuffer/ DirectXExecuteIndirectargument buffer / VulkanmultiDrawIndexedIndirectbuffer) when an object survives the cull. - GpuLight
- One local light in the per-scene storage buffer the forward pass iterates
(bound at Metal fragment buffer(8)). 64 bytes = four 16-byte lanes, so every
packed_float3 sits inside one lane with no GPU alignment promotion. Must match
the
GpuLightstruct in the single-source shaders. - GpuObject
Data - Per-object record consumed by the Metal “bindless” static main pass.
- Instanced
Cluster - One GPU-instanced draw: a shared mesh slice + material rendered at many
world-space transforms in a single
drawIndexedInstanced/cmd_draw_indexed(instance_count > 1). The cluster has a single union AABB across all instances; it is frustum-tested as a whole. Cluster culling trades per- instance precision for one draw call instead of N. - Instanced
LodBucket - One LOD bucket emitted by
InstancedCluster::lod_buckets: the index range for that LOD plus the subset of instance matrices that picked it. Each bucket becomes onedrawIndexedInstancedcall. - Light
Uniforms - All scene lights packed into a single GPU buffer pushed at fragment buffer(4). Must stay in sync with LightUniforms in every .metal shader.
- Line
Vertex - Compact vertex type used exclusively by the line pass. 32 bytes: the expanded ribbon corner in world space, its signed position across the ribbon width (for the shader’s edge fade), and the corner colour.
- LodSlice
- One LOD level past LOD0 for a
DrawObject. Holds the rebased shared-index buffer slice and the camera-distance threshold above which the renderer picks this slice instead of the one stored on the parentDrawObject.LodSlices are stored in ascendingswitch_distanceorder; the runtime picks the highest-indexed slice whose threshold is ≤ the current camera distance. The samebase_vertexas the parent applies: LOD decimation reuses the LOD0 vertex range, only the index list changes. - Material
Uniforms - Per-draw-call material parameters pushed to the fragment shader at buffer(3).
Must stay in sync with the
MaterialUniformsstruct in every .metal shader. - Particle
Params - Per-frame uniform consumed by the particle compute + render kernels. Carries
the resolved emitter tunables (position, direction, gravity, …) plus the
dynamic per-frame inputs the compute kernel needs to age + integrate +
respawn the pool. Pushed at compute buffer(2) and vertex buffer(1) of the
Metal particle passes, so the layout must stay in sync with
ParticleParamsinshaders/particle_types.slang. 144 bytes. - Point
Light Data - One point light entry in LightUniforms. Layout (32 bytes) must match PointLightData in every .metal shader. Same packed_float3 requirement as DirectionalLightData above.
- Post
Process Params - Post-process tunables resolved from the
PostProcessConfigasset (or its defaults), plus the two display-output flags the backend resolves from the display’s EDR capability at init. Pushed verbatim to the bloom prefilter and composite fragment shaders, so the layout must stay in sync with thePostUniformsstruct in those shaders. 36 bytes. - Post
Process Tunables - The authored half of
PostProcessParams: everything aPostProcessConfig(or a settings slider) resolves to. Carries no display-output flag, so a live push can never disturb the EDR path the backend negotiated at init. - RtGeom
Entry - One entry of the ray-tracing geometry table, indexed by the intersector’s
instance_id(the instance’s position in the TLAS instance buffer, one entry per instance, in instance order). Lets the RT kernel find the hit triangle’s indices in the shared index buffer, transform its local-space vertices into world space for the geometric normal, and pick a base albedo to shade the hit with.#[repr(C)], 128 bytes: the layout must stay in sync with theRtGeomEntrystruct in the shared RT records (rt_types.slang), wheretintandemissivearepacked_float3so the field offsets match; a plainfloat3there would stride the buffer differently and fault the trace. The_padtail rounds the struct to 128 bytes so its array stride is a multiple of the 16-byte GPU alignment of thefloat4x4model(MSL/HLSL/GLSL round a matrix-bearing struct up to a 16-byte multiple, so a 116-byte Rust struct would stride 116 while the shader strides 128 and faults the trace). Thesize_eq/offsetsunit tests below lock the Rust side. The model matrix is stored here (rather than read from the intersector’s instance transform) so the kernel’s normal math is self-contained. - RtParams
- Per-frame uniform for the hardware ray-traced reflection pass. Like
SsrParamsit carries the clamped intensity / distance, the view-ray scale used to rebuild a view-space position from the SSR pre-pass G-buffer, and the IBL prefilter mip count for the miss fallback. Unlike SSR it traces a world-space ray against an acceleration structure, so it also carries the camera-to-world transform (to lift the view-space hit point + normal into world space), the world camera position (the ray origin), and the sun direction + colour the hit-shading uses. Pushed verbatim to the RT kernel, so the layout must stay in sync with theRtParamsstruct there. 144 bytes, 16-byte aligned (everyvec3is padded to afloat4). - Shadow
Pass Push - Per-shadow-pass push constant identifying which cascade is being rendered.
Used so the shadow vertex shader can index
ShadowUniforms.light_vps[i]from a single bound UBO instead of re-binding a different uniform per pass. - Shadow
Uniforms - Cascaded shadow map view-projection matrices and split depths.
- Skinned
Draw Object - One skeletally animated draw: a slice of the shared skinned vertex/index buffers plus the per-joint matrix buffer the vertex shader blends.
- Spot
Shadow Data - One shadowed spot light’s slice of the spot shadow map array. Indexed by
GpuLight.shadow_index; the index doubles as the array slice. Uploaded once per scene, since local lights are static. - Ssao
Params - Per-frame uniform for the SSAO (GTAO) horizon-search kernel. Carries the
clamped authored tunables plus the view-ray scale the kernel needs to
rebuild a view-space position from the linear depth the SSAO pre-pass
writes. Pushed verbatim to the SSAO kernel fragment shader, so the layout
must stay in sync with the
SsaoParamsstruct there. 16 bytes. - Ssgi
Params - Per-frame uniform for the screen-space global-illumination (SSGI) gather +
composite. Carries the clamped authored tunables and the view-ray scale the
gather pass uses to project a view-space ray point back to a screen UV.
Pushed verbatim to the SSGI gather + composite fragment shaders, so the
layout must stay in sync with the
SsgiParamsstruct there. 32 bytes. - SsrParams
- Per-frame uniform for the screen-space reflection (SSR) ray-march. Carries
the clamped authored tunables, the view-ray scale the resolve pass uses to
project a view-space ray point back to a screen UV, and the data the resolve
needs to sample the IBL prefilter cubemap as a fallback. Pushed verbatim to
the SSR resolve fragment shader, so the layout must stay in sync with the
SsrParamsstruct there. 96 bytes. - Text
Draw Call - One text draw call: quads for all visible characters sharing one atlas texture.
- Text
Uniforms - Uniforms pushed to the text vertex shader once per text draw call. Carries the framebuffer size so the shader can convert pixel coords to NDC.
- Text
Vertex - Compact vertex type used exclusively by the text render pass. 32 bytes: screen-pixel position, atlas UV, text colour, and sampling mode.
Constants§
- CLUSTER_
COUNT - Total clusters in the froxel grid.
- CLUSTER_
GRID_ X - Clustered forward lighting froxel grid. The screen is tiled CLUSTER_GRID_X x CLUSTER_GRID_Y with CLUSTER_GRID_Z exponential depth slices; a compute pass bins the local lights into per-cluster index lists the forward pass reads instead of iterating every light.
- CLUSTER_
GRID_ Y - Cluster tiles down the screen. See
CLUSTER_GRID_X. - CLUSTER_
GRID_ Z - Exponential depth slices per cluster column. See
CLUSTER_GRID_X. - CLUSTER_
LIGHT_ LIST_ STRIDE u32slots one cluster occupies in the light-index buffer: the count plusMAX_LIGHTS_PER_CLUSTERindices.- FALLBACK_
TEXTURE_ COUNT - Pool entries reserved past the real textures: the flat-normal fallback at
texture_count, then the white albedo fallback attexture_count + 1. Every backend appends them in this order, so the two*_pool_indexresolvers below agree with each backend’s pool construction. - LIGHT_
KIND_ AREA GpuLight.kindfor a rectangular area light. SeeLIGHT_KIND_POINT.- LIGHT_
KIND_ POINT - GpuLight.kind discriminants.
- LIGHT_
KIND_ SPOT GpuLight.kindfor a spot light. SeeLIGHT_KIND_POINT.- MAX_
AREA_ LIGHTS - Capacity of the per-scene AreaLightData table. Area lights are far heavier to shade than point or spot lights (a polygon integral per fragment), so the cap is deliberately well under MAX_LOCAL_LIGHTS.
- MAX_
DIRECTIONAL_ LIGHTS - Capacity of the fixed directional-light array in
LightUniforms. - MAX_
JOINTS - Maximum number of joints in a single skinned-mesh skeleton. Enforced
CPU-side as a clamp on each
SkinnedDrawObject.joint_countand on the matchingskinned_joint_matricesVec length. The skinned shaders read the joints buffer through a pointer (constant float4x4 *joints) using vertex-encoded joint indices, so the GPU buffer size and joint count are fully dynamic: this constant just caps how many matrices the per-frame upload may carry per object. - MAX_
LIGHTS_ PER_ CLUSTER - Per-cluster light-index list capacity. Each cluster occupies CLUSTER_LIGHT_LIST_STRIDE u32 slots: slot 0 is the count, slots 1.. are light indices into the GpuLight buffer. Lights past the cap are dropped.
- MAX_
LOCAL_ LIGHTS - Capacity of the per-scene local-light storage buffer the forward pass reads. Distinct from MAX_POINT_LIGHTS, which still bounds the fixed LightUniforms point array consumed by the raymarch / fog / probe paths. Lights past this cap are dropped with a warning.
- MAX_
POINT_ LIGHTS - Capacity of the fixed point-light array in
LightUniforms, which the raymarch / fog / probe paths read. - MAX_
SHADER_ BUCKETS - Upper bound on world shader buckets a cull dispatch can route between (the ICB argument-buffer array length in the cull shaders). Mirrored by MAX_SHADER_BUCKETS in cull.metal, enforced by the world-shape check, and quoted as a number in the Shader asset docs.
- MAX_
SHADOWED_ SPOTS - Slices in the spot shadow map array: the number of spot lights that can cast
shadows at once. Spots past this still light the scene with
shadow_indexleft at -1. Hardcoded for the same reason as NUM_SHADOW_CASCADES. - NO_
ALBEDO_ SLOT - Sentinel albedo
texture_slotmeaning “this object has no albedo texture.” Slot 0 cannot say that: it is a real handle, held by whichever texture the world declares first, so an unset albedo encoded as 0 sampled that texture and tinted it.usize::MAXcollides with no handle and lets a backend substitute the synthesized white fallback, which leavestintas the object’s colour without a shader branch. - NO_
NORMAL_ MAP_ SLOT - Sentinel
normal_map_slotmeaning “this object has no normal map.” The texture pool is a single handle-indexed table shared by albedo and normal maps, so a real normal map carries its own texture handle (which may be 0);usize::MAXcannot collide with any handle and lets a backend substitute the synthesized flat-normal fallback (tangent-space (0,0,1)) without a shader branch. Backends map this to the fallback’s reserved pool index. - NUM_
SHADOW_ CASCADES - Number of cascades the directional shadow pre-pass renders into the shadow map array. Hardcoded because changing N requires re-compiling the shaders (the array length appears in the MSL/HLSL/GLSL source).
Functions§
- albedo_
pool_ index - Resolve an albedo
texture_slotto its index in the handle-indexed texture pool. A real albedo addresses its own texture slot (clamped into the real-texture range so a stale slot reads the last valid entry rather than out of bounds);NO_ALBEDO_SLOTaddresses the white fallback attexture_count + 1, so an untextured material samples white and shows itstintrather than whichever texture happens to hold slot 0. - draw_
args_ bucket_ bits - Pack a
DrawObject’s shader bucket into theGpuDrawArgs::flagsupper bits, clamped to the routing budget the cull kernels implement. A bucket past the budget renders with the world default program rather than reading a command region that does not exist; the world-shape check fails such a world at build time, so the clamp is a backstop. - draw_
args_ flags - Pack the per-frame cull-decision bits for one
DrawObject. Mirrors the CPUvisible = BVH(cullable) + always_drawpartition: an object draws when it is visible and resident, and is frustum-tested only when it has finite bounds. - instance_
object_ records - Expand every instance of every cluster into a flat
GpuObjectDatalist for the GPU-driven bindless instanced path, in cluster-then-instance order (so a parallel per-instance draw-args list can be walked in the same order). The texture-pool indices are resolved throughalbedo_pool_index/normal_pool_index, matchingbuild_object_buffer’s static addressing.texture_countis the pool’s real-texture count (the flat-normal fallback sits attexture_count). - normal_
pool_ index - Resolve a
normal_map_slotto its index in the handle-indexed texture pool. A real normal map addresses its own texture slot (clamped into the real-texture range);NO_NORMAL_MAP_SLOTaddresses the flat-normal fallback attexture_count(the first reserved entry past the last real texture), so the shader never needs a “has a normal map?” branch. - pack_
object_ record - Pack one
DrawObjectinto itsGpuObjectDatarecord for the DirectX and Vulkan bindless static pass. The caller supplies the resolved texture-pool indices:albedo_index/normal_indexare dense indices into the one handle-indexed pool (a normal-less object’snormal_indexpoints at the pool’s flat-normal fallback slot), identical across all three backends. - pack_
skinned_ record - Build the GPU-driven cull/draw record for one skinned object, folded into the
bindless main pass as rigid geometry. The skin compute kernel deforms the
bind-pose vertices into MODEL space, so
modelis applied after skinning (model -> world) exactly like a static object; the cull bound is the padded bind-pose AABB transformed bymodel. Mirrorspack_instance_record, sourcing material + flat texture indices from the skinned object. - spot_
shadow_ slice_ size - Per-slice edge of the spot shadow map array, derived from the authored
directional
shadow_map_sizeso one quality knob scales both. Quartered because a spot’s cone covers far less world area than a CSM cascade, and the array multiplies the cost by MAX_SHADOWED_SPOTS.