spirv: sim: adjust so Step{E,H}Context does not use ArrayHandle

the specific way to accomplish this is touchy.
see <https://github.com/EmbarkStudios/rust-gpu/issues/312#issuecomment-738824131>:

> So I'd say placing any of the spirv_std::storage_class types into an aggregate (including capturing it in a closure) is unsupported for now

in our specific case, we can't return a tuple where one element is a `&`
to a spirv Input, and another element is a `&mut` to a spirv Output.

when we have a struct, it can enclose either ONLY inputs,
or ONLY outputs -- not a mix.

i'm not 100% on how the Serialized stuff works, since it appears to
violate that. i guess that's exactly what this ArrayHandle stuff
achieves though.
This commit is contained in:
2022-07-24 22:57:41 -07:00
parent 05f5f75dd3
commit ebd2762d7a
3 changed files with 61 additions and 53 deletions

View File

@@ -39,10 +39,9 @@ fn step_h<R: Real, M: Material<R>>(
) { ) {
if id.x() < meta.dim.x() && id.y() < meta.dim.y() && id.z() < meta.dim.z() { if id.x() < meta.dim.x() && id.y() < meta.dim.y() && id.z() < meta.dim.z() {
let sim_state = SerializedStepH::new(meta, stimulus_h, material, e, h, m); let sim_state = SerializedStepH::new(meta, stimulus_h, material, e, h, m);
let (update_state, mut out_h, mut out_m) = sim_state.index(id); let update_state = sim_state.index(id);
let (new_h, new_m) = update_state.step_h(); let (new_h, new_m) = update_state.step_h();
out_h.write(new_h); sim_state.write_output(id, new_h, new_m);
out_m.write(new_m);
} }
} }
@@ -57,9 +56,9 @@ fn step_e<R: Real, M: Material<R>>(
if id.x() < meta.dim.x() && id.y() < meta.dim.y() && id.z() < meta.dim.z() { if id.x() < meta.dim.x() && id.y() < meta.dim.y() && id.z() < meta.dim.z() {
let sim_state = SerializedStepE::new(meta, stimulus_e, material, e, h); let sim_state = SerializedStepE::new(meta, stimulus_e, material, e, h);
let (update_state, mut out_e) = sim_state.index(id); let update_state = sim_state.index(id);
let new_e = update_state.step_e(); let new_e = update_state.step_e();
out_e.write(new_e); sim_state.write_output(id, new_e);
} }
} }

View File

