Move to workspace
This commit is contained in:
Generated
+17
@@ -921,6 +921,12 @@ version = "0.5.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
|
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "humantime"
|
||||||
|
version = "2.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_collections"
|
name = "icu_collections"
|
||||||
version = "2.1.1"
|
version = "2.1.1"
|
||||||
@@ -2543,6 +2549,7 @@ dependencies = [
|
|||||||
"rand",
|
"rand",
|
||||||
"rspirv",
|
"rspirv",
|
||||||
"simplelog",
|
"simplelog",
|
||||||
|
"tape-load",
|
||||||
"utf-8",
|
"utf-8",
|
||||||
"vulkano",
|
"vulkano",
|
||||||
"vulkano-shaders",
|
"vulkano-shaders",
|
||||||
@@ -2550,6 +2557,16 @@ dependencies = [
|
|||||||
"winit",
|
"winit",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tape-load"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"foldhash",
|
||||||
|
"glam",
|
||||||
|
"humantime",
|
||||||
|
"rspirv",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termcolor"
|
name = "termcolor"
|
||||||
version = "1.4.1"
|
version = "1.4.1"
|
||||||
|
|||||||
+8
-47
@@ -1,45 +1,12 @@
|
|||||||
[package]
|
[workspace]
|
||||||
name = "tape-drive"
|
resolver = "3"
|
||||||
version = "0.3.0"
|
members = ["tape-load", "tape-drive"]
|
||||||
edition = "2024"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
[profile.final]
|
||||||
|
inherits = "release"
|
||||||
[dependencies]
|
strip = true
|
||||||
vulkano = "0.35.1"
|
lto = true
|
||||||
vulkano-shaders = { version = "0.35.0", features = ["shaderc-debug"] }
|
codegen-units = 1
|
||||||
winit = "0.30"
|
|
||||||
vulkano-util = "0.35.0"
|
|
||||||
|
|
||||||
obj = "0.10"
|
|
||||||
bytemuck = { version = "1.13", features = [
|
|
||||||
"derive",
|
|
||||||
"extern_crate_std",
|
|
||||||
"min_const_generics",
|
|
||||||
] }
|
|
||||||
|
|
||||||
glam = "0.30.3"
|
|
||||||
|
|
||||||
egui = "0.31.1"
|
|
||||||
egui_winit_vulkano = "0.28.0"
|
|
||||||
egui_plot = "0.32.1"
|
|
||||||
|
|
||||||
#serde = { version = "1", features = ["derive"] }
|
|
||||||
#serde_json = "1"
|
|
||||||
|
|
||||||
utf-8 = "0.7"
|
|
||||||
|
|
||||||
rand = "0.9.1"
|
|
||||||
foldhash = "0.1.5"
|
|
||||||
|
|
||||||
log = "0.4"
|
|
||||||
simplelog = "0.12"
|
|
||||||
|
|
||||||
rspirv = "0.12"
|
|
||||||
|
|
||||||
num_cpus = "1"
|
|
||||||
|
|
||||||
notify = "8.2"
|
|
||||||
|
|
||||||
# using latest gits
|
# using latest gits
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
@@ -49,9 +16,3 @@ notify = "8.2"
|
|||||||
#vulkano-taskgraph = { git = "https://github.com/vulkano-rs/vulkano" }
|
#vulkano-taskgraph = { git = "https://github.com/vulkano-rs/vulkano" }
|
||||||
#vulkano-util = { git = "https://github.com/vulkano-rs/vulkano" }
|
#vulkano-util = { git = "https://github.com/vulkano-rs/vulkano" }
|
||||||
#egui_winit_vulkano = { git = "https://github.com/Molive-0/egui_winit_vulkano" }
|
#egui_winit_vulkano = { git = "https://github.com/Molive-0/egui_winit_vulkano" }
|
||||||
|
|
||||||
[profile.final]
|
|
||||||
inherits = "release"
|
|
||||||
strip = true
|
|
||||||
lto = true
|
|
||||||
codegen-units = 1
|
|
||||||
|
|||||||
-2829
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
|||||||
|
[package]
|
||||||
|
name = "tape-drive"
|
||||||
|
version = "0.3.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
vulkano = "0.35.1"
|
||||||
|
vulkano-shaders = { version = "0.35.0", features = ["shaderc-debug"] }
|
||||||
|
winit = "0.30"
|
||||||
|
vulkano-util = "0.35.0"
|
||||||
|
|
||||||
|
obj = "0.10"
|
||||||
|
bytemuck = { version = "1.13", features = [
|
||||||
|
"derive",
|
||||||
|
"extern_crate_std",
|
||||||
|
"min_const_generics",
|
||||||
|
] }
|
||||||
|
|
||||||
|
glam = "0.30.3"
|
||||||
|
|
||||||
|
egui = "0.31.1"
|
||||||
|
egui_winit_vulkano = "0.28.0"
|
||||||
|
egui_plot = "0.32.1"
|
||||||
|
|
||||||
|
#serde = { version = "1", features = ["derive"] }
|
||||||
|
#serde_json = "1"
|
||||||
|
|
||||||
|
utf-8 = "0.7"
|
||||||
|
|
||||||
|
rand = "0.9.1"
|
||||||
|
foldhash = "0.1.5"
|
||||||
|
|
||||||
|
log = "0.4"
|
||||||
|
simplelog = "0.12"
|
||||||
|
|
||||||
|
rspirv = "0.12"
|
||||||
|
|
||||||
|
num_cpus = "1"
|
||||||
|
|
||||||
|
notify = "8.2"
|
||||||
|
tape-load = { version = "*", path = "../tape-load" }
|
||||||
@@ -6,12 +6,13 @@ import sys
|
|||||||
import subprocess
|
import subprocess
|
||||||
import re
|
import re
|
||||||
|
|
||||||
SHADERS_DIR = "shaders_out"
|
SHADERS_OUT = "shaders_out"
|
||||||
|
SHADERS_IN = "src/shaders"
|
||||||
TARGET_ENV = "vulkan1.3"
|
TARGET_ENV = "vulkan1.3"
|
||||||
|
|
||||||
if os.path.isdir(SHADERS_DIR):
|
if os.path.isdir(SHADERS_OUT):
|
||||||
shutil.rmtree(SHADERS_DIR)
|
shutil.rmtree(SHADERS_OUT)
|
||||||
os.mkdir(SHADERS_DIR)
|
os.mkdir(SHADERS_OUT)
|
||||||
|
|
||||||
normal_shaders = [
|
normal_shaders = [
|
||||||
("fullscreen.vert", "vert"),
|
("fullscreen.vert", "vert"),
|
||||||
@@ -33,8 +34,8 @@ for shader, ty in normal_shaders:
|
|||||||
"--target-env",
|
"--target-env",
|
||||||
TARGET_ENV,
|
TARGET_ENV,
|
||||||
"-o",
|
"-o",
|
||||||
f"{SHADERS_DIR}/{shader}.spv",
|
f"{SHADERS_OUT}/{shader}.spv",
|
||||||
f"src/shaders/{shader}.glsl",
|
f"{SHADERS_IN}/{shader}.glsl",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
@@ -43,7 +44,7 @@ for shader, ty in normal_shaders:
|
|||||||
replacement_shaders = [("trace.frag", "frag"), ("normals.frag", "frag")]
|
replacement_shaders = [("trace.frag", "frag"), ("normals.frag", "frag")]
|
||||||
|
|
||||||
for shader, ty in replacement_shaders:
|
for shader, ty in replacement_shaders:
|
||||||
print(f"src/shaders/{shader}.glsl")
|
print(f"{SHADERS_IN}/{shader}.glsl")
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
[
|
[
|
||||||
"glslangValidator",
|
"glslangValidator",
|
||||||
@@ -55,7 +56,7 @@ for shader, ty in replacement_shaders:
|
|||||||
"--target-env",
|
"--target-env",
|
||||||
TARGET_ENV,
|
TARGET_ENV,
|
||||||
"--quiet",
|
"--quiet",
|
||||||
"src/shaders/trace.frag.glsl",
|
f"{SHADERS_IN}/{shader}.glsl",
|
||||||
],
|
],
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
@@ -63,9 +64,11 @@ for shader, ty in replacement_shaders:
|
|||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
sys.exit(result.returncode)
|
sys.exit(result.returncode)
|
||||||
asm = result.stdout
|
asm = result.stdout
|
||||||
asm = re.sub(r"(?ms)%11 =.*OpFunctionEnd", "", asm)
|
with open(f"{SHADERS_OUT}/{shader}.old.spv-dis", "w") as f:
|
||||||
|
f.write(asm)
|
||||||
|
asm = re.sub(r"(?ms)%11 =.*?OpFunctionEnd", "", asm)
|
||||||
asm = re.sub(r"%11 ", "%1000 ", asm)
|
asm = re.sub(r"%11 ", "%1000 ", asm)
|
||||||
with open(f"{SHADERS_DIR}/{shader}.spv-dis", "w") as f:
|
with open(f"{SHADERS_OUT}/{shader}.spv-dis", "w") as f:
|
||||||
f.write(asm)
|
f.write(asm)
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
[
|
[
|
||||||
@@ -74,7 +77,7 @@ for shader, ty in replacement_shaders:
|
|||||||
"--target-env",
|
"--target-env",
|
||||||
"vulkan1.3",
|
"vulkan1.3",
|
||||||
"-o",
|
"-o",
|
||||||
f"{SHADERS_DIR}/{shader}.spv",
|
f"{SHADERS_OUT}/{shader}.spv",
|
||||||
],
|
],
|
||||||
input=asm,
|
input=asm,
|
||||||
encoding="ascii",
|
encoding="ascii",
|
||||||
@@ -38,7 +38,8 @@ pub(crate) struct GState {
|
|||||||
|
|
||||||
pub(crate) new_csgs_needed: u8,
|
pub(crate) new_csgs_needed: u8,
|
||||||
|
|
||||||
pub(crate) fps: [f64; 128],
|
pub(crate) cpu_mpf: [f64; 1024],
|
||||||
|
pub(crate) gpu_mpf: [f64; 1024],
|
||||||
|
|
||||||
pub(crate) debug: PreviousDebug,
|
pub(crate) debug: PreviousDebug,
|
||||||
|
|
||||||
@@ -65,7 +66,8 @@ impl Default for GState {
|
|||||||
|
|
||||||
new_csgs_needed: 0,
|
new_csgs_needed: 0,
|
||||||
|
|
||||||
fps: [0.0; 128],
|
cpu_mpf: [0.0; 1024],
|
||||||
|
gpu_mpf: [0.0; 1024],
|
||||||
|
|
||||||
debug: Default::default(),
|
debug: Default::default(),
|
||||||
|
|
||||||
@@ -271,17 +273,41 @@ pub(crate) fn gui_up(gui: &mut Gui, state: &mut GState) {
|
|||||||
state.lights.push(Light::default());
|
state.lights.push(Light::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
let fps: PlotPoints = state
|
let cpu_mpf: PlotPoints = state
|
||||||
.fps
|
.cpu_mpf
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(x, y)| [x as f64, *y])
|
.map(|(x, y)| [x as f64, *y])
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.into();
|
.into();
|
||||||
let average_fps = state.fps.iter().sum::<f64>() / state.fps.len() as f64;
|
let average_cpu_mpf =
|
||||||
let line = Line::new("fps_line", fps);
|
state.cpu_mpf.iter().sum::<f64>() / state.cpu_mpf.len() as f64;
|
||||||
ui.heading(format!("FPS ({:.2})", average_fps));
|
let line = Line::new("cpu_mpf_line", cpu_mpf);
|
||||||
Plot::new("fps")
|
ui.heading(format!("CPU ms per frame ({:.2})", average_cpu_mpf));
|
||||||
|
ui.heading(format!(
|
||||||
|
"CPU frames per second ({:.2})",
|
||||||
|
1000.0 / average_cpu_mpf
|
||||||
|
));
|
||||||
|
Plot::new("cpu_mpf")
|
||||||
|
.view_aspect(2.0)
|
||||||
|
.show(ui, |plot_ui| plot_ui.line(line));
|
||||||
|
|
||||||
|
let gpu_mpf: PlotPoints = state
|
||||||
|
.gpu_mpf
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(x, y)| [x as f64, *y])
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into();
|
||||||
|
let average_gpu_mpf =
|
||||||
|
state.gpu_mpf.iter().sum::<f64>() / state.gpu_mpf.len() as f64;
|
||||||
|
let line = Line::new("gpu_mpf_line", gpu_mpf);
|
||||||
|
ui.heading(format!("GPU ms per frame ({:.2})", average_gpu_mpf));
|
||||||
|
ui.heading(format!(
|
||||||
|
"GPU frames per second ({:.2})",
|
||||||
|
1000.0 / average_gpu_mpf
|
||||||
|
));
|
||||||
|
Plot::new("gpu_mpf")
|
||||||
.view_aspect(2.0)
|
.view_aspect(2.0)
|
||||||
.show(ui, |plot_ui| plot_ui.line(line));
|
.show(ui, |plot_ui| plot_ui.line(line));
|
||||||
|
|
||||||
@@ -5,14 +5,12 @@ const DUMP_SPV_TO_FILE: bool = true;
|
|||||||
const PIPELINE_CACHING: bool = false;
|
const PIPELINE_CACHING: bool = false;
|
||||||
const IGNORE_STENCIL: bool = true;
|
const IGNORE_STENCIL: bool = true;
|
||||||
|
|
||||||
const BYTECODE_IMITATES_GLSL: bool = false;
|
|
||||||
|
|
||||||
const DEFAULT_SUBDIVISION: u32 = 16;
|
const DEFAULT_SUBDIVISION: u32 = 16;
|
||||||
const MAXIMUM_SUBDIVISION: u32 = 64;
|
const MAXIMUM_SUBDIVISION: u32 = 64;
|
||||||
const MINUMUM_SUBDIVISION: u32 = 8;
|
const MINUMUM_SUBDIVISION: u32 = 8;
|
||||||
|
|
||||||
const RUN_STANDARD_PIPELINE: bool = false;
|
const RUN_STANDARD_PIPELINE: bool = true;
|
||||||
const RUN_RT_PIPELINE: bool = true;
|
const RUN_RT_PIPELINE: bool = false;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
error::Error,
|
error::Error,
|
||||||
@@ -77,6 +75,7 @@ use vulkano::{
|
|||||||
ShaderBindingTable,
|
ShaderBindingTable,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
query::{QueryPool, QueryPoolCreateInfo, QueryResultFlags, QueryType},
|
||||||
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
|
render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass},
|
||||||
shader::{ShaderModule, ShaderModuleCreateInfo, SpecializationConstant},
|
shader::{ShaderModule, ShaderModuleCreateInfo, SpecializationConstant},
|
||||||
swapchain::{
|
swapchain::{
|
||||||
@@ -84,7 +83,7 @@ use vulkano::{
|
|||||||
acquire_next_image,
|
acquire_next_image,
|
||||||
},
|
},
|
||||||
sync::{
|
sync::{
|
||||||
self, GpuFuture,
|
self, GpuFuture, PipelineStage,
|
||||||
future::{FenceSignalFuture, NowFuture},
|
future::{FenceSignalFuture, NowFuture},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -106,17 +105,10 @@ use crate::{
|
|||||||
trace_vs::{Camera, Lights, PushConstantData},
|
trace_vs::{Camera, Lights, PushConstantData},
|
||||||
};
|
};
|
||||||
mod objects;
|
mod objects;
|
||||||
|
use tape_load::{instruction_set, interpreters, ssa, types, vm};
|
||||||
|
|
||||||
use crate::objects::*;
|
use crate::objects::*;
|
||||||
|
|
||||||
mod ssa;
|
|
||||||
|
|
||||||
mod instruction_set;
|
|
||||||
|
|
||||||
mod interpreter;
|
|
||||||
|
|
||||||
mod types;
|
|
||||||
mod vm;
|
|
||||||
|
|
||||||
mod threads;
|
mod threads;
|
||||||
|
|
||||||
mod scene;
|
mod scene;
|
||||||
@@ -229,6 +221,7 @@ struct App {
|
|||||||
rcx: Arc<Mutex<Option<RenderContext>>>,
|
rcx: Arc<Mutex<Option<RenderContext>>>,
|
||||||
_watcher: Option<RecommendedWatcher>,
|
_watcher: Option<RecommendedWatcher>,
|
||||||
glsl_changed: Arc<AtomicBool>,
|
glsl_changed: Arc<AtomicBool>,
|
||||||
|
application_start: Instant,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -264,6 +257,7 @@ struct RenderContext {
|
|||||||
recreate_swapchain: bool,
|
recreate_swapchain: bool,
|
||||||
recreate_pipelines: bool,
|
recreate_pipelines: bool,
|
||||||
previous_frame_end: Vec<Option<FenceSignalFuture<Box<dyn GpuFuture>>>>,
|
previous_frame_end: Vec<Option<FenceSignalFuture<Box<dyn GpuFuture>>>>,
|
||||||
|
time_query_pool: Arc<QueryPool>,
|
||||||
gui: Gui,
|
gui: Gui,
|
||||||
render_start: Instant,
|
render_start: Instant,
|
||||||
}
|
}
|
||||||
@@ -559,10 +553,10 @@ impl App {
|
|||||||
notify::EventKind::Modify(_) => {
|
notify::EventKind::Modify(_) => {
|
||||||
info!("event: {:?}", event);
|
info!("event: {:?}", event);
|
||||||
watcher_glsl_changed.store(true, std::sync::atomic::Ordering::Relaxed);
|
watcher_glsl_changed.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
}
|
}
|
||||||
_ => {}
|
},
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => error!("watch error: {:?}", e),
|
Err(e) => error!("watch error: {:?}", e),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -614,6 +608,7 @@ impl App {
|
|||||||
rcx: Arc::new(Mutex::new(None)),
|
rcx: Arc::new(Mutex::new(None)),
|
||||||
_watcher: watcher,
|
_watcher: watcher,
|
||||||
glsl_changed,
|
glsl_changed,
|
||||||
|
application_start: Instant::now(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -964,6 +959,10 @@ impl ApplicationHandler for App {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let mut query_create_info = QueryPoolCreateInfo::query_type(QueryType::Timestamp);
|
||||||
|
query_create_info.query_count = 2;
|
||||||
|
let time_query_pool = QueryPool::new(self.device.clone(), query_create_info).unwrap();
|
||||||
|
|
||||||
*self.rcx.lock().unwrap() = Some(RenderContext {
|
*self.rcx.lock().unwrap() = Some(RenderContext {
|
||||||
window,
|
window,
|
||||||
swapchain,
|
swapchain,
|
||||||
@@ -987,6 +986,7 @@ impl ApplicationHandler for App {
|
|||||||
recreate_swapchain: false,
|
recreate_swapchain: false,
|
||||||
recreate_pipelines: false,
|
recreate_pipelines: false,
|
||||||
previous_frame_end,
|
previous_frame_end,
|
||||||
|
time_query_pool,
|
||||||
gui,
|
gui,
|
||||||
render_start: Instant::now(),
|
render_start: Instant::now(),
|
||||||
});
|
});
|
||||||
@@ -1025,16 +1025,16 @@ impl ApplicationHandler for App {
|
|||||||
match &event {
|
match &event {
|
||||||
WindowEvent::CloseRequested => {
|
WindowEvent::CloseRequested => {
|
||||||
event_loop.exit();
|
event_loop.exit();
|
||||||
}
|
},
|
||||||
WindowEvent::Resized(_) => {
|
WindowEvent::Resized(_) => {
|
||||||
rcx.recreate_swapchain = true;
|
rcx.recreate_swapchain = true;
|
||||||
}
|
},
|
||||||
WindowEvent::ScaleFactorChanged { .. } => {
|
WindowEvent::ScaleFactorChanged { .. } => {
|
||||||
rcx.recreate_swapchain = true;
|
rcx.recreate_swapchain = true;
|
||||||
}
|
},
|
||||||
WindowEvent::DroppedFile(_file) => {
|
WindowEvent::DroppedFile(_file) => {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
},
|
||||||
WindowEvent::MouseInput {
|
WindowEvent::MouseInput {
|
||||||
device_id: d,
|
device_id: d,
|
||||||
state: s,
|
state: s,
|
||||||
@@ -1045,7 +1045,7 @@ impl ApplicationHandler for App {
|
|||||||
if b == &MouseButton::Right {
|
if b == &MouseButton::Right {
|
||||||
self.cstate.looking = s == &ElementState::Pressed;
|
self.cstate.looking = s == &ElementState::Pressed;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
WindowEvent::KeyboardInput {
|
WindowEvent::KeyboardInput {
|
||||||
device_id: _,
|
device_id: _,
|
||||||
event: input,
|
event: input,
|
||||||
@@ -1053,19 +1053,19 @@ impl ApplicationHandler for App {
|
|||||||
} => match input.physical_key {
|
} => match input.physical_key {
|
||||||
PhysicalKey::Code(KeyCode::KeyW) => {
|
PhysicalKey::Code(KeyCode::KeyW) => {
|
||||||
self.cstate.keys.w = input.state == ElementState::Pressed;
|
self.cstate.keys.w = input.state == ElementState::Pressed;
|
||||||
}
|
},
|
||||||
PhysicalKey::Code(KeyCode::KeyS) => {
|
PhysicalKey::Code(KeyCode::KeyS) => {
|
||||||
self.cstate.keys.s = input.state == ElementState::Pressed;
|
self.cstate.keys.s = input.state == ElementState::Pressed;
|
||||||
}
|
},
|
||||||
PhysicalKey::Code(KeyCode::KeyA) => {
|
PhysicalKey::Code(KeyCode::KeyA) => {
|
||||||
self.cstate.keys.a = input.state == ElementState::Pressed;
|
self.cstate.keys.a = input.state == ElementState::Pressed;
|
||||||
}
|
},
|
||||||
PhysicalKey::Code(KeyCode::KeyD) => {
|
PhysicalKey::Code(KeyCode::KeyD) => {
|
||||||
self.cstate.keys.d = input.state == ElementState::Pressed;
|
self.cstate.keys.d = input.state == ElementState::Pressed;
|
||||||
}
|
},
|
||||||
PhysicalKey::Code(KeyCode::ShiftLeft) => {
|
PhysicalKey::Code(KeyCode::ShiftLeft) => {
|
||||||
self.cstate.looking = input.state == ElementState::Pressed;
|
self.cstate.looking = input.state == ElementState::Pressed;
|
||||||
}
|
},
|
||||||
PhysicalKey::Code(KeyCode::Space) => {
|
PhysicalKey::Code(KeyCode::Space) => {
|
||||||
if input.state == ElementState::Pressed {
|
if input.state == ElementState::Pressed {
|
||||||
self.thread_work_creation
|
self.thread_work_creation
|
||||||
@@ -1087,18 +1087,18 @@ impl ApplicationHandler for App {
|
|||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
PhysicalKey::Code(KeyCode::KeyG) => {
|
PhysicalKey::Code(KeyCode::KeyG) => {
|
||||||
if input.state == ElementState::Pressed {
|
if input.state == ElementState::Pressed {
|
||||||
self.draw_gui = !self.draw_gui;
|
self.draw_gui = !self.draw_gui;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
_ => {}
|
_ => {},
|
||||||
},
|
},
|
||||||
WindowEvent::RedrawRequested => {
|
WindowEvent::RedrawRequested => {
|
||||||
self.redraw(rcx);
|
self.redraw(rcx);
|
||||||
}
|
},
|
||||||
_ => {}
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1537,9 +1537,9 @@ impl App {
|
|||||||
} else {
|
} else {
|
||||||
self.gstate.csg[index as usize] = csg;
|
self.gstate.csg[index as usize] = csg;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
WorkComplete::GetPushConstants(..) => {}
|
WorkComplete::GetPushConstants(..) => {},
|
||||||
WorkComplete::RecompilePipelines(..) => {}
|
WorkComplete::RecompilePipelines(..) => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1706,7 +1706,7 @@ impl App {
|
|||||||
match work {
|
match work {
|
||||||
WorkComplete::RecompilePipelines(_index) => {
|
WorkComplete::RecompilePipelines(_index) => {
|
||||||
csg_left -= 1;
|
csg_left -= 1;
|
||||||
}
|
},
|
||||||
other => work_for_later.push(other),
|
other => work_for_later.push(other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1720,14 +1720,14 @@ impl App {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 1..self.gstate.fps.len() {
|
for i in 1..self.gstate.cpu_mpf.len() {
|
||||||
self.gstate.fps[i - 1] = self.gstate.fps[i];
|
self.gstate.cpu_mpf[i - 1] = self.gstate.cpu_mpf[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
self.time = (Instant::now() - rcx.render_start).as_secs_f32();
|
self.time = (Instant::now() - self.application_start).as_secs_f32();
|
||||||
|
|
||||||
self.gstate.fps[self.gstate.fps.len() - 1] =
|
self.gstate.cpu_mpf[self.gstate.cpu_mpf.len() - 1] =
|
||||||
1.0 / (Instant::now() - rcx.render_start).as_secs_f64();
|
(Instant::now() - rcx.render_start).as_secs_f64() * 1000.0;
|
||||||
|
|
||||||
for future in rcx.previous_frame_end.iter_mut().flatten() {
|
for future in rcx.previous_frame_end.iter_mut().flatten() {
|
||||||
future.cleanup_finished();
|
future.cleanup_finished();
|
||||||
@@ -1857,7 +1857,7 @@ impl App {
|
|||||||
match work {
|
match work {
|
||||||
WorkComplete::RecompilePipelines(_index) => {
|
WorkComplete::RecompilePipelines(_index) => {
|
||||||
csg_left -= 1;
|
csg_left -= 1;
|
||||||
}
|
},
|
||||||
other => work_for_later.push(other),
|
other => work_for_later.push(other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1872,7 +1872,7 @@ impl App {
|
|||||||
Err(VulkanError::OutOfDate) => {
|
Err(VulkanError::OutOfDate) => {
|
||||||
rcx.recreate_swapchain = true;
|
rcx.recreate_swapchain = true;
|
||||||
return;
|
return;
|
||||||
}
|
},
|
||||||
Err(e) => panic!("Failed to acquire next image: {e}"),
|
Err(e) => panic!("Failed to acquire next image: {e}"),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1927,6 +1927,16 @@ impl App {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
builder
|
||||||
|
.reset_query_pool(rcx.time_query_pool.clone(), 0..2)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
builder
|
||||||
|
.write_timestamp(rcx.time_query_pool.clone(), 0, PipelineStage::TopOfPipe)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
let mut futures = camera_and_lights.boxed();
|
let mut futures = camera_and_lights.boxed();
|
||||||
|
|
||||||
if RUN_RT_PIPELINE {
|
if RUN_RT_PIPELINE {
|
||||||
@@ -1975,7 +1985,7 @@ impl App {
|
|||||||
Some(future.boxed())
|
Some(future.boxed())
|
||||||
};
|
};
|
||||||
push_constants_left -= 1;
|
push_constants_left -= 1;
|
||||||
}
|
},
|
||||||
other => work_for_later.push(other),
|
other => work_for_later.push(other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2013,6 +2023,12 @@ impl App {
|
|||||||
builder.end_render_pass(Default::default()).unwrap();
|
builder.end_render_pass(Default::default()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
builder
|
||||||
|
.write_timestamp(rcx.time_query_pool.clone(), 1, PipelineStage::BottomOfPipe)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
let command_buffer = builder.build().unwrap();
|
let command_buffer = builder.build().unwrap();
|
||||||
|
|
||||||
for future in rcx.previous_frame_end.iter_mut().flatten() {
|
for future in rcx.previous_frame_end.iter_mut().flatten() {
|
||||||
@@ -2020,6 +2036,22 @@ impl App {
|
|||||||
future.cleanup_finished();
|
future.cleanup_finished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut time_stamps = [0u64; 2];
|
||||||
|
|
||||||
|
rcx.time_query_pool
|
||||||
|
.get_results(0..2, &mut time_stamps, QueryResultFlags::WAIT)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let delta_in_ms = (time_stamps[1] - time_stamps[0]) as f32
|
||||||
|
* self.device.physical_device().properties().timestamp_period
|
||||||
|
/ 1000000.0;
|
||||||
|
|
||||||
|
for i in 1..self.gstate.gpu_mpf.len() {
|
||||||
|
self.gstate.gpu_mpf[i - 1] = self.gstate.gpu_mpf[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
self.gstate.gpu_mpf[self.gstate.gpu_mpf.len() - 1] = delta_in_ms as f64;
|
||||||
|
|
||||||
let future = rcx.previous_frame_end[image_index]
|
let future = rcx.previous_frame_end[image_index]
|
||||||
.take()
|
.take()
|
||||||
.map(|f| f.boxed())
|
.map(|f| f.boxed())
|
||||||
@@ -2050,20 +2082,20 @@ impl App {
|
|||||||
match future.map_err(Validated::unwrap) {
|
match future.map_err(Validated::unwrap) {
|
||||||
Ok(future) => {
|
Ok(future) => {
|
||||||
rcx.previous_frame_end[image_index] = Some(future);
|
rcx.previous_frame_end[image_index] = Some(future);
|
||||||
}
|
},
|
||||||
Err(VulkanError::OutOfDate) => {
|
Err(VulkanError::OutOfDate) => {
|
||||||
rcx.recreate_swapchain = true;
|
rcx.recreate_swapchain = true;
|
||||||
rcx.previous_frame_end[image_index] = None;
|
rcx.previous_frame_end[image_index] = None;
|
||||||
}
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Failed to flush future: {e:?}");
|
error!("Failed to flush future: {e:?}");
|
||||||
rcx.previous_frame_end[image_index] = None;
|
rcx.previous_frame_end[image_index] = None;
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for work in self.thread_work_completion.try_iter() {
|
for work in self.thread_work_completion.try_iter() {
|
||||||
match work {
|
match work {
|
||||||
WorkComplete::GetPushConstants(..) => {}
|
WorkComplete::GetPushConstants(..) => {},
|
||||||
other => work_for_later.push(other),
|
other => work_for_later.push(other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,6 +11,7 @@ use glam::{EulerRot, Mat4, Vec3};
|
|||||||
use log::info;
|
use log::info;
|
||||||
use rand::{Rng, SeedableRng, rngs::SmallRng};
|
use rand::{Rng, SeedableRng, rngs::SmallRng};
|
||||||
use rspirv::{binary::Assemble, dr::Module};
|
use rspirv::{binary::Assemble, dr::Module};
|
||||||
|
use tape_load::interpreters;
|
||||||
use vulkano::{
|
use vulkano::{
|
||||||
buffer::{Subbuffer, allocator::SubbufferAllocator},
|
buffer::{Subbuffer, allocator::SubbufferAllocator},
|
||||||
command_buffer::{CommandBufferExecFuture, allocator::StandardCommandBufferAllocator},
|
command_buffer::{CommandBufferExecFuture, allocator::StandardCommandBufferAllocator},
|
||||||
@@ -42,7 +43,7 @@ use crate::{
|
|||||||
DUMP_SPV_TO_FILE, IVertex, MAXIMUM_SUBDIVISION, MINUMUM_SUBDIVISION, ShaderModules,
|
DUMP_SPV_TO_FILE, IVertex, MAXIMUM_SUBDIVISION, MINUMUM_SUBDIVISION, ShaderModules,
|
||||||
get_spec_constants, gpu_upload,
|
get_spec_constants, gpu_upload,
|
||||||
gui::PreviousDebug,
|
gui::PreviousDebug,
|
||||||
interpreter::{self, IntervalInterpreter, PointInterpreter, VALUE_0},
|
interpreters::{VALUE_0, interval::IntervalInterpreter, point::PointInterpreter},
|
||||||
objects::CSG,
|
objects::CSG,
|
||||||
ssa::{SSAInput, SSAOpcode, SSAOpcodeSized, SSATape},
|
ssa::{SSAInput, SSAOpcode, SSAOpcodeSized, SSATape},
|
||||||
trace_vs::{Object, PushConstantData},
|
trace_vs::{Object, PushConstantData},
|
||||||
@@ -520,25 +521,25 @@ fn interval_check(
|
|||||||
command_allocator: Arc<StandardCommandBufferAllocator>,
|
command_allocator: Arc<StandardCommandBufferAllocator>,
|
||||||
transfer_queue: Arc<Queue>,
|
transfer_queue: Arc<Queue>,
|
||||||
) -> CommandBufferExecFuture<NowFuture> {
|
) -> CommandBufferExecFuture<NowFuture> {
|
||||||
const INTERPRET_INPUT_X: interpreter::Value =
|
const INTERPRET_INPUT_X: interpreters::Value =
|
||||||
interpreter::Value::from_array([10000.0, 0.0, 0.0, -10000.0, 0.0, 0.0, 0.0, 0.0]);
|
interpreters::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 =
|
const INTERPRET_INPUT_Y: interpreters::Value =
|
||||||
interpreter::Value::from_array([0.0, 10000.0, 0.0, 0.0, -10000.0, 0.0, 0.0, 0.0]);
|
interpreters::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 =
|
const INTERPRET_INPUT_Z: interpreters::Value =
|
||||||
interpreter::Value::from_array([0.0, 0.0, 10000.0, 0.0, 0.0, -10000.0, 0.0, 0.0]);
|
interpreters::Value::from_array([0.0, 0.0, 10000.0, 0.0, 0.0, -10000.0, 0.0, 0.0]);
|
||||||
const INTERPRET_MUL: interpreter::Value =
|
const INTERPRET_MUL: interpreters::Value =
|
||||||
interpreter::Value::from_array([-1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 0.0, 0.0]);
|
interpreters::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([
|
const INTERPRET_ADD: interpreters::Value = interpreters::Value::from_array([
|
||||||
10000.0, 10000.0, 10000.0, -10000.0, -10000.0, -10000.0, 0.0, 0.0,
|
10000.0, 10000.0, 10000.0, -10000.0, -10000.0, -10000.0, 0.0, 0.0,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let mut interpreter = PointInterpreter::new(csg);
|
let mut interpreter = PointInterpreter::new(&csg.parts);
|
||||||
let interpreter_out = interpreter
|
let interpreter_out = interpreter
|
||||||
.scene(
|
.scene(
|
||||||
INTERPRET_INPUT_X,
|
INTERPRET_INPUT_X,
|
||||||
INTERPRET_INPUT_Y,
|
INTERPRET_INPUT_Y,
|
||||||
INTERPRET_INPUT_Z,
|
INTERPRET_INPUT_Z,
|
||||||
interpreter::Value::splat(time),
|
interpreters::Value::splat(time),
|
||||||
)
|
)
|
||||||
.mul_add(INTERPRET_MUL, INTERPRET_ADD)
|
.mul_add(INTERPRET_MUL, INTERPRET_ADD)
|
||||||
.to_array();
|
.to_array();
|
||||||
@@ -576,7 +577,7 @@ fn interval_check(
|
|||||||
for y in 0..ydim {
|
for y in 0..ydim {
|
||||||
for z in 0..(zdim / 8) {
|
for z in 0..(zdim / 8) {
|
||||||
let interval_input_z: Interval = Interval::new_unchecked(
|
let interval_input_z: Interval = Interval::new_unchecked(
|
||||||
interpreter::Value::from_array([
|
interpreters::Value::from_array([
|
||||||
((((8.0 / (zdim as f32)) * z as f32) + (0.0 / (zdim as f32)))
|
((((8.0 / (zdim as f32)) * z as f32) + (0.0 / (zdim as f32)))
|
||||||
* obj.dimensions[2])
|
* obj.dimensions[2])
|
||||||
+ obj.lowest_corner[2],
|
+ obj.lowest_corner[2],
|
||||||
@@ -602,7 +603,7 @@ fn interval_check(
|
|||||||
* obj.dimensions[2])
|
* obj.dimensions[2])
|
||||||
+ obj.lowest_corner[2],
|
+ obj.lowest_corner[2],
|
||||||
]),
|
]),
|
||||||
interpreter::Value::from_array([
|
interpreters::Value::from_array([
|
||||||
((((8.0 / (zdim as f32)) * z as f32) + (1.0 / (zdim as f32)))
|
((((8.0 / (zdim as f32)) * z as f32) + (1.0 / (zdim as f32)))
|
||||||
* obj.dimensions[2])
|
* obj.dimensions[2])
|
||||||
+ obj.lowest_corner[2],
|
+ obj.lowest_corner[2],
|
||||||
@@ -630,7 +631,7 @@ fn interval_check(
|
|||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut interpreter = IntervalInterpreter::new(csg);
|
let mut interpreter = IntervalInterpreter::new(&csg.parts);
|
||||||
let output = interpreter.scene(
|
let output = interpreter.scene(
|
||||||
Interval::const_splat2(
|
Interval::const_splat2(
|
||||||
(x as f32 / (xdim as f32)) * obj.dimensions[0] + obj.lowest_corner[0],
|
(x as f32 / (xdim as f32)) * obj.dimensions[0] + obj.lowest_corner[0],
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
[package]
|
||||||
|
name = "tape-load"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
glam = "0.30.3"
|
||||||
|
rspirv = "0.12"
|
||||||
|
foldhash = "0.1.5"
|
||||||
|
humantime = "2.3"
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub(crate) enum InstructionSet {
|
pub enum InstructionSet {
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
/// Returns the input. Useful for copying registers.
|
/// Returns the input. Useful for copying registers.
|
||||||
@@ -1,411 +1,15 @@
|
|||||||
use std::simd::{
|
use std::simd::{StdFloat, cmp::SimdPartialOrd, num::SimdFloat};
|
||||||
StdFloat,
|
|
||||||
cmp::{SimdPartialEq, SimdPartialOrd},
|
|
||||||
num::SimdFloat,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
BYTECODE_IMITATES_GLSL, CSG,
|
interpreters::VALUE_0,
|
||||||
ssa::{SSAInput, SSAInstruction, SSAOpcode},
|
ssa::{SSAInput, SSAInstruction, SSAOpcode, SSATape},
|
||||||
types::Interval,
|
types::Interval,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type Value = std::simd::f32x8;
|
|
||||||
pub type Mask = std::simd::mask32x8;
|
|
||||||
|
|
||||||
pub const VALUE_NAN: Value = Value::splat(core::f32::NAN);
|
|
||||||
pub const VALUE_1: Value = Value::splat(1.0);
|
|
||||||
pub const VALUE_0: Value = Value::splat(0.0);
|
|
||||||
pub const VALUE_05: Value = Value::splat(0.5);
|
|
||||||
pub const VALUE_M1: Value = Value::splat(-1.0);
|
|
||||||
pub const VALUE_2: Value = Value::splat(2.0);
|
|
||||||
pub const VALUE_PI: Value = Value::splat(core::f32::consts::PI);
|
|
||||||
pub const VALUE_PI_2: Value = Value::splat(core::f32::consts::FRAC_PI_2);
|
|
||||||
pub const VALUE_TAU: Value = Value::splat(core::f32::consts::TAU);
|
|
||||||
|
|
||||||
pub fn glsign(f: Value) -> Value {
|
|
||||||
if BYTECODE_IMITATES_GLSL {
|
|
||||||
f.simd_eq(VALUE_0).select(f, f.signum())
|
|
||||||
} else {
|
|
||||||
f.signum()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn glfract(f: Value) -> Value {
|
|
||||||
if BYTECODE_IMITATES_GLSL {
|
|
||||||
f - f.floor()
|
|
||||||
} else {
|
|
||||||
f.fract()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct PointInterpreter<'csg> {
|
pub struct IntervalInterpreter<'csg> {
|
||||||
value_map: Vec<Value>,
|
|
||||||
csg: &'csg CSG,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PointInterpreter<'_> {
|
|
||||||
fn load(&self, consider: SSAInput) -> Value {
|
|
||||||
match consider {
|
|
||||||
SSAInput::Register(r) => self.value_map[r as usize],
|
|
||||||
SSAInput::Constant(c) => Value::splat(c),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn store(&mut self, location: u32, value: Value) {
|
|
||||||
self.value_map[location as usize] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'csg> PointInterpreter<'csg> {
|
|
||||||
pub(crate) fn new(csg: &'csg CSG) -> Self {
|
|
||||||
PointInterpreter {
|
|
||||||
value_map: vec![VALUE_0; csg.parts.last_output as usize],
|
|
||||||
csg,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clear_stacks(&mut self) {
|
|
||||||
self.value_map = vec![VALUE_0; self.csg.parts.last_output as usize];
|
|
||||||
}
|
|
||||||
|
|
||||||
fn param_one(&mut self, instruction: &SSAInstruction, func: impl Fn(Value) -> Value) {
|
|
||||||
for i in 0..instruction.opcode.size as usize {
|
|
||||||
let val_a = self.load(instruction.inputs[i]);
|
|
||||||
self.store(instruction.outputs[i], func(val_a));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn param_two(&mut self, instruction: &SSAInstruction, func: impl Fn(Value, Value) -> Value) {
|
|
||||||
for i in 0..instruction.opcode.size as usize {
|
|
||||||
let val_a = self.load(instruction.inputs[i]);
|
|
||||||
let val_b = self.load(instruction.inputs[i + instruction.opcode.size as usize]);
|
|
||||||
self.store(instruction.outputs[i], func(val_a, val_b));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn param_three(
|
|
||||||
&mut self,
|
|
||||||
instruction: &SSAInstruction,
|
|
||||||
func: impl Fn(Value, Value, Value) -> Value,
|
|
||||||
) {
|
|
||||||
for i in 0..instruction.opcode.size as usize {
|
|
||||||
let val_a = self.load(instruction.inputs[i]);
|
|
||||||
let val_b = self.load(instruction.inputs[i + instruction.opcode.size as usize]);
|
|
||||||
let val_c = self.load(instruction.inputs[i + (instruction.opcode.size * 2) as usize]);
|
|
||||||
self.store(instruction.outputs[i], func(val_a, val_b, val_c));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn param_four(
|
|
||||||
&mut self,
|
|
||||||
instruction: &SSAInstruction,
|
|
||||||
func: impl Fn(Value, Value, Value, Value) -> Value,
|
|
||||||
) {
|
|
||||||
for i in 0..instruction.opcode.size as usize {
|
|
||||||
let val_a = self.load(instruction.inputs[i]);
|
|
||||||
let val_b = self.load(instruction.inputs[i + instruction.opcode.size as usize]);
|
|
||||||
let val_c = self.load(instruction.inputs[i + (instruction.opcode.size * 2) as usize]);
|
|
||||||
let val_d = self.load(instruction.inputs[i + (instruction.opcode.size * 3) as usize]);
|
|
||||||
self.store(instruction.outputs[i], func(val_a, val_b, val_c, val_d));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// cargo asm "tape-drive::interpreter::PointInterpreter::scene" --no-color
|
|
||||||
// --rust > scene.asm
|
|
||||||
|
|
||||||
pub(crate) fn scene(&mut self, px: Value, py: Value, pz: Value, time: Value) -> Value {
|
|
||||||
self.clear_stacks();
|
|
||||||
|
|
||||||
for instruction in &self.csg.parts.tape {
|
|
||||||
use SSAOpcode::*;
|
|
||||||
match instruction.opcode.opcode {
|
|
||||||
SSAReturn => {
|
|
||||||
return self.load(instruction.inputs[0]);
|
|
||||||
},
|
|
||||||
SSAPosition => {
|
|
||||||
self.store(instruction.outputs[0], px);
|
|
||||||
self.store(instruction.outputs[1], py);
|
|
||||||
self.store(instruction.outputs[2], pz);
|
|
||||||
self.store(instruction.outputs[3], time);
|
|
||||||
},
|
|
||||||
SSAAdd => {
|
|
||||||
self.param_two(instruction, |val_a, val_b| val_a + val_b);
|
|
||||||
},
|
|
||||||
SSASub => {
|
|
||||||
self.param_two(instruction, |val_a, val_b| val_a - val_b);
|
|
||||||
},
|
|
||||||
SSAMul => {
|
|
||||||
self.param_two(instruction, |val_a, val_b| val_a * val_b);
|
|
||||||
},
|
|
||||||
SSADiv => {
|
|
||||||
self.param_two(instruction, |val_a, val_b| val_a / val_b);
|
|
||||||
},
|
|
||||||
SSAMod => {
|
|
||||||
self.param_two(instruction, |val_a, val_b| val_a % val_b);
|
|
||||||
},
|
|
||||||
SSAAtan2 => self.param_two(instruction, |val_a, val_b| {
|
|
||||||
let mut val_a = val_a.to_array();
|
|
||||||
let val_b = val_b.to_array();
|
|
||||||
for i in 0..Value::LEN {
|
|
||||||
val_a[i] = val_a[i].atan2(val_b[i]);
|
|
||||||
}
|
|
||||||
Value::from_array(val_a)
|
|
||||||
}),
|
|
||||||
SSAMin => {
|
|
||||||
self.param_two(instruction, |val_a, val_b| val_a.simd_min(val_b));
|
|
||||||
},
|
|
||||||
SSAMinMaterial => todo!(),
|
|
||||||
SSAMax => {
|
|
||||||
self.param_two(instruction, |val_a, val_b| val_a.simd_max(val_b));
|
|
||||||
},
|
|
||||||
SSAMaxMaterial => todo!(),
|
|
||||||
SSADot => {
|
|
||||||
let val_a = (0..instruction.opcode.size)
|
|
||||||
.map(|i| self.load(instruction.inputs[i as usize]))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let val_b = (instruction.opcode.size..(instruction.opcode.size * 2))
|
|
||||||
.map(|i| self.load(instruction.inputs[i as usize]))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
self.store(
|
|
||||||
instruction.outputs[0],
|
|
||||||
match instruction.opcode.size {
|
|
||||||
1 => val_a[0] * val_b[0],
|
|
||||||
2 => (val_a[0] * val_b[0]) + (val_a[1] * val_b[1]),
|
|
||||||
3 => {
|
|
||||||
(val_a[0] * val_b[0])
|
|
||||||
+ (val_a[1] * val_b[1])
|
|
||||||
+ (val_a[2] * val_b[2])
|
|
||||||
},
|
|
||||||
4 => {
|
|
||||||
(val_a[0] * val_b[0])
|
|
||||||
+ (val_a[1] * val_b[1])
|
|
||||||
+ (val_a[2] * val_b[2])
|
|
||||||
+ (val_a[3] * val_b[3])
|
|
||||||
},
|
|
||||||
_ => unreachable!(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
SSALength => {
|
|
||||||
let val_a = (0..instruction.opcode.size)
|
|
||||||
.map(|i| self.load(instruction.inputs[i as usize]))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
self.store(
|
|
||||||
instruction.outputs[0],
|
|
||||||
match instruction.opcode.size {
|
|
||||||
1 => val_a[0],
|
|
||||||
2 => ((val_a[0] * val_a[0]) + (val_a[1] * val_a[1])).sqrt(),
|
|
||||||
3 => ((val_a[0] * val_a[0])
|
|
||||||
+ (val_a[1] * val_a[1])
|
|
||||||
+ (val_a[2] * val_a[2]))
|
|
||||||
.sqrt(),
|
|
||||||
4 => ((val_a[0] * val_a[0])
|
|
||||||
+ (val_a[1] * val_a[1])
|
|
||||||
+ (val_a[2] * val_a[2])
|
|
||||||
+ (val_a[3] * val_a[3]))
|
|
||||||
.sqrt(),
|
|
||||||
_ => unreachable!(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
SSADistance => {
|
|
||||||
let val_a = (0..instruction.opcode.size)
|
|
||||||
.map(|i| self.load(instruction.inputs[i as usize]))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let val_b = (instruction.opcode.size..(instruction.opcode.size * 2))
|
|
||||||
.map(|i| self.load(instruction.inputs[i as usize]))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
self.store(
|
|
||||||
instruction.outputs[0],
|
|
||||||
match instruction.opcode.size {
|
|
||||||
1 => val_b[0] - val_a[0],
|
|
||||||
2 => (((val_a[0] - val_b[0]) * (val_a[0] - val_b[0]))
|
|
||||||
+ ((val_a[1] - val_b[1]) * (val_a[1] - val_b[1])))
|
|
||||||
.sqrt(),
|
|
||||||
3 => (((val_a[0] - val_b[0]) * (val_a[0] - val_b[0]))
|
|
||||||
+ ((val_a[1] - val_b[1]) * (val_a[1] - val_b[1]))
|
|
||||||
+ ((val_a[2] - val_b[2]) * (val_a[2] - val_b[2]))
|
|
||||||
+ ((val_a[3] - val_b[3]) * (val_a[3] - val_b[3])))
|
|
||||||
.sqrt(),
|
|
||||||
4 => (((val_a[0] - val_b[0]) * (val_a[0] - val_b[0]))
|
|
||||||
+ ((val_a[1] - val_b[1]) * (val_a[1] - val_b[1]))
|
|
||||||
+ ((val_a[2] - val_b[2]) * (val_a[2] - val_b[2]))
|
|
||||||
+ ((val_a[3] - val_b[3]) * (val_a[3] - val_b[3]))
|
|
||||||
+ ((val_a[4] - val_b[4]) * (val_a[4] - val_b[4])))
|
|
||||||
.sqrt(),
|
|
||||||
_ => unreachable!(),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
SSANegate => {
|
|
||||||
self.param_one(instruction, |val_a| -val_a);
|
|
||||||
},
|
|
||||||
SSARound => {
|
|
||||||
self.param_one(instruction, |val_a| val_a.round());
|
|
||||||
},
|
|
||||||
SSAAbs => {
|
|
||||||
self.param_one(instruction, |val_a| val_a.abs());
|
|
||||||
},
|
|
||||||
SSAFloor => {
|
|
||||||
self.param_one(instruction, |val_a| val_a.floor());
|
|
||||||
},
|
|
||||||
SSACeil => {
|
|
||||||
self.param_one(instruction, |val_a| val_a.ceil());
|
|
||||||
},
|
|
||||||
SSAFract => {
|
|
||||||
self.param_one(instruction, |val_a| glfract(val_a));
|
|
||||||
},
|
|
||||||
SSASin => {
|
|
||||||
self.param_one(instruction, |val_a| val_a.sin());
|
|
||||||
},
|
|
||||||
SSACos => {
|
|
||||||
self.param_one(instruction, |val_a| val_a.cos());
|
|
||||||
},
|
|
||||||
SSATan => {
|
|
||||||
self.param_one(instruction, |val_a| {
|
|
||||||
Value::from_array(val_a.to_array().map(|f| f.tan()))
|
|
||||||
});
|
|
||||||
},
|
|
||||||
SSAAsin => {
|
|
||||||
self.param_one(instruction, |val_a| {
|
|
||||||
Value::from_array(val_a.to_array().map(|f| f.asin()))
|
|
||||||
});
|
|
||||||
},
|
|
||||||
SSAAcos => {
|
|
||||||
self.param_one(instruction, |val_a| {
|
|
||||||
Value::from_array(val_a.to_array().map(|f| f.acos()))
|
|
||||||
});
|
|
||||||
},
|
|
||||||
SSAAtan => {
|
|
||||||
self.param_one(instruction, |val_a| {
|
|
||||||
Value::from_array(val_a.to_array().map(|f| f.atan()))
|
|
||||||
});
|
|
||||||
},
|
|
||||||
SSAExp => {
|
|
||||||
self.param_one(instruction, |val_a| val_a.exp());
|
|
||||||
},
|
|
||||||
SSALog => {
|
|
||||||
self.param_one(instruction, |val_a| val_a.ln());
|
|
||||||
},
|
|
||||||
SSASqrt => {
|
|
||||||
self.param_one(instruction, |val_a| val_a.sqrt());
|
|
||||||
},
|
|
||||||
SSASquare => {
|
|
||||||
self.param_one(instruction, |val_a| val_a * val_a);
|
|
||||||
},
|
|
||||||
SSACube => {
|
|
||||||
self.param_one(instruction, |val_a| val_a * val_a * val_a);
|
|
||||||
},
|
|
||||||
SSASmoothMin => {
|
|
||||||
self.param_three(instruction, |d1, d2, k| {
|
|
||||||
let h =
|
|
||||||
(VALUE_05 + (VALUE_05 * (d2 - d1) / k)).simd_clamp(VALUE_0, VALUE_1);
|
|
||||||
return ((d2 * (VALUE_1 - h)) + (d1 * h)) - k * h * (VALUE_1 - h);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
SSASmoothMax => {
|
|
||||||
self.param_three(instruction, |d1, d2, k| {
|
|
||||||
let h =
|
|
||||||
(VALUE_05 - (VALUE_05 * (d2 + d1) / k)).simd_clamp(VALUE_0, VALUE_1);
|
|
||||||
return ((d2 * (VALUE_1 - h)) + (-d1 * h)) + k * h * (VALUE_1 - h);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
SSASmoothMinMaterial => todo!(),
|
|
||||||
SSASmoothMaxMaterial => todo!(),
|
|
||||||
SSAClamp => {
|
|
||||||
self.param_three(instruction, |val_a, val_b, val_c| {
|
|
||||||
val_a.simd_clamp(val_b, val_c)
|
|
||||||
});
|
|
||||||
},
|
|
||||||
SSAMix => {
|
|
||||||
self.param_three(instruction, |val_a, val_b, val_c| {
|
|
||||||
(val_a * (VALUE_1 - val_c)) + (val_b * val_c)
|
|
||||||
});
|
|
||||||
},
|
|
||||||
SSAFMA => {
|
|
||||||
self.param_three(instruction, |val_a, val_b, val_c| {
|
|
||||||
val_a.mul_add(val_b, val_c)
|
|
||||||
});
|
|
||||||
},
|
|
||||||
SSASDFSphere => {
|
|
||||||
let pos_x = self.load(instruction.inputs[0]);
|
|
||||||
let pos_y = self.load(instruction.inputs[1]);
|
|
||||||
let pos_z = self.load(instruction.inputs[2]);
|
|
||||||
let radius = self.load(instruction.inputs[3]);
|
|
||||||
self.store(
|
|
||||||
instruction.outputs[0],
|
|
||||||
((pos_x * pos_x) + (pos_y * pos_y) + (pos_z * pos_z)).sqrt() - radius,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
SSASDFBox => {
|
|
||||||
let pos_x = self.load(instruction.inputs[0]);
|
|
||||||
let pos_y = self.load(instruction.inputs[1]);
|
|
||||||
let pos_z = self.load(instruction.inputs[2]);
|
|
||||||
let rad_x = self.load(instruction.inputs[3]);
|
|
||||||
let rad_y = self.load(instruction.inputs[4]);
|
|
||||||
let rad_z = self.load(instruction.inputs[5]);
|
|
||||||
let qx = pos_x.abs() - rad_x;
|
|
||||||
let qy = pos_y.abs() - rad_y;
|
|
||||||
let qz = pos_z.abs() - rad_z;
|
|
||||||
let qxmax = qx.simd_max(VALUE_0);
|
|
||||||
let qymax = qy.simd_max(VALUE_0);
|
|
||||||
let qzmax = qz.simd_max(VALUE_0);
|
|
||||||
self.store(
|
|
||||||
instruction.outputs[0],
|
|
||||||
((qxmax * qxmax) + (qymax * qymax) + (qzmax * qzmax)).sqrt()
|
|
||||||
+ qx.simd_max(qy.simd_max(qz)).simd_min(VALUE_0),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
SSASDFTorus => {
|
|
||||||
let pos_x = self.load(instruction.inputs[0]);
|
|
||||||
let pos_y = self.load(instruction.inputs[1]);
|
|
||||||
let pos_z = self.load(instruction.inputs[2]);
|
|
||||||
let radius1 = self.load(instruction.inputs[3]);
|
|
||||||
let radius2 = self.load(instruction.inputs[4]);
|
|
||||||
let q = ((pos_x * pos_x) + (pos_z * pos_z)).sqrt() - radius1;
|
|
||||||
self.store(
|
|
||||||
instruction.outputs[0],
|
|
||||||
((q * q) + (pos_y * pos_y)).sqrt() - radius2,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
SSACompare => {
|
|
||||||
self.param_two(instruction, |val_a, val_b| {
|
|
||||||
val_a
|
|
||||||
.simd_gt(val_b)
|
|
||||||
.select(VALUE_1, val_a.simd_lt(val_b).select(VALUE_M1, VALUE_0))
|
|
||||||
});
|
|
||||||
},
|
|
||||||
SSAAnd => {
|
|
||||||
self.param_two(instruction, |val_a, val_b| {
|
|
||||||
val_a.simd_eq(VALUE_0).select(val_a, val_b)
|
|
||||||
});
|
|
||||||
},
|
|
||||||
SSAOr => {
|
|
||||||
self.param_two(instruction, |val_a, val_b| {
|
|
||||||
val_a.simd_eq(VALUE_0).select(val_b, val_a)
|
|
||||||
});
|
|
||||||
},
|
|
||||||
SSARecip => {
|
|
||||||
self.param_one(instruction, |val_a| val_a.recip());
|
|
||||||
},
|
|
||||||
SSANot => {
|
|
||||||
self.param_one(instruction, |val_a| {
|
|
||||||
val_a.simd_eq(VALUE_0).select(VALUE_1, VALUE_0)
|
|
||||||
});
|
|
||||||
},
|
|
||||||
SSAStop => return VALUE_0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return VALUE_NAN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub(crate) struct IntervalInterpreter<'csg> {
|
|
||||||
value_map: Vec<Interval>,
|
value_map: Vec<Interval>,
|
||||||
csg: &'csg CSG,
|
csg: &'csg SSATape,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntervalInterpreter<'_> {
|
impl IntervalInterpreter<'_> {
|
||||||
@@ -422,15 +26,15 @@ impl IntervalInterpreter<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'csg> IntervalInterpreter<'csg> {
|
impl<'csg> IntervalInterpreter<'csg> {
|
||||||
pub(crate) fn new(csg: &'csg CSG) -> Self {
|
pub fn new(csg: &'csg SSATape) -> Self {
|
||||||
IntervalInterpreter {
|
IntervalInterpreter {
|
||||||
value_map: vec![Interval::ZERO; csg.parts.last_output as usize],
|
value_map: vec![Interval::ZERO; csg.last_output as usize],
|
||||||
csg,
|
csg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_stacks(&mut self) {
|
fn clear_stacks(&mut self) {
|
||||||
self.value_map = vec![Interval::ZERO; self.csg.parts.last_output as usize];
|
self.value_map = vec![Interval::ZERO; self.csg.last_output as usize];
|
||||||
}
|
}
|
||||||
|
|
||||||
fn param_one(&mut self, instruction: &SSAInstruction, func: impl Fn(Interval) -> Interval) {
|
fn param_one(&mut self, instruction: &SSAInstruction, func: impl Fn(Interval) -> Interval) {
|
||||||
@@ -482,7 +86,7 @@ impl<'csg> IntervalInterpreter<'csg> {
|
|||||||
// cargo asm "tape-drive::interpreter::IntervalInterpreter::scene" --no-color
|
// cargo asm "tape-drive::interpreter::IntervalInterpreter::scene" --no-color
|
||||||
// --rust > scene.asm
|
// --rust > scene.asm
|
||||||
|
|
||||||
pub(crate) fn scene(
|
pub fn scene(
|
||||||
&mut self,
|
&mut self,
|
||||||
px: Interval,
|
px: Interval,
|
||||||
py: Interval,
|
py: Interval,
|
||||||
@@ -491,7 +95,7 @@ impl<'csg> IntervalInterpreter<'csg> {
|
|||||||
) -> Interval {
|
) -> Interval {
|
||||||
self.clear_stacks();
|
self.clear_stacks();
|
||||||
|
|
||||||
for instruction in &self.csg.parts.tape {
|
for instruction in &self.csg.tape {
|
||||||
use SSAOpcode::*;
|
use SSAOpcode::*;
|
||||||
match instruction.opcode.opcode {
|
match instruction.opcode.opcode {
|
||||||
SSAReturn => {
|
SSAReturn => {
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
use std::simd::{StdFloat, cmp::SimdPartialEq, num::SimdFloat};
|
||||||
|
|
||||||
|
use crate::BYTECODE_IMITATES_GLSL;
|
||||||
|
|
||||||
|
pub mod interval;
|
||||||
|
pub mod point;
|
||||||
|
|
||||||
|
pub type Value = std::simd::f32x8;
|
||||||
|
pub type Mask = std::simd::mask32x8;
|
||||||
|
|
||||||
|
pub const VALUE_NAN: Value = Value::splat(core::f32::NAN);
|
||||||
|
pub const VALUE_1: Value = Value::splat(1.0);
|
||||||
|
pub const VALUE_0: Value = Value::splat(0.0);
|
||||||
|
pub const VALUE_05: Value = Value::splat(0.5);
|
||||||
|
pub const VALUE_M1: Value = Value::splat(-1.0);
|
||||||
|
pub const VALUE_2: Value = Value::splat(2.0);
|
||||||
|
pub const VALUE_PI: Value = Value::splat(core::f32::consts::PI);
|
||||||
|
pub const VALUE_PI_2: Value = Value::splat(core::f32::consts::FRAC_PI_2);
|
||||||
|
pub const VALUE_TAU: Value = Value::splat(core::f32::consts::TAU);
|
||||||
|
|
||||||
|
pub fn glsign(f: Value) -> Value {
|
||||||
|
if BYTECODE_IMITATES_GLSL {
|
||||||
|
f.simd_eq(VALUE_0).select(f, f.signum())
|
||||||
|
} else {
|
||||||
|
f.signum()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn glfract(f: Value) -> Value {
|
||||||
|
if BYTECODE_IMITATES_GLSL {
|
||||||
|
f - f.floor()
|
||||||
|
} else {
|
||||||
|
f.fract()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,373 @@
|
|||||||
|
use std::simd::{
|
||||||
|
StdFloat,
|
||||||
|
cmp::{SimdPartialEq, SimdPartialOrd},
|
||||||
|
num::SimdFloat,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
interpreters::{VALUE_0, VALUE_1, VALUE_05, VALUE_M1, VALUE_NAN, Value, glfract},
|
||||||
|
ssa::{SSAInput, SSAInstruction, SSAOpcode, SSATape},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct PointInterpreter<'csg> {
|
||||||
|
value_map: Vec<Value>,
|
||||||
|
csg: &'csg SSATape,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PointInterpreter<'_> {
|
||||||
|
fn load(&self, consider: SSAInput) -> Value {
|
||||||
|
match consider {
|
||||||
|
SSAInput::Register(r) => self.value_map[r as usize],
|
||||||
|
SSAInput::Constant(c) => Value::splat(c),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn store(&mut self, location: u32, value: Value) {
|
||||||
|
self.value_map[location as usize] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'csg> PointInterpreter<'csg> {
|
||||||
|
pub fn new(csg: &'csg SSATape) -> Self {
|
||||||
|
PointInterpreter {
|
||||||
|
value_map: vec![VALUE_0; csg.last_output as usize],
|
||||||
|
csg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clear_stacks(&mut self) {
|
||||||
|
self.value_map = vec![VALUE_0; self.csg.last_output as usize];
|
||||||
|
}
|
||||||
|
|
||||||
|
fn param_one(&mut self, instruction: &SSAInstruction, func: impl Fn(Value) -> Value) {
|
||||||
|
for i in 0..instruction.opcode.size as usize {
|
||||||
|
let val_a = self.load(instruction.inputs[i]);
|
||||||
|
self.store(instruction.outputs[i], func(val_a));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn param_two(&mut self, instruction: &SSAInstruction, func: impl Fn(Value, Value) -> Value) {
|
||||||
|
for i in 0..instruction.opcode.size as usize {
|
||||||
|
let val_a = self.load(instruction.inputs[i]);
|
||||||
|
let val_b = self.load(instruction.inputs[i + instruction.opcode.size as usize]);
|
||||||
|
self.store(instruction.outputs[i], func(val_a, val_b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn param_three(
|
||||||
|
&mut self,
|
||||||
|
instruction: &SSAInstruction,
|
||||||
|
func: impl Fn(Value, Value, Value) -> Value,
|
||||||
|
) {
|
||||||
|
for i in 0..instruction.opcode.size as usize {
|
||||||
|
let val_a = self.load(instruction.inputs[i]);
|
||||||
|
let val_b = self.load(instruction.inputs[i + instruction.opcode.size as usize]);
|
||||||
|
let val_c = self.load(instruction.inputs[i + (instruction.opcode.size * 2) as usize]);
|
||||||
|
self.store(instruction.outputs[i], func(val_a, val_b, val_c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn param_four(
|
||||||
|
&mut self,
|
||||||
|
instruction: &SSAInstruction,
|
||||||
|
func: impl Fn(Value, Value, Value, Value) -> Value,
|
||||||
|
) {
|
||||||
|
for i in 0..instruction.opcode.size as usize {
|
||||||
|
let val_a = self.load(instruction.inputs[i]);
|
||||||
|
let val_b = self.load(instruction.inputs[i + instruction.opcode.size as usize]);
|
||||||
|
let val_c = self.load(instruction.inputs[i + (instruction.opcode.size * 2) as usize]);
|
||||||
|
let val_d = self.load(instruction.inputs[i + (instruction.opcode.size * 3) as usize]);
|
||||||
|
self.store(instruction.outputs[i], func(val_a, val_b, val_c, val_d));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cargo asm "tape-drive::interpreter::PointInterpreter::scene" --no-color
|
||||||
|
// --rust > scene.asm
|
||||||
|
|
||||||
|
pub fn scene(&mut self, px: Value, py: Value, pz: Value, time: Value) -> Value {
|
||||||
|
self.clear_stacks();
|
||||||
|
|
||||||
|
for instruction in &self.csg.tape {
|
||||||
|
use SSAOpcode::*;
|
||||||
|
match instruction.opcode.opcode {
|
||||||
|
SSAReturn => {
|
||||||
|
return self.load(instruction.inputs[0]);
|
||||||
|
},
|
||||||
|
SSAPosition => {
|
||||||
|
self.store(instruction.outputs[0], px);
|
||||||
|
self.store(instruction.outputs[1], py);
|
||||||
|
self.store(instruction.outputs[2], pz);
|
||||||
|
self.store(instruction.outputs[3], time);
|
||||||
|
},
|
||||||
|
SSAAdd => {
|
||||||
|
self.param_two(instruction, |val_a, val_b| val_a + val_b);
|
||||||
|
},
|
||||||
|
SSASub => {
|
||||||
|
self.param_two(instruction, |val_a, val_b| val_a - val_b);
|
||||||
|
},
|
||||||
|
SSAMul => {
|
||||||
|
self.param_two(instruction, |val_a, val_b| val_a * val_b);
|
||||||
|
},
|
||||||
|
SSADiv => {
|
||||||
|
self.param_two(instruction, |val_a, val_b| val_a / val_b);
|
||||||
|
},
|
||||||
|
SSAMod => {
|
||||||
|
self.param_two(instruction, |val_a, val_b| val_a % val_b);
|
||||||
|
},
|
||||||
|
SSAAtan2 => self.param_two(instruction, |val_a, val_b| {
|
||||||
|
let mut val_a = val_a.to_array();
|
||||||
|
let val_b = val_b.to_array();
|
||||||
|
for i in 0..Value::LEN {
|
||||||
|
val_a[i] = val_a[i].atan2(val_b[i]);
|
||||||
|
}
|
||||||
|
Value::from_array(val_a)
|
||||||
|
}),
|
||||||
|
SSAMin => {
|
||||||
|
self.param_two(instruction, |val_a, val_b| val_a.simd_min(val_b));
|
||||||
|
},
|
||||||
|
SSAMinMaterial => todo!(),
|
||||||
|
SSAMax => {
|
||||||
|
self.param_two(instruction, |val_a, val_b| val_a.simd_max(val_b));
|
||||||
|
},
|
||||||
|
SSAMaxMaterial => todo!(),
|
||||||
|
SSADot => {
|
||||||
|
let val_a = (0..instruction.opcode.size)
|
||||||
|
.map(|i| self.load(instruction.inputs[i as usize]))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let val_b = (instruction.opcode.size..(instruction.opcode.size * 2))
|
||||||
|
.map(|i| self.load(instruction.inputs[i as usize]))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
self.store(
|
||||||
|
instruction.outputs[0],
|
||||||
|
match instruction.opcode.size {
|
||||||
|
1 => val_a[0] * val_b[0],
|
||||||
|
2 => (val_a[0] * val_b[0]) + (val_a[1] * val_b[1]),
|
||||||
|
3 => {
|
||||||
|
(val_a[0] * val_b[0])
|
||||||
|
+ (val_a[1] * val_b[1])
|
||||||
|
+ (val_a[2] * val_b[2])
|
||||||
|
},
|
||||||
|
4 => {
|
||||||
|
(val_a[0] * val_b[0])
|
||||||
|
+ (val_a[1] * val_b[1])
|
||||||
|
+ (val_a[2] * val_b[2])
|
||||||
|
+ (val_a[3] * val_b[3])
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSALength => {
|
||||||
|
let val_a = (0..instruction.opcode.size)
|
||||||
|
.map(|i| self.load(instruction.inputs[i as usize]))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
self.store(
|
||||||
|
instruction.outputs[0],
|
||||||
|
match instruction.opcode.size {
|
||||||
|
1 => val_a[0],
|
||||||
|
2 => ((val_a[0] * val_a[0]) + (val_a[1] * val_a[1])).sqrt(),
|
||||||
|
3 => ((val_a[0] * val_a[0])
|
||||||
|
+ (val_a[1] * val_a[1])
|
||||||
|
+ (val_a[2] * val_a[2]))
|
||||||
|
.sqrt(),
|
||||||
|
4 => ((val_a[0] * val_a[0])
|
||||||
|
+ (val_a[1] * val_a[1])
|
||||||
|
+ (val_a[2] * val_a[2])
|
||||||
|
+ (val_a[3] * val_a[3]))
|
||||||
|
.sqrt(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSADistance => {
|
||||||
|
let val_a = (0..instruction.opcode.size)
|
||||||
|
.map(|i| self.load(instruction.inputs[i as usize]))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let val_b = (instruction.opcode.size..(instruction.opcode.size * 2))
|
||||||
|
.map(|i| self.load(instruction.inputs[i as usize]))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
self.store(
|
||||||
|
instruction.outputs[0],
|
||||||
|
match instruction.opcode.size {
|
||||||
|
1 => val_b[0] - val_a[0],
|
||||||
|
2 => (((val_a[0] - val_b[0]) * (val_a[0] - val_b[0]))
|
||||||
|
+ ((val_a[1] - val_b[1]) * (val_a[1] - val_b[1])))
|
||||||
|
.sqrt(),
|
||||||
|
3 => (((val_a[0] - val_b[0]) * (val_a[0] - val_b[0]))
|
||||||
|
+ ((val_a[1] - val_b[1]) * (val_a[1] - val_b[1]))
|
||||||
|
+ ((val_a[2] - val_b[2]) * (val_a[2] - val_b[2]))
|
||||||
|
+ ((val_a[3] - val_b[3]) * (val_a[3] - val_b[3])))
|
||||||
|
.sqrt(),
|
||||||
|
4 => (((val_a[0] - val_b[0]) * (val_a[0] - val_b[0]))
|
||||||
|
+ ((val_a[1] - val_b[1]) * (val_a[1] - val_b[1]))
|
||||||
|
+ ((val_a[2] - val_b[2]) * (val_a[2] - val_b[2]))
|
||||||
|
+ ((val_a[3] - val_b[3]) * (val_a[3] - val_b[3]))
|
||||||
|
+ ((val_a[4] - val_b[4]) * (val_a[4] - val_b[4])))
|
||||||
|
.sqrt(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSANegate => {
|
||||||
|
self.param_one(instruction, |val_a| -val_a);
|
||||||
|
},
|
||||||
|
SSARound => {
|
||||||
|
self.param_one(instruction, |val_a| val_a.round());
|
||||||
|
},
|
||||||
|
SSAAbs => {
|
||||||
|
self.param_one(instruction, |val_a| val_a.abs());
|
||||||
|
},
|
||||||
|
SSAFloor => {
|
||||||
|
self.param_one(instruction, |val_a| val_a.floor());
|
||||||
|
},
|
||||||
|
SSACeil => {
|
||||||
|
self.param_one(instruction, |val_a| val_a.ceil());
|
||||||
|
},
|
||||||
|
SSAFract => {
|
||||||
|
self.param_one(instruction, |val_a| glfract(val_a));
|
||||||
|
},
|
||||||
|
SSASin => {
|
||||||
|
self.param_one(instruction, |val_a| val_a.sin());
|
||||||
|
},
|
||||||
|
SSACos => {
|
||||||
|
self.param_one(instruction, |val_a| val_a.cos());
|
||||||
|
},
|
||||||
|
SSATan => {
|
||||||
|
self.param_one(instruction, |val_a| {
|
||||||
|
Value::from_array(val_a.to_array().map(|f| f.tan()))
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAAsin => {
|
||||||
|
self.param_one(instruction, |val_a| {
|
||||||
|
Value::from_array(val_a.to_array().map(|f| f.asin()))
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAAcos => {
|
||||||
|
self.param_one(instruction, |val_a| {
|
||||||
|
Value::from_array(val_a.to_array().map(|f| f.acos()))
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAAtan => {
|
||||||
|
self.param_one(instruction, |val_a| {
|
||||||
|
Value::from_array(val_a.to_array().map(|f| f.atan()))
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAExp => {
|
||||||
|
self.param_one(instruction, |val_a| val_a.exp());
|
||||||
|
},
|
||||||
|
SSALog => {
|
||||||
|
self.param_one(instruction, |val_a| val_a.ln());
|
||||||
|
},
|
||||||
|
SSASqrt => {
|
||||||
|
self.param_one(instruction, |val_a| val_a.sqrt());
|
||||||
|
},
|
||||||
|
SSASquare => {
|
||||||
|
self.param_one(instruction, |val_a| val_a * val_a);
|
||||||
|
},
|
||||||
|
SSACube => {
|
||||||
|
self.param_one(instruction, |val_a| val_a * val_a * val_a);
|
||||||
|
},
|
||||||
|
SSASmoothMin => {
|
||||||
|
self.param_three(instruction, |d1, d2, k| {
|
||||||
|
let h =
|
||||||
|
(VALUE_05 + (VALUE_05 * (d2 - d1) / k)).simd_clamp(VALUE_0, VALUE_1);
|
||||||
|
return ((d2 * (VALUE_1 - h)) + (d1 * h)) - k * h * (VALUE_1 - h);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSASmoothMax => {
|
||||||
|
self.param_three(instruction, |d1, d2, k| {
|
||||||
|
let h =
|
||||||
|
(VALUE_05 - (VALUE_05 * (d2 + d1) / k)).simd_clamp(VALUE_0, VALUE_1);
|
||||||
|
return ((d2 * (VALUE_1 - h)) + (-d1 * h)) + k * h * (VALUE_1 - h);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSASmoothMinMaterial => todo!(),
|
||||||
|
SSASmoothMaxMaterial => todo!(),
|
||||||
|
SSAClamp => {
|
||||||
|
self.param_three(instruction, |val_a, val_b, val_c| {
|
||||||
|
val_a.simd_clamp(val_b, val_c)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAMix => {
|
||||||
|
self.param_three(instruction, |val_a, val_b, val_c| {
|
||||||
|
(val_a * (VALUE_1 - val_c)) + (val_b * val_c)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAFMA => {
|
||||||
|
self.param_three(instruction, |val_a, val_b, val_c| {
|
||||||
|
val_a.mul_add(val_b, val_c)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSASDFSphere => {
|
||||||
|
let pos_x = self.load(instruction.inputs[0]);
|
||||||
|
let pos_y = self.load(instruction.inputs[1]);
|
||||||
|
let pos_z = self.load(instruction.inputs[2]);
|
||||||
|
let radius = self.load(instruction.inputs[3]);
|
||||||
|
self.store(
|
||||||
|
instruction.outputs[0],
|
||||||
|
((pos_x * pos_x) + (pos_y * pos_y) + (pos_z * pos_z)).sqrt() - radius,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSASDFBox => {
|
||||||
|
let pos_x = self.load(instruction.inputs[0]);
|
||||||
|
let pos_y = self.load(instruction.inputs[1]);
|
||||||
|
let pos_z = self.load(instruction.inputs[2]);
|
||||||
|
let rad_x = self.load(instruction.inputs[3]);
|
||||||
|
let rad_y = self.load(instruction.inputs[4]);
|
||||||
|
let rad_z = self.load(instruction.inputs[5]);
|
||||||
|
let qx = pos_x.abs() - rad_x;
|
||||||
|
let qy = pos_y.abs() - rad_y;
|
||||||
|
let qz = pos_z.abs() - rad_z;
|
||||||
|
let qxmax = qx.simd_max(VALUE_0);
|
||||||
|
let qymax = qy.simd_max(VALUE_0);
|
||||||
|
let qzmax = qz.simd_max(VALUE_0);
|
||||||
|
self.store(
|
||||||
|
instruction.outputs[0],
|
||||||
|
((qxmax * qxmax) + (qymax * qymax) + (qzmax * qzmax)).sqrt()
|
||||||
|
+ qx.simd_max(qy.simd_max(qz)).simd_min(VALUE_0),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSASDFTorus => {
|
||||||
|
let pos_x = self.load(instruction.inputs[0]);
|
||||||
|
let pos_y = self.load(instruction.inputs[1]);
|
||||||
|
let pos_z = self.load(instruction.inputs[2]);
|
||||||
|
let radius1 = self.load(instruction.inputs[3]);
|
||||||
|
let radius2 = self.load(instruction.inputs[4]);
|
||||||
|
let q = ((pos_x * pos_x) + (pos_z * pos_z)).sqrt() - radius1;
|
||||||
|
self.store(
|
||||||
|
instruction.outputs[0],
|
||||||
|
((q * q) + (pos_y * pos_y)).sqrt() - radius2,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSACompare => {
|
||||||
|
self.param_two(instruction, |val_a, val_b| {
|
||||||
|
val_a
|
||||||
|
.simd_gt(val_b)
|
||||||
|
.select(VALUE_1, val_a.simd_lt(val_b).select(VALUE_M1, VALUE_0))
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAAnd => {
|
||||||
|
self.param_two(instruction, |val_a, val_b| {
|
||||||
|
val_a.simd_eq(VALUE_0).select(val_a, val_b)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAOr => {
|
||||||
|
self.param_two(instruction, |val_a, val_b| {
|
||||||
|
val_a.simd_eq(VALUE_0).select(val_b, val_a)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSARecip => {
|
||||||
|
self.param_one(instruction, |val_a| val_a.recip());
|
||||||
|
},
|
||||||
|
SSANot => {
|
||||||
|
self.param_one(instruction, |val_a| {
|
||||||
|
val_a.simd_eq(VALUE_0).select(VALUE_1, VALUE_0)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAStop => return VALUE_0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return VALUE_NAN;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#![feature(portable_simd)]
|
||||||
|
pub mod instruction_set;
|
||||||
|
pub mod interpreters;
|
||||||
|
mod spirv_compilers;
|
||||||
|
pub mod ssa;
|
||||||
|
pub mod types;
|
||||||
|
pub mod vm;
|
||||||
|
|
||||||
|
const BYTECODE_IMITATES_GLSL: bool = false;
|
||||||
@@ -0,0 +1,876 @@
|
|||||||
|
use foldhash::{HashMap, HashMapExt};
|
||||||
|
use rspirv::{dr::Builder, spirv};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
spirv_compilers::SpirVTypes,
|
||||||
|
ssa::{SSAInput, SSAInstruction, SSAOpcode, SSATape},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub(crate) fn compile_gradient_function(
|
||||||
|
b: &mut Builder,
|
||||||
|
tape: &SSATape,
|
||||||
|
types: SpirVTypes,
|
||||||
|
function_id: Option<spirv::Word>,
|
||||||
|
) {
|
||||||
|
let _scene = b
|
||||||
|
.begin_function(
|
||||||
|
types.float,
|
||||||
|
function_id,
|
||||||
|
//spirv::FunctionControl::DONT_INLINE
|
||||||
|
spirv::FunctionControl::INLINE
|
||||||
|
| spirv::FunctionControl::PURE
|
||||||
|
| spirv::FunctionControl::CONST,
|
||||||
|
types.point_fn_type,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let pos_p = b.function_parameter(types.vec4p).unwrap();
|
||||||
|
|
||||||
|
b.begin_block(None).unwrap();
|
||||||
|
|
||||||
|
let pos = b.load(types.vec4, None, pos_p, None, []).unwrap();
|
||||||
|
|
||||||
|
let mut mapping = HashMap::<u32, u32>::new();
|
||||||
|
|
||||||
|
for (line, instruction) in tape.tape.iter().enumerate() {
|
||||||
|
use SSAOpcode::*;
|
||||||
|
use rspirv::dr::Operand::IdRef;
|
||||||
|
|
||||||
|
b.line(types.jit_string, line as u32, 0);
|
||||||
|
|
||||||
|
fn input_resolve(
|
||||||
|
float: u32,
|
||||||
|
b: &mut rspirv::dr::Builder,
|
||||||
|
mapping: &HashMap<u32, u32>,
|
||||||
|
value: SSAInput,
|
||||||
|
) -> u32 {
|
||||||
|
match value {
|
||||||
|
SSAInput::Register(r) => mapping[&r],
|
||||||
|
SSAInput::Constant(c) => b.constant_bit32(float, c.to_bits()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn param_one(
|
||||||
|
float: u32,
|
||||||
|
b: &mut rspirv::dr::Builder,
|
||||||
|
mapping: &mut HashMap<u32, u32>,
|
||||||
|
instruction: &SSAInstruction,
|
||||||
|
func: impl Fn(&mut rspirv::dr::Builder, u32) -> u32,
|
||||||
|
) {
|
||||||
|
for i in 0..instruction.opcode.size as usize {
|
||||||
|
let val_a = input_resolve(float, b, &mapping, instruction.inputs[i]);
|
||||||
|
mapping.insert(instruction.outputs[i], func(b, val_a));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn param_two(
|
||||||
|
float: u32,
|
||||||
|
b: &mut rspirv::dr::Builder,
|
||||||
|
mapping: &mut HashMap<u32, u32>,
|
||||||
|
instruction: &SSAInstruction,
|
||||||
|
func: impl Fn(&mut rspirv::dr::Builder, u32, u32) -> u32,
|
||||||
|
) {
|
||||||
|
for i in 0..instruction.opcode.size as usize {
|
||||||
|
let val_a = input_resolve(float, b, &mapping, instruction.inputs[i]);
|
||||||
|
let val_b = input_resolve(
|
||||||
|
float,
|
||||||
|
b,
|
||||||
|
&mapping,
|
||||||
|
instruction.inputs[i + instruction.opcode.size as usize],
|
||||||
|
);
|
||||||
|
mapping.insert(instruction.outputs[i], func(b, val_a, val_b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn param_three(
|
||||||
|
float: u32,
|
||||||
|
b: &mut rspirv::dr::Builder,
|
||||||
|
mapping: &mut HashMap<u32, u32>,
|
||||||
|
instruction: &SSAInstruction,
|
||||||
|
func: impl Fn(&mut rspirv::dr::Builder, u32, u32, u32) -> u32,
|
||||||
|
) {
|
||||||
|
for i in 0..instruction.opcode.size as usize {
|
||||||
|
let val_a = input_resolve(float, b, &mapping, instruction.inputs[i]);
|
||||||
|
let val_b = input_resolve(
|
||||||
|
float,
|
||||||
|
b,
|
||||||
|
&mapping,
|
||||||
|
instruction.inputs[i + instruction.opcode.size as usize],
|
||||||
|
);
|
||||||
|
let val_c = input_resolve(
|
||||||
|
float,
|
||||||
|
b,
|
||||||
|
&mapping,
|
||||||
|
instruction.inputs[i + (instruction.opcode.size as usize * 2)],
|
||||||
|
);
|
||||||
|
mapping.insert(instruction.outputs[i], func(b, val_a, val_b, val_c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn param_four(
|
||||||
|
float: u32,
|
||||||
|
b: &mut rspirv::dr::Builder,
|
||||||
|
mapping: &mut HashMap<u32, u32>,
|
||||||
|
instruction: &SSAInstruction,
|
||||||
|
func: impl Fn(&mut rspirv::dr::Builder, u32, u32, u32, u32) -> u32,
|
||||||
|
) {
|
||||||
|
for i in 0..instruction.opcode.size as usize {
|
||||||
|
let val_a = input_resolve(float, b, &mapping, instruction.inputs[i]);
|
||||||
|
let val_b = input_resolve(
|
||||||
|
float,
|
||||||
|
b,
|
||||||
|
&mapping,
|
||||||
|
instruction.inputs[i + instruction.opcode.size as usize],
|
||||||
|
);
|
||||||
|
let val_c = input_resolve(
|
||||||
|
float,
|
||||||
|
b,
|
||||||
|
&mapping,
|
||||||
|
instruction.inputs[i + (instruction.opcode.size as usize * 2)],
|
||||||
|
);
|
||||||
|
let val_d = input_resolve(
|
||||||
|
float,
|
||||||
|
b,
|
||||||
|
&mapping,
|
||||||
|
instruction.inputs[i + (instruction.opcode.size as usize * 3)],
|
||||||
|
);
|
||||||
|
mapping.insert(instruction.outputs[i], func(b, val_a, val_b, val_c, val_d));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match instruction.opcode.opcode {
|
||||||
|
SSAStop => {
|
||||||
|
let zero = b.constant_bit32(types.float, (0.0f32).to_bits());
|
||||||
|
b.ret_value(zero).unwrap();
|
||||||
|
},
|
||||||
|
SSAReturn => {
|
||||||
|
let value = input_resolve(types.float, b, &mapping, instruction.inputs[0]);
|
||||||
|
b.ret_value(value).unwrap();
|
||||||
|
},
|
||||||
|
SSAPosition => {
|
||||||
|
mapping.insert(
|
||||||
|
instruction.outputs[0],
|
||||||
|
b.composite_extract(types.float, None, pos, [0]).unwrap(),
|
||||||
|
);
|
||||||
|
mapping.insert(
|
||||||
|
instruction.outputs[1],
|
||||||
|
b.composite_extract(types.float, None, pos, [1]).unwrap(),
|
||||||
|
);
|
||||||
|
mapping.insert(
|
||||||
|
instruction.outputs[2],
|
||||||
|
b.composite_extract(types.float, None, pos, [2]).unwrap(),
|
||||||
|
);
|
||||||
|
mapping.insert(
|
||||||
|
instruction.outputs[3],
|
||||||
|
b.composite_extract(types.float, None, pos, [3]).unwrap(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAAdd => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| b.f_add(types.float, None, val_a, val_b).unwrap(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSASub => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| b.f_sub(types.float, None, val_a, val_b).unwrap(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAMul => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| b.f_mul(types.float, None, val_a, val_b).unwrap(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSADiv => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| b.f_div(types.float, None, val_a, val_b).unwrap(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAMod => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| b.f_mod(types.float, None, val_a, val_b).unwrap(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAAtan2 => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Atan2 as u32,
|
||||||
|
[IdRef(val_a), IdRef(val_b)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAMin => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FMin as u32,
|
||||||
|
[IdRef(val_a), IdRef(val_b)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAMinMaterial => todo!(),
|
||||||
|
SSAMax => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FMax as u32,
|
||||||
|
[IdRef(val_a), IdRef(val_b)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAMaxMaterial => todo!(),
|
||||||
|
SSADot => {
|
||||||
|
let val_a = (0..instruction.opcode.size)
|
||||||
|
.map(|i| {
|
||||||
|
input_resolve(types.float, b, &mapping, instruction.inputs[i as usize])
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let val_b = (instruction.opcode.size..(instruction.opcode.size * 2))
|
||||||
|
.map(|i| {
|
||||||
|
input_resolve(types.float, b, &mapping, instruction.inputs[i as usize])
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let dot = if instruction.opcode.size == 1 {
|
||||||
|
b.f_mul(types.float, None, val_a[0], val_b[0]).unwrap()
|
||||||
|
} else {
|
||||||
|
let vector = [types.void, types.float, types.vec2, types.vec3, types.vec4]
|
||||||
|
[instruction.opcode.size as usize];
|
||||||
|
let val_a = b.composite_construct(vector, None, val_a).unwrap();
|
||||||
|
let val_b = b.composite_construct(vector, None, val_b).unwrap();
|
||||||
|
b.dot(types.float, None, val_a, val_b).unwrap()
|
||||||
|
};
|
||||||
|
mapping.insert(instruction.outputs[0], dot);
|
||||||
|
},
|
||||||
|
SSALength => {
|
||||||
|
let val_a = (0..instruction.opcode.size)
|
||||||
|
.map(|i| {
|
||||||
|
input_resolve(types.float, b, &mapping, instruction.inputs[i as usize])
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let length = if instruction.opcode.size == 1 {
|
||||||
|
val_a[0]
|
||||||
|
} else {
|
||||||
|
let vector = [types.void, types.float, types.vec2, types.vec3, types.vec4]
|
||||||
|
[instruction.opcode.size as usize];
|
||||||
|
let val_a = b.composite_construct(vector, None, val_a).unwrap();
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Length as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
};
|
||||||
|
mapping.insert(instruction.outputs[0], length);
|
||||||
|
},
|
||||||
|
SSADistance => {
|
||||||
|
let val_a = (0..instruction.opcode.size)
|
||||||
|
.map(|i| {
|
||||||
|
input_resolve(types.float, b, &mapping, instruction.inputs[i as usize])
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let val_b = (instruction.opcode.size..(instruction.opcode.size * 2))
|
||||||
|
.map(|i| {
|
||||||
|
input_resolve(types.float, b, &mapping, instruction.inputs[i as usize])
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let distance = if instruction.opcode.size == 1 {
|
||||||
|
b.f_sub(types.float, None, val_b[0], val_a[0]).unwrap()
|
||||||
|
} else {
|
||||||
|
let vector = [types.void, types.float, types.vec2, types.vec3, types.vec4]
|
||||||
|
[instruction.opcode.size as usize];
|
||||||
|
let val_a = b.composite_construct(vector, None, val_a).unwrap();
|
||||||
|
let val_b = b.composite_construct(vector, None, val_b).unwrap();
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Distance as u32,
|
||||||
|
[IdRef(val_a), IdRef(val_b)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
};
|
||||||
|
mapping.insert(instruction.outputs[0], distance);
|
||||||
|
},
|
||||||
|
SSARecip => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
let one = b.constant_bit32(types.float, (1.0f32).to_bits());
|
||||||
|
b.f_div(types.float, None, one, val_a).unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSANegate => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.f_negate(types.float, None, val_a).unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSARound => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Round as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAAbs => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FAbs as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAFloor => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Floor as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSACeil => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Ceil as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAFract => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Fract as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSASin => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Sin as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSACos => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Cos as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSATan => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Tan as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAAsin => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Asin as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAAcos => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Acos as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAAtan => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Atan as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAExp => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Exp as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSALog => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Log as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSASqrt => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Sqrt as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSASquare => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.f_mul(types.float, None, val_a, val_a).unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSACube => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
let square = b.f_mul(types.float, None, val_a, val_a).unwrap();
|
||||||
|
b.f_mul(types.float, None, val_a, square).unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSASmoothMin => {
|
||||||
|
param_three(types.float, b, &mut mapping, instruction, |b, d1, d2, k| {
|
||||||
|
let half_const = b.constant_bit32(types.float, (0.5f32).to_bits());
|
||||||
|
let zero_const = b.constant_bit32(types.float, (0.0f32).to_bits());
|
||||||
|
let one_const = b.constant_bit32(types.float, (1.0f32).to_bits());
|
||||||
|
let sub = b.f_sub(types.float, None, d2, d1).unwrap();
|
||||||
|
let mul_half = b.f_mul(types.float, None, sub, half_const).unwrap();
|
||||||
|
let div_k = b.f_div(types.float, None, mul_half, k).unwrap();
|
||||||
|
let add_half = b.f_add(types.float, None, div_k, half_const).unwrap();
|
||||||
|
let h = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FClamp as u32,
|
||||||
|
[IdRef(add_half), IdRef(zero_const), IdRef(one_const)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let negh = b.f_sub(types.float, None, one_const, h).unwrap();
|
||||||
|
let h_negh = b.f_mul(types.float, None, h, negh).unwrap();
|
||||||
|
let kh_negh = b.f_mul(types.float, None, k, h_negh).unwrap();
|
||||||
|
let mix = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FMix as u32,
|
||||||
|
[IdRef(d2), IdRef(d1), IdRef(h)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
b.f_sub(types.float, None, mix, kh_negh).unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSASmoothMax => {
|
||||||
|
param_three(types.float, b, &mut mapping, instruction, |b, d1, d2, k| {
|
||||||
|
let half_const = b.constant_bit32(types.float, (0.5f32).to_bits());
|
||||||
|
let zero_const = b.constant_bit32(types.float, (0.0f32).to_bits());
|
||||||
|
let one_const = b.constant_bit32(types.float, (1.0f32).to_bits());
|
||||||
|
let sub = b.f_add(types.float, None, d2, d1).unwrap();
|
||||||
|
let mul_half = b.f_mul(types.float, None, sub, half_const).unwrap();
|
||||||
|
let div_k = b.f_div(types.float, None, mul_half, k).unwrap();
|
||||||
|
let add_half = b.f_sub(types.float, None, half_const, div_k).unwrap();
|
||||||
|
let h = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FClamp as u32,
|
||||||
|
[IdRef(add_half), IdRef(zero_const), IdRef(one_const)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let negh = b.f_sub(types.float, None, one_const, h).unwrap();
|
||||||
|
let h_negh = b.f_mul(types.float, None, h, negh).unwrap();
|
||||||
|
let kh_negh = b.f_mul(types.float, None, k, h_negh).unwrap();
|
||||||
|
let negate = b.f_negate(types.float, None, d1).unwrap();
|
||||||
|
let mix = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FMix as u32,
|
||||||
|
[IdRef(d2), IdRef(negate), IdRef(h)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
b.f_add(types.float, None, mix, kh_negh).unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSASmoothMinMaterial => todo!(),
|
||||||
|
SSASmoothMaxMaterial => todo!(),
|
||||||
|
SSAClamp => {
|
||||||
|
param_three(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b, val_c| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FClamp as u32,
|
||||||
|
[IdRef(val_a), IdRef(val_b), IdRef(val_c)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAMix => {
|
||||||
|
param_three(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b, val_c| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FMix as u32,
|
||||||
|
[IdRef(val_a), IdRef(val_b), IdRef(val_c)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAFMA => {
|
||||||
|
param_three(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b, val_c| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Fma as u32,
|
||||||
|
[IdRef(val_a), IdRef(val_b), IdRef(val_c)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSASDFSphere => {
|
||||||
|
let pos_part = (0..3)
|
||||||
|
.map(|i| {
|
||||||
|
input_resolve(types.float, b, &mapping, instruction.inputs[i as usize])
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let pos = b.composite_construct(types.vec3, None, pos_part).unwrap();
|
||||||
|
let radius =
|
||||||
|
input_resolve(types.float, b, &mapping, instruction.inputs[3 as usize]);
|
||||||
|
|
||||||
|
let length = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Length as u32,
|
||||||
|
[IdRef(pos)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let sphere = b.f_sub(types.float, None, length, radius).unwrap();
|
||||||
|
|
||||||
|
mapping.insert(instruction.outputs[0], sphere);
|
||||||
|
},
|
||||||
|
SSASDFBox => {
|
||||||
|
let pos_part = (0..3)
|
||||||
|
.map(|i| {
|
||||||
|
input_resolve(types.float, b, &mapping, instruction.inputs[i as usize])
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let pos = b.composite_construct(types.vec3, None, pos_part).unwrap();
|
||||||
|
|
||||||
|
let dim_part = (3..6)
|
||||||
|
.map(|i| {
|
||||||
|
input_resolve(types.float, b, &mapping, instruction.inputs[i as usize])
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let dim = b.composite_construct(types.vec3, None, dim_part).unwrap();
|
||||||
|
|
||||||
|
let abs = b
|
||||||
|
.ext_inst(
|
||||||
|
types.vec3,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FAbs as u32,
|
||||||
|
[IdRef(pos)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let q = b.f_sub(types.vec3, None, abs, dim).unwrap();
|
||||||
|
|
||||||
|
let zero = b.constant_bit32(types.float, 0);
|
||||||
|
let zero_vec3 = b
|
||||||
|
.composite_construct(types.vec3, None, [zero, zero, zero])
|
||||||
|
.unwrap();
|
||||||
|
let q_limit = b
|
||||||
|
.ext_inst(
|
||||||
|
types.vec3,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FMax as u32,
|
||||||
|
[IdRef(q), IdRef(zero_vec3)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let length = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Length as u32,
|
||||||
|
[IdRef(q_limit)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let q_x = b.composite_extract(types.float, None, q, [0]).unwrap();
|
||||||
|
let q_y = b.composite_extract(types.float, None, q, [1]).unwrap();
|
||||||
|
let q_z = b.composite_extract(types.float, None, q, [2]).unwrap();
|
||||||
|
let max1 = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FMax as u32,
|
||||||
|
[IdRef(q_x), IdRef(q_y)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let max2 = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FMax as u32,
|
||||||
|
[IdRef(max1), IdRef(q_z)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let min = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FMax as u32,
|
||||||
|
[IdRef(max2), IdRef(zero)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
mapping.insert(
|
||||||
|
instruction.outputs[0],
|
||||||
|
b.f_add(types.float, None, length, min).unwrap(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSASDFTorus => {
|
||||||
|
let pos_part = (0..3)
|
||||||
|
.map(|i| {
|
||||||
|
input_resolve(types.float, b, &mapping, instruction.inputs[i as usize])
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let pos_vec2 = b
|
||||||
|
.composite_construct(types.vec2, None, [pos_part[0], pos_part[2]])
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let rad1 = input_resolve(types.float, b, &mapping, instruction.inputs[3 as usize]);
|
||||||
|
let rad2 = input_resolve(types.float, b, &mapping, instruction.inputs[4 as usize]);
|
||||||
|
|
||||||
|
let dot = b.dot(types.float, None, pos_vec2, pos_vec2).unwrap();
|
||||||
|
let sqrt = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Sqrt as u32,
|
||||||
|
[IdRef(dot)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let subtx = b.f_sub(types.float, None, sqrt, rad1).unwrap();
|
||||||
|
|
||||||
|
let q = b
|
||||||
|
.composite_construct(types.vec2, None, [subtx, pos_part[1]])
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let length = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Length as u32,
|
||||||
|
[IdRef(q)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
mapping.insert(
|
||||||
|
instruction.outputs[0],
|
||||||
|
b.f_sub(types.float, None, length, rad2).unwrap(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSACompare => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| {
|
||||||
|
let nan = b.constant_bit32(types.float, f32::NAN.to_bits());
|
||||||
|
let zero = b.constant_bit32(types.float, (0.0f32).to_bits());
|
||||||
|
let one = b.constant_bit32(types.float, (1.0f32).to_bits());
|
||||||
|
let onen = b.constant_bit32(types.float, (-1.0f32).to_bits());
|
||||||
|
let equal = b.f_ord_equal(types.bool, None, val_a, val_b).unwrap();
|
||||||
|
let less = b.f_ord_less_than(types.bool, None, val_a, val_b).unwrap();
|
||||||
|
let more = b
|
||||||
|
.f_ord_greater_than(types.bool, None, val_a, val_b)
|
||||||
|
.unwrap();
|
||||||
|
let select_less = b.select(types.float, None, less, onen, nan).unwrap();
|
||||||
|
let select_more =
|
||||||
|
b.select(types.float, None, more, one, select_less).unwrap();
|
||||||
|
let select_eq = b
|
||||||
|
.select(types.float, None, equal, zero, select_more)
|
||||||
|
.unwrap();
|
||||||
|
select_eq
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAAnd => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| {
|
||||||
|
let zero = b.constant_bit32(types.float, (0.0f32).to_bits());
|
||||||
|
let equal = b.f_ord_equal(types.bool, None, val_a, zero).unwrap();
|
||||||
|
b.select(types.float, None, equal, val_a, val_b).unwrap()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAOr => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| {
|
||||||
|
let zero = b.constant_bit32(types.float, (0.0f32).to_bits());
|
||||||
|
let equal = b.f_ord_equal(types.bool, None, val_a, zero).unwrap();
|
||||||
|
b.select(types.float, None, equal, val_b, val_a).unwrap()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSANot => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
let zero = b.constant_bit32(types.float, (0.0f32).to_bits());
|
||||||
|
let one = b.constant_bit32(types.float, (1.0f32).to_bits());
|
||||||
|
let equal = b.f_ord_equal(types.bool, None, val_a, zero).unwrap();
|
||||||
|
b.select(types.float, None, equal, one, zero).unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.end_function().unwrap();
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,18 @@
|
|||||||
|
pub(crate) mod gradient;
|
||||||
|
pub(crate) mod point;
|
||||||
|
//pub(crate) mod interval;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub(crate) struct SpirVTypes {
|
||||||
|
pub glsl: u32,
|
||||||
|
pub void: u32,
|
||||||
|
pub float: u32,
|
||||||
|
pub bool: u32,
|
||||||
|
pub vec2: u32,
|
||||||
|
pub vec3: u32,
|
||||||
|
pub vec4: u32,
|
||||||
|
pub vec4p: u32,
|
||||||
|
pub point_fn_type: u32,
|
||||||
|
pub interval_fn_type: u32,
|
||||||
|
pub jit_string: u32,
|
||||||
|
}
|
||||||
@@ -0,0 +1,876 @@
|
|||||||
|
use foldhash::{HashMap, HashMapExt};
|
||||||
|
use rspirv::{dr::Builder, spirv};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
spirv_compilers::SpirVTypes,
|
||||||
|
ssa::{SSAInput, SSAInstruction, SSAOpcode, SSATape},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub(crate) fn compile_point_function(
|
||||||
|
b: &mut Builder,
|
||||||
|
tape: &SSATape,
|
||||||
|
types: SpirVTypes,
|
||||||
|
function_id: Option<spirv::Word>,
|
||||||
|
) {
|
||||||
|
let _scene = b
|
||||||
|
.begin_function(
|
||||||
|
types.float,
|
||||||
|
function_id,
|
||||||
|
//spirv::FunctionControl::DONT_INLINE
|
||||||
|
spirv::FunctionControl::INLINE
|
||||||
|
| spirv::FunctionControl::PURE
|
||||||
|
| spirv::FunctionControl::CONST,
|
||||||
|
types.point_fn_type,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let pos_p = b.function_parameter(types.vec4p).unwrap();
|
||||||
|
|
||||||
|
b.begin_block(None).unwrap();
|
||||||
|
|
||||||
|
let pos = b.load(types.vec4, None, pos_p, None, []).unwrap();
|
||||||
|
|
||||||
|
let mut mapping = HashMap::<u32, u32>::new();
|
||||||
|
|
||||||
|
for (line, instruction) in tape.tape.iter().enumerate() {
|
||||||
|
use SSAOpcode::*;
|
||||||
|
use rspirv::dr::Operand::IdRef;
|
||||||
|
|
||||||
|
b.line(types.jit_string, line as u32, 0);
|
||||||
|
|
||||||
|
fn input_resolve(
|
||||||
|
float: u32,
|
||||||
|
b: &mut rspirv::dr::Builder,
|
||||||
|
mapping: &HashMap<u32, u32>,
|
||||||
|
value: SSAInput,
|
||||||
|
) -> u32 {
|
||||||
|
match value {
|
||||||
|
SSAInput::Register(r) => mapping[&r],
|
||||||
|
SSAInput::Constant(c) => b.constant_bit32(float, c.to_bits()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn param_one(
|
||||||
|
float: u32,
|
||||||
|
b: &mut rspirv::dr::Builder,
|
||||||
|
mapping: &mut HashMap<u32, u32>,
|
||||||
|
instruction: &SSAInstruction,
|
||||||
|
func: impl Fn(&mut rspirv::dr::Builder, u32) -> u32,
|
||||||
|
) {
|
||||||
|
for i in 0..instruction.opcode.size as usize {
|
||||||
|
let val_a = input_resolve(float, b, &mapping, instruction.inputs[i]);
|
||||||
|
mapping.insert(instruction.outputs[i], func(b, val_a));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn param_two(
|
||||||
|
float: u32,
|
||||||
|
b: &mut rspirv::dr::Builder,
|
||||||
|
mapping: &mut HashMap<u32, u32>,
|
||||||
|
instruction: &SSAInstruction,
|
||||||
|
func: impl Fn(&mut rspirv::dr::Builder, u32, u32) -> u32,
|
||||||
|
) {
|
||||||
|
for i in 0..instruction.opcode.size as usize {
|
||||||
|
let val_a = input_resolve(float, b, &mapping, instruction.inputs[i]);
|
||||||
|
let val_b = input_resolve(
|
||||||
|
float,
|
||||||
|
b,
|
||||||
|
&mapping,
|
||||||
|
instruction.inputs[i + instruction.opcode.size as usize],
|
||||||
|
);
|
||||||
|
mapping.insert(instruction.outputs[i], func(b, val_a, val_b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn param_three(
|
||||||
|
float: u32,
|
||||||
|
b: &mut rspirv::dr::Builder,
|
||||||
|
mapping: &mut HashMap<u32, u32>,
|
||||||
|
instruction: &SSAInstruction,
|
||||||
|
func: impl Fn(&mut rspirv::dr::Builder, u32, u32, u32) -> u32,
|
||||||
|
) {
|
||||||
|
for i in 0..instruction.opcode.size as usize {
|
||||||
|
let val_a = input_resolve(float, b, &mapping, instruction.inputs[i]);
|
||||||
|
let val_b = input_resolve(
|
||||||
|
float,
|
||||||
|
b,
|
||||||
|
&mapping,
|
||||||
|
instruction.inputs[i + instruction.opcode.size as usize],
|
||||||
|
);
|
||||||
|
let val_c = input_resolve(
|
||||||
|
float,
|
||||||
|
b,
|
||||||
|
&mapping,
|
||||||
|
instruction.inputs[i + (instruction.opcode.size as usize * 2)],
|
||||||
|
);
|
||||||
|
mapping.insert(instruction.outputs[i], func(b, val_a, val_b, val_c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn param_four(
|
||||||
|
float: u32,
|
||||||
|
b: &mut rspirv::dr::Builder,
|
||||||
|
mapping: &mut HashMap<u32, u32>,
|
||||||
|
instruction: &SSAInstruction,
|
||||||
|
func: impl Fn(&mut rspirv::dr::Builder, u32, u32, u32, u32) -> u32,
|
||||||
|
) {
|
||||||
|
for i in 0..instruction.opcode.size as usize {
|
||||||
|
let val_a = input_resolve(float, b, &mapping, instruction.inputs[i]);
|
||||||
|
let val_b = input_resolve(
|
||||||
|
float,
|
||||||
|
b,
|
||||||
|
&mapping,
|
||||||
|
instruction.inputs[i + instruction.opcode.size as usize],
|
||||||
|
);
|
||||||
|
let val_c = input_resolve(
|
||||||
|
float,
|
||||||
|
b,
|
||||||
|
&mapping,
|
||||||
|
instruction.inputs[i + (instruction.opcode.size as usize * 2)],
|
||||||
|
);
|
||||||
|
let val_d = input_resolve(
|
||||||
|
float,
|
||||||
|
b,
|
||||||
|
&mapping,
|
||||||
|
instruction.inputs[i + (instruction.opcode.size as usize * 3)],
|
||||||
|
);
|
||||||
|
mapping.insert(instruction.outputs[i], func(b, val_a, val_b, val_c, val_d));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match instruction.opcode.opcode {
|
||||||
|
SSAStop => {
|
||||||
|
let zero = b.constant_bit32(types.float, (0.0f32).to_bits());
|
||||||
|
b.ret_value(zero).unwrap();
|
||||||
|
},
|
||||||
|
SSAReturn => {
|
||||||
|
let value = input_resolve(types.float, b, &mapping, instruction.inputs[0]);
|
||||||
|
b.ret_value(value).unwrap();
|
||||||
|
},
|
||||||
|
SSAPosition => {
|
||||||
|
mapping.insert(
|
||||||
|
instruction.outputs[0],
|
||||||
|
b.composite_extract(types.float, None, pos, [0]).unwrap(),
|
||||||
|
);
|
||||||
|
mapping.insert(
|
||||||
|
instruction.outputs[1],
|
||||||
|
b.composite_extract(types.float, None, pos, [1]).unwrap(),
|
||||||
|
);
|
||||||
|
mapping.insert(
|
||||||
|
instruction.outputs[2],
|
||||||
|
b.composite_extract(types.float, None, pos, [2]).unwrap(),
|
||||||
|
);
|
||||||
|
mapping.insert(
|
||||||
|
instruction.outputs[3],
|
||||||
|
b.composite_extract(types.float, None, pos, [3]).unwrap(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAAdd => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| b.f_add(types.float, None, val_a, val_b).unwrap(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSASub => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| b.f_sub(types.float, None, val_a, val_b).unwrap(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAMul => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| b.f_mul(types.float, None, val_a, val_b).unwrap(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSADiv => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| b.f_div(types.float, None, val_a, val_b).unwrap(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAMod => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| b.f_mod(types.float, None, val_a, val_b).unwrap(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAAtan2 => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Atan2 as u32,
|
||||||
|
[IdRef(val_a), IdRef(val_b)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAMin => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FMin as u32,
|
||||||
|
[IdRef(val_a), IdRef(val_b)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAMinMaterial => todo!(),
|
||||||
|
SSAMax => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FMax as u32,
|
||||||
|
[IdRef(val_a), IdRef(val_b)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAMaxMaterial => todo!(),
|
||||||
|
SSADot => {
|
||||||
|
let val_a = (0..instruction.opcode.size)
|
||||||
|
.map(|i| {
|
||||||
|
input_resolve(types.float, b, &mapping, instruction.inputs[i as usize])
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let val_b = (instruction.opcode.size..(instruction.opcode.size * 2))
|
||||||
|
.map(|i| {
|
||||||
|
input_resolve(types.float, b, &mapping, instruction.inputs[i as usize])
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let dot = if instruction.opcode.size == 1 {
|
||||||
|
b.f_mul(types.float, None, val_a[0], val_b[0]).unwrap()
|
||||||
|
} else {
|
||||||
|
let vector = [types.void, types.float, types.vec2, types.vec3, types.vec4]
|
||||||
|
[instruction.opcode.size as usize];
|
||||||
|
let val_a = b.composite_construct(vector, None, val_a).unwrap();
|
||||||
|
let val_b = b.composite_construct(vector, None, val_b).unwrap();
|
||||||
|
b.dot(types.float, None, val_a, val_b).unwrap()
|
||||||
|
};
|
||||||
|
mapping.insert(instruction.outputs[0], dot);
|
||||||
|
},
|
||||||
|
SSALength => {
|
||||||
|
let val_a = (0..instruction.opcode.size)
|
||||||
|
.map(|i| {
|
||||||
|
input_resolve(types.float, b, &mapping, instruction.inputs[i as usize])
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let length = if instruction.opcode.size == 1 {
|
||||||
|
val_a[0]
|
||||||
|
} else {
|
||||||
|
let vector = [types.void, types.float, types.vec2, types.vec3, types.vec4]
|
||||||
|
[instruction.opcode.size as usize];
|
||||||
|
let val_a = b.composite_construct(vector, None, val_a).unwrap();
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Length as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
};
|
||||||
|
mapping.insert(instruction.outputs[0], length);
|
||||||
|
},
|
||||||
|
SSADistance => {
|
||||||
|
let val_a = (0..instruction.opcode.size)
|
||||||
|
.map(|i| {
|
||||||
|
input_resolve(types.float, b, &mapping, instruction.inputs[i as usize])
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let val_b = (instruction.opcode.size..(instruction.opcode.size * 2))
|
||||||
|
.map(|i| {
|
||||||
|
input_resolve(types.float, b, &mapping, instruction.inputs[i as usize])
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let distance = if instruction.opcode.size == 1 {
|
||||||
|
b.f_sub(types.float, None, val_b[0], val_a[0]).unwrap()
|
||||||
|
} else {
|
||||||
|
let vector = [types.void, types.float, types.vec2, types.vec3, types.vec4]
|
||||||
|
[instruction.opcode.size as usize];
|
||||||
|
let val_a = b.composite_construct(vector, None, val_a).unwrap();
|
||||||
|
let val_b = b.composite_construct(vector, None, val_b).unwrap();
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Distance as u32,
|
||||||
|
[IdRef(val_a), IdRef(val_b)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
};
|
||||||
|
mapping.insert(instruction.outputs[0], distance);
|
||||||
|
},
|
||||||
|
SSARecip => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
let one = b.constant_bit32(types.float, (1.0f32).to_bits());
|
||||||
|
b.f_div(types.float, None, one, val_a).unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSANegate => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.f_negate(types.float, None, val_a).unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSARound => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Round as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAAbs => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FAbs as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAFloor => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Floor as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSACeil => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Ceil as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAFract => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Fract as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSASin => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Sin as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSACos => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Cos as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSATan => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Tan as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAAsin => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Asin as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAAcos => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Acos as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAAtan => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Atan as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSAExp => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Exp as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSALog => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Log as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSASqrt => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Sqrt as u32,
|
||||||
|
[IdRef(val_a)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSASquare => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
b.f_mul(types.float, None, val_a, val_a).unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSACube => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
let square = b.f_mul(types.float, None, val_a, val_a).unwrap();
|
||||||
|
b.f_mul(types.float, None, val_a, square).unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSASmoothMin => {
|
||||||
|
param_three(types.float, b, &mut mapping, instruction, |b, d1, d2, k| {
|
||||||
|
let half_const = b.constant_bit32(types.float, (0.5f32).to_bits());
|
||||||
|
let zero_const = b.constant_bit32(types.float, (0.0f32).to_bits());
|
||||||
|
let one_const = b.constant_bit32(types.float, (1.0f32).to_bits());
|
||||||
|
let sub = b.f_sub(types.float, None, d2, d1).unwrap();
|
||||||
|
let mul_half = b.f_mul(types.float, None, sub, half_const).unwrap();
|
||||||
|
let div_k = b.f_div(types.float, None, mul_half, k).unwrap();
|
||||||
|
let add_half = b.f_add(types.float, None, div_k, half_const).unwrap();
|
||||||
|
let h = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FClamp as u32,
|
||||||
|
[IdRef(add_half), IdRef(zero_const), IdRef(one_const)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let negh = b.f_sub(types.float, None, one_const, h).unwrap();
|
||||||
|
let h_negh = b.f_mul(types.float, None, h, negh).unwrap();
|
||||||
|
let kh_negh = b.f_mul(types.float, None, k, h_negh).unwrap();
|
||||||
|
let mix = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FMix as u32,
|
||||||
|
[IdRef(d2), IdRef(d1), IdRef(h)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
b.f_sub(types.float, None, mix, kh_negh).unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSASmoothMax => {
|
||||||
|
param_three(types.float, b, &mut mapping, instruction, |b, d1, d2, k| {
|
||||||
|
let half_const = b.constant_bit32(types.float, (0.5f32).to_bits());
|
||||||
|
let zero_const = b.constant_bit32(types.float, (0.0f32).to_bits());
|
||||||
|
let one_const = b.constant_bit32(types.float, (1.0f32).to_bits());
|
||||||
|
let sub = b.f_add(types.float, None, d2, d1).unwrap();
|
||||||
|
let mul_half = b.f_mul(types.float, None, sub, half_const).unwrap();
|
||||||
|
let div_k = b.f_div(types.float, None, mul_half, k).unwrap();
|
||||||
|
let add_half = b.f_sub(types.float, None, half_const, div_k).unwrap();
|
||||||
|
let h = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FClamp as u32,
|
||||||
|
[IdRef(add_half), IdRef(zero_const), IdRef(one_const)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let negh = b.f_sub(types.float, None, one_const, h).unwrap();
|
||||||
|
let h_negh = b.f_mul(types.float, None, h, negh).unwrap();
|
||||||
|
let kh_negh = b.f_mul(types.float, None, k, h_negh).unwrap();
|
||||||
|
let negate = b.f_negate(types.float, None, d1).unwrap();
|
||||||
|
let mix = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FMix as u32,
|
||||||
|
[IdRef(d2), IdRef(negate), IdRef(h)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
b.f_add(types.float, None, mix, kh_negh).unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
SSASmoothMinMaterial => todo!(),
|
||||||
|
SSASmoothMaxMaterial => todo!(),
|
||||||
|
SSAClamp => {
|
||||||
|
param_three(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b, val_c| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FClamp as u32,
|
||||||
|
[IdRef(val_a), IdRef(val_b), IdRef(val_c)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAMix => {
|
||||||
|
param_three(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b, val_c| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FMix as u32,
|
||||||
|
[IdRef(val_a), IdRef(val_b), IdRef(val_c)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAFMA => {
|
||||||
|
param_three(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b, val_c| {
|
||||||
|
b.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Fma as u32,
|
||||||
|
[IdRef(val_a), IdRef(val_b), IdRef(val_c)],
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSASDFSphere => {
|
||||||
|
let pos_part = (0..3)
|
||||||
|
.map(|i| {
|
||||||
|
input_resolve(types.float, b, &mapping, instruction.inputs[i as usize])
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let pos = b.composite_construct(types.vec3, None, pos_part).unwrap();
|
||||||
|
let radius =
|
||||||
|
input_resolve(types.float, b, &mapping, instruction.inputs[3 as usize]);
|
||||||
|
|
||||||
|
let length = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Length as u32,
|
||||||
|
[IdRef(pos)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let sphere = b.f_sub(types.float, None, length, radius).unwrap();
|
||||||
|
|
||||||
|
mapping.insert(instruction.outputs[0], sphere);
|
||||||
|
},
|
||||||
|
SSASDFBox => {
|
||||||
|
let pos_part = (0..3)
|
||||||
|
.map(|i| {
|
||||||
|
input_resolve(types.float, b, &mapping, instruction.inputs[i as usize])
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let pos = b.composite_construct(types.vec3, None, pos_part).unwrap();
|
||||||
|
|
||||||
|
let dim_part = (3..6)
|
||||||
|
.map(|i| {
|
||||||
|
input_resolve(types.float, b, &mapping, instruction.inputs[i as usize])
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let dim = b.composite_construct(types.vec3, None, dim_part).unwrap();
|
||||||
|
|
||||||
|
let abs = b
|
||||||
|
.ext_inst(
|
||||||
|
types.vec3,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FAbs as u32,
|
||||||
|
[IdRef(pos)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let q = b.f_sub(types.vec3, None, abs, dim).unwrap();
|
||||||
|
|
||||||
|
let zero = b.constant_bit32(types.float, 0);
|
||||||
|
let zero_vec3 = b
|
||||||
|
.composite_construct(types.vec3, None, [zero, zero, zero])
|
||||||
|
.unwrap();
|
||||||
|
let q_limit = b
|
||||||
|
.ext_inst(
|
||||||
|
types.vec3,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FMax as u32,
|
||||||
|
[IdRef(q), IdRef(zero_vec3)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let length = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Length as u32,
|
||||||
|
[IdRef(q_limit)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let q_x = b.composite_extract(types.float, None, q, [0]).unwrap();
|
||||||
|
let q_y = b.composite_extract(types.float, None, q, [1]).unwrap();
|
||||||
|
let q_z = b.composite_extract(types.float, None, q, [2]).unwrap();
|
||||||
|
let max1 = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FMax as u32,
|
||||||
|
[IdRef(q_x), IdRef(q_y)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let max2 = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FMax as u32,
|
||||||
|
[IdRef(max1), IdRef(q_z)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let min = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::FMax as u32,
|
||||||
|
[IdRef(max2), IdRef(zero)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
mapping.insert(
|
||||||
|
instruction.outputs[0],
|
||||||
|
b.f_add(types.float, None, length, min).unwrap(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSASDFTorus => {
|
||||||
|
let pos_part = (0..3)
|
||||||
|
.map(|i| {
|
||||||
|
input_resolve(types.float, b, &mapping, instruction.inputs[i as usize])
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let pos_vec2 = b
|
||||||
|
.composite_construct(types.vec2, None, [pos_part[0], pos_part[2]])
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let rad1 = input_resolve(types.float, b, &mapping, instruction.inputs[3 as usize]);
|
||||||
|
let rad2 = input_resolve(types.float, b, &mapping, instruction.inputs[4 as usize]);
|
||||||
|
|
||||||
|
let dot = b.dot(types.float, None, pos_vec2, pos_vec2).unwrap();
|
||||||
|
let sqrt = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Sqrt as u32,
|
||||||
|
[IdRef(dot)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let subtx = b.f_sub(types.float, None, sqrt, rad1).unwrap();
|
||||||
|
|
||||||
|
let q = b
|
||||||
|
.composite_construct(types.vec2, None, [subtx, pos_part[1]])
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let length = b
|
||||||
|
.ext_inst(
|
||||||
|
types.float,
|
||||||
|
None,
|
||||||
|
types.glsl,
|
||||||
|
spirv::GLOp::Length as u32,
|
||||||
|
[IdRef(q)],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
mapping.insert(
|
||||||
|
instruction.outputs[0],
|
||||||
|
b.f_sub(types.float, None, length, rad2).unwrap(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSACompare => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| {
|
||||||
|
let nan = b.constant_bit32(types.float, f32::NAN.to_bits());
|
||||||
|
let zero = b.constant_bit32(types.float, (0.0f32).to_bits());
|
||||||
|
let one = b.constant_bit32(types.float, (1.0f32).to_bits());
|
||||||
|
let onen = b.constant_bit32(types.float, (-1.0f32).to_bits());
|
||||||
|
let equal = b.f_ord_equal(types.bool, None, val_a, val_b).unwrap();
|
||||||
|
let less = b.f_ord_less_than(types.bool, None, val_a, val_b).unwrap();
|
||||||
|
let more = b
|
||||||
|
.f_ord_greater_than(types.bool, None, val_a, val_b)
|
||||||
|
.unwrap();
|
||||||
|
let select_less = b.select(types.float, None, less, onen, nan).unwrap();
|
||||||
|
let select_more =
|
||||||
|
b.select(types.float, None, more, one, select_less).unwrap();
|
||||||
|
let select_eq = b
|
||||||
|
.select(types.float, None, equal, zero, select_more)
|
||||||
|
.unwrap();
|
||||||
|
select_eq
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAAnd => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| {
|
||||||
|
let zero = b.constant_bit32(types.float, (0.0f32).to_bits());
|
||||||
|
let equal = b.f_ord_equal(types.bool, None, val_a, zero).unwrap();
|
||||||
|
b.select(types.float, None, equal, val_a, val_b).unwrap()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSAOr => {
|
||||||
|
param_two(
|
||||||
|
types.float,
|
||||||
|
b,
|
||||||
|
&mut mapping,
|
||||||
|
instruction,
|
||||||
|
|b, val_a, val_b| {
|
||||||
|
let zero = b.constant_bit32(types.float, (0.0f32).to_bits());
|
||||||
|
let equal = b.f_ord_equal(types.bool, None, val_a, zero).unwrap();
|
||||||
|
b.select(types.float, None, equal, val_b, val_a).unwrap()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
SSANot => {
|
||||||
|
param_one(types.float, b, &mut mapping, instruction, |b, val_a| {
|
||||||
|
let zero = b.constant_bit32(types.float, (0.0f32).to_bits());
|
||||||
|
let one = b.constant_bit32(types.float, (1.0f32).to_bits());
|
||||||
|
let equal = b.f_ord_equal(types.bool, None, val_a, zero).unwrap();
|
||||||
|
b.select(types.float, None, equal, one, zero).unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.end_function().unwrap();
|
||||||
|
}
|
||||||
@@ -0,0 +1,536 @@
|
|||||||
|
use core::f32;
|
||||||
|
|
||||||
|
use rspirv::{binary::Disassemble, dr::Module, spirv};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
instruction_set::InstructionSet,
|
||||||
|
spirv_compilers::{
|
||||||
|
SpirVTypes,
|
||||||
|
//gradient::compile_gradient_function,
|
||||||
|
//interval::compile_interval_function,
|
||||||
|
point::compile_point_function,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const JIT_VERSION: u32 = 1;
|
||||||
|
|
||||||
|
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
|
||||||
|
pub enum SSAOpcode {
|
||||||
|
SSAAdd,
|
||||||
|
SSASub,
|
||||||
|
SSAMul,
|
||||||
|
SSADiv,
|
||||||
|
SSAAtan2,
|
||||||
|
SSAMin,
|
||||||
|
SSAMax,
|
||||||
|
SSACompare,
|
||||||
|
SSAMod,
|
||||||
|
SSAAnd,
|
||||||
|
SSAOr,
|
||||||
|
|
||||||
|
SSANegate,
|
||||||
|
SSAAbs,
|
||||||
|
SSARecip,
|
||||||
|
SSASqrt,
|
||||||
|
SSASquare,
|
||||||
|
SSAFloor,
|
||||||
|
SSACeil,
|
||||||
|
SSARound,
|
||||||
|
SSASin,
|
||||||
|
SSACos,
|
||||||
|
SSATan,
|
||||||
|
SSAAsin,
|
||||||
|
SSAAcos,
|
||||||
|
SSAAtan,
|
||||||
|
SSAExp,
|
||||||
|
SSALog,
|
||||||
|
SSANot,
|
||||||
|
|
||||||
|
SSAFract,
|
||||||
|
SSACube,
|
||||||
|
SSASmoothMin,
|
||||||
|
SSASmoothMax,
|
||||||
|
SSAClamp,
|
||||||
|
SSAMix,
|
||||||
|
SSAFMA,
|
||||||
|
|
||||||
|
SSADot,
|
||||||
|
SSALength,
|
||||||
|
SSADistance,
|
||||||
|
|
||||||
|
#[default]
|
||||||
|
SSAStop,
|
||||||
|
SSAReturn,
|
||||||
|
SSAPosition,
|
||||||
|
SSAMinMaterial,
|
||||||
|
SSAMaxMaterial,
|
||||||
|
SSASmoothMinMaterial,
|
||||||
|
SSASmoothMaxMaterial,
|
||||||
|
SSASDFSphere,
|
||||||
|
SSASDFBox,
|
||||||
|
SSASDFTorus,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
|
||||||
|
pub struct SSAOpcodeSized {
|
||||||
|
pub opcode: SSAOpcode,
|
||||||
|
pub size: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||||
|
pub enum SSAInput {
|
||||||
|
Register(u32),
|
||||||
|
Constant(f32),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct SSAInstruction {
|
||||||
|
pub opcode: SSAOpcodeSized,
|
||||||
|
pub inputs: Vec<SSAInput>,
|
||||||
|
pub outputs: Vec<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, PartialEq, Clone)]
|
||||||
|
pub struct SSATape {
|
||||||
|
pub last_output: u32,
|
||||||
|
pub tape: Vec<SSAInstruction>,
|
||||||
|
constants: Vec<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
|
||||||
|
struct GPUOpcode(u8);
|
||||||
|
|
||||||
|
pub struct GPUTape {
|
||||||
|
pub instructions: Vec<u8>,
|
||||||
|
pub io: Vec<u8>,
|
||||||
|
pub constants: Vec<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SSAOpcodeSized {
|
||||||
|
const fn output(&self) -> u8 {
|
||||||
|
use SSAOpcode::*;
|
||||||
|
match self.opcode {
|
||||||
|
SSAStop => 0,
|
||||||
|
SSAReturn => 0,
|
||||||
|
SSAPosition => 4,
|
||||||
|
SSAMinMaterial => 1,
|
||||||
|
SSAMaxMaterial => 1,
|
||||||
|
SSASmoothMinMaterial => 1,
|
||||||
|
SSASmoothMaxMaterial => 1,
|
||||||
|
SSADistance => 1,
|
||||||
|
SSALength => 1,
|
||||||
|
SSADot => 1,
|
||||||
|
SSASDFSphere => 1,
|
||||||
|
SSASDFBox => 1,
|
||||||
|
SSASDFTorus => 1,
|
||||||
|
_ => self.size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn input(&self) -> u8 {
|
||||||
|
use SSAOpcode::*;
|
||||||
|
match self.opcode {
|
||||||
|
SSAStop => 0,
|
||||||
|
SSAReturn => 1,
|
||||||
|
SSAPosition => 0,
|
||||||
|
SSAMinMaterial => 2,
|
||||||
|
SSAMaxMaterial => 2,
|
||||||
|
SSASmoothMinMaterial => 3,
|
||||||
|
SSASmoothMaxMaterial => 3,
|
||||||
|
SSASDFSphere => 3 + 1,
|
||||||
|
SSASDFBox => 3 + 3,
|
||||||
|
SSASDFTorus => 3 + 2,
|
||||||
|
SSAAdd | SSASub | SSAMul | SSADiv | SSAAtan2 | SSAMin | SSAMax | SSACompare
|
||||||
|
| SSAMod | SSAAnd | SSAOr | SSADot | SSADistance => self.size * 2,
|
||||||
|
SSASmoothMin | SSASmoothMax | SSAClamp | SSAMix | SSAFMA => self.size * 3,
|
||||||
|
_ => self.size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn lifetime_elementwise(&self) -> (u8, u8) {
|
||||||
|
use SSAOpcode::*;
|
||||||
|
match self.opcode {
|
||||||
|
SSAStop | SSAReturn | SSAPosition | SSAMinMaterial | SSAMaxMaterial
|
||||||
|
| SSASmoothMinMaterial | SSASmoothMaxMaterial | SSASDFSphere | SSASDFBox
|
||||||
|
| SSASDFTorus | SSADot | SSADistance | SSALength => (0, 0),
|
||||||
|
SSAAdd | SSASub | SSAMul | SSADiv | SSAAtan2 | SSAMin | SSACompare | SSAMod
|
||||||
|
| SSAAnd | SSAOr => (2, 1),
|
||||||
|
SSASmoothMin | SSASmoothMax | SSAClamp | SSAMix | SSAFMA => (3, 1),
|
||||||
|
_ => (1, 1),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn to_raw_opcode(&self) -> GPUOpcode {
|
||||||
|
use InstructionSet::*;
|
||||||
|
use SSAOpcode::*;
|
||||||
|
const fn opcode_drop(inst: InstructionSet, width: u8) -> GPUOpcode {
|
||||||
|
assert!(width <= 4);
|
||||||
|
assert!(width > 0);
|
||||||
|
GPUOpcode(inst as u8 + ((width - 1) << 6))
|
||||||
|
}
|
||||||
|
match self.opcode {
|
||||||
|
SSAStop => opcode_drop(OPReturn, 1),
|
||||||
|
SSAReturn => opcode_drop(OPReturn, 1),
|
||||||
|
SSAPosition => opcode_drop(OPPosition, 1),
|
||||||
|
SSAMinMaterial => opcode_drop(OPMinMaterial, 1),
|
||||||
|
SSAMaxMaterial => opcode_drop(OPMaxMaterial, 1),
|
||||||
|
SSASmoothMinMaterial => opcode_drop(OPSmoothMinMaterial, 1),
|
||||||
|
SSASmoothMaxMaterial => opcode_drop(OPSmoothMaxMaterial, 1),
|
||||||
|
SSASDFSphere => opcode_drop(OPSDFSphere, 1),
|
||||||
|
SSASDFBox => opcode_drop(OPSDFBox, 1),
|
||||||
|
SSASDFTorus => opcode_drop(OPSDFTorus, 1),
|
||||||
|
SSAAdd => opcode_drop(OPAdd, self.size),
|
||||||
|
SSASub => opcode_drop(OPSub, self.size),
|
||||||
|
SSAMul => opcode_drop(OPMul, self.size),
|
||||||
|
SSADiv => opcode_drop(OPDiv, self.size),
|
||||||
|
SSAMod => opcode_drop(OPMod, self.size),
|
||||||
|
SSAAtan2 => opcode_drop(OPAtan2, self.size),
|
||||||
|
SSAMin => opcode_drop(OPMin, self.size),
|
||||||
|
SSAMax => opcode_drop(OPMax, self.size),
|
||||||
|
SSADot => opcode_drop(OPDot, self.size),
|
||||||
|
SSALength => opcode_drop(OPLength, self.size),
|
||||||
|
SSADistance => opcode_drop(OPDistance, self.size),
|
||||||
|
SSANegate => opcode_drop(OPNegate, self.size),
|
||||||
|
SSARound => opcode_drop(OPRound, self.size),
|
||||||
|
SSAAbs => opcode_drop(OPAbs, self.size),
|
||||||
|
SSAFloor => opcode_drop(OPFloor, self.size),
|
||||||
|
SSACeil => opcode_drop(OPCeil, self.size),
|
||||||
|
SSAFract => opcode_drop(OPFract, self.size),
|
||||||
|
SSASin => opcode_drop(OPSin, self.size),
|
||||||
|
SSACos => opcode_drop(OPCos, self.size),
|
||||||
|
SSATan => opcode_drop(OPTan, self.size),
|
||||||
|
SSAAsin => opcode_drop(OPAsin, self.size),
|
||||||
|
SSAAcos => opcode_drop(OPAcos, self.size),
|
||||||
|
SSAAtan => opcode_drop(OPAtan, self.size),
|
||||||
|
SSAExp => opcode_drop(OPExp, self.size),
|
||||||
|
SSALog => opcode_drop(OPLog, self.size),
|
||||||
|
SSASqrt => opcode_drop(OPSqrt, self.size),
|
||||||
|
SSASquare => opcode_drop(OPSquare, self.size),
|
||||||
|
SSACube => opcode_drop(OPCube, self.size),
|
||||||
|
SSASmoothMin => opcode_drop(OPSmoothMin, self.size),
|
||||||
|
SSASmoothMax => opcode_drop(OPSmoothMax, self.size),
|
||||||
|
SSAClamp => opcode_drop(OPClamp, self.size),
|
||||||
|
SSAMix => opcode_drop(OPMix, self.size),
|
||||||
|
SSAFMA => opcode_drop(OPFMA, self.size),
|
||||||
|
SSACompare => opcode_drop(OPCompare, self.size),
|
||||||
|
SSAAnd => opcode_drop(OPAnd, self.size),
|
||||||
|
SSAOr => opcode_drop(OPOr, self.size),
|
||||||
|
SSARecip => opcode_drop(OPRecip, self.size),
|
||||||
|
SSANot => opcode_drop(OPNot, self.size),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SSATape {
|
||||||
|
pub fn push_instruction(
|
||||||
|
&mut self,
|
||||||
|
opcode: SSAOpcodeSized,
|
||||||
|
inputs: Vec<SSAInput>,
|
||||||
|
) -> Vec<SSAInput> {
|
||||||
|
assert!(
|
||||||
|
inputs
|
||||||
|
.iter()
|
||||||
|
.filter_map(|i| match i {
|
||||||
|
SSAInput::Constant(_) => None,
|
||||||
|
SSAInput::Register(r) => Some(r),
|
||||||
|
})
|
||||||
|
.all(|&i| i < self.last_output)
|
||||||
|
);
|
||||||
|
assert!(opcode.size <= 4);
|
||||||
|
assert!(opcode.size >= 1);
|
||||||
|
assert_eq!(inputs.len(), opcode.input() as usize);
|
||||||
|
|
||||||
|
let outputs = (self.last_output..)
|
||||||
|
.take(opcode.output() as usize)
|
||||||
|
.collect::<Vec<u32>>();
|
||||||
|
let outputs_register = outputs
|
||||||
|
.iter()
|
||||||
|
.map(|r| SSAInput::Register(*r))
|
||||||
|
.collect::<Vec<SSAInput>>();
|
||||||
|
self.last_output += opcode.output() as u32;
|
||||||
|
|
||||||
|
self.constants.extend(inputs.iter().filter_map(|i| match i {
|
||||||
|
SSAInput::Constant(0.0) => None,
|
||||||
|
SSAInput::Constant(c) => Some(c),
|
||||||
|
SSAInput::Register(_) => None,
|
||||||
|
}));
|
||||||
|
|
||||||
|
self.tape.push(SSAInstruction {
|
||||||
|
opcode,
|
||||||
|
inputs,
|
||||||
|
outputs,
|
||||||
|
});
|
||||||
|
return outputs_register;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compile_to_gpu(&self) -> GPUTape {
|
||||||
|
let mut lifetimes = Vec::<(u32, u32)>::with_capacity(self.last_output as usize);
|
||||||
|
|
||||||
|
let mut time_unit = 0;
|
||||||
|
|
||||||
|
for SSAInstruction {
|
||||||
|
opcode,
|
||||||
|
inputs,
|
||||||
|
outputs,
|
||||||
|
} in self.tape.iter()
|
||||||
|
{
|
||||||
|
let per_element = opcode.lifetime_elementwise();
|
||||||
|
|
||||||
|
if per_element == (0, 0) {
|
||||||
|
for &value in inputs {
|
||||||
|
if let SSAInput::Register(r) = value {
|
||||||
|
assert!((r as usize) < lifetimes.len());
|
||||||
|
lifetimes[r as usize].1 = time_unit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for &value in outputs {
|
||||||
|
assert_eq!(value as usize, lifetimes.len());
|
||||||
|
lifetimes.push((time_unit, time_unit));
|
||||||
|
}
|
||||||
|
time_unit += 1;
|
||||||
|
} else {
|
||||||
|
let mut input_iterators = (0..per_element.0)
|
||||||
|
.map(|i| inputs.iter().skip(i.into()).step_by(per_element.0.into()))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let mut output_iterators = (0..per_element.1)
|
||||||
|
.map(|i| outputs.iter().skip(i.into()).step_by(per_element.1.into()))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
opcode.input() / per_element.0,
|
||||||
|
opcode.output() / per_element.1
|
||||||
|
);
|
||||||
|
|
||||||
|
for _ in 0..(opcode.input() / per_element.0) {
|
||||||
|
for iterator in input_iterators.iter_mut() {
|
||||||
|
let &value = iterator.next().unwrap();
|
||||||
|
if let SSAInput::Register(r) = value {
|
||||||
|
assert!((r as usize) < lifetimes.len());
|
||||||
|
lifetimes[r as usize].1 = time_unit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for iterator in output_iterators.iter_mut() {
|
||||||
|
let &value = iterator.next().unwrap();
|
||||||
|
assert_eq!(value as usize, lifetimes.len());
|
||||||
|
lifetimes.push((time_unit, time_unit));
|
||||||
|
}
|
||||||
|
time_unit += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registers are held UNTIL, non inclusive.
|
||||||
|
let mut register_hold = [0u32; 14];
|
||||||
|
|
||||||
|
let mut register_allocation = vec![0u8; lifetimes.len()];
|
||||||
|
|
||||||
|
for ((life_start, life_end), allocation) in
|
||||||
|
lifetimes.iter().zip(register_allocation.iter_mut())
|
||||||
|
{
|
||||||
|
if life_start == life_end {
|
||||||
|
*allocation = 0;
|
||||||
|
} else if let Some(register) = register_hold.iter().position(|reg| reg <= life_start) {
|
||||||
|
register_hold[register] = *life_end;
|
||||||
|
*allocation = (register + 1) as u8;
|
||||||
|
} else {
|
||||||
|
panic!("Failed to allocate registers");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut gpu_tape = GPUTape {
|
||||||
|
instructions: vec![],
|
||||||
|
io: vec![],
|
||||||
|
constants: self.constants.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut low_nibble = true;
|
||||||
|
let mut staging_byte = 0u8;
|
||||||
|
|
||||||
|
for SSAInstruction {
|
||||||
|
opcode,
|
||||||
|
inputs,
|
||||||
|
outputs,
|
||||||
|
} in self.tape.iter()
|
||||||
|
{
|
||||||
|
let code = opcode.to_raw_opcode();
|
||||||
|
gpu_tape.instructions.push(code.0);
|
||||||
|
|
||||||
|
let per_element = opcode.lifetime_elementwise();
|
||||||
|
|
||||||
|
if per_element == (0, 0) {
|
||||||
|
for input in inputs {
|
||||||
|
let register = match input {
|
||||||
|
SSAInput::Constant(0.0) => 0,
|
||||||
|
SSAInput::Constant(_) => 15,
|
||||||
|
SSAInput::Register(u) => register_allocation[*u as usize],
|
||||||
|
};
|
||||||
|
|
||||||
|
if low_nibble {
|
||||||
|
staging_byte |= register;
|
||||||
|
} else {
|
||||||
|
staging_byte |= register << 4;
|
||||||
|
gpu_tape.io.push(staging_byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
low_nibble = !low_nibble;
|
||||||
|
}
|
||||||
|
|
||||||
|
for output in outputs {
|
||||||
|
let register = register_allocation[*output as usize];
|
||||||
|
|
||||||
|
if low_nibble {
|
||||||
|
staging_byte |= register;
|
||||||
|
} else {
|
||||||
|
staging_byte |= register << 4;
|
||||||
|
gpu_tape.io.push(staging_byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
low_nibble = !low_nibble;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop is implemented as SSAReturn(0);
|
||||||
|
if opcode.opcode == SSAOpcode::SSAStop {
|
||||||
|
let register = 0;
|
||||||
|
|
||||||
|
if low_nibble {
|
||||||
|
staging_byte |= register;
|
||||||
|
} else {
|
||||||
|
staging_byte |= register << 4;
|
||||||
|
gpu_tape.io.push(staging_byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
low_nibble = !low_nibble;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let mut input_iterators = (0..per_element.0)
|
||||||
|
.map(|i| inputs.iter().skip(i.into()).step_by(per_element.0.into()))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let mut output_iterators = (0..per_element.1)
|
||||||
|
.map(|i| outputs.iter().skip(i.into()).step_by(per_element.1.into()))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
opcode.input() / per_element.0,
|
||||||
|
opcode.output() / per_element.1
|
||||||
|
);
|
||||||
|
|
||||||
|
for _ in 0..(opcode.input() / per_element.0) {
|
||||||
|
for iterator in input_iterators.iter_mut() {
|
||||||
|
let &value = iterator.next().unwrap();
|
||||||
|
let register = match value {
|
||||||
|
SSAInput::Constant(0.0) => 0,
|
||||||
|
SSAInput::Constant(_) => 15,
|
||||||
|
SSAInput::Register(u) => register_allocation[u as usize],
|
||||||
|
};
|
||||||
|
|
||||||
|
if low_nibble {
|
||||||
|
staging_byte |= register;
|
||||||
|
} else {
|
||||||
|
staging_byte |= register << 4;
|
||||||
|
gpu_tape.io.push(staging_byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
low_nibble = !low_nibble;
|
||||||
|
}
|
||||||
|
for iterator in output_iterators.iter_mut() {
|
||||||
|
let &value = iterator.next().unwrap();
|
||||||
|
let register = register_allocation[value as usize];
|
||||||
|
|
||||||
|
if low_nibble {
|
||||||
|
staging_byte |= register;
|
||||||
|
} else {
|
||||||
|
staging_byte |= register << 4;
|
||||||
|
gpu_tape.io.push(staging_byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
low_nibble = !low_nibble;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !low_nibble {
|
||||||
|
gpu_tape.io.push(staging_byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
gpu_tape
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compile_to_spirv(&self, module: Option<Module>) -> rspirv::dr::Module {
|
||||||
|
let with_module = module.is_some();
|
||||||
|
let mut b = if let Some(module) = module {
|
||||||
|
rspirv::dr::Builder::new_from_module(module)
|
||||||
|
} else {
|
||||||
|
let mut b = rspirv::dr::Builder::new();
|
||||||
|
b.set_version(1, 6);
|
||||||
|
b.module_processed(format!("Tape Drive JIT {JIT_VERSION}"));
|
||||||
|
b.memory_model(spirv::AddressingModel::Logical, spirv::MemoryModel::GLSL450);
|
||||||
|
b
|
||||||
|
};
|
||||||
|
let glsl = if with_module {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
b.ext_inst_import("GLSL.std.450")
|
||||||
|
};
|
||||||
|
|
||||||
|
let void = b.type_void();
|
||||||
|
let float = b.type_float(32);
|
||||||
|
let bool = b.type_bool();
|
||||||
|
let vec2 = b.type_vector(float, 2);
|
||||||
|
let vec3 = b.type_vector(float, 3);
|
||||||
|
let vec4 = b.type_vector(float, 4);
|
||||||
|
let vec4p = b.type_pointer(None, spirv::StorageClass::Function, vec4);
|
||||||
|
let point_fn_type = b.type_function(float, vec![vec4p]);
|
||||||
|
let interval_fn_type = b.type_function(vec2, vec![vec4p, vec4p]);
|
||||||
|
let jit_string = b.string("JIT");
|
||||||
|
|
||||||
|
let types = SpirVTypes {
|
||||||
|
glsl,
|
||||||
|
void,
|
||||||
|
float,
|
||||||
|
bool,
|
||||||
|
vec2,
|
||||||
|
vec3,
|
||||||
|
vec4,
|
||||||
|
vec4p,
|
||||||
|
point_fn_type,
|
||||||
|
interval_fn_type,
|
||||||
|
jit_string,
|
||||||
|
};
|
||||||
|
|
||||||
|
compile_point_function(
|
||||||
|
&mut b,
|
||||||
|
&self,
|
||||||
|
types,
|
||||||
|
if with_module { Some(1000) } else { None },
|
||||||
|
);
|
||||||
|
|
||||||
|
//compile_interval_function(
|
||||||
|
// &mut b,
|
||||||
|
// &self,
|
||||||
|
// types,
|
||||||
|
// if with_module { Some(2000) } else { None },
|
||||||
|
//);
|
||||||
|
|
||||||
|
//compile_gradient_function(
|
||||||
|
// &mut b,
|
||||||
|
// &self,
|
||||||
|
// types,
|
||||||
|
// if with_module { Some(3000) } else { None },
|
||||||
|
//);
|
||||||
|
|
||||||
|
let module = b.module();
|
||||||
|
|
||||||
|
std::fs::write(
|
||||||
|
format!(
|
||||||
|
"{}.spv-dis",
|
||||||
|
humantime::format_rfc3339(std::time::SystemTime::now())
|
||||||
|
)
|
||||||
|
.to_string(),
|
||||||
|
module.disassemble(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
module
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,11 +2,10 @@ use std::simd::{
|
|||||||
StdFloat,
|
StdFloat,
|
||||||
cmp::{SimdPartialEq, SimdPartialOrd},
|
cmp::{SimdPartialEq, SimdPartialOrd},
|
||||||
num::SimdFloat,
|
num::SimdFloat,
|
||||||
u32x8,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
interpreter::{
|
interpreters::{
|
||||||
Mask, VALUE_0, VALUE_1, VALUE_2, VALUE_05, VALUE_M1, VALUE_NAN, VALUE_PI, VALUE_PI_2,
|
Mask, VALUE_0, VALUE_1, VALUE_2, VALUE_05, VALUE_M1, VALUE_NAN, VALUE_PI, VALUE_PI_2,
|
||||||
VALUE_TAU, Value, glfract, glsign,
|
VALUE_TAU, Value, glfract, glsign,
|
||||||
},
|
},
|
||||||
Reference in New Issue
Block a user