spirv: get the optimized IsoConductorOr<Ferroxcube3R1> plumbed all the way through
buffer_proto5 example shows it in action (results weren't verified)
This commit is contained in:
@@ -719,4 +719,6 @@ fn main() {
|
||||
None => error!("skipping sim because no valid geometry: {:?}", params),
|
||||
}
|
||||
}
|
||||
|
||||
info!("done");
|
||||
}
|
||||
|
@@ -44,7 +44,7 @@ impl<R: Real, M: Default> Driver<SimState<R, M>> {
|
||||
}
|
||||
|
||||
impl<M: spirv::IntoFfi> SpirvDriver<M>
|
||||
where M::Ffi: Default
|
||||
where M::Ffi: Default + 'static
|
||||
{
|
||||
pub fn new_spirv<C: Coord>(size: C, feature_size: f32) -> Self {
|
||||
Self::new_with_state(SpirvSim::new(size.to_index(feature_size), feature_size))
|
||||
|
@@ -7,6 +7,7 @@ use crate::geom::{Index, Vec3, Vec3u};
|
||||
|
||||
/// hide the actual spirv backend structures inside a submodule to make their use/boundary clear.
|
||||
mod ffi {
|
||||
pub use spirv_backend_lib::entry_points;
|
||||
pub use spirv_backend_lib::sim::SerializedSimMeta;
|
||||
pub use spirv_backend_lib::support::{Optional, Vec3Std, UVec3Std};
|
||||
pub use spirv_backend_lib::mat::{Ferroxcube3R1MH, FullyGenericMaterial, IsoConductorOr, Material, MBPgram, MHPgram};
|
||||
@@ -34,6 +35,27 @@ pub trait IntoLib {
|
||||
fn into_lib(self) -> Self::Lib;
|
||||
}
|
||||
|
||||
macro_rules! identity {
|
||||
($($param:ident,)* => $t:ty) => {
|
||||
impl<$($param: IntoFfi),*> IntoFfi for $t {
|
||||
type Ffi = $t;
|
||||
fn into_ffi(self) -> Self::Ffi {
|
||||
self
|
||||
}
|
||||
}
|
||||
impl<$($param: IntoLib),*> IntoLib for $t {
|
||||
type Lib = $t;
|
||||
fn into_lib(self) -> Self::Lib {
|
||||
self
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// XXX: should work for any other lifetime, not just 'static
|
||||
identity!(=> &'static str);
|
||||
identity!(T0, T1, => (T0, T1));
|
||||
|
||||
impl<L: IntoFfi> IntoFfi for Option<L>
|
||||
where L::Ffi: Default
|
||||
{
|
||||
@@ -338,3 +360,12 @@ impl<'de, F> Deserialize<'de> for Remote<F>
|
||||
Ok(Remote(local.into_ffi()))
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION BINDINGS
|
||||
pub fn entry_points<L>() -> Option<(&'static str, &'static str)>
|
||||
where
|
||||
L: IntoFfi,
|
||||
L::Ffi: 'static
|
||||
{
|
||||
ffi::entry_points::<L::Ffi>().into_lib()
|
||||
}
|
||||
|
@@ -17,7 +17,7 @@ use crate::sim::{CellStateWithM, GenericSim, MaterialSim, Sample, SampleableSim}
|
||||
use crate::stim::AbstractStimulus;
|
||||
|
||||
mod bindings;
|
||||
pub use bindings::{IntoFfi, IntoLib, IsoConductorOr, FullyGenericMaterial, Remote, SimMeta, Material};
|
||||
pub use bindings::{entry_points, IntoFfi, IntoLib, IsoConductorOr, FullyGenericMaterial, Remote, SimMeta, Material};
|
||||
|
||||
/// Wrapper around an inner state object which offloads stepping onto a spirv backend (e.g. GPU).
|
||||
#[derive(Clone, Default, Serialize, Deserialize)]
|
||||
@@ -48,14 +48,17 @@ struct WgpuData {
|
||||
}
|
||||
|
||||
impl WgpuData {
|
||||
pub fn new<M>(volume: u64) -> Self {
|
||||
pub fn new<M: IntoFfi>(volume: u64) -> Self
|
||||
where M::Ffi: 'static
|
||||
{
|
||||
use std::mem::size_of;
|
||||
let max_elem_size = size_of::<M>().max(size_of::<Vec3<f32>>());
|
||||
let max_buf_size = volume * max_elem_size as u64 + 0x1000;
|
||||
let entry_names = entry_points::<M>().unwrap_or(("invalid_mat", "invalid_mat"));
|
||||
let (device, queue) = futures::executor::block_on(open_device(max_buf_size));
|
||||
let shader_binary = get_shader();
|
||||
let shader_module = unsafe { device.create_shader_module_spirv(&shader_binary) };
|
||||
let (step_bind_group_layout, step_h_pipeline, step_e_pipeline) = make_pipelines(&device, &shader_module);
|
||||
let (step_bind_group_layout, step_h_pipeline, step_e_pipeline) = make_pipelines(&device, &shader_module, entry_names);
|
||||
Self {
|
||||
step_bind_group_layout,
|
||||
step_h_pipeline,
|
||||
@@ -68,7 +71,7 @@ impl WgpuData {
|
||||
|
||||
impl Default for WgpuData {
|
||||
fn default() -> Self {
|
||||
Self::new::<()>(0)
|
||||
Self::new::<FullyGenericMaterial>(0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,10 +155,10 @@ where
|
||||
}
|
||||
|
||||
impl<M: IntoFfi> SpirvSim<M>
|
||||
where M::Ffi: Default
|
||||
where M::Ffi: Default + 'static
|
||||
{
|
||||
pub fn new(size: Index, feature_size: f32) -> Self {
|
||||
Self::new_with_wgpu_handle(size, feature_size, Some(Arc::new(WgpuData::new::<M::Ffi>(size.volume()))))
|
||||
Self::new_with_wgpu_handle(size, feature_size, Some(Arc::new(WgpuData::new::<M>(size.volume()))))
|
||||
}
|
||||
|
||||
pub fn new_no_wgpu(size: Index, feature_size: f32) -> Self {
|
||||
@@ -534,7 +537,7 @@ async fn open_device(max_buf_size: u64) -> (wgpu::Device, wgpu::Queue) {
|
||||
(device, queue)
|
||||
}
|
||||
|
||||
fn make_pipelines(device: &wgpu::Device, shader_module: &wgpu::ShaderModule) -> (
|
||||
fn make_pipelines(device: &wgpu::Device, shader_module: &wgpu::ShaderModule, entry_names: (&'static str, &'static str)) -> (
|
||||
wgpu::BindGroupLayout, wgpu::ComputePipeline, wgpu::ComputePipeline
|
||||
) {
|
||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
@@ -619,14 +622,14 @@ fn make_pipelines(device: &wgpu::Device, shader_module: &wgpu::ShaderModule) ->
|
||||
label: None,
|
||||
layout: Some(&pipeline_layout),
|
||||
module: shader_module,
|
||||
entry_point: "step_h_generic_material",
|
||||
entry_point: entry_names.0,
|
||||
});
|
||||
|
||||
let compute_step_e_pipeline = device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
|
||||
label: None,
|
||||
layout: Some(&pipeline_layout),
|
||||
module: shader_module,
|
||||
entry_point: "step_e_generic_material",
|
||||
entry_point: entry_names.1,
|
||||
});
|
||||
|
||||
(bind_group_layout, compute_step_h_pipeline, compute_step_e_pipeline)
|
||||
|
@@ -20,7 +20,9 @@ pub mod support;
|
||||
pub use sim::{SerializedSimMeta, SerializedStepE, SerializedStepH};
|
||||
pub use support::{Optional, UnsizedArray, UVec3Std, Vec3Std};
|
||||
|
||||
use mat::{FullyGenericMaterial, Material};
|
||||
use mat::{IsoConductorOr, Ferroxcube3R1MH, FullyGenericMaterial, Material};
|
||||
|
||||
type Iso3R1 = IsoConductorOr<Ferroxcube3R1MH>;
|
||||
|
||||
fn step_h<M: Material>(
|
||||
id: UVec3,
|
||||
@@ -53,31 +55,58 @@ fn step_e<M: Material>(
|
||||
}
|
||||
}
|
||||
|
||||
// LocalSize/numthreads
|
||||
#[spirv(compute(threads(4, 4, 4)))]
|
||||
pub fn step_h_generic_material(
|
||||
#[spirv(global_invocation_id)] id: UVec3,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] meta: &SerializedSimMeta,
|
||||
// XXX: delete this input?
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] _unused_stimulus: &UnsizedArray<Vec3Std>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 2)] material: &UnsizedArray<FullyGenericMaterial>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 3)] e: &UnsizedArray<Vec3Std>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 4)] h: &mut UnsizedArray<Vec3Std>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 5)] m: &mut UnsizedArray<Vec3Std>,
|
||||
) {
|
||||
step_h(id, meta, material, e, h, m)
|
||||
/// Return the step_h/step_e entry point names for the provided material
|
||||
pub fn entry_points<M: 'static>() -> Optional<(&'static str, &'static str)> {
|
||||
use core::any::TypeId;
|
||||
let mappings = [
|
||||
(TypeId::of::<FullyGenericMaterial>(),
|
||||
("step_h_generic_material", "step_e_generic_material")
|
||||
),
|
||||
(TypeId::of::<Iso3R1>(),
|
||||
("step_h_iso_3r1", "step_e_iso_3r1")
|
||||
),
|
||||
];
|
||||
|
||||
for (id, names) in mappings {
|
||||
if id == TypeId::of::<M>() {
|
||||
return Optional::some(names);
|
||||
}
|
||||
}
|
||||
Optional::none()
|
||||
}
|
||||
|
||||
#[spirv(compute(threads(4, 4, 4)))]
|
||||
pub fn step_e_generic_material(
|
||||
#[spirv(global_invocation_id)] id: UVec3,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] meta: &SerializedSimMeta,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] stimulus: &UnsizedArray<Vec3Std>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 2)] material: &UnsizedArray<FullyGenericMaterial>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 3)] e: &mut UnsizedArray<Vec3Std>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 4)] h: &UnsizedArray<Vec3Std>,
|
||||
// XXX: can/should this m input be deleted?
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 5)] _unused_m: &UnsizedArray<Vec3Std>,
|
||||
) {
|
||||
step_e(id, meta, stimulus, material, e, h)
|
||||
macro_rules! steps {
|
||||
($mat:ty, $step_h:ident, $step_e:ident) => {
|
||||
// LocalSize/numthreads
|
||||
#[spirv(compute(threads(4, 4, 4)))]
|
||||
pub fn $step_h(
|
||||
#[spirv(global_invocation_id)] id: UVec3,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] meta: &SerializedSimMeta,
|
||||
// XXX: delete this input?
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] _unused_stimulus: &UnsizedArray<Vec3Std>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 2)] material: &UnsizedArray<$mat>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 3)] e: &UnsizedArray<Vec3Std>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 4)] h: &mut UnsizedArray<Vec3Std>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 5)] m: &mut UnsizedArray<Vec3Std>,
|
||||
) {
|
||||
step_h(id, meta, material, e, h, m)
|
||||
}
|
||||
|
||||
#[spirv(compute(threads(4, 4, 4)))]
|
||||
pub fn $step_e(
|
||||
#[spirv(global_invocation_id)] id: UVec3,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] meta: &SerializedSimMeta,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] stimulus: &UnsizedArray<Vec3Std>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 2)] material: &UnsizedArray<$mat>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 3)] e: &mut UnsizedArray<Vec3Std>,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 4)] h: &UnsizedArray<Vec3Std>,
|
||||
// XXX: can/should this m input be deleted?
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 5)] _unused_m: &UnsizedArray<Vec3Std>,
|
||||
) {
|
||||
step_e(id, meta, stimulus, material, e, h)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
steps!(FullyGenericMaterial, step_h_generic_material, step_e_generic_material);
|
||||
steps!(Iso3R1, step_h_iso_3r1, step_e_iso_3r1);
|
||||
|
@@ -246,7 +246,8 @@ impl<M: Material + Copy> Material for IsoConductorOr<M> {
|
||||
}
|
||||
fn move_b_vec(&self, m: Vec3Std, target_b: Vec3Std) -> Vec3Std {
|
||||
if self.value < 0.0 {
|
||||
self.mat.move_b_vec(m, target_b)
|
||||
let mat = self.mat; //< XXX hack for ZST
|
||||
mat.move_b_vec(m, target_b)
|
||||
} else {
|
||||
m
|
||||
}
|
||||
|
Reference in New Issue
Block a user