Skip to main content

concinnity_core/render/vulkan/
uniforms.rs

1//! repr(C) uniform / push-constant structs only the Vulkan frame encoders bind
2//! (std140 / std430 / push-constant layouts). Each is mirrored field-for-field
3//! in a `.glsl`/`.vert`/`.frag`/`.comp` shader under `vulkan/shaders/`, or in
4//! the one `.slang` block Vulkan alone declares.
5//!
6//! Blocks whose shader counterpart is a single-source `.slang` declaration are
7//! declared once for every backend in `crate::render::uniforms`; what is left here is
8//! what only this backend binds. Their layouts are checked by `shader_layout` in
9//! concinnity-device, which reads the expected offsets out of slangc's
10//! reflection per target. The hand-written asserts below are for the families
11//! whose shaders are still per backend -- the cull kernel, the skinning and
12//! morph kernels, the raymarch SDF templates, the velocity pass, and Metal's
13//! water.
14
15/// Byte size of the auto-exposure push-constant range. Pins the struct size to
16/// what the pipeline layout declares.
17pub const AUTO_EXPOSURE_PUSH_BYTES: u32 = 16;
18
19/// The GPU-cull push constant (cull.slang): six already-normalised frustum
20/// planes (xyz = normal, w = d), the camera position sharing its 16-byte slot with
21/// the build-time object count, then the shader-bucket routing (120 B total).
22#[derive(Copy, Clone)]
23#[repr(C)]
24pub struct CullParams {
25    /// Frustum planes, each `(normal.xyz, d)`.
26    pub planes: [[f32; 4]; 6],
27    /// World-space camera position.
28    pub cam_pos: [f32; 3],
29    /// Draw records the kernel iterates.
30    pub object_count: u32,
31    /// Shader-bucket command regions in the indirect buffer. The kernel writes
32    /// every record's slot in all `bucket_count` regions (a draw in the record's
33    /// own bucket, a no-op everywhere else); region `b` starts at command
34    /// `b * bucket_stride`. `bucket_count = 1` degenerates to a single region.
35    pub bucket_count: u32,
36    /// `u32` slots one bucket occupies in the output list.
37    pub bucket_stride: u32,
38}
39
40/// Cull-side Hi-Z uniforms (cull.slang, 80 bytes): the previous frame's
41/// un-jittered view-projection, the Hi-Z mip-0 dimensions, the mip count, and an
42/// enable flag. Mirrors the Metal / DirectX CullUniforms tail.
43#[derive(Copy, Clone)]
44#[repr(C)]
45pub struct CullHizParams {
46    /// Previous frame's un-jittered view-projection. Projects each AABB into the
47    /// depth space the Hi-Z pyramid was reduced from (`M * v`).
48    pub prev_view_proj: [[f32; 4]; 4],
49    /// Hi-Z mip-0 dimensions (in texels).
50    pub hiz_size: [f32; 2],
51    /// How many mip levels live in the bound texture.
52    pub hiz_mip_count: u32,
53    /// 0 skips the Hi-Z test entirely (first frame / after a resize, before a
54    /// valid pyramid exists).
55    pub hiz_enabled: u32,
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61    use core::mem::{offset_of, size_of};
62
63    // CullParams must match the `CullParams` push-constant block in cull.slang:
64    // six frustum planes, then cam_pos sharing its 16-byte slot with
65    // object_count. `shader_layout` in concinnity-device reflects the same
66    // source; this is the copy that runs without slangc.
67    #[test]
68    fn cull_params_layout_matches_the_shader() {
69        assert_eq!(size_of::<CullParams>(), 120);
70        assert_eq!(offset_of!(CullParams, planes), 0);
71        assert_eq!(offset_of!(CullParams, cam_pos), 96);
72        assert_eq!(offset_of!(CullParams, object_count), 108);
73        assert_eq!(offset_of!(CullParams, bucket_count), 112);
74        assert_eq!(offset_of!(CullParams, bucket_stride), 116);
75    }
76
77    // CullHizParams in cull.slang: mat4 (64) + float2 (8) + two uints. Total 80
78    // bytes, tightly packed after the mat4.
79    #[test]
80    fn cull_hiz_params_layout_matches_the_shader() {
81        assert_eq!(size_of::<CullHizParams>(), 80);
82        assert_eq!(offset_of!(CullHizParams, prev_view_proj), 0);
83        assert_eq!(offset_of!(CullHizParams, hiz_size), 64);
84        assert_eq!(offset_of!(CullHizParams, hiz_mip_count), 72);
85        assert_eq!(offset_of!(CullHizParams, hiz_enabled), 76);
86    }
87}