Fix RNG transmutation
This commit is contained in:
@@ -43,7 +43,7 @@ pub fn main() -> Result<()> {
|
|||||||
|
|
||||||
main_chaos_game(
|
main_chaos_game(
|
||||||
ITERATIONS_DISCARD,
|
ITERATIONS_DISCARD,
|
||||||
&[4u8],
|
&[4u8; 32],
|
||||||
&transforms,
|
&transforms,
|
||||||
&weights,
|
&weights,
|
||||||
&variations,
|
&variations,
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ impl<'a, R: Rng> Iterator for ChaosGame<'a, R> {
|
|||||||
/// Shader entry point for running the chaos game to produce new IFS coordinates
|
/// Shader entry point for running the chaos game to produce new IFS coordinates
|
||||||
pub mod entry {
|
pub mod entry {
|
||||||
use crate::chaos_game::ChaosGame;
|
use crate::chaos_game::ChaosGame;
|
||||||
use crate::rng::xoshiro_from_state;
|
use crate::rng::xoshiro256starstar_from_seed;
|
||||||
use crate::transform::Transform;
|
use crate::transform::Transform;
|
||||||
use crate::variation::Variation;
|
use crate::variation::Variation;
|
||||||
use glam::Vec2;
|
use glam::Vec2;
|
||||||
@@ -121,15 +121,16 @@ pub mod entry {
|
|||||||
#[spirv(compute(entry_point_name = "main_chaos_game", threads(1)))]
|
#[spirv(compute(entry_point_name = "main_chaos_game", threads(1)))]
|
||||||
pub fn main_chaos_game(
|
pub fn main_chaos_game(
|
||||||
#[spirv(spec_constant(id = 1, default = 20))] iteration_discard: u32,
|
#[spirv(spec_constant(id = 1, default = 20))] iteration_discard: u32,
|
||||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] _rng_seed: &[u8],
|
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] rng_seed: &[u8],
|
||||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] transforms: &[Transform],
|
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] transforms: &[Transform],
|
||||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 2)] weights: &[f32],
|
#[spirv(storage_buffer, descriptor_set = 0, binding = 2)] weights: &[f32],
|
||||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 3)] variations: &[Variation],
|
#[spirv(storage_buffer, descriptor_set = 0, binding = 3)] variations: &[Variation],
|
||||||
#[spirv(storage_buffer, descriptor_set = 1, binding = 0)] output: &mut [Vec2],
|
#[spirv(storage_buffer, descriptor_set = 1, binding = 0)] output: &mut [Vec2],
|
||||||
) {
|
) {
|
||||||
let rng_seed_actual = [0u8; 32];
|
let mut rng_seed_actual = [0u8; 32];
|
||||||
|
(0..32).for_each(|i| rng_seed_actual[i] = rng_seed[i]);
|
||||||
|
|
||||||
let mut rng = xoshiro_from_state(rng_seed_actual);
|
let mut rng = xoshiro256starstar_from_seed(rng_seed_actual);
|
||||||
let mut chaos_game = ChaosGame::new(&mut rng, transforms, weights, variations);
|
let mut chaos_game = ChaosGame::new(&mut rng, transforms, weights, variations);
|
||||||
|
|
||||||
for _ in 0..iteration_discard {
|
for _ in 0..iteration_discard {
|
||||||
|
|||||||
@@ -14,9 +14,42 @@ use rand_xoshiro::Xoshiro256StarStar;
|
|||||||
/// This function assumes a properly-initialized state array;
|
/// This function assumes a properly-initialized state array;
|
||||||
/// output may silently degenerate if the initial state is all zeros,
|
/// output may silently degenerate if the initial state is all zeros,
|
||||||
/// so this module is private to the crate.
|
/// so this module is private to the crate.
|
||||||
pub(crate) fn xoshiro_from_state(
|
pub(crate) fn xoshiro256starstar_from_seed(
|
||||||
_rng_state: <Xoshiro256StarStar as SeedableRng>::Seed,
|
rng_state: <Xoshiro256StarStar as SeedableRng>::Seed,
|
||||||
) -> Xoshiro256StarStar {
|
) -> Xoshiro256StarStar {
|
||||||
let rng_state_actual = [1u64, 2u64, 3u64, 4u64];
|
let mut rng_state_actual = [0u64; 4];
|
||||||
|
|
||||||
|
// NOTE: Bit shifting is bad, but we don't have great alternatives:
|
||||||
|
// - `chunks_exact` has issues with pointer casting
|
||||||
|
// - `u64::from_le_bytes` has issues with `OpBitcast` in SPIR-V validation
|
||||||
|
for i in 0..rng_state_actual.len() {
|
||||||
|
for j in 0..size_of::<u64>() {
|
||||||
|
rng_state_actual[i] |= (rng_state[i * size_of::<u64>() + j] as u64) << j * 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe { core::mem::transmute(rng_state_actual) }
|
unsafe { core::mem::transmute(rng_state_actual) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use crate::rng::xoshiro256starstar_from_seed;
|
||||||
|
use core::iter::zip;
|
||||||
|
use rand::{RngExt, SeedableRng};
|
||||||
|
use rand_xoshiro::Xoshiro256StarStar;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn match_seeded() {
|
||||||
|
let mut seed: <Xoshiro256StarStar as SeedableRng>::Seed = [0u8; 32];
|
||||||
|
for i in 0..seed.len() {
|
||||||
|
seed[i] = i as u8;
|
||||||
|
}
|
||||||
|
|
||||||
|
let rng1 = Xoshiro256StarStar::from_seed(seed).random_iter::<u64>();
|
||||||
|
let rng2 = xoshiro256starstar_from_seed(seed).random_iter::<u64>();
|
||||||
|
|
||||||
|
zip(rng1, rng2)
|
||||||
|
.take(100)
|
||||||
|
.for_each(|(rng1_value, rng2_value)| assert_eq!(rng1_value, rng2_value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user