simd interpreter

This commit is contained in:
2025-06-24 21:12:43 +01:00
parent 17cad7761a
commit 1ea3d73543
4 changed files with 46 additions and 56 deletions
+23 -39
View File
@@ -1,7 +1,7 @@
use std::simd::{ use std::simd::{
StdFloat, StdFloat,
cmp::{SimdPartialEq, SimdPartialOrd}, cmp::{SimdPartialEq, SimdPartialOrd},
num::{SimdFloat, SimdInt}, num::SimdFloat,
}; };
use crate::{ use crate::{
@@ -9,8 +9,7 @@ use crate::{
ssa::{SSAInput, SSAInstruction, SSAOpcode}, ssa::{SSAInput, SSAInstruction, SSAOpcode},
}; };
type Value = core::simd::f32x8; pub type Value = std::simd::f32x8;
type IValue = core::simd::i32x8;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub(crate) struct Interpreter<'csg> { pub(crate) struct Interpreter<'csg> {
@@ -94,6 +93,8 @@ impl<'csg> Interpreter<'csg> {
} }
} }
// cargo asm "erroccfisuvsc::interpreter::Interpreter::scene" --no-color --rust > scene.asm
pub(crate) fn scene(&mut self, px: Value, py: Value, pz: Value) -> Value { pub(crate) fn scene(&mut self, px: Value, py: Value, pz: Value) -> Value {
self.clear_stacks(); self.clear_stacks();
@@ -123,9 +124,14 @@ impl<'csg> Interpreter<'csg> {
SSAMod => { SSAMod => {
self.param_two(instruction, |val_a, val_b| val_a % val_b); self.param_two(instruction, |val_a, val_b| val_a % val_b);
}, },
SSAAtan2 => { SSAAtan2 => self.param_two(instruction, |val_a, val_b| {
self.param_two(instruction, |val_a, val_b| val_a.atan2(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 => { SSAMin => {
self.param_two(instruction, |val_a, val_b| val_a.simd_min(val_b)); self.param_two(instruction, |val_a, val_b| val_a.simd_min(val_b));
}, },
@@ -213,7 +219,7 @@ impl<'csg> Interpreter<'csg> {
+ ((val_a[2] - val_b[2]) * (val_a[2] - val_b[2])) + ((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[3] - val_b[3]) * (val_a[3] - val_b[3])))
.sqrt(), .sqrt(),
3 => (((val_a[0] - val_b[0]) * (val_a[0] - val_b[0])) 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[1] - val_b[1]) * (val_a[1] - val_b[1]))
+ ((val_a[2] - val_b[2]) * (val_a[2] - val_b[2])) + ((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[3] - val_b[3]) * (val_a[3] - val_b[3]))
@@ -282,45 +288,23 @@ impl<'csg> Interpreter<'csg> {
}, },
SSATan => { SSATan => {
self.param_one(instruction, |val_a| { self.param_one(instruction, |val_a| {
let sign_bit = val_a.is_sign_positive(); Value::from_array(val_a.to_array().map(|f| f.tan()))
let x = val_a.abs();
let y = x * Value::splat(core::f32::consts::FRAC_2_PI * 2.);
let emm2 = (y.cast::<i32>() + IValue::splat(1)) & IValue::splat(!1);
let y = emm2.cast::<f32>();
let polymask = (emm2 & IValue::splat(2)).simd_eq(IValue::splat(0));
const MINUS_CEPHES_DP1: Value = Value::splat(-0.78515625);
const MINUS_CEPHES_DP2: Value = Value::splat(-2.4187564849853515625e-4);
const MINUS_CEPHES_DP3: Value = Value::splat(-3.77489497744594108e-8);
let z = ((x + (y * MINUS_CEPHES_DP1)) + (y * MINUS_CEPHES_DP2))
+ (y * MINUS_CEPHES_DP3);
let zz = z * z;
const TANCOF_P0: Value = Value::splat(9.38540185543E-3);
const TANCOF_P1: Value = Value::splat(3.11992232697E-3);
const TANCOF_P2: Value = Value::splat(2.44301354525E-2);
const TANCOF_P3: Value = Value::splat(5.34112807005E-2);
const TANCOF_P4: Value = Value::splat(1.33387994085E-1);
const TANCOF_P5: Value = Value::splat(3.33331568548E-1);
let y = ((((((((TANCOF_P0 * zz) + TANCOF_P1) * zz) + TANCOF_P2 * zz)
+ TANCOF_P3 * zz)
+ TANCOF_P4 * zz)
+ TANCOF_P5)
* zz
* z)
+ z;
let y2 = (Value::splat(1.0) / y)
* sign_bit.select(Value::splat(-1.0), Value::splat(0.0));
let y = polymask.select(y, y2);
y * sign_bit.select(Value::splat(-1.0), Value::splat(0.0))
}); });
}, },
SSAAsin => { SSAAsin => {
self.param_one(instruction, |val_a| val_a.asin()); self.param_one(instruction, |val_a| {
Value::from_array(val_a.to_array().map(|f| f.asin()))
});
}, },
SSAAcos => { SSAAcos => {
self.param_one(instruction, |val_a| val_a.acos()); self.param_one(instruction, |val_a| {
Value::from_array(val_a.to_array().map(|f| f.acos()))
});
}, },
SSAAtan => { SSAAtan => {
self.param_one(instruction, |val_a| val_a.atan()); self.param_one(instruction, |val_a| {
Value::from_array(val_a.to_array().map(|f| f.atan()))
});
}, },
SSAExp => { SSAExp => {
self.param_one(instruction, |val_a| val_a.exp()); self.param_one(instruction, |val_a| val_a.exp());
+22 -13
View File
@@ -7,6 +7,7 @@ use std::{
fs::{File, remove_file, rename}, fs::{File, remove_file, rename},
io::{Cursor, Read, Write}, io::{Cursor, Read, Write},
path::{Path, PathBuf}, path::{Path, PathBuf},
simd::StdFloat,
sync::Arc, sync::Arc,
time::Instant, time::Instant,
}; };
@@ -306,7 +307,7 @@ impl App {
) )
.unwrap(); .unwrap();
let mut device_extensions = DeviceExtensions { let device_extensions = DeviceExtensions {
khr_swapchain: true, khr_swapchain: true,
ext_mesh_shader: false, ext_mesh_shader: false,
khr_fragment_shading_rate: false, khr_fragment_shading_rate: false,
@@ -625,7 +626,7 @@ impl ApplicationHandler for App {
.flatten() .flatten()
.collect::<Vec<_>>(); .collect::<Vec<_>>();
File::create("out.spv").unwrap().write(&module_as_bytes); File::create("out.spv").unwrap().write(&module_as_bytes).unwrap();
let smodule = unsafe { let smodule = unsafe {
::vulkano::shader::ShaderModule::new( ::vulkano::shader::ShaderModule::new(
@@ -917,7 +918,7 @@ impl App {
.flatten() .flatten()
.collect::<Vec<_>>(); .collect::<Vec<_>>();
File::create("out.spv").unwrap().write(&module_as_bytes); File::create("out.spv").unwrap().write(&module_as_bytes).unwrap();
let smodule = unsafe { let smodule = unsafe {
::vulkano::shader::ShaderModule::new( ::vulkano::shader::ShaderModule::new(
@@ -1149,17 +1150,25 @@ impl App {
* Mat4::from_scale(csg.scale * 2.0)) * Mat4::from_scale(csg.scale * 2.0))
.to_cols_array_2d(); .to_cols_array_2d();
const INTERPRET_INPUT_X: interpreter::Value =
interpreter::Value::from_array([10000.0, 0.0, 0.0, -10000.0, 0.0, 0.0, 0.0, 0.0]);
const INTERPRET_INPUT_Y: interpreter::Value =
interpreter::Value::from_array([0.0, 10000.0, 0.0, 0.0, -10000.0, 0.0, 0.0, 0.0]);
const INTERPRET_INPUT_Z: interpreter::Value =
interpreter::Value::from_array([0.0, 0.0, 10000.0, 0.0, 0.0, -10000.0, 0.0, 0.0]);
const INTERPRET_MUL: interpreter::Value =
interpreter::Value::from_array([-1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 0.0, 0.0]);
const INTERPRET_ADD: interpreter::Value = interpreter::Value::from_array([
10000.0, 10000.0, 10000.0, -10000.0, -10000.0, -10000.0, 0.0, 0.0,
]);
let mut interpreter = Interpreter::new(csg); let mut interpreter = Interpreter::new(csg);
let highest_corner = Vec3::new( let interpreter_out = interpreter
10000.0 - interpreter.scene(Vec3::new(10000.0, 0.0, 0.0)), .scene(INTERPRET_INPUT_X, INTERPRET_INPUT_Y, INTERPRET_INPUT_Z)
10000.0 - interpreter.scene(Vec3::new(0.0, 10000.0, 0.0)), .mul_add(INTERPRET_MUL, INTERPRET_ADD).to_array();
10000.0 - interpreter.scene(Vec3::new(0.0, 0.0, 10000.0)),
); let highest_corner = Vec3::new(interpreter_out[0], interpreter_out[1], interpreter_out[2]);
let lowest_corner = Vec3::new( let lowest_corner = Vec3::new(interpreter_out[3], interpreter_out[4], interpreter_out[5]);
-10000.0 + interpreter.scene(Vec3::new(-10000.0, 0.0, 0.0)),
-10000.0 + interpreter.scene(Vec3::new(0.0, -10000.0, 0.0)),
-10000.0 + interpreter.scene(Vec3::new(0.0, 0.0, -10000.0)),
);
push_constants.dimensions = (highest_corner - lowest_corner).to_array().into(); push_constants.dimensions = (highest_corner - lowest_corner).to_array().into();
push_constants.lowest_corner = lowest_corner.into(); push_constants.lowest_corner = lowest_corner.into();
+1 -3
View File
@@ -1,7 +1,7 @@
use std::{collections::HashMap, io::Read, sync::Arc}; use std::{collections::HashMap, io::Read, sync::Arc};
use bytemuck::{Pod, Zeroable}; use bytemuck::{Pod, Zeroable};
use glam::{self, Mat2, Mat3, Mat4, Vec2, Vec3, Vec4}; use glam::{self, Vec3};
use obj::{LoadConfig, ObjData, ObjError}; use obj::{LoadConfig, ObjData, ObjError};
use vulkano::{ use vulkano::{
buffer::{Buffer, BufferCreateInfo, BufferUsage, Subbuffer}, buffer::{Buffer, BufferCreateInfo, BufferUsage, Subbuffer},
@@ -43,8 +43,6 @@ pub(crate) struct CSG {
pub(crate) scale: Vec3, pub(crate) scale: Vec3,
} }
pub(crate) type Float = f32;
pub(crate) fn load_obj( pub(crate) fn load_obj(
memory_allocator: &Arc<StandardMemoryAllocator>, memory_allocator: &Arc<StandardMemoryAllocator>,
input: &mut dyn Read, input: &mut dyn Read,
-1
View File
@@ -1,6 +1,5 @@
use egui::ahash::HashMapExt; use egui::ahash::HashMapExt;
use foldhash::HashMap; use foldhash::HashMap;
use log::info;
use rspirv::{dr::Module, spirv}; use rspirv::{dr::Module, spirv};
use crate::instruction_set::InstructionSet; use crate::instruction_set::InstructionSet;