use core::mem::offset_of;
#[repr(C)]
#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
pub struct GpuTransportParams {
pub num_pixels: u32,
pub max_bounces: u32,
pub sample_offset: u32,
pub env_mode: u32,
pub l0: f32,
pub studio_temp_k: f32,
pub studio_spot_mult: f32,
pub studio_exposure: f32,
pub studio_light_yaw: f32,
pub studio_light_pitch: f32,
pub pixel_offset: u32,
pub write_debug_buffers: u32,
pub white_balance: [f32; 3],
pub studio_use_d65: u32,
pub studio_model: u32,
pub backdrop: f32,
_pad_backdrop: [u32; 2],
}
pub mod studio_model {
pub const STUDIO: u32 = 0;
pub const ISO_HEMISPHERE: u32 = 1;
pub const LIGHT_TENT: u32 = 2;
pub const DAYLIGHT_DOME: u32 = 3;
}
pub mod transport_env_mode {
pub const UNIFORM_FURNACE: u32 = 0;
pub const STUDIO_RIG: u32 = 1;
pub const HDR_MAP: u32 = 2;
}
impl GpuTransportParams {
#[must_use]
#[expect(
clippy::too_many_arguments,
reason = "one parameter per GpuTransportParams field, in field order, because \
that field order is itself the #[repr(C)] layout spectral_transport.wgsl's \
uniform buffer binds against; bundling them into a context struct here \
would just re-introduce this exact struct one level removed"
)]
pub const fn new(
num_pixels: u32,
max_bounces: u32,
sample_offset: u32,
env_mode: u32,
l0: f32,
studio_temp_k: f32,
studio_spot_mult: f32,
studio_exposure: f32,
studio_light_yaw: f32,
studio_light_pitch: f32,
white_balance: [f32; 3],
) -> Self {
Self {
num_pixels,
max_bounces,
sample_offset,
env_mode,
l0,
studio_temp_k,
studio_spot_mult,
studio_exposure,
studio_light_yaw,
studio_light_pitch,
pixel_offset: 0,
write_debug_buffers: 1,
white_balance,
studio_use_d65: 0,
studio_model: 0,
backdrop: 0.0,
_pad_backdrop: [0; 2],
}
}
#[must_use]
pub const fn with_pixel_offset(mut self, pixel_offset: u32) -> Self {
self.pixel_offset = pixel_offset;
self
}
#[must_use]
pub const fn with_debug_buffers_disabled(mut self) -> Self {
self.write_debug_buffers = 0;
self
}
#[must_use]
pub const fn with_studio_use_d65(mut self, use_d65: bool) -> Self {
self.studio_use_d65 = if use_d65 { 1 } else { 0 };
self
}
#[must_use]
pub const fn with_studio_model(mut self, model: u32) -> Self {
self.studio_model = model;
self
}
#[must_use]
pub const fn with_backdrop(mut self, backdrop: f32) -> Self {
self.backdrop = backdrop;
self
}
}
const _: () = {
assert!(offset_of!(GpuTransportParams, num_pixels) == 0);
assert!(offset_of!(GpuTransportParams, max_bounces) == 4);
assert!(offset_of!(GpuTransportParams, sample_offset) == 8);
assert!(offset_of!(GpuTransportParams, env_mode) == 12);
assert!(offset_of!(GpuTransportParams, l0) == 16);
assert!(offset_of!(GpuTransportParams, studio_temp_k) == 20);
assert!(offset_of!(GpuTransportParams, studio_spot_mult) == 24);
assert!(offset_of!(GpuTransportParams, studio_exposure) == 28);
assert!(offset_of!(GpuTransportParams, studio_light_yaw) == 32);
assert!(offset_of!(GpuTransportParams, studio_light_pitch) == 36);
assert!(offset_of!(GpuTransportParams, white_balance) == 48);
assert!(offset_of!(GpuTransportParams, studio_use_d65) == 60);
assert!(offset_of!(GpuTransportParams, studio_model) == 64);
assert!(offset_of!(GpuTransportParams, backdrop) == 68);
assert!(offset_of!(GpuTransportParams, _pad_backdrop) == 72);
assert!(size_of::<GpuTransportParams>() == 80);
};