From 44099dffa99e1e813d04c84d6915f68d754a3aa1 Mon Sep 17 00:00:00 2001 From: Wito Wiala Date: Tue, 19 May 2026 22:54:27 +0100 Subject: [PATCH] Plowing straight ahead --- shared/src/core/color.rs | 12 +++---- shared/src/lib.rs | 2 +- shared/src/spectra/colorspace.rs | 4 +-- shared/src/utils/alloc.rs | 9 ++++- shared/src/utils/math.rs | 6 ++++ src/core/texture.rs | 2 ++ src/samplers/halton.rs | 2 +- src/shapes/mesh.rs | 12 +++---- src/spectra/colorspace.rs | 15 ++++---- src/spectra/data.rs | 27 +++------------ src/spectra/mod.rs | 22 ++++++------ src/utils/math.rs | 59 -------------------------------- src/utils/mod.rs | 25 ++++++++++++++ src/utils/parameters.rs | 16 ++++----- 14 files changed, 87 insertions(+), 126 deletions(-) delete mode 100644 src/utils/math.rs diff --git a/shared/src/core/color.rs b/shared/src/core/color.rs index 5064fbf..c45f972 100644 --- a/shared/src/core/color.rs +++ b/shared/src/core/color.rs @@ -1045,7 +1045,7 @@ const SRGB_TO_LINEAR_LUT: [Float; 256] = [ pub const RES: u32 = 64; #[repr(C)] -#[derive(Clone, Copy, Debug, Default)] +#[derive(Clone, Copy, Debug, Default, PartialEq)] pub struct Coeffs { pub c0: Float, pub c1: Float, @@ -1099,10 +1099,10 @@ impl Mul for Coeffs { } #[repr(C)] -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub struct RGBToSpectrumTable { - pub z_nodes: Ptr, - pub coeffs: Ptr, + pub z_nodes: GVec, + pub coeffs: GVec, pub n_nodes: u32, } @@ -1113,7 +1113,7 @@ impl RGBToSpectrumTable { #[inline(always)] fn get_coeffs(&self, bucket: u32, z: u32, y: u32, x: u32) -> Coeffs { let offset = bucket * (RES * RES * RES) + z * (RES * RES) + y * (RES) + x; - unsafe { *self.coeffs.add(offset as usize) } + unsafe { *self.coeffs.as_ptr().add(offset as usize) } } pub fn evaluate(&self, rgb: RGB) -> RGBSigmoidPolynomial { @@ -1153,7 +1153,7 @@ impl RGBToSpectrumTable { let x = coord_a / z; let y = coord_b / z; - let z_nodes = unsafe { core::slice::from_raw_parts(self.z_nodes.as_raw(), RES as usize) }; + let z_nodes = &self.z_nodes; let zi = find_interval(RES, |i| z_nodes[i as usize] < z) as usize; let dz = (z - z_nodes[zi]) / (z_nodes[zi + 1] - z_nodes[zi]); let x_float = x * (RES - 1) as Float; diff --git a/shared/src/lib.rs b/shared/src/lib.rs index 2e9d39c..b6160f5 100644 --- a/shared/src/lib.rs +++ b/shared/src/lib.rs @@ -18,5 +18,5 @@ pub mod textures; pub mod utils; pub use core::pbrt::*; -pub use utils::alloc::{gbox, gvec, gvec_from_slice, gvec_with_capacity, GVec, GBox}; +pub use utils::alloc::{gbox, gvec, gvec_from_slice, gvec_with_capacity, leak, GBox, GVec}; pub use utils::{Array2D, PBRTOptions, Ptr, Transform}; diff --git a/shared/src/spectra/colorspace.rs b/shared/src/spectra/colorspace.rs index f2f1e19..24b72ec 100644 --- a/shared/src/spectra/colorspace.rs +++ b/shared/src/spectra/colorspace.rs @@ -62,7 +62,7 @@ impl ColorSpaceId { } #[repr(C)] -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Copy)] pub struct RGBColorSpace { pub r: Point2f, pub g: Point2f, @@ -71,7 +71,7 @@ pub struct RGBColorSpace { pub xyz_from_rgb: SquareMatrix3f, pub rgb_from_xyz: SquareMatrix3f, pub illuminant: Ptr, - pub rgb_to_spectrum_table: RGBToSpectrumTable, + pub rgb_to_spectrum_table: Ptr, } unsafe impl Send for RGBColorSpace {} diff --git a/shared/src/utils/alloc.rs b/shared/src/utils/alloc.rs index 1b55e7d..724d994 100644 --- a/shared/src/utils/alloc.rs +++ b/shared/src/utils/alloc.rs @@ -1,8 +1,9 @@ extern crate alloc; +use crate::utils::ptr::Ptr; use alloc::alloc::Global; -use alloc::vec::Vec; use alloc::boxed::Box; +use alloc::vec::Vec; use core::alloc::{AllocError, Allocator, Layout}; use core::ptr::NonNull; @@ -200,3 +201,9 @@ pub fn gvec_from_slice(slice: &[T]) -> GVec { pub fn gbox(value: T) -> GBox { Box::new_in(value, GpuAlloc::default()) } + +pub fn leak(val: T) -> Ptr { + let b = gbox(val); + let leaked: &'static T = Box::leak(b); + Ptr::from(leaked) +} diff --git a/shared/src/utils/math.rs b/shared/src/utils/math.rs index ff75ec3..2c43f1c 100644 --- a/shared/src/utils/math.rs +++ b/shared/src/utils/math.rs @@ -827,6 +827,12 @@ impl DigitPermutation { } } +pub fn compute_radical_inverse_permutations(seed: u64) -> GVec { + let mut result = gvec(); + result.extend(PRIMES.iter().map(|&base| DigitPermutation::new(base as i32, seed))); + result +} + pub fn scrambled_radical_inverse(base_index: u32, mut a: u64, perm: &DigitPermutation) -> Float { let base = PRIMES[base_index as usize] as u64; diff --git a/src/core/texture.rs b/src/core/texture.rs index 1de74fa..252e120 100644 --- a/src/core/texture.rs +++ b/src/core/texture.rs @@ -40,6 +40,7 @@ pub enum FloatTexture { Mix(FloatMixTexture), DirectionMix(FloatDirectionMixTexture), // #[device(custom = "upload_image", variant_type = "GPUFloatImageTexture")] + Scaled(FloatScaledTexture) Image(FloatImageTexture), Bilerp(FloatBilerpTexture), } @@ -105,6 +106,7 @@ impl FloatTexture { } } +#[derive(Clone, Debug)] pub enum SpectrumTexture { Constant(SpectrumConstantTexture), Checkerboard(SpectrumCheckerboardTexture), diff --git a/src/samplers/halton.rs b/src/samplers/halton.rs index fedff0b..85da4fb 100644 --- a/src/samplers/halton.rs +++ b/src/samplers/halton.rs @@ -1,6 +1,6 @@ use super::*; use crate::globals::get_options; -use crate::utils::math::compute_radical_inverse_permutations; +use shared::utils::math::compute_radical_inverse_permutations; use anyhow::{Result, anyhow}; use shared::core::geometry::Point2i; use shared::core::sampler::{HaltonSampler, MAX_HALTON_RESOLUTION, RandomizeStrategy}; diff --git a/src/shapes/mesh.rs b/src/shapes/mesh.rs index 25d7e67..d43d5b1 100644 --- a/src/shapes/mesh.rs +++ b/src/shapes/mesh.rs @@ -258,12 +258,12 @@ impl TriQuadMesh { TriangleMesh::new( render_from_object, reverse_orientation, - self.tri_indices, - self.p, - self.n, - Vec::new(), - self.uv, - self.face_indices, + &self.tri_indices, + &self.p, + &self.n, + &Vec::new(), + &self.uv, + &self.face_indices, ) } } diff --git a/src/spectra/colorspace.rs b/src/spectra/colorspace.rs index 109e732..bf8efb9 100644 --- a/src/spectra/colorspace.rs +++ b/src/spectra/colorspace.rs @@ -12,8 +12,8 @@ pub trait CreateRGBColorSpace { r: Point2f, g: Point2f, b: Point2f, - illuminant: Arc, - rgb_to_spectrum_table: Ptr, + illuminant: &DenselySampledSpectrum, + rgb_to_spectrum_table: &RGBToSpectrumTable, ) -> Self; } @@ -22,11 +22,12 @@ impl CreateRGBColorSpace for RGBColorSpace { r: Point2f, g: Point2f, b: Point2f, - illuminant: Arc, - rgb_to_spectrum_table: Ptr, + illuminant: &DenselySampledSpectrum, + rgb_to_spectrum_table: &RGBToSpectrumTable, ) -> Self { let stdspec = get_spectra_context(); - let illum_spectrum = Spectrum::Dense(illuminant.as_ref().clone()); + let illum_ptr = Ptr::from(illuminant); + let illum_spectrum = Spectrum::Dense(illuminant); let w_xyz: XYZ = illum_spectrum.to_xyz(&stdspec); let w = w_xyz.xy(); @@ -49,8 +50,8 @@ impl CreateRGBColorSpace for RGBColorSpace { g, b, w, - illuminant: Ptr::from(illuminant.as_ref()), - rgb_to_spectrum_table, + illuminant: illum_ptr, + rgb_to_spectrum_table: Ptr::from(rgb_to_spectrum_table), xyz_from_rgb, rgb_from_xyz, } diff --git a/src/spectra/data.rs b/src/spectra/data.rs index 7e64341..3641095 100644 --- a/src/spectra/data.rs +++ b/src/spectra/data.rs @@ -1,7 +1,7 @@ -use shared::Float; use shared::core::spectrum::Spectrum; use shared::spectra::cie::*; -use shared::spectra::{PiecewiseLinearSpectrum, DenselySampledSpectrum}; +use shared::spectra::{DenselySampledSpectrum, PiecewiseLinearSpectrum}; +use shared::{gbox, leak, Float, Ptr}; use std::collections::HashMap; use std::sync::LazyLock; @@ -17,7 +17,7 @@ pub fn create_cie(data: &[Float]) -> DenselySampledSpectrum { .collect(); let buffer = PiecewiseLinearSpectrum::new(lambdas, data.to_vec()); - let spec = Spectrum::Piecewise(buffer); + let spec = Spectrum::Piecewise(Ptr::from(&*buffer)); DenselySampledSpectrum::from_spectrum(&spec) } @@ -27,7 +27,7 @@ pub static NAMED_SPECTRA: LazyLock> = LazyLock::new(|| macro_rules! add { ($name:expr, $data:expr, $norm:expr) => { let buffer = PiecewiseLinearSpectrum::from_interleaved($data, $norm); - let spectrum = Spectrum::Piecewise(buffer); + let spectrum = Spectrum::Piecewise(leak(buffer)); m.insert($name.to_string(), spectrum); }; } @@ -49,7 +49,6 @@ pub static NAMED_SPECTRA: LazyLock> = LazyLock::new(|| add!("stdillum-F12", &CIE_ILLUM_F12, true); add!("illum-acesD60", &ACES_ILLUM_D60, true); - // --- Glasses --- add!("glass-BK7", &GLASS_BK7_ETA, false); add!("glass-BAF10", &GLASS_BAF10_ETA, false); add!("glass-FK51A", &GLASS_FK51A_ETA, false); @@ -58,7 +57,6 @@ pub static NAMED_SPECTRA: LazyLock> = LazyLock::new(|| add!("glass-F10", &GLASS_SF10_ETA, false); add!("glass-F11", &GLASS_SF11_ETA, false); - // --- Metals --- add!("metal-Ag-eta", &AG_ETA, false); add!("metal-Ag-k", &AG_K, false); add!("metal-Al-eta", &AL_ETA, false); @@ -74,87 +72,70 @@ pub static NAMED_SPECTRA: LazyLock> = LazyLock::new(|| add!("metal-TiO2-eta", &TIO2_ETA, false); add!("metal-TiO2-k", &TIO2_K, false); - // --- Canon EOS 100D --- add!("canon_eos_100d_r", &CANON_EOS_100D_R, false); add!("canon_eos_100d_g", &CANON_EOS_100D_G, false); add!("canon_eos_100d_b", &CANON_EOS_100D_B, false); - // --- Canon EOS 1DX MkII --- add!("canon_eos_1dx_mkii_r", &CANON_EOS_1DX_MKII_R, false); add!("canon_eos_1dx_mkii_g", &CANON_EOS_1DX_MKII_G, false); add!("canon_eos_1dx_mkii_b", &CANON_EOS_1DX_MKII_B, false); - // --- Canon EOS 200D --- add!("canon_eos_200d_r", &CANON_EOS_200D_R, false); add!("canon_eos_200d_g", &CANON_EOS_200D_G, false); add!("canon_eos_200d_b", &CANON_EOS_200D_B, false); - // --- Canon EOS 200D MkII --- add!("canon_eos_200d_mkii_r", &CANON_EOS_200D_MKII_R, false); add!("canon_eos_200d_mkii_g", &CANON_EOS_200D_MKII_G, false); add!("canon_eos_200d_mkii_b", &CANON_EOS_200D_MKII_B, false); - // --- Canon EOS 5D --- add!("canon_eos_5d_r", &CANON_EOS_5D_R, false); add!("canon_eos_5d_g", &CANON_EOS_5D_G, false); add!("canon_eos_5d_b", &CANON_EOS_5D_B, false); - // --- Canon EOS 5D MkII --- add!("canon_eos_5d_mkii_r", &CANON_EOS_5D_MKII_R, false); add!("canon_eos_5d_mkii_g", &CANON_EOS_5D_MKII_G, false); add!("canon_eos_5d_mkii_b", &CANON_EOS_5D_MKII_B, false); - // --- Canon EOS 5D MkIII --- add!("canon_eos_5d_mkiii_r", &CANON_EOS_5D_MKIII_R, false); add!("canon_eos_5d_mkiii_g", &CANON_EOS_5D_MKIII_G, false); add!("canon_eos_5d_mkiii_b", &CANON_EOS_5D_MKIII_B, false); - // --- Canon EOS 5D MkIV --- add!("canon_eos_5d_mkiv_r", &CANON_EOS_5D_MKIV_R, false); add!("canon_eos_5d_mkiv_g", &CANON_EOS_5D_MKIV_G, false); add!("canon_eos_5d_mkiv_b", &CANON_EOS_5D_MKIV_B, false); - // --- Canon EOS 5DS --- add!("canon_eos_5ds_r", &CANON_EOS_5DS_R, false); add!("canon_eos_5ds_g", &CANON_EOS_5DS_G, false); add!("canon_eos_5ds_b", &CANON_EOS_5DS_B, false); - // --- Canon EOS M --- add!("canon_eos_m_r", &CANON_EOS_M_R, false); add!("canon_eos_m_g", &CANON_EOS_M_G, false); add!("canon_eos_m_b", &CANON_EOS_M_B, false); - // --- Hasselblad L1D 20C --- add!("hasselblad_l1d_20c_r", &HASSELBLAD_L1D_20C_R, false); add!("hasselblad_l1d_20c_g", &HASSELBLAD_L1D_20C_G, false); add!("hasselblad_l1d_20c_b", &HASSELBLAD_L1D_20C_B, false); - // --- Nikon D810 --- add!("nikon_d810_r", &NIKON_D810_R, false); add!("nikon_d810_g", &NIKON_D810_G, false); add!("nikon_d810_b", &NIKON_D810_B, false); - // --- Nikon D850 --- add!("nikon_d850_r", &NIKON_D850_R, false); add!("nikon_d850_g", &NIKON_D850_G, false); add!("nikon_d850_b", &NIKON_D850_B, false); - // --- Sony ILCE 6400 --- add!("sony_ilce_6400_r", &SONY_ILCE_6400_R, false); add!("sony_ilce_6400_g", &SONY_ILCE_6400_G, false); add!("sony_ilce_6400_b", &SONY_ILCE_6400_B, false); - // --- Sony ILCE 7M3 --- add!("sony_ilce_7m3_r", &SONY_ILCE_7M3_R, false); add!("sony_ilce_7m3_g", &SONY_ILCE_7M3_G, false); add!("sony_ilce_7m3_b", &SONY_ILCE_7M3_B, false); - // --- Sony ILCE 7RM3 --- add!("sony_ilce_7rm3_r", &SONY_ILCE_7RM3_R, false); add!("sony_ilce_7rm3_g", &SONY_ILCE_7RM3_G, false); add!("sony_ilce_7rm3_b", &SONY_ILCE_7RM3_B, false); - // --- Sony ILCE 9 --- add!("sony_ilce_9_r", &SONY_ILCE_9_R, false); add!("sony_ilce_9_g", &SONY_ILCE_9_G, false); add!("sony_ilce_9_b", &SONY_ILCE_9_B, false); diff --git a/src/spectra/mod.rs b/src/spectra/mod.rs index 9d89680..4782c93 100644 --- a/src/spectra/mod.rs +++ b/src/spectra/mod.rs @@ -28,19 +28,16 @@ fn get_d65_illuminant_buffer() -> Arc { } pub fn cie_x() -> Spectrum { - Spectrum::Dense(CIE_X_DATA) + Spectrum::Dense(Ptr::from(&*CIE_X_DATA)) } - pub fn cie_y() -> Spectrum { - Spectrum::Dense(CIE_Y_DATA) + Spectrum::Dense(Ptr::from(&*CIE_Y_DATA)) } - pub fn cie_z() -> Spectrum { - Spectrum::Dense(CIE_Z_DATA) + Spectrum::Dense(Ptr::from(&*CIE_Z_DATA)) } - pub fn cie_d65() -> Spectrum { - Spectrum::Dense(CIE_D65_DATA) + Spectrum::Dense(Ptr::from(&*CIE_D65_DATA)) } pub fn get_spectra_context() -> StandardSpectra { @@ -52,6 +49,7 @@ pub fn get_spectra_context() -> StandardSpectra { } } + pub static SRGB: LazyLock> = LazyLock::new(|| { let illum = get_d65_illuminant_buffer(); let r = Point2f::new(0.64, 0.33); @@ -85,7 +83,7 @@ pub static ACES: LazyLock> = LazyLock::new(|| { let r = Point2f::new(0.7347, 0.2653); let g = Point2f::new(0.0000, 1.0000); let b = Point2f::new(0.0001, -0.0770); - let table_ptr = Ptr::from(&ACES_TABLE.view); + let table_ptr = Ptr::from(&ACES_TABLE); Arc::new(RGBColorSpace::new(r, g, b, illum, table_ptr)) }); @@ -120,10 +118,10 @@ pub fn get_colorspace_context() -> StandardColorSpaces { pub fn get_colorspace_device() -> DeviceStandardColorSpaces { DeviceStandardColorSpaces { - srgb: Ptr::from(&*SRGB), - dci_p3: Ptr::from(&*DCI_P3), - rec2020: Ptr::from(&*REC2020), - aces2065_1: Ptr::from(&*ACES), + srgb: Ptr::from(&**SRGB), + dci_p3: Ptr::from(&**DCI_P3), + rec2020: Ptr::from(&**REC2020), + aces2065_1: Ptr::from(&**ACES), } } diff --git a/src/utils/math.rs b/src/utils/math.rs deleted file mode 100644 index eb3f2b5..0000000 --- a/src/utils/math.rs +++ /dev/null @@ -1,59 +0,0 @@ -use half::f16; -use shared::utils::hash::hash_buffer; -use shared::utils::math::{permutation_element, DigitPermutation, PRIMES}; -use shared::Float; - -#[inline(always)] -pub fn f16_to_f32(bits: u16) -> f32 { - #[cfg(feature = "cuda")] - { - // Use hardware intrinsic on CUDA - // Cast bits to cuda_f16, then cast to f32 - let half_val = unsafe { core::mem::transmute::(bits) }; - half_val.to_f32() - } - - #[cfg(feature = "vulkan")] - { - // Use shared logic or spirv-std intrinsics if available. - // Sadly, f16 support in rust-gpu is still maturing. - // A manual bit-conversion function is often safest here. - f16_to_f32_software(bits) - } - - #[cfg(not(any(feature = "cuda", feature = "vulkan")))] - { - f16::from_bits(bits).to_f32() - } -} - - -pub fn compute_radical_inverse_permutations(seed: u64) -> (Vec, Vec) { - let temp_data: Vec> = PRIMES - .iter() - .map(|&base| DigitPermutation::new(base as i32, seed).permutations) - .collect(); - let mut storage: Vec = Vec::with_capacity(temp_data.iter().map(|v| v.len()).sum()); - - for vec in &temp_data { - storage.extend_from_slice(vec); - } - - let mut views = Vec::with_capacity(PRIMES.len()); - // let mut current_offset = 0; - - // let storage_base_ptr = storage.as_ptr(); - - for (i, &base) in PRIMES.iter().enumerate() { - let len = temp_data[i].len(); - let n_digits = len as u32 / base as u32; - - // let ptr_to_data = storage_base_ptr.add(current_offset); - - views.push(DigitPermutation::new(base as i32, n_digits as u64)); - - // current_offset += len; - } - - (storage, views) -} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index b4e70d6..06c6280 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -28,3 +28,28 @@ pub type Arena = arena::Arena; #[cfg(not(any(feature = "cuda", feature = "vulkan")))] pub type Arena = arena::Arena; + +use half::f16; + +#[inline(always)] +pub fn f16_to_f32(bits: u16) -> f32 { + #[cfg(feature = "cuda")] + { + // Use hardware intrinsic on CUDA + // Cast bits to cuda_f16, then cast to f32 + let half_val = unsafe { core::mem::transmute::(bits) }; + half_val.to_f32() + } + + #[cfg(feature = "vulkan")] + { + // Use shared logic or spirv-std intrinsics if available. + // Keep an eye on rust-gpu + f16_to_f32_software(bits) + } + + #[cfg(not(any(feature = "cuda", feature = "vulkan")))] + { + f16::from_bits(bits).to_f32() + } +} diff --git a/src/utils/parameters.rs b/src/utils/parameters.rs index db4cd77..dcc1e17 100644 --- a/src/utils/parameters.rs +++ b/src/utils/parameters.rs @@ -1,7 +1,7 @@ use crate::core::spectrum::SPECTRUM_FILE_CACHE; -use crate::spectra::piecewise::ReadFromFile; use crate::core::texture::{FloatTexture, SpectrumTexture}; use crate::spectra::data::get_named_spectrum; +use crate::spectra::piecewise::ReadFromFile; use crate::utils::FileLoc; use anyhow::{bail, Result}; use shared::core::color::RGB; @@ -655,11 +655,11 @@ impl ParameterDictionary { }) .unzip(); - vec![Spectrum::Piecewise(PiecewiseLinearSpectrum { - lambdas: lambdas.as_ptr().into(), - values: values.as_ptr().into(), + vec![Spectrum::Piecewise(leak(PiecewiseLinearSpectrum { + lambdas: gvec_from_slice(lambdas), + values: gvec_from_slice(values), count: lambdas.len() as u32, - })] + }))] } fn extract_file_spectrum(&self, param: &ParsedParameter) -> Vec { @@ -681,18 +681,18 @@ fn read_spectrum_from_file(filename: &str) -> Result { { let cache = SPECTRUM_FILE_CACHE.lock(); if let Some(s) = cache.get(&fn_key) { - return Ok(s.clone()); + return Ok(*s); // Spectrum is Copy, so just copy it } } let pls = PiecewiseLinearSpectrum::read(&fn_key) .ok_or_else(|| format!("unable to read or parse spectrum file '{}'", fn_key))?; - let spectrum = Spectrum::Piecewise(*pls); + let spectrum = Spectrum::Piecewise(leak(pls)); { let mut cache = SPECTRUM_FILE_CACHE.lock(); - cache.insert(fn_key, spectrum.clone()); + cache.insert(fn_key, spectrum); } Ok(spectrum)