Multithreaded render
This commit is contained in:
Generated
+11
-3
@@ -681,12 +681,10 @@ dependencies = [
|
|||||||
"foldhash",
|
"foldhash",
|
||||||
"glam",
|
"glam",
|
||||||
"log",
|
"log",
|
||||||
|
"num_cpus",
|
||||||
"obj",
|
"obj",
|
||||||
"rand 0.9.1",
|
"rand 0.9.1",
|
||||||
"rayon",
|
|
||||||
"rspirv",
|
"rspirv",
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"simplelog",
|
"simplelog",
|
||||||
"utf-8",
|
"utf-8",
|
||||||
"vulkano",
|
"vulkano",
|
||||||
@@ -1332,6 +1330,16 @@ dependencies = [
|
|||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_cpus"
|
||||||
|
version = "1.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_enum"
|
name = "num_enum"
|
||||||
version = "0.7.4"
|
version = "0.7.4"
|
||||||
|
|||||||
+4
-4
@@ -24,13 +24,11 @@ egui = "0.31.1"
|
|||||||
egui_winit_vulkano = "0.28.0"
|
egui_winit_vulkano = "0.28.0"
|
||||||
egui_plot = "0.32.1"
|
egui_plot = "0.32.1"
|
||||||
|
|
||||||
serde = { version = "1", features = ["derive"] }
|
#serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
#serde_json = "1"
|
||||||
|
|
||||||
utf-8 = "0.7"
|
utf-8 = "0.7"
|
||||||
|
|
||||||
rayon = "1.7"
|
|
||||||
|
|
||||||
rand = "0.9.1"
|
rand = "0.9.1"
|
||||||
foldhash = "*"
|
foldhash = "*"
|
||||||
|
|
||||||
@@ -39,6 +37,8 @@ simplelog = "0.12"
|
|||||||
|
|
||||||
rspirv = "0.12"
|
rspirv = "0.12"
|
||||||
|
|
||||||
|
num_cpus = "1"
|
||||||
|
|
||||||
# using latest gits
|
# using latest gits
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
#vulkano = { git = "https://github.com/vulkano-rs/vulkano" }
|
#vulkano = { git = "https://github.com/vulkano-rs/vulkano" }
|
||||||
|
|||||||
+7
-14
@@ -1,12 +1,10 @@
|
|||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use egui::{Color32, Frame, Id};
|
use egui::{Color32, Frame, Id};
|
||||||
use egui_plot::{Line, Plot, PlotPoints};
|
use egui_plot::{Line, Plot, PlotPoints};
|
||||||
use egui_winit_vulkano::Gui;
|
use egui_winit_vulkano::Gui;
|
||||||
use glam::Vec3;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::objects::{CSG, Light, Mesh};
|
||||||
create_csg,
|
|
||||||
objects::{CSG, Light, Mesh},
|
|
||||||
};
|
|
||||||
|
|
||||||
fn sized_text(ui: &mut egui::Ui, text: impl Into<String>, size: f32) {
|
fn sized_text(ui: &mut egui::Ui, text: impl Into<String>, size: f32) {
|
||||||
ui.label(egui::RichText::new(text).size(size));
|
ui.label(egui::RichText::new(text).size(size));
|
||||||
@@ -29,7 +27,7 @@ pub(crate) struct GState {
|
|||||||
|
|
||||||
pub(crate) meshes: Vec<Mesh>,
|
pub(crate) meshes: Vec<Mesh>,
|
||||||
pub(crate) lights: Vec<Light>,
|
pub(crate) lights: Vec<Light>,
|
||||||
pub(crate) csg: Vec<CSG>,
|
pub(crate) csg: Vec<Arc<RwLock<CSG>>>,
|
||||||
|
|
||||||
pub(crate) fps: [f64; 128],
|
pub(crate) fps: [f64; 128],
|
||||||
|
|
||||||
@@ -53,7 +51,7 @@ impl Default for GState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn gui_up(gui: &mut Gui, state: &mut GState) {
|
pub(crate) fn gui_up(gui: &mut Gui, state: &mut GState, new_csg_needed: &mut bool) {
|
||||||
gui.immediate_ui(|gui| {
|
gui.immediate_ui(|gui| {
|
||||||
let ctx = gui.context();
|
let ctx = gui.context();
|
||||||
egui::SidePanel::left(Id::new("main_left"))
|
egui::SidePanel::left(Id::new("main_left"))
|
||||||
@@ -118,6 +116,7 @@ pub(crate) fn gui_up(gui: &mut Gui, state: &mut GState) {
|
|||||||
ui.heading("Implicit Surfaces");
|
ui.heading("Implicit Surfaces");
|
||||||
let mut csgdel = vec![];
|
let mut csgdel = vec![];
|
||||||
for csg in &mut state.csg {
|
for csg in &mut state.csg {
|
||||||
|
let mut csg = csg.write().unwrap();
|
||||||
ui.label(csg.name.clone());
|
ui.label(csg.name.clone());
|
||||||
csgdel.push(ui.small_button("remove csg").clicked());
|
csgdel.push(ui.small_button("remove csg").clicked());
|
||||||
ui.add(
|
ui.add(
|
||||||
@@ -153,13 +152,7 @@ pub(crate) fn gui_up(gui: &mut Gui, state: &mut GState) {
|
|||||||
state.csg.remove(i);
|
state.csg.remove(i);
|
||||||
}
|
}
|
||||||
if state.csg.len() < 32 && ui.small_button("add csg").clicked() {
|
if state.csg.len() < 32 && ui.small_button("add csg").clicked() {
|
||||||
state.csg.push(CSG {
|
*new_csg_needed = true;
|
||||||
name: "generated".to_string(),
|
|
||||||
parts: create_csg(),
|
|
||||||
pos: Vec3::ZERO,
|
|
||||||
rot: Vec3::ZERO,
|
|
||||||
scale: Vec3::ONE,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
ui.heading("Lights");
|
ui.heading("Lights");
|
||||||
let mut lightdel = vec![];
|
let mut lightdel = vec![];
|
||||||
|
|||||||
+175
-600
File diff suppressed because it is too large
Load Diff
+3
-1
@@ -8,7 +8,7 @@ use vulkano::{
|
|||||||
memory::allocator::{
|
memory::allocator::{
|
||||||
AllocationCreateInfo, MemoryAllocatePreference, MemoryTypeFilter, StandardMemoryAllocator,
|
AllocationCreateInfo, MemoryAllocatePreference, MemoryTypeFilter, StandardMemoryAllocator,
|
||||||
},
|
},
|
||||||
pipeline::graphics::vertex_input::Vertex,
|
pipeline::{GraphicsPipeline, graphics::vertex_input::Vertex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::ssa::SSATape;
|
use crate::ssa::SSATape;
|
||||||
@@ -41,6 +41,8 @@ pub(crate) struct CSG {
|
|||||||
pub(crate) pos: Vec3,
|
pub(crate) pos: Vec3,
|
||||||
pub(crate) rot: Vec3,
|
pub(crate) rot: Vec3,
|
||||||
pub(crate) scale: Vec3,
|
pub(crate) scale: Vec3,
|
||||||
|
pub(crate) deferred_pipeline: Arc<GraphicsPipeline>,
|
||||||
|
pub(crate) normals_pipeline: Arc<GraphicsPipeline>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn load_obj(
|
pub(crate) fn load_obj(
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use egui::ahash::HashMapExt;
|
use egui::ahash::HashMapExt;
|
||||||
use foldhash::HashMap;
|
use foldhash::HashMap;
|
||||||
use rspirv::{dr::Module, spirv};
|
use rspirv::{dr::Module, spirv};
|
||||||
|
|||||||
+467
@@ -0,0 +1,467 @@
|
|||||||
|
use std::{
|
||||||
|
fs::File,
|
||||||
|
io::Write,
|
||||||
|
simd::{StdFloat, cmp::SimdPartialOrd},
|
||||||
|
sync::{Arc, RwLock, mpmc, mpsc},
|
||||||
|
time::Instant,
|
||||||
|
};
|
||||||
|
|
||||||
|
use foldhash::HashSet;
|
||||||
|
use glam::{EulerRot, Mat4, Vec3};
|
||||||
|
use log::info;
|
||||||
|
use rspirv::{binary::Assemble, dr::Module};
|
||||||
|
use vulkano::{
|
||||||
|
device::Device,
|
||||||
|
pipeline::{
|
||||||
|
DynamicState, GraphicsPipeline, PipelineCreateFlags, PipelineLayout,
|
||||||
|
PipelineShaderStageCreateInfo,
|
||||||
|
cache::PipelineCache,
|
||||||
|
graphics::{
|
||||||
|
GraphicsPipelineCreateInfo,
|
||||||
|
color_blend::{ColorBlendAttachmentState, ColorBlendState},
|
||||||
|
depth_stencil::{DepthState, DepthStencilState},
|
||||||
|
input_assembly::InputAssemblyState,
|
||||||
|
multisample::MultisampleState,
|
||||||
|
rasterization::{CullMode, FrontFace, PolygonMode, RasterizationState},
|
||||||
|
vertex_input::{Vertex, VertexDefinition, VertexInputState},
|
||||||
|
},
|
||||||
|
layout::PipelineDescriptorSetLayoutCreateInfo,
|
||||||
|
},
|
||||||
|
render_pass::{RenderPass, Subpass},
|
||||||
|
shader::{ShaderModule, ShaderModuleCreateInfo},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
DUMP_SPV_TO_FILE, IVertex, ShaderModules, get_spec_constants,
|
||||||
|
gui::PreviousDebug,
|
||||||
|
implicit_vs::PushConstantData,
|
||||||
|
interpreter::{self, IntervalInterpreter, PointInterpreter, VALUE_0},
|
||||||
|
objects::CSG,
|
||||||
|
ssa::{SSAInput, SSAOpcode, SSAOpcodeSized, SSATape},
|
||||||
|
types::Interval,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum WorkItem {
|
||||||
|
CreateCSG(
|
||||||
|
Arc<Device>,
|
||||||
|
Module,
|
||||||
|
Module,
|
||||||
|
Arc<RenderPass>,
|
||||||
|
Arc<PipelineCache>,
|
||||||
|
ShaderModules,
|
||||||
|
PreviousDebug,
|
||||||
|
isize,
|
||||||
|
),
|
||||||
|
GetPushConstants(Arc<RwLock<CSG>>, f32, usize),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum WorkComplete {
|
||||||
|
CreateCSG(Arc<RwLock<CSG>>, isize),
|
||||||
|
GetPushConstants(PushConstantData, usize),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn thread_loop(recv: mpmc::Receiver<WorkItem>, send: mpsc::SyncSender<WorkComplete>) {
|
||||||
|
for work in recv.into_iter() {
|
||||||
|
match work {
|
||||||
|
WorkItem::CreateCSG(
|
||||||
|
device,
|
||||||
|
trace_module,
|
||||||
|
normals_module,
|
||||||
|
render_pass,
|
||||||
|
cache,
|
||||||
|
modules,
|
||||||
|
debug,
|
||||||
|
index,
|
||||||
|
) => {
|
||||||
|
let csg_start = Instant::now();
|
||||||
|
let parts = create_csg();
|
||||||
|
|
||||||
|
let trace_shader_module =
|
||||||
|
sdf_specialize_module(device.clone(), &parts, trace_module, &format!("trace"));
|
||||||
|
let normals_shader_module = sdf_specialize_module(
|
||||||
|
device.clone(),
|
||||||
|
&parts,
|
||||||
|
normals_module,
|
||||||
|
&format!("normals"),
|
||||||
|
);
|
||||||
|
|
||||||
|
let (deferred_pipeline, normals_pipeline) = deferred_pipelines_recompile(
|
||||||
|
device,
|
||||||
|
render_pass,
|
||||||
|
cache,
|
||||||
|
modules,
|
||||||
|
trace_shader_module,
|
||||||
|
normals_shader_module,
|
||||||
|
debug,
|
||||||
|
);
|
||||||
|
|
||||||
|
let csg = Arc::new(RwLock::new(CSG {
|
||||||
|
name: "example".to_string(),
|
||||||
|
parts,
|
||||||
|
pos: Vec3::ZERO,
|
||||||
|
rot: Vec3::ZERO,
|
||||||
|
scale: Vec3::ONE,
|
||||||
|
deferred_pipeline,
|
||||||
|
normals_pipeline,
|
||||||
|
}));
|
||||||
|
|
||||||
|
send.send(WorkComplete::CreateCSG(csg, index)).unwrap();
|
||||||
|
|
||||||
|
let csg_end = Instant::now();
|
||||||
|
info!(
|
||||||
|
"CSG compile took {} milliseconds",
|
||||||
|
(csg_end - csg_start).as_secs_f64() * 1000.0
|
||||||
|
);
|
||||||
|
},
|
||||||
|
WorkItem::GetPushConstants(csg, time, index) => {
|
||||||
|
let mut push_constants = PushConstantData {
|
||||||
|
world: Mat4::IDENTITY.to_cols_array_2d(),
|
||||||
|
dimensions: Vec3::ONE.to_array().into(),
|
||||||
|
lowest_corner: Vec3::ZERO.into(),
|
||||||
|
enable: [0; 16],
|
||||||
|
material: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let csg = csg.read().unwrap();
|
||||||
|
|
||||||
|
push_constants.world = (Mat4::from_translation(csg.pos * 0.01)
|
||||||
|
* Mat4::from_euler(
|
||||||
|
EulerRot::XYZ,
|
||||||
|
csg.rot.x.to_radians(),
|
||||||
|
csg.rot.y.to_radians(),
|
||||||
|
csg.rot.z.to_radians(),
|
||||||
|
)
|
||||||
|
* Mat4::from_scale(csg.scale * 2.0))
|
||||||
|
.to_cols_array_2d();
|
||||||
|
|
||||||
|
interval_check(&csg, &mut push_constants, time);
|
||||||
|
|
||||||
|
push_constants.material = index as _;
|
||||||
|
|
||||||
|
send.send(WorkComplete::GetPushConstants(push_constants, index))
|
||||||
|
.unwrap();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deferred_pipelines_recompile(
|
||||||
|
device: Arc<Device>,
|
||||||
|
render_pass: Arc<RenderPass>,
|
||||||
|
cache: Arc<PipelineCache>,
|
||||||
|
shader_modules: ShaderModules,
|
||||||
|
trace_shader_module: Arc<ShaderModule>,
|
||||||
|
normals_shader_module: Arc<ShaderModule>,
|
||||||
|
debug: PreviousDebug,
|
||||||
|
) -> (Arc<GraphicsPipeline>, Arc<GraphicsPipeline>) {
|
||||||
|
let specs = get_spec_constants(&debug);
|
||||||
|
|
||||||
|
let dynamic_state = [DynamicState::Viewport].into_iter().collect::<HashSet<_>>();
|
||||||
|
|
||||||
|
let implicit_vs_entry = shader_modules
|
||||||
|
.implicit_vs
|
||||||
|
.specialize(specs.clone())
|
||||||
|
.unwrap()
|
||||||
|
.single_entry_point()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let vertex_input_state = [IVertex::per_vertex()]
|
||||||
|
.definition(&implicit_vs_entry)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let implicit_vs_info = PipelineShaderStageCreateInfo::new(implicit_vs_entry);
|
||||||
|
|
||||||
|
let implicit_fs_info = PipelineShaderStageCreateInfo::new(
|
||||||
|
trace_shader_module
|
||||||
|
.specialize(specs.clone())
|
||||||
|
.unwrap()
|
||||||
|
.single_entry_point()
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let layout = PipelineLayout::new(
|
||||||
|
device.clone(),
|
||||||
|
PipelineDescriptorSetLayoutCreateInfo::from_stages([&implicit_vs_info, &implicit_fs_info])
|
||||||
|
.into_pipeline_layout_create_info(device.clone())
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let stages = [implicit_vs_info.clone(), implicit_fs_info]
|
||||||
|
.into_iter()
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let deferred_subpass = Subpass::from(render_pass.clone(), 0).unwrap();
|
||||||
|
|
||||||
|
let implicit_pipeline = GraphicsPipeline::new(
|
||||||
|
device.clone(),
|
||||||
|
Some(cache.clone()),
|
||||||
|
GraphicsPipelineCreateInfo {
|
||||||
|
flags: PipelineCreateFlags::DISABLE_OPTIMIZATION,
|
||||||
|
stages,
|
||||||
|
vertex_input_state: Some(vertex_input_state.clone()),
|
||||||
|
input_assembly_state: Some(InputAssemblyState::default()),
|
||||||
|
dynamic_state: dynamic_state.clone(),
|
||||||
|
viewport_state: Some(Default::default()),
|
||||||
|
rasterization_state: Some(RasterizationState {
|
||||||
|
front_face: FrontFace::Clockwise,
|
||||||
|
cull_mode: CullMode::Back,
|
||||||
|
polygon_mode: PolygonMode::Fill,
|
||||||
|
..RasterizationState::default()
|
||||||
|
}),
|
||||||
|
depth_stencil_state: Some(DepthStencilState {
|
||||||
|
depth: Some(DepthState::simple()),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
multisample_state: Some(MultisampleState::default()),
|
||||||
|
color_blend_state: Some(ColorBlendState::with_attachment_states(
|
||||||
|
deferred_subpass.num_color_attachments(),
|
||||||
|
ColorBlendAttachmentState::default(),
|
||||||
|
)),
|
||||||
|
subpass: Some(deferred_subpass.into()),
|
||||||
|
..GraphicsPipelineCreateInfo::layout(layout.clone())
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let fullscreen_vs_entry = shader_modules
|
||||||
|
.fullscreen_vs
|
||||||
|
.specialize(specs.clone())
|
||||||
|
.unwrap()
|
||||||
|
.single_entry_point()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let vertex_input_state = VertexInputState::new();
|
||||||
|
|
||||||
|
let fullscreen_vs_info = PipelineShaderStageCreateInfo::new(fullscreen_vs_entry);
|
||||||
|
|
||||||
|
let normals_fs_info = PipelineShaderStageCreateInfo::new(
|
||||||
|
normals_shader_module
|
||||||
|
.specialize(specs.clone())
|
||||||
|
.unwrap()
|
||||||
|
.single_entry_point()
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let layout = PipelineLayout::new(
|
||||||
|
device.clone(),
|
||||||
|
PipelineDescriptorSetLayoutCreateInfo::from_stages([&fullscreen_vs_info, &normals_fs_info])
|
||||||
|
.into_pipeline_layout_create_info(device.clone())
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let stages = [fullscreen_vs_info.clone(), normals_fs_info]
|
||||||
|
.into_iter()
|
||||||
|
.collect();
|
||||||
|
let normals_subpass = Subpass::from(render_pass.clone(), 1).unwrap();
|
||||||
|
|
||||||
|
let normals_pipeline = GraphicsPipeline::new(
|
||||||
|
device.clone(),
|
||||||
|
Some(cache.clone()),
|
||||||
|
GraphicsPipelineCreateInfo {
|
||||||
|
flags: PipelineCreateFlags::DISABLE_OPTIMIZATION,
|
||||||
|
stages,
|
||||||
|
vertex_input_state: Some(vertex_input_state.clone()),
|
||||||
|
input_assembly_state: Some(InputAssemblyState::default()),
|
||||||
|
dynamic_state: dynamic_state.clone(),
|
||||||
|
viewport_state: Some(Default::default()),
|
||||||
|
rasterization_state: Some(RasterizationState {
|
||||||
|
front_face: FrontFace::Clockwise,
|
||||||
|
cull_mode: CullMode::Back,
|
||||||
|
polygon_mode: PolygonMode::Fill,
|
||||||
|
..RasterizationState::default()
|
||||||
|
}),
|
||||||
|
depth_stencil_state: None,
|
||||||
|
multisample_state: Some(MultisampleState::default()),
|
||||||
|
color_blend_state: Some(ColorBlendState::with_attachment_states(
|
||||||
|
normals_subpass.num_color_attachments(),
|
||||||
|
ColorBlendAttachmentState::default(),
|
||||||
|
)),
|
||||||
|
subpass: Some(normals_subpass.into()),
|
||||||
|
..GraphicsPipelineCreateInfo::layout(layout.clone())
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
(implicit_pipeline, normals_pipeline)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_csg() -> SSATape {
|
||||||
|
let mut tape = SSATape::default();
|
||||||
|
let pos = tape.push_instruction(
|
||||||
|
SSAOpcodeSized {
|
||||||
|
opcode: SSAOpcode::SSAPosition,
|
||||||
|
size: 1,
|
||||||
|
},
|
||||||
|
vec![],
|
||||||
|
);
|
||||||
|
let offset = tape.push_instruction(
|
||||||
|
SSAOpcodeSized {
|
||||||
|
opcode: SSAOpcode::SSAAdd,
|
||||||
|
size: 3,
|
||||||
|
},
|
||||||
|
vec![
|
||||||
|
pos[0],
|
||||||
|
pos[1],
|
||||||
|
pos[2],
|
||||||
|
SSAInput::Constant(rand::random_range(0.0..3.0)),
|
||||||
|
SSAInput::Constant(rand::random_range(0.0..3.0)),
|
||||||
|
SSAInput::Constant(rand::random_range(0.0..3.0)),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
let sphere = tape.push_instruction(
|
||||||
|
SSAOpcodeSized {
|
||||||
|
opcode: SSAOpcode::SSASDFSphere,
|
||||||
|
size: 1,
|
||||||
|
},
|
||||||
|
vec![
|
||||||
|
offset[0],
|
||||||
|
offset[1],
|
||||||
|
offset[2],
|
||||||
|
SSAInput::Constant(rand::random_range(0.0..1.0)),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
let torus = tape.push_instruction(
|
||||||
|
SSAOpcodeSized {
|
||||||
|
opcode: SSAOpcode::SSASDFTorus,
|
||||||
|
size: 1,
|
||||||
|
},
|
||||||
|
vec![
|
||||||
|
pos[0],
|
||||||
|
pos[1],
|
||||||
|
pos[2],
|
||||||
|
SSAInput::Constant(rand::random_range(0.0..1.0)),
|
||||||
|
SSAInput::Constant(rand::random_range(0.0..1.0)),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
let min = tape.push_instruction(
|
||||||
|
SSAOpcodeSized {
|
||||||
|
opcode: SSAOpcode::SSAMin,
|
||||||
|
size: 1,
|
||||||
|
},
|
||||||
|
vec![sphere[0], torus[0]],
|
||||||
|
);
|
||||||
|
tape.push_instruction(
|
||||||
|
SSAOpcodeSized {
|
||||||
|
opcode: SSAOpcode::SSAReturn,
|
||||||
|
size: 1,
|
||||||
|
},
|
||||||
|
min,
|
||||||
|
);
|
||||||
|
tape
|
||||||
|
}
|
||||||
|
|
||||||
|
fn interval_check(csg: &CSG, push_constants: &mut PushConstantData, time: f32) {
|
||||||
|
const INTERPRET_INPUT_X: interpreter::Value =
|
||||||
|
interpreter::Value::from_array([10000.0, 0.0, 0.0, -10000.0, 0.0, 0.0, 0.0, 0.0]);
|
||||||
|
const INTERPRET_INPUT_Y: interpreter::Value =
|
||||||
|
interpreter::Value::from_array([0.0, 10000.0, 0.0, 0.0, -10000.0, 0.0, 0.0, 0.0]);
|
||||||
|
const INTERPRET_INPUT_Z: interpreter::Value =
|
||||||
|
interpreter::Value::from_array([0.0, 0.0, 10000.0, 0.0, 0.0, -10000.0, 0.0, 0.0]);
|
||||||
|
const INTERPRET_MUL: interpreter::Value =
|
||||||
|
interpreter::Value::from_array([-1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 0.0, 0.0]);
|
||||||
|
const INTERPRET_ADD: interpreter::Value = interpreter::Value::from_array([
|
||||||
|
10000.0, 10000.0, 10000.0, -10000.0, -10000.0, -10000.0, 0.0, 0.0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
let mut interpreter = PointInterpreter::new(csg);
|
||||||
|
let interpreter_out = interpreter
|
||||||
|
.scene(
|
||||||
|
INTERPRET_INPUT_X,
|
||||||
|
INTERPRET_INPUT_Y,
|
||||||
|
INTERPRET_INPUT_Z,
|
||||||
|
interpreter::Value::splat(time),
|
||||||
|
)
|
||||||
|
.mul_add(INTERPRET_MUL, INTERPRET_ADD)
|
||||||
|
.to_array();
|
||||||
|
|
||||||
|
let highest_corner = Vec3::new(interpreter_out[0], interpreter_out[1], interpreter_out[2]);
|
||||||
|
let lowest_corner = Vec3::new(interpreter_out[3], interpreter_out[4], interpreter_out[5]);
|
||||||
|
|
||||||
|
push_constants.dimensions = (highest_corner - lowest_corner).to_array().into();
|
||||||
|
push_constants.lowest_corner = lowest_corner.into();
|
||||||
|
|
||||||
|
push_constants.enable = [0; 16];
|
||||||
|
|
||||||
|
for x in 0..8 {
|
||||||
|
for y in 0..8 {
|
||||||
|
let interval_input_z: Interval = Interval::new_unchecked(
|
||||||
|
interpreter::Value::from_array([
|
||||||
|
(0.0 / 8.0) * push_constants.dimensions[2] + push_constants.lowest_corner[2],
|
||||||
|
(1.0 / 8.0) * push_constants.dimensions[2] + push_constants.lowest_corner[2],
|
||||||
|
(2.0 / 8.0) * push_constants.dimensions[2] + push_constants.lowest_corner[2],
|
||||||
|
(3.0 / 8.0) * push_constants.dimensions[2] + push_constants.lowest_corner[2],
|
||||||
|
(4.0 / 8.0) * push_constants.dimensions[2] + push_constants.lowest_corner[2],
|
||||||
|
(5.0 / 8.0) * push_constants.dimensions[2] + push_constants.lowest_corner[2],
|
||||||
|
(6.0 / 8.0) * push_constants.dimensions[2] + push_constants.lowest_corner[2],
|
||||||
|
(7.0 / 8.0) * push_constants.dimensions[2] + push_constants.lowest_corner[2],
|
||||||
|
]),
|
||||||
|
interpreter::Value::from_array([
|
||||||
|
(1.0 / 8.0) * push_constants.dimensions[2] + push_constants.lowest_corner[2],
|
||||||
|
(2.0 / 8.0) * push_constants.dimensions[2] + push_constants.lowest_corner[2],
|
||||||
|
(3.0 / 8.0) * push_constants.dimensions[2] + push_constants.lowest_corner[2],
|
||||||
|
(4.0 / 8.0) * push_constants.dimensions[2] + push_constants.lowest_corner[2],
|
||||||
|
(5.0 / 8.0) * push_constants.dimensions[2] + push_constants.lowest_corner[2],
|
||||||
|
(6.0 / 8.0) * push_constants.dimensions[2] + push_constants.lowest_corner[2],
|
||||||
|
(7.0 / 8.0) * push_constants.dimensions[2] + push_constants.lowest_corner[2],
|
||||||
|
(8.0 / 8.0) * push_constants.dimensions[2] + push_constants.lowest_corner[2],
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut interpreter = IntervalInterpreter::new(csg);
|
||||||
|
let output = interpreter.scene(
|
||||||
|
Interval::const_splat2(
|
||||||
|
(x as f32 / 8.0) * push_constants.dimensions[0]
|
||||||
|
+ push_constants.lowest_corner[0],
|
||||||
|
((x + 1) as f32 / 8.0) * push_constants.dimensions[0]
|
||||||
|
+ push_constants.lowest_corner[0],
|
||||||
|
),
|
||||||
|
Interval::const_splat2(
|
||||||
|
(y as f32 / 8.0) * push_constants.dimensions[1]
|
||||||
|
+ push_constants.lowest_corner[1],
|
||||||
|
((y + 1) as f32 / 8.0) * push_constants.dimensions[1]
|
||||||
|
+ push_constants.lowest_corner[1],
|
||||||
|
),
|
||||||
|
interval_input_z,
|
||||||
|
Interval::const_splat(time),
|
||||||
|
);
|
||||||
|
|
||||||
|
let output = ((output.lower().simd_le(VALUE_0) & output.upper().simd_ge(VALUE_0))
|
||||||
|
.to_bitmask() as u32)
|
||||||
|
<< ((y & 0b11) * 8);
|
||||||
|
push_constants.enable[(x << 1) | (y >> 2)] |= output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sdf_specialize_module(
|
||||||
|
device: Arc<Device>,
|
||||||
|
parts: &SSATape,
|
||||||
|
module: Module,
|
||||||
|
name: &str,
|
||||||
|
) -> Arc<ShaderModule> {
|
||||||
|
let new_module = parts.compile_to_spirv(Some(module));
|
||||||
|
|
||||||
|
let assembled_module = new_module.assemble();
|
||||||
|
let module_as_bytes = assembled_module
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.map(u32::to_le_bytes)
|
||||||
|
.flatten()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if DUMP_SPV_TO_FILE {
|
||||||
|
File::create(format!("{name}.out.spv"))
|
||||||
|
.unwrap()
|
||||||
|
.write(&module_as_bytes)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
::vulkano::shader::ShaderModule::new(device, ShaderModuleCreateInfo::new(&assembled_module))
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user