@@ -1,6 +1,6 @@
// use spirv_std::RuntimeArray; // use spirv_std::RuntimeArray;
use crate::support::{ use crate::support::{
Array3, Array3Mut, ArrayHandle, ArrayHandleMut, Optional, UnsizedArray Array3, Array3Mut, Optional, UnsizedArray
}; };
use coremem_types::mat::Material; use coremem_types::mat::Material;
use coremem_types::real::Real; use coremem_types::real::Real;
@@ -41,19 +41,14 @@ impl<'a, R, M> SerializedStepH<'a, R, M> {
} }
impl<'a, R: Real, M> SerializedStepH<'a, R, M> { impl<'a, R: Real, M> SerializedStepH<'a, R, M> {
/// returns a context which the user can call `step_h` on, /// returns a context which the user can call `step_h` on
/// plus output handles which the the results can be written to. pub fn index(&self, idx: Vec3u) -> StepHContext<'a, R, M> {
pub fn index(self, idx: Vec3u) -> (
StepHContext<'a, R, M>,
ArrayHandleMut<'a, Vec3<R>>, // out_h
ArrayHandleMut<'a, Vec3<R>>, // out_m
){
let dim = self.meta.dim; let dim = self.meta.dim;
let stim_h_matrix = Array3::new(self.stimulus_h, dim); let stim_h_matrix = Array3::new(self.stimulus_h, dim);
let mat_matrix = Array3::new(self.material, dim); let mat_matrix = Array3::new(self.material, dim);
let e = Array3::new(self.e, dim); let e = Array3::new(self.e, dim);
let h = Array3Mut::new(self.h, dim); let h = Array3::new(self.h, dim);
let m = Array3Mut::new(self.m, dim); let m = Array3::new(self.m, dim);
let in_e = VolumeSamplePos { let in_e = VolumeSamplePos {
mid: e.get(idx).unwrap(), mid: e.get(idx).unwrap(),
@@ -61,24 +56,30 @@ impl<'a, R: Real, M> SerializedStepH<'a, R, M> {
yp1: e.get(idx + Vec3u::unit_y()), yp1: e.get(idx + Vec3u::unit_y()),
zp1: e.get(idx + Vec3u::unit_z()), zp1: e.get(idx + Vec3u::unit_z()),
}; };
let out_h = h.into_mut_handle(idx); let in_h = h.get(idx).unwrap();
let out_m = m.into_mut_handle(idx); let in_m = m.get(idx).unwrap();
let mat = mat_matrix.into_handle(idx); let mat = mat_matrix.into_ref(idx);
( StepHContext {
StepHContext { inv_feature_size: self.meta.inv_feature_size,
inv_feature_size: self.meta.inv_feature_size, time_step: self.meta.time_step,
time_step: self.meta.time_step, stim_h: stim_h_matrix.get(idx).unwrap(),
stim_h: stim_h_matrix.get(idx).unwrap(), mat,
mat, in_e,
in_e, in_h,
in_h: out_h.get(), in_m,
in_m: out_m.get(), }
}, }
out_h,
out_m, pub fn write_output(self, idx: Vec3u, h: Vec3<R>, m: Vec3<R>) {
) let dim = self.meta.dim;
let arr_h = Array3Mut::new(self.h, dim);
let arr_m = Array3Mut::new(self.m, dim);
let mut out_h = arr_h.into_mut_handle(idx);
let mut out_m = arr_m.into_mut_handle(idx);
out_h.write(h);
out_m.write(m);
} }
} }
@@ -106,14 +107,11 @@ impl<'a, R, M> SerializedStepE<'a, R, M> {
} }
impl<'a, R: Real, M> SerializedStepE<'a, R, M> { impl<'a, R: Real, M> SerializedStepE<'a, R, M> {
pub fn index(self, idx: Vec3u) -> ( pub fn index(&self, idx: Vec3u) -> StepEContext<'a, R, M> {
StepEContext<'a, R, M>,
ArrayHandleMut<'a, Vec3<R>> // out_e
){
let dim = self.meta.dim; let dim = self.meta.dim;
let stim_e_matrix = Array3::new(self.stimulus_e, dim); let stim_e_matrix = Array3::new(self.stimulus_e, dim);
let mat_matrix = Array3::new(self.material, dim); let mat_matrix = Array3::new(self.material, dim);
let e = Array3Mut::new(self.e, dim); let e = Array3::new(self.e, dim);
let h = Array3::new(self.h, dim); let h = Array3::new(self.h, dim);
let xm1 = if idx.x() == 0 { let xm1 = if idx.x() == 0 {
@@ -138,21 +136,25 @@ impl<'a, R: Real, M> SerializedStepE<'a, R, M> {
ym1, ym1,
zm1, zm1,
}; };
let out_e = e.into_mut_handle(idx); let in_e = e.get(idx).unwrap();
let mat = mat_matrix.into_handle(idx); let mat = mat_matrix.into_ref(idx);
( StepEContext {
StepEContext { inv_feature_size: self.meta.inv_feature_size,
inv_feature_size: self.meta.inv_feature_size, time_step: self.meta.time_step,
time_step: self.meta.time_step, stim_e: stim_e_matrix.get(idx).unwrap(),
stim_e: stim_e_matrix.get(idx).unwrap(), mat,
mat, in_h,
in_h, in_e,
in_e: out_e.get(), }
}, }
out_e,
) pub fn write_output(self, idx: Vec3u, e: Vec3<R>) {
let dim = self.meta.dim;
let arr_e = Array3Mut::new(self.e, dim);
let mut out_e = arr_e.into_mut_handle(idx);
out_e.write(e);
} }
} }
@@ -292,7 +294,7 @@ pub struct StepEContext<'a, R, M> {
inv_feature_size: R, inv_feature_size: R,
time_step: R, time_step: R,
stim_e: Vec3<R>, stim_e: Vec3<R>,
mat: ArrayHandle<'a, M>, mat: &'a M,
/// Input field sampled near this location /// Input field sampled near this location
in_h: VolumeSampleNeg<R>, in_h: VolumeSampleNeg<R>,
in_e: Vec3<R>, in_e: Vec3<R>,
@@ -307,7 +309,7 @@ impl<'a, R: Real, M: Material<R>> StepEContext<'a, R, M> {
// $\nabla x H = \epsilon_0 dE/dt + \sigma E$ // $\nabla x H = \epsilon_0 dE/dt + \sigma E$
// no-conductivity version: // no-conductivity version:
// let delta_e = nabla_h * (self.time_step * EPS0_INV); // let delta_e = nabla_h * (self.time_step * EPS0_INV);
let sigma = self.mat.get_ref().conductivity(); let sigma = self.mat.conductivity();
let e_prev = self.in_e; let e_prev = self.in_e;
let delta_e = (nabla_h - e_prev.elem_mul(sigma)).elem_div( let delta_e = (nabla_h - e_prev.elem_mul(sigma)).elem_div(
sigma*self.time_step + Vec3::uniform(twice_eps0) sigma*self.time_step + Vec3::uniform(twice_eps0)
@@ -322,7 +324,7 @@ pub struct StepHContext<'a, R, M> {
inv_feature_size: R, inv_feature_size: R,
time_step: R, time_step: R,
stim_h: Vec3<R>, stim_h: Vec3<R>,
mat: ArrayHandle<'a, M>, mat: &'a M,
/// Input field sampled near this location /// Input field sampled near this location
in_e: VolumeSamplePos<R>, in_e: VolumeSamplePos<R>,
in_h: Vec3<R>, in_h: Vec3<R>,
@@ -346,7 +348,7 @@ impl<'a, R: Real, M: Material<R>> StepHContext<'a, R, M> {
let old_b = (old_h + old_m) * mu0; let old_b = (old_h + old_m) * mu0;
let new_b = old_b + delta_b + self.stim_h * mu0; let new_b = old_b + delta_b + self.stim_h * mu0;
let mat = self.mat.get_ref(); let mat = self.mat;
let new_m = mat.move_b_vec(old_m, new_b); let new_m = mat.move_b_vec(old_m, new_b);
let new_h = new_b * mu0_inv - new_m; let new_h = new_b * mu0_inv - new_m;
// println!("spirv-step_h delta_h: {:?}", delta_h); // println!("spirv-step_h delta_h: {:?}", delta_h);

View File

@@ -211,6 +211,13 @@ impl<'a, T> Array3<'a, T> {
self.data.get_handle(idx) self.data.get_handle(idx)
} }
} }
pub fn into_ref(self, idx: Vec3u) -> &'a T {
let idx = checked_index(idx, self.dim).unwrap();
unsafe {
self.data.index_ref(idx)
}
}
} }
impl<'a, T: Copy + Default> Array3<'a, T> { impl<'a, T: Copy + Default> Array3<'a, T> {