New instruction set
This commit is contained in:
Generated
+26
@@ -649,6 +649,7 @@ dependencies = [
|
||||
"obj",
|
||||
"rand",
|
||||
"rayon",
|
||||
"rspirv",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"simplelog",
|
||||
@@ -1911,6 +1912,22 @@ dependencies = [
|
||||
"xmlparser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rspirv"
|
||||
version = "0.12.0+sdk-1.3.268.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69cf3a93856b6e5946537278df0d3075596371b1950ccff012f02b0f7eafec8d"
|
||||
dependencies = [
|
||||
"rustc-hash",
|
||||
"spirv",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.43"
|
||||
@@ -2130,6 +2147,15 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spirv"
|
||||
version = "0.3.0+sdk-1.3.268.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
|
||||
@@ -37,6 +37,8 @@ foldhash = "*"
|
||||
log = "0.4"
|
||||
simplelog = "0.12"
|
||||
|
||||
rspirv = "0.12"
|
||||
|
||||
# using latest gits
|
||||
[patch.crates-io]
|
||||
vulkano = { git = "https://github.com/vulkano-rs/vulkano" }
|
||||
|
||||
@@ -12,29 +12,7 @@ fn main() -> io::Result<()> {
|
||||
let dest_path = Path::new(&out_dir).join("instructionset.rs");
|
||||
let f = File::open("src/instructionset.glsl")?;
|
||||
let f = BufReader::new(f);
|
||||
let mut out = "#[allow(non_snake_case)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub(crate) enum InputTypes{
|
||||
#[allow(non_snake_case)]
|
||||
Vec1,
|
||||
#[allow(non_snake_case)]
|
||||
Vec2,
|
||||
#[allow(non_snake_case)]
|
||||
Vec3,
|
||||
#[allow(non_snake_case)]
|
||||
Vec4,
|
||||
#[allow(non_snake_case)]
|
||||
VecX,
|
||||
#[allow(non_snake_case)]
|
||||
MatX1,
|
||||
#[allow(non_snake_case)]
|
||||
MatX2,
|
||||
#[allow(non_snake_case)]
|
||||
MatX3,
|
||||
#[allow(non_snake_case)]
|
||||
MatX4,
|
||||
}
|
||||
|
||||
let mut out = "
|
||||
#[repr(u8)]
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
@@ -43,79 +21,23 @@ fn main() -> io::Result<()> {
|
||||
"
|
||||
.to_owned();
|
||||
|
||||
let mut outputimpl = "
|
||||
pub(crate) fn output(&self) -> Vec<InputTypes>
|
||||
{
|
||||
match self {
|
||||
|
||||
"
|
||||
.to_owned();
|
||||
|
||||
let mut inputimpl = "
|
||||
pub(crate) fn input(&self) -> Vec<InputTypes>
|
||||
{
|
||||
match self {
|
||||
|
||||
"
|
||||
.to_owned();
|
||||
|
||||
for (index, l) in f.lines().enumerate() {
|
||||
for l in f.lines() {
|
||||
let line = l?;
|
||||
let entries = line.split("//").map(str::trim).collect::<Vec<&str>>();
|
||||
if entries[0].is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let name = &entries[0][11..entries[0].len() - 12];
|
||||
let comment = entries[3];
|
||||
let before_equals = entries[0].split("=").map(str::trim).collect::<Vec<&str>>();
|
||||
let name = &before_equals[0][11..];
|
||||
let value = &before_equals[1][..before_equals[1].len() - 1];
|
||||
let comment = entries[1];
|
||||
|
||||
out += &format!(
|
||||
"#[allow(non_snake_case)]\n#[allow(dead_code)]\n/// {comment}\n{name}={index},\n"
|
||||
"#[allow(non_snake_case)]\n#[allow(dead_code)]\n/// {comment}\n{name}={value},\n"
|
||||
);
|
||||
|
||||
inputimpl += &format!("#[allow(non_snake_case)]\nInstructionSet::{name} => vec![");
|
||||
for input in entries[1].split(' ').map(str::trim) {
|
||||
if input.is_empty() {
|
||||
continue;
|
||||
}
|
||||
match input {
|
||||
"V1" => inputimpl += "InputTypes::Vec1,",
|
||||
"V2" => inputimpl += "InputTypes::Vec2,",
|
||||
"V3" => inputimpl += "InputTypes::Vec3,",
|
||||
"V4" => inputimpl += "InputTypes::Vec4,",
|
||||
"VX" => inputimpl += "InputTypes::VecX,",
|
||||
"MX1" => inputimpl += "InputTypes::MatX1,",
|
||||
"MX2" => inputimpl += "InputTypes::MatX2,",
|
||||
"MX3" => inputimpl += "InputTypes::MatX3,",
|
||||
"MX4" => inputimpl += "InputTypes::MatX4,",
|
||||
_ => panic!("unknown input?? [{input}]"),
|
||||
}
|
||||
}
|
||||
inputimpl += "],\n";
|
||||
|
||||
outputimpl += &format!("#[allow(non_snake_case)]\nInstructionSet::{name} => vec![");
|
||||
for output in entries[2].split(' ').map(str::trim) {
|
||||
if output.is_empty() {
|
||||
continue;
|
||||
}
|
||||
match output {
|
||||
"V1" => outputimpl += "InputTypes::Vec1,",
|
||||
"V2" => outputimpl += "InputTypes::Vec2,",
|
||||
"V3" => outputimpl += "InputTypes::Vec3,",
|
||||
"V4" => outputimpl += "InputTypes::Vec4,",
|
||||
"VX" => outputimpl += "InputTypes::VecX,",
|
||||
_ => panic!("unknown output?? [{output}]"),
|
||||
}
|
||||
}
|
||||
outputimpl += "],\n";
|
||||
}
|
||||
out += "}";
|
||||
inputimpl += "}}";
|
||||
outputimpl += "}}";
|
||||
out += "#[allow(non_snake_case)]\nimpl InstructionSet {\n";
|
||||
out += &inputimpl;
|
||||
out += &outputimpl;
|
||||
out += "}";
|
||||
|
||||
fs::write(dest_path, out).unwrap();
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
+64
-149
@@ -1,149 +1,64 @@
|
||||
const uint OPNop=__LINE__-1; // // // No operation.
|
||||
const uint OPStop=__LINE__-1; // // // Stops execution of the tape and returns 0.
|
||||
const uint OPReturn=__LINE__-1; //V1 // // Stops execution of the tape and returns a single value.
|
||||
const uint OPPosition=__LINE__-1; // //V3 // Returns the current position being sampled.
|
||||
const uint OPPositionX=__LINE__-1; // //V1 // Returns the X component of the current position being sampled.
|
||||
const uint OPPositionY=__LINE__-1; // //V1 // Returns the Y component of the current position being sampled.
|
||||
const uint OPPositionZ=__LINE__-1; // //V1 // Returns the Z component of the current position being sampled.
|
||||
const uint OPCopyVecX=__LINE__-1; //V1 //V1 // Returns the input. Useful for copying registers.
|
||||
const uint OPPromoteVec1Vec1Vec2=__LINE__-1; //V1 V1 //V2 // Copies two Vec1 registers into a single Vec2.
|
||||
const uint OPPromoteVec1Vec1Vec1Vec3=__LINE__-1; //V1 V1 V1 //V3 // Copies three Vec1 registers into a single Vec3.
|
||||
const uint OPPromoteVec1Vec1Vec1Vec1Vec4=__LINE__-1; //V1 V1 V1 V1 //V4 // Copies four Vec1 registers into a single Vec4.
|
||||
const uint OPPromoteVec2Vec1Vec3=__LINE__-1; //V2 V1 //V3 // Copies one Vec2 register and one Vec1 register into a single Vec3.
|
||||
const uint OPPromoteVec1Vec2Vec3=__LINE__-1; //V1 V2 //V3 // Copies one Vec1 register and one Vec2 register into a single Vec3.
|
||||
const uint OPPromoteVec2Vec1Vec1Vec4=__LINE__-1; //V2 V1 V1 //V4 // Copies one Vec2 register and two Vec1 registers into a single Vec4.
|
||||
const uint OPPromoteVec1Vec2Vec1Vec4=__LINE__-1; //V1 V2 V1 //V4 // Copies one Vec1 register, one Vec2 register, and one Vec1 register into a single Vec4.
|
||||
const uint OPPromoteVec1Vec1Vec2Vec4=__LINE__-1; //V1 V1 V2 //V4 // Copies two Vec1 registers and one Vec2 register into a single Vec4.
|
||||
const uint OPPromoteVec2Vec2Vec4=__LINE__-1; //V2 V2 //V4 // Copies two Vec2 registers into a single Vec4.
|
||||
const uint OPPromoteVec3Vec1Vec4=__LINE__-1; //V3 V1 //V4 // Copies one Vec3 register and one Vec1 register into a single Vec4.
|
||||
const uint OPPromoteVec1Vec3Vec4=__LINE__-1; //V1 V3 //V4 // Copies one Vec1 register and one Vec3 register into a single Vec4.
|
||||
const uint OPAddVecXVecX=__LINE__-1; //V1 V1 //V1 // Adds a VecX to a VecX component-wise.
|
||||
const uint OPAddVec1VecX=__LINE__-1; //V1 VX //VX // Adds a Vec1 to a VecX component-wise.
|
||||
const uint OPAddVecXVec1=__LINE__-1; //VX V1 //VX // Adds a VecX to a Vec1 component-wise.
|
||||
const uint OPSubVecXVecX=__LINE__-1; //V1 V1 //V1 // Subtracts a VecX from a VecX component-wise.
|
||||
const uint OPSubVec1VecX=__LINE__-1; //V1 VX //VX // Subtracts a VecX from a Vec1 component-wise.
|
||||
const uint OPSubVecXVec1=__LINE__-1; //VX V1 //VX // Subtracts a Vec1 from a VecX component-wise.
|
||||
const uint OPMulVecXVecX=__LINE__-1; //V1 V1 //V1 // Multiplies a VecX and a VecX component-wise.
|
||||
const uint OPMulVec1VecX=__LINE__-1; //V1 VX //VX // Multiplies a Vec1 and a VecX component-wise.
|
||||
const uint OPMulVecXVec1=__LINE__-1; //VX V1 //VX // Multiplies a VecX and a Vec1 component-wise.
|
||||
const uint OPDivVecXVecX=__LINE__-1; //V1 V1 //V1 // Divides a VecX by a VecX component-wise.
|
||||
const uint OPDivVec1VecX=__LINE__-1; //V1 VX //VX // Divides a Vec1 by a VecX component-wise.
|
||||
const uint OPDivVecXVec1=__LINE__-1; //VX V1 //VX // Divides a VecX by a Vec1 component-wise.
|
||||
const uint OPModVecXVecX=__LINE__-1; //V1 V1 //V1 // Calculates a VecX modulo a VecX component-wise.
|
||||
const uint OPModVec1VecX=__LINE__-1; //V1 VX //VX // Calculates a Vec1 modulo a VecX component-wise.
|
||||
const uint OPModVecXVec1=__LINE__-1; //VX V1 //VX // Calculates a VecX modulo a Vec1 component-wise.
|
||||
const uint OPRemVecXVecX=__LINE__-1; //V1 V1 //V1 // Calculates a VecX remainder a VecX component-wise.
|
||||
const uint OPRemVec1VecX=__LINE__-1; //V1 VX //VX // Calculates a Vec1 remainder a VecX component-wise.
|
||||
const uint OPRemVecXVec1=__LINE__-1; //VX V1 //VX // Calculates a VecX remainder a Vec1 component-wise.
|
||||
const uint OPPowVecXVecX=__LINE__-1; //V1 V1 //V1 // Calculates a VecX to the power of a VecX component-wise.
|
||||
const uint OPPowVec1VecX=__LINE__-1; //V1 VX //VX // Calculates a Vec1 to the power of a VecX component-wise.
|
||||
const uint OPPowVecXVec1=__LINE__-1; //VX V1 //VX // Calculates a VecX to the power of a Vec1 component-wise.
|
||||
const uint OPAtan2VecXVecX=__LINE__-1; //V1 V1 //V1 // Calculates a VecX Atan2 a VecX component-wise.
|
||||
const uint OPAtan2Vec1VecX=__LINE__-1; //V1 VX //VX // Calculates a Vec1 Atan2 a VecX component-wise.
|
||||
const uint OPAtan2VecXVec1=__LINE__-1; //VX V1 //VX // Calculates a VecX Atan2 a Vec1 component-wise.
|
||||
const uint OPMinVecXVecX=__LINE__-1; //V1 V1 //V1 // Calculates the minimum of a VecX and a VecX component-wise.
|
||||
const uint OPMinVec1VecX=__LINE__-1; //V1 VX //VX // Calculates the minimum of a Vec1 and a VecX component-wise.
|
||||
const uint OPMinVecXVec1=__LINE__-1; //VX V1 //VX // Calculates the minimum of a VecX and a Vec1 component-wise.
|
||||
const uint OPMinMaterialVec1Vec1=__LINE__-1; //V1 V1 //V1 // Calculates the minimum of two Vec1s, and also carries over the relevant material metadata.
|
||||
const uint OPMaxVecXVecX=__LINE__-1; //V1 V1 //V1 // Calculates the maximum of a VecX and a VecX component-wise.
|
||||
const uint OPMaxVec1VecX=__LINE__-1; //V1 VX //VX // Calculates the maximum of a Vec1 and a VecX component-wise.
|
||||
const uint OPMaxVecXVec1=__LINE__-1; //VX V1 //VX // Calculates the maximum of a VecX and a Vec1 component-wise.
|
||||
const uint OPMaxMaterialVec1Vec1=__LINE__-1; //V1 V1 //V1 // Calculates the maximum of two Vec1s, and also carries over the relevant material metadata.
|
||||
const uint OPCrossVec3Vec3=__LINE__-1; //V3 V3 //V3 // Returns the cross product of two Vec3s.
|
||||
const uint OPDotVecXVecX=__LINE__-1; //VX VX //V1 // Returns the dot product of two VecXs.
|
||||
const uint OPLengthVecX=__LINE__-1; //VX //V1 // Returns the length (magnitude) of a VecX.
|
||||
const uint OPDistanceVecXVecX=__LINE__-1; //VX VX //V1 // Returns the length (magnitude) of the vector between two VecXs.
|
||||
const uint OPNormalizeVecX=__LINE__-1; //VX //VX // Returns the normalised version of a VecX.
|
||||
const uint OPFaceForwardVecXVecX=__LINE__-1; //VX VX //VX // See GLSL's "FaceForward"
|
||||
const uint OPReflectVecXVecX=__LINE__-1; //VX VX //VX // See GLSL's "Reflect"
|
||||
const uint OPRefractVecXVecXVec1=__LINE__-1; //VX VX V1 //VX // See GLSL's "Refract"
|
||||
const uint OPMulVecXMatX1=__LINE__-1; //VX MX1 //VX // Multiplies an X long vector by an X by 1 sized matrix, returning an X long vector.
|
||||
const uint OPMulVecXMatX2=__LINE__-1; //VX MX2 //VX // Multiplies an X long vector by an X by 2 sized matrix, returning an X long vector.
|
||||
const uint OPMulVecXMatX3=__LINE__-1; //VX MX3 //VX // Multiplies an X long vector by an X by 3 sized matrix, returning an X long vector.
|
||||
const uint OPMulVecXMatX4=__LINE__-1; //VX MX4 //VX // Multiplies an X long vector by an X by 4 sized matrix, returning an X long vector.
|
||||
const uint OPNegateVecX=__LINE__-1; //VX //VX // Returns the negation of all components of a VecX.
|
||||
const uint OPRoundVecX=__LINE__-1; //VX //VX // Returns all components of a VecX rounded to the nearest integer.
|
||||
const uint OPRoundEvenVecX=__LINE__-1; //VX //VX // Returns all components of a VecX rounded to the nearest even integer.
|
||||
const uint OPTruncVecX=__LINE__-1; //VX //VX // Returns all components of a VecX rounded towards zero.
|
||||
const uint OPAbsVecX=__LINE__-1; //VX //VX // Returns the absolute value of all components of a VecX.
|
||||
const uint OPSignVecX=__LINE__-1; //VX //VX // Returns the sign of all components of a VecX.
|
||||
const uint OPFloorVecX=__LINE__-1; //VX //VX // Returns the floor of all components of a VecX.
|
||||
const uint OPCeilVecX=__LINE__-1; //VX //VX // Returns the ceiling of all components of a VecX.
|
||||
const uint OPFractVecX=__LINE__-1; //VX //VX // Returns the fractional part of all components of a VecX.
|
||||
const uint OPRadiansVecX=__LINE__-1; //VX //VX // Converts all components of a VecX from degrees to radians.
|
||||
const uint OPDegreesVecX=__LINE__-1; //VX //VX // Converts all components of a VecX from radians to degrees.
|
||||
const uint OPSinVecX=__LINE__-1; //VX //VX // Returns the sine of all components of a VecX.
|
||||
const uint OPCosVecX=__LINE__-1; //VX //VX // Returns the cosine of all components of a VecX.
|
||||
const uint OPTanVecX=__LINE__-1; //VX //VX // Returns the tangent of all components of a VecX.
|
||||
const uint OPAsinVecX=__LINE__-1; //VX //VX // Returns the arc sine of all components of a VecX.
|
||||
const uint OPAcosVecX=__LINE__-1; //VX //VX // Returns the arc cosine of all components of a VecX.
|
||||
const uint OPAtanVecX=__LINE__-1; //VX //VX // Returns the arc tangent of all components of a VecX.
|
||||
const uint OPSinhVecX=__LINE__-1; //VX //VX // Returns the hyperbolic sine of all components of a VecX.
|
||||
const uint OPCoshVecX=__LINE__-1; //VX //VX // Returns the hyperbolic cosine of all components of a VecX.
|
||||
const uint OPTanhVecX=__LINE__-1; //VX //VX // Returns the hyperbolic tangent of all components of a VecX.
|
||||
const uint OPAsinhVecX=__LINE__-1; //VX //VX // Returns the hyperbolic arc sine of all components of a VecX.
|
||||
const uint OPAcoshVecX=__LINE__-1; //VX //VX // Returns the hyperbolic arc cosine of all components of a VecX.
|
||||
const uint OPAtanhVecX=__LINE__-1; //VX //VX // Returns the hyperbolic arc tangent of all components of a VecX.
|
||||
const uint OPExpVecX=__LINE__-1; //VX //VX // Returns e raised to all components of a VecX.
|
||||
const uint OPLogVecX=__LINE__-1; //VX //VX // Returns the natural logarithm of all components of a VecX.
|
||||
const uint OPExp2VecX=__LINE__-1; //VX //VX // Returns 2 raised to all components of a VecX.
|
||||
const uint OPLog2VecX=__LINE__-1; //VX //VX // Returns the base 2 logarithm of all components of a VecX.
|
||||
const uint OPSqrtVecX=__LINE__-1; //VX //VX // Returns the square root of all components of a VecX.
|
||||
const uint OPInverseSqrtVecX=__LINE__-1; //VX //VX // Returns one over the square root of all components of a VecX.
|
||||
const uint OPSquareVecX=__LINE__-1; //VX //VX // Returns the square of all components of a VecX.
|
||||
const uint OPCubeVecX=__LINE__-1; //VX //VX // Returns the cube of all components of a VecX.
|
||||
const uint OPSmoothMinVecXVecXVecX=__LINE__-1; //VX VX VX //VX // Returns the smooth minimum between a VecX and a VecX, varied by a VecX.
|
||||
const uint OPSmoothMinVecXVecXVec1=__LINE__-1; //VX VX V1 //VX // Returns the smooth minimum between a VecX and a VecX, varied by a Vec1.
|
||||
const uint OPSmoothMinVecXVec1VecX=__LINE__-1; //VX V1 VX //VX // Returns the smooth minimum between a VecX and a Vec1, varied by a VecX.
|
||||
const uint OPSmoothMinVecXVec1Vec1=__LINE__-1; //VX V1 V1 //VX // Returns the smooth minimum between a VecX and a Vec1, varied by a Vec1.
|
||||
const uint OPSmoothMinVec1VecXVecX=__LINE__-1; //V1 VX VX //VX // Returns the smooth minimum between a Vec1 and a VecX, varied by a VecX.
|
||||
const uint OPSmoothMinVec1VecXVec1=__LINE__-1; //V1 VX V1 //VX // Returns the smooth minimum between a Vec1 and a VecX, varied by a Vec1.
|
||||
const uint OPSmoothMinVec1Vec1VecX=__LINE__-1; //V1 V1 VX //VX // Returns the smooth minimum between a Vec1 and a Vec1, varied by a VecX.
|
||||
const uint OPSmoothMaxVecXVecXVecX=__LINE__-1; //VX VX VX //VX // Returns the smooth maximum between a VecX and a VecX, varied by a VecX.
|
||||
const uint OPSmoothMaxVecXVecXVec1=__LINE__-1; //VX VX V1 //VX // Returns the smooth maximum between a VecX and a VecX, varied by a Vec1.
|
||||
const uint OPSmoothMaxVecXVec1VecX=__LINE__-1; //VX V1 VX //VX // Returns the smooth maximum between a VecX and a Vec1, varied by a VecX.
|
||||
const uint OPSmoothMaxVecXVec1Vec1=__LINE__-1; //VX V1 V1 //VX // Returns the smooth maximum between a VecX and a Vec1, varied by a Vec1.
|
||||
const uint OPSmoothMaxVec1VecXVecX=__LINE__-1; //V1 VX VX //VX // Returns the smooth maximum between a Vec1 and a VecX, varied by a VecX.
|
||||
const uint OPSmoothMaxVec1VecXVec1=__LINE__-1; //V1 VX V1 //VX // Returns the smooth maximum between a Vec1 and a VecX, varied by a Vec1.
|
||||
const uint OPSmoothMaxVec1Vec1VecX=__LINE__-1; //V1 V1 VX //VX // Returns the smooth maximum between a Vec1 and a Vec1, varied by a VecX.
|
||||
const uint OPSmoothMinMaterialVec1=__LINE__-1; //V1 V1 V1 //V1 // Returns the smooth minimum between a Vec1 and a Vec1, varied by a Vec1, and also carries over the relevant material metadata.
|
||||
const uint OPSmoothMaxMaterialVec1=__LINE__-1; //V1 V1 V1 //V1 // Returns the smooth maximum between a Vec1 and a Vec1, varied by a Vec1, and also carries over the relevant material metadata.
|
||||
const uint OPClampVecXVecXVecX=__LINE__-1; //VX VX VX //VX // Clamps a VecX between a VecX and a VecX.
|
||||
const uint OPClampVecXVecXVec1=__LINE__-1; //VX VX V1 //VX // Clamps a VecX between a VecX and a Vec1.
|
||||
const uint OPClampVecXVec1VecX=__LINE__-1; //VX V1 VX //VX // Clamps a VecX between a Vec1 and a VecX.
|
||||
const uint OPClampVecXVec1Vec1=__LINE__-1; //VX V1 V1 //VX // Clamps a VecX between a Vec1 and a Vec1.
|
||||
const uint OPClampVec1VecXVecX=__LINE__-1; //V1 VX VX //VX // Clamps a Vec1 between a VecX and a VecX.
|
||||
const uint OPClampVec1VecXVec1=__LINE__-1; //V1 VX V1 //VX // Clamps a Vec1 between a VecX and a Vec1.
|
||||
const uint OPClampVec1Vec1VecX=__LINE__-1; //V1 V1 VX //VX // Clamps a Vec1 between a Vec1 and a VecX.
|
||||
const uint OPMixVecXVecXVecX=__LINE__-1; //VX VX VX //VX // Mixes between a VecX and a VecX, varied by a VecX.
|
||||
const uint OPMixVecXVecXVec1=__LINE__-1; //VX VX V1 //VX // Mixes between a VecX and a VecX, varied by a Vec1.
|
||||
const uint OPMixVecXVec1VecX=__LINE__-1; //VX V1 VX //VX // Mixes between a VecX and a Vec1, varied by a VecX.
|
||||
const uint OPMixVecXVec1Vec1=__LINE__-1; //VX V1 V1 //VX // Mixes between a VecX and a Vec1, varied by a Vec1.
|
||||
const uint OPMixVec1VecXVecX=__LINE__-1; //V1 VX VX //VX // Mixes between a Vec1 and a VecX, varied by a VecX.
|
||||
const uint OPMixVec1VecXVec1=__LINE__-1; //V1 VX V1 //VX // Mixes between a Vec1 and a VecX, varied by a Vec1.
|
||||
const uint OPMixVec1Vec1VecX=__LINE__-1; //V1 V1 VX //VX // Mixes between a Vec1 and a Vec1, varied by a VecX.
|
||||
const uint OPStepVecXVecXVecX=__LINE__-1; //VX VX VX //VX // Steps between a VecX and a VecX, varied by a VecX.
|
||||
const uint OPStepVecXVecXVec1=__LINE__-1; //VX VX V1 //VX // Steps between a VecX and a VecX, varied by a Vec1.
|
||||
const uint OPStepVecXVec1VecX=__LINE__-1; //VX V1 VX //VX // Steps between a VecX and a Vec1, varied by a VecX.
|
||||
const uint OPStepVecXVec1Vec1=__LINE__-1; //VX V1 V1 //VX // Steps between a VecX and a Vec1, varied by a Vec1.
|
||||
const uint OPStepVec1VecXVecX=__LINE__-1; //V1 VX VX //VX // Steps between a Vec1 and a VecX, varied by a VecX.
|
||||
const uint OPStepVec1VecXVec1=__LINE__-1; //V1 VX V1 //VX // Steps between a Vec1 and a VecX, varied by a Vec1.
|
||||
const uint OPStepVec1Vec1VecX=__LINE__-1; //V1 V1 VX //VX // Steps between a Vec1 and a Vec1, varied by a VecX.
|
||||
const uint OPSmoothStepVecXVecXVecX=__LINE__-1; //VX VX VX //VX // Smooth Steps between a VecX and a VecX, varied by a VecX.
|
||||
const uint OPSmoothStepVecXVecXVec1=__LINE__-1; //VX VX V1 //VX // Smooth Steps between a VecX and a VecX, varied by a Vec1.
|
||||
const uint OPSmoothStepVecXVec1VecX=__LINE__-1; //VX V1 VX //VX // Smooth Steps between a VecX and a Vec1, varied by a VecX.
|
||||
const uint OPSmoothStepVecXVec1Vec1=__LINE__-1; //VX V1 V1 //VX // Smooth Steps between a VecX and a Vec1, varied by a Vec1.
|
||||
const uint OPSmoothStepVec1VecXVecX=__LINE__-1; //V1 VX VX //VX // Smooth Steps between a Vec1 and a VecX, varied by a VecX.
|
||||
const uint OPSmoothStepVec1VecXVec1=__LINE__-1; //V1 VX V1 //VX // Smooth Steps between a Vec1 and a VecX, varied by a Vec1.
|
||||
const uint OPSmoothStepVec1Vec1VecX=__LINE__-1; //V1 V1 VX //VX // Smooth Steps between a Vec1 and a Vec1, varied by a VecX.
|
||||
const uint OPFMAVecXVecXVecX=__LINE__-1; //VX VX VX //VX // Calculates a VecX multiplied by a VecX, then adds a VecX.
|
||||
const uint OPFMAVecXVecXVec1=__LINE__-1; //VX VX V1 //VX // Calculates a VecX multiplied by a VecX, then adds a Vec1.
|
||||
const uint OPFMAVecXVec1VecX=__LINE__-1; //VX V1 VX //VX // Calculates a VecX multiplied by a Vec1, then adds a VecX.
|
||||
const uint OPFMAVecXVec1Vec1=__LINE__-1; //VX V1 V1 //VX // Calculates a VecX multiplied by a Vec1, then adds a Vec1.
|
||||
const uint OPFMAVec1VecXVecX=__LINE__-1; //V1 VX VX //VX // Calculates a Vec1 multiplied by a VecX, then adds a VecX.
|
||||
const uint OPFMAVec1VecXVec1=__LINE__-1; //V1 VX V1 //VX // Calculates a Vec1 multiplied by a VecX, then adds a Vec1.
|
||||
const uint OPFMAVec1Vec1VecX=__LINE__-1; //V1 V1 VX //VX // Calculates a Vec1 multiplied by a Vec1, then adds a VecX.
|
||||
const uint OPSDFSphere=__LINE__-1; //V3 V1 //V1 // Returns the distance to a sphere.
|
||||
const uint OPSDFBox=__LINE__-1; //V3 V3 //V1 // Returns the distance to a box.
|
||||
const uint OPSDFTorus=__LINE__-1; //V3 V2 //V1 // Returns the distance to a torus.
|
||||
const uint OPInvalid=__LINE__-1; // // // Invalid instruction.
|
||||
const uint OPCopy =0; // Returns the input. Useful for copying registers.
|
||||
const uint OPAdd =1; // Adds a vector to a vector component-wise.
|
||||
const uint OPSub =2; // Subtracts a vector from a vector component-wise.
|
||||
const uint OPMul =3; // Multiplies a vector and a vector component-wise.
|
||||
const uint OPDiv =4; // Divides a vector by a vector component-wise.
|
||||
const uint OPMod =5; // Calculates a vector modulo a vector component-wise.
|
||||
const uint OPRem =6; // Calculates a vector remainder a vector component-wise.
|
||||
const uint OPPow =7; // Calculates a vector to the power of a vector component-wise.
|
||||
const uint OPAtan2 =8; // Calculates a vector Atan2 a vector component-wise.
|
||||
const uint OPMin =9; // Calculates the minimum of a vector and a vector component-wise.
|
||||
const uint OPMax =10; // Calculates the maximum of a vector and a vector component-wise.
|
||||
const uint OPNegate =11; // Returns the negation of all components of a vector.
|
||||
const uint OPRound =12; // Returns all components of a vector rounded to the nearest integer.
|
||||
const uint OPRoundEven =13; // Returns all components of a vector rounded to the nearest even integer.
|
||||
const uint OPTrunc =14; // Returns all components of a vector rounded towards zero.
|
||||
const uint OPAbs =15; // Returns the absolute value of all components of a vector.
|
||||
const uint OPSign =16; // Returns the sign of all components of a vector.
|
||||
const uint OPFloor =17; // Returns the floor of all components of a vector.
|
||||
const uint OPCeil =18; // Returns the ceiling of all components of a vector.
|
||||
const uint OPFract =19; // Returns the fractional part of all components of a vector.
|
||||
const uint OPSin =20; // Returns the sine of all components of a vector.
|
||||
const uint OPCos =21; // Returns the cosine of all components of a vector.
|
||||
const uint OPTan =22; // Returns the tangent of all components of a vector.
|
||||
const uint OPAsin =23; // Returns the arc sine of all components of a vector.
|
||||
const uint OPAcos =24; // Returns the arc cosine of all components of a vector.
|
||||
const uint OPAtan =25; // Returns the arc tangent of all components of a vector.
|
||||
const uint OPSinh =26; // Returns the hyperbolic sine of all components of a vector.
|
||||
const uint OPCosh =27; // Returns the hyperbolic cosine of all components of a vector.
|
||||
const uint OPTanh =28; // Returns the hyperbolic tangent of all components of a vector.
|
||||
const uint OPAsinh =29; // Returns the hyperbolic arc sine of all components of a vector.
|
||||
const uint OPAcosh =30; // Returns the hyperbolic arc cosine of all components of a vector.
|
||||
const uint OPAtanh =31; // Returns the hyperbolic arc tangent of all components of a vector.
|
||||
const uint OPExp =32; // Returns e raised to all components of a vector.
|
||||
const uint OPLog =33; // Returns the natural logarithm of all components of a vector.
|
||||
const uint OPExp2 =34; // Returns 2 raised to all components of a vector.
|
||||
const uint OPLog2 =35; // Returns the base 2 logarithm of all components of a vector.
|
||||
const uint OPSqrt =36; // Returns the square root of all components of a vector.
|
||||
const uint OPInverseSqrt =37; // Returns one over the square root of all components of a vector.
|
||||
const uint OPSquare =38; // Returns the square of all components of a vector.
|
||||
const uint OPCube =39; // Returns the cube of all components of a vector.
|
||||
const uint OPSmoothMin =40; // Returns the smooth minimum between a vector and a vector, varied by a vector.
|
||||
const uint OPSmoothMax =41; // Returns the smooth maximum between a vector and a vector, varied by a vector.
|
||||
const uint OPClamp =42; // Clamps a vector between a vector and a vector.
|
||||
const uint OPMix =43; // Mixes between a vector and a vector, varied by a vector.
|
||||
const uint OPStep =44; // Steps between a vector and a vector, varied by a vector.
|
||||
const uint OPSmoothStep =45; // Smooth Steps between a vector and a vector, varied by a vector.
|
||||
const uint OPFMA =46; // Calculates a vector multiplied by a vector, then adds a vector.
|
||||
const uint OPDot =47; // Returns the dot product of two vectors.
|
||||
const uint OPLength =48; // Returns the length (magnitude) of a vector.
|
||||
const uint OPDistance =49; // Returns the length (magnitude) of the vector between two vectors.
|
||||
const uint OPNormalize =50; // Returns the normalised version of a vector.
|
||||
|
||||
const uint OPNop =(0*64)+63; // No operation.
|
||||
const uint OPStop =(1*64)+63; // Stops execution of the tape and returns 0.
|
||||
const uint OPReturn =(2*64)+63; // Stops execution of the tape and returns a single value.
|
||||
const uint OPPosition =(3*64)+63; // Returns the current position being sampled.
|
||||
const uint OPMinMaterial =(0*64)+62; // Calculates the minimum of two Vec1s, and also carries over the relevant material metadata.
|
||||
const uint OPMaxMaterial =(1*64)+62; // Calculates the maximum of two Vec1s, and also carries over the relevant material metadata.
|
||||
const uint OPSmoothMinMaterial =(2*64)+62; // Returns the smooth minimum between a Vec1 and a Vec1, varied by a Vec1, and also carries over the relevant material metadata.
|
||||
const uint OPSmoothMaxMaterial =(3*64)+62; // Returns the smooth maximum between a Vec1 and a Vec1, varied by a Vec1, and also carries over the relevant material metadata.
|
||||
const uint OPCross =(0*64)+61; // Returns the cross product of two Vec3s.
|
||||
const uint OPSDFSphere =(1*64)+61; // Returns the distance to a sphere.
|
||||
const uint OPSDFBox =(2*64)+61; // Returns the distance to a box.
|
||||
const uint OPSDFTorus =(3*64)+61; // Returns the distance to a torus.
|
||||
+8
-30
@@ -3,20 +3,18 @@ Ground up redesign of the interpreter
|
||||
|
||||
Maximum mesh shaders at once is 32*32*2, or 2048. For 65,536 vgprs, each mesh shader can only use 32.
|
||||
|
||||
Instead of a stack, use SSA and then limited registers (16?). This is a bit more compile friendly.
|
||||
Instead of a stack, use SSA and then limited registers . This is a bit more compile friendly.
|
||||
|
||||
There are 16 available registers. Register 0 is always 0, and register 16 is the next item in the const tape.
|
||||
There are 16 available registers. Register 0 is always 0, and register 15 is the next item in the const tape.
|
||||
This leaves 14 usable 32 bit float registers.
|
||||
|
||||
Vectors are constructed starting at the input variable and counting up - e.g. a the vec3 at 5 is made from vec3(5, 6, 7);
|
||||
|
||||
Instruction format:
|
||||
32 bits
|
||||
8 bits
|
||||
|
||||
First 16 bits encode four 4 bit registers that are used as inputs. Next 4 bits are output register.
|
||||
1 bit encodes if the instruction works up or down.
|
||||
3 bits encode the length of the VecX type, where 0 means Vec1 and 7 means Vec8.
|
||||
This leaves 8 bits to encode an opcode, for 256 possible opcodes.
|
||||
If the lowest 6 bits are below 47, the top two bits are length of the VecX type, where 0 means Vec1 and 3 means Vec4.
|
||||
Otherwise, all 8 bits encode an instruction.
|
||||
|
||||
Each following 8 bits encode two 4 bit registers that are registers. All inputs are listed, then all outputs. It is padded to 8 bits with zeros.
|
||||
|
||||
Each SDF can have up to 8 materials associated with it. The relative weight of each material is tracked through the interpreter as an
|
||||
array of 8 floats, and at the end they are evaluated once.
|
||||
@@ -74,8 +72,6 @@ For a mesh that takes up 1024x1024 pixel on screen, each quad takes up 16x16 pix
|
||||
- floor
|
||||
- ceil
|
||||
- fract
|
||||
- radians
|
||||
- degrees
|
||||
- sin
|
||||
- cos
|
||||
- tan
|
||||
@@ -106,23 +102,9 @@ For a mesh that takes up 1024x1024 pixel on screen, each quad takes up 16x16 pix
|
||||
- LengthVecX (returns vec1)
|
||||
- DistanceVecX (returns vec1)
|
||||
- NormaliseVecX (returns vec1)
|
||||
- FaceForwardVecX (returns vecx)
|
||||
- ReflectVecX (returns vecx)
|
||||
- RefractVecX (returns vecx)
|
||||
## Data manipulation
|
||||
### Instructions
|
||||
- CopyVecX
|
||||
- PromoteVec1Vec1Vec2
|
||||
- PromoteVec1Vec1Vec1Vec3
|
||||
- PromoteVec1Vec1Vec1Vec1Vec4
|
||||
- PromoteVec2Vec1Vec3
|
||||
- PromoteVec1Vec2Vec3
|
||||
- PromoteVec2Vec1Vec1Vec4
|
||||
- PromoteVec1Vec2Vec1Vec4
|
||||
- PromoteVec1Vec1Vec2Vec4
|
||||
- PromoteVec2Vec2Vec4
|
||||
- PromoteVec3Vec1Vec4
|
||||
- PromoteVec1Vec3Vec4
|
||||
## SDF
|
||||
- SDFSphere
|
||||
- SDFBox
|
||||
@@ -130,8 +112,4 @@ For a mesh that takes up 1024x1024 pixel on screen, each quad takes up 16x16 pix
|
||||
## Extra
|
||||
- Stop
|
||||
- Nop
|
||||
- Position
|
||||
|
||||
# Possible extra instructions
|
||||
- Vector extract/insert dynamic?
|
||||
- OpVectorShuffle
|
||||
- Position
|
||||
+3
-254
@@ -87,6 +87,8 @@ mod objects;
|
||||
use crate::objects::*;
|
||||
mod mcsg_deserialise;
|
||||
|
||||
mod ssa;
|
||||
|
||||
mod instruction_set {
|
||||
include!(concat!(env!("OUT_DIR"), "/instructionset.rs"));
|
||||
}
|
||||
@@ -1805,260 +1807,7 @@ fn object_size_dependent_setup(
|
||||
let mut desc: Vec<Description> = vec![Default::default()];
|
||||
|
||||
'nextcsg: for csg in state {
|
||||
let mut data: Vec<[u32; 4]> = vec![];
|
||||
|
||||
let to_push = [
|
||||
scene.len() as u32,
|
||||
floats.len() as u32,
|
||||
vec2s.len() as u32,
|
||||
vec4s.len() as u32,
|
||||
mat2s.len() as u32,
|
||||
mat3s.len() as u32,
|
||||
mat4s.len() as u32,
|
||||
mats.len() as u32,
|
||||
deps.len() as u32,
|
||||
];
|
||||
|
||||
let example = vec![
|
||||
CSGPart::opcode(
|
||||
InstructionSet::OPMulVec3Float,
|
||||
vec![Inputs::Variable, Inputs::Float(0.9)],
|
||||
),
|
||||
CSGPart::opcode(InstructionSet::OPDupVec3, vec![Inputs::Variable]),
|
||||
CSGPart::opcode(
|
||||
InstructionSet::OPAddVec3Vec3,
|
||||
vec![Inputs::Variable, Inputs::Vec3([-0.7, -1.2, -0.7].into())],
|
||||
),
|
||||
CSGPart::opcode(
|
||||
InstructionSet::OPSDFSphere,
|
||||
vec![Inputs::Float(0.5), Inputs::Variable],
|
||||
),
|
||||
//CSGPart::opcode(InstructionSet::OPNop,vec![]),
|
||||
//CSGPart::opcode(InstructionSet::OPDupVec3, vec![Inputs::Variable]),
|
||||
//CSGPart::opcode(InstructionSet::OPAddVec3Vec3, vec![Inputs::Variable,
|
||||
// Inputs::Vec3([-0.2, -0.2, -0.2].into())]),
|
||||
// CSGPart::opcode(InstructionSet::OPAddVec3Vec3, vec![Inputs::Variable,
|
||||
// Inputs::Vec3([-0.0, -0.0, -0.0].into())]),
|
||||
// CSGPart::opcode(InstructionSet::OPSDFSphere,vec![Inputs::Float(1.2),
|
||||
// Inputs::Variable]),
|
||||
CSGPart::opcode(
|
||||
InstructionSet::OPSDFTorus,
|
||||
vec![Inputs::Vec2([0.7, 0.4].into()), Inputs::Variable],
|
||||
),
|
||||
//CSGPart::opcode(InstructionSet::OPSDFBox, vec![Inputs::Vec3([0.7, 0.4, 0.7].into()),
|
||||
// Inputs::Variable]),
|
||||
CSGPart::opcode(
|
||||
InstructionSet::OPMinFloat,
|
||||
vec![Inputs::Variable, Inputs::Variable],
|
||||
),
|
||||
CSGPart::opcode(
|
||||
InstructionSet::OPDivFloatFloat,
|
||||
vec![Inputs::Variable, Inputs::Float(0.9)],
|
||||
),
|
||||
CSGPart::opcode(InstructionSet::OPStop, vec![Inputs::Variable]),
|
||||
];
|
||||
|
||||
let parts = if actual { &csg.parts } else { &example };
|
||||
|
||||
let mut dependencies: Vec<[u8; 2]> = vec![];
|
||||
for _ in 0..parts.len() {
|
||||
dependencies.push([u8::MAX, u8::MAX]);
|
||||
}
|
||||
|
||||
let mut runtime_floats: Vec<usize> = vec![];
|
||||
let mut runtime_vec2s: Vec<usize> = vec![];
|
||||
let mut runtime_vec3s: Vec<usize> = vec![usize::MAX];
|
||||
let mut runtime_vec4s: Vec<usize> = vec![];
|
||||
let mut runtime_mat2s: Vec<usize> = vec![];
|
||||
let mut runtime_mat3s: Vec<usize> = vec![];
|
||||
let mut runtime_mat4s: Vec<usize> = vec![];
|
||||
|
||||
for (index, part) in parts.iter().enumerate() {
|
||||
let inputs = part.opcode.input();
|
||||
for (expected, actual) in inputs.iter().zip(part.constants.iter()) {
|
||||
if actual != expected {
|
||||
error!(
|
||||
"csg {} is invalid ({:?} != {:?})",
|
||||
csg.name, actual, expected
|
||||
);
|
||||
continue 'nextcsg;
|
||||
}
|
||||
if actual == &Inputs::Variable {
|
||||
match *expected {
|
||||
InputTypes::Float => match runtime_floats.pop() {
|
||||
Some(u) => {
|
||||
if dependencies[u][0] != u8::MAX {
|
||||
dependencies[u][1] = index as u8
|
||||
} else {
|
||||
dependencies[u][0] = index as u8
|
||||
}
|
||||
},
|
||||
None => {
|
||||
error!("csg {} underflowed on floats", csg.name);
|
||||
continue 'nextcsg;
|
||||
},
|
||||
},
|
||||
InputTypes::Vec2 => match runtime_vec2s.pop() {
|
||||
Some(u) => {
|
||||
if dependencies[u][0] != u8::MAX {
|
||||
dependencies[u][1] = index as u8
|
||||
} else {
|
||||
dependencies[u][0] = index as u8
|
||||
}
|
||||
},
|
||||
None => {
|
||||
error!("csg {} underflowed on vec2s", csg.name);
|
||||
continue 'nextcsg;
|
||||
},
|
||||
},
|
||||
InputTypes::Vec3 => match runtime_vec3s.pop() {
|
||||
Some(u) => {
|
||||
if u != usize::MAX {
|
||||
if dependencies[u][0] != u8::MAX {
|
||||
dependencies[u][1] = index as u8
|
||||
} else {
|
||||
dependencies[u][0] = index as u8
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
error!("csg {} underflowed on vec3s", csg.name);
|
||||
continue 'nextcsg;
|
||||
},
|
||||
},
|
||||
InputTypes::Vec4 => match runtime_vec4s.pop() {
|
||||
Some(u) => {
|
||||
if dependencies[u][0] != u8::MAX {
|
||||
dependencies[u][1] = index as u8
|
||||
} else {
|
||||
dependencies[u][0] = index as u8
|
||||
}
|
||||
},
|
||||
None => {
|
||||
error!("csg {} underflowed on vec4s", csg.name);
|
||||
continue 'nextcsg;
|
||||
},
|
||||
},
|
||||
InputTypes::Mat2 => match runtime_mat2s.pop() {
|
||||
Some(u) => {
|
||||
if dependencies[u][0] != u8::MAX {
|
||||
dependencies[u][1] = index as u8
|
||||
} else {
|
||||
dependencies[u][0] = index as u8
|
||||
}
|
||||
},
|
||||
None => {
|
||||
error!("csg {} underflowed on mat2s", csg.name);
|
||||
continue 'nextcsg;
|
||||
},
|
||||
},
|
||||
InputTypes::Mat3 => match runtime_mat3s.pop() {
|
||||
Some(u) => {
|
||||
if dependencies[u][0] != u8::MAX {
|
||||
dependencies[u][1] = index as u8
|
||||
} else {
|
||||
dependencies[u][0] = index as u8
|
||||
}
|
||||
},
|
||||
None => {
|
||||
error!("csg {} underflowed on mat3s", csg.name);
|
||||
continue 'nextcsg;
|
||||
},
|
||||
},
|
||||
InputTypes::Mat4 => match runtime_mat4s.pop() {
|
||||
Some(u) => {
|
||||
if dependencies[u][0] != u8::MAX {
|
||||
dependencies[u][1] = index as u8
|
||||
} else {
|
||||
dependencies[u][0] = index as u8
|
||||
}
|
||||
},
|
||||
None => {
|
||||
error!("csg {} underflowed on mat4s", csg.name);
|
||||
continue 'nextcsg;
|
||||
},
|
||||
},
|
||||
}
|
||||
} else {
|
||||
match *actual {
|
||||
Inputs::Float(f) => floats.push(f),
|
||||
Inputs::Vec2(f) => vec2s.push(f.map(|x| x).into()),
|
||||
Inputs::Vec3(f) => vec4s.push(f.map(|x| x).extend(1.).into()),
|
||||
Inputs::Vec4(f) => vec4s.push(f.map(|x| x).into()),
|
||||
Inputs::Mat2(f) => mat2s.push(f.to_cols_array_2d()),
|
||||
Inputs::Mat3(f) => mat3s.push(f.to_cols_array_2d()),
|
||||
Inputs::Mat4(f) => mat4s.push(f.to_cols_array_2d()),
|
||||
Inputs::Variable => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
let outputs = part.opcode.output();
|
||||
for output in outputs {
|
||||
match output {
|
||||
InputTypes::Float => runtime_floats.push(index),
|
||||
InputTypes::Vec2 => runtime_vec2s.push(index),
|
||||
InputTypes::Vec3 => runtime_vec3s.push(index),
|
||||
InputTypes::Vec4 => runtime_vec4s.push(index),
|
||||
InputTypes::Mat2 => runtime_mat2s.push(index),
|
||||
InputTypes::Mat3 => runtime_mat3s.push(index),
|
||||
InputTypes::Mat4 => runtime_mat4s.push(index),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut lower = true;
|
||||
let mut minor = 0;
|
||||
let mut major = 0;
|
||||
|
||||
for part in parts.iter() {
|
||||
if major == data.len() {
|
||||
data.push([0; 4]);
|
||||
}
|
||||
data[major][minor] |= (part.code as u32) << (if lower { 0 } else { 16 });
|
||||
|
||||
lower = !lower;
|
||||
if lower {
|
||||
minor += 1;
|
||||
if minor == 4 {
|
||||
minor = 0;
|
||||
major += 1;
|
||||
if major == 29 {
|
||||
panic!("CSGParts Too full!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let temp_csg = &CSG {
|
||||
name: "test".to_string(),
|
||||
parts: parts.to_vec(),
|
||||
pos: Vec3::ZERO,
|
||||
rot: Vec3::ZERO,
|
||||
scale: Vec3::ONE,
|
||||
};
|
||||
|
||||
let mut interpreter = interpreter::Interpreter::new(temp_csg);
|
||||
const CLIPCHECK: Float = 65536.;
|
||||
|
||||
let bounds = set_bound.unwrap_or([
|
||||
((CLIPCHECK - interpreter.scene(vec3(CLIPCHECK, 0., 0.))) * 1.00001) as f32,
|
||||
((CLIPCHECK - interpreter.scene(vec3(0., CLIPCHECK, 0.))) * 1.00001) as f32,
|
||||
((CLIPCHECK - interpreter.scene(vec3(0., 0., CLIPCHECK))) * 1.00001) as f32,
|
||||
((-CLIPCHECK + interpreter.scene(vec3(-CLIPCHECK, 0., 0.))) * 1.00001) as f32,
|
||||
((-CLIPCHECK + interpreter.scene(vec3(0., -CLIPCHECK, 0.))) * 1.00001) as f32,
|
||||
((-CLIPCHECK + interpreter.scene(vec3(0., 0., -CLIPCHECK))) * 1.00001) as f32,
|
||||
]);
|
||||
|
||||
//trace!("bounds: {:?}",bounds);
|
||||
|
||||
desc.push(Description {
|
||||
pointers: to_push,
|
||||
bounds,
|
||||
});
|
||||
|
||||
scene.append(&mut data);
|
||||
|
||||
deps.append(&mut dependencies);
|
||||
|
||||
}
|
||||
|
||||
trace!("floats: {floats:?}");
|
||||
|
||||
@@ -1,520 +0,0 @@
|
||||
use std::{
|
||||
fmt::Display,
|
||||
io::{BufReader, Read},
|
||||
str::Chars,
|
||||
};
|
||||
|
||||
use serde::{
|
||||
Deserialize,
|
||||
de::{
|
||||
self, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, SeqAccess, VariantAccess,
|
||||
Visitor,
|
||||
},
|
||||
forward_to_deserialize_any,
|
||||
};
|
||||
use utf8::BufReadDecoder;
|
||||
|
||||
type Result<T> = core::result::Result<T, Error>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum Error {
|
||||
Message(String),
|
||||
UTF8(String),
|
||||
TrailingCharacters,
|
||||
Eof,
|
||||
ExpectedString,
|
||||
Syntax,
|
||||
ExpectedArrayEnd,
|
||||
ExpectedArray,
|
||||
ExpectedMapEnd,
|
||||
ExpectedMap,
|
||||
ExpectedMapColon,
|
||||
ExpectedEnum,
|
||||
}
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Error::Message(msg) | Error::UTF8(msg) => f.write_str(msg),
|
||||
_ => f.write_fmt(format_args!("Error: {self:?}")),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl std::error::Error for Error {}
|
||||
impl serde::de::Error for Error {
|
||||
fn custom<T: Display>(msg: T) -> Self {
|
||||
Error::Message(msg.to_string())
|
||||
}
|
||||
}
|
||||
impl serde::ser::Error for Error {
|
||||
fn custom<T: Display>(msg: T) -> Self {
|
||||
Error::Message(msg.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct Deserializer<'de> {
|
||||
// This string starts with the input data and characters are truncated off
|
||||
// the beginning as data is parsed.
|
||||
input: BufReadDecoder<BufReader<&'de mut dyn Read>>,
|
||||
read_buf: String,
|
||||
peek: Option<(char, usize)>,
|
||||
}
|
||||
|
||||
impl<'de> Deserializer<'de> {
|
||||
// By convention, `Deserializer` constructors are named like `from_xyz`.
|
||||
// That way basic use cases are satisfied by something like
|
||||
// `serde_json::from_str(...)` while advanced use cases that require a
|
||||
// deserializer can make one with `serde_json::Deserializer::from_str(...)`.
|
||||
|
||||
pub(crate) fn from_reader(input: &'de mut dyn Read) -> Self {
|
||||
Deserializer {
|
||||
input: BufReadDecoder::new(BufReader::new(input)),
|
||||
read_buf: String::new(),
|
||||
peek: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// By convention, the pub(crate)lic API of a Serde deserializer is one or more
|
||||
// `from_xyz` methods such as `from_str`, `from_bytes`, or `from_reader`
|
||||
// depending on what Rust types the deserializer is able to consume as input.
|
||||
//
|
||||
// This basic deserializer supports only `from_str`.
|
||||
pub(crate) fn from_reader<'a, T>(s: &'a mut dyn Read) -> Result<T>
|
||||
where
|
||||
T: Deserialize<'a>,
|
||||
{
|
||||
let mut deserializer = Deserializer::from_reader(s);
|
||||
let t = T::deserialize(&mut deserializer)?;
|
||||
if deserializer.check_end() {
|
||||
Ok(t)
|
||||
} else {
|
||||
Err(Error::TrailingCharacters)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_char(mut s: Chars) -> Result<(char, usize)> {
|
||||
let mut count = 0usize;
|
||||
loop {
|
||||
let next = s.next().ok_or(Error::Eof);
|
||||
count += 1;
|
||||
if next.as_ref().is_ok_and(|&c| c.is_whitespace()) {
|
||||
continue;
|
||||
}
|
||||
if next.as_ref().is_ok_and(|this| this == &'/') {
|
||||
if s.next() == Some('/') {
|
||||
while s.next().is_some_and(|s| s != '\n' && s != '\r') {
|
||||
count += 1;
|
||||
}
|
||||
count += 1;
|
||||
}
|
||||
count += 1;
|
||||
} else {
|
||||
return next.map(|c| (c, count));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SERDE IS NOT A PARSING LIBRARY. This impl block defines a few basic parsing
|
||||
// functions from scratch. More complicated formats may wish to use a dedicated
|
||||
// parsing library to help implement their Serde deserializer.
|
||||
impl Deserializer<'_> {
|
||||
fn check_end(&mut self) -> bool {
|
||||
self.input.next_strict().is_none()
|
||||
}
|
||||
|
||||
// Look at the first character in the input without consuming it.
|
||||
fn peek_char(&mut self) -> Result<(char, usize)> {
|
||||
if let Some(p) = self.peek {
|
||||
Ok(p)
|
||||
} else {
|
||||
loop {
|
||||
match get_char(self.read_buf.chars()) {
|
||||
Ok(c) => {
|
||||
self.peek = Some(c);
|
||||
return Ok(c);
|
||||
},
|
||||
Err(Error::Eof) => match self.input.next_strict() {
|
||||
Some(e) => {
|
||||
match e {
|
||||
Ok(s) => {
|
||||
s.clone_into(&mut self.read_buf);
|
||||
},
|
||||
Err(e) => return Err(Error::UTF8(format!("{e}"))),
|
||||
};
|
||||
},
|
||||
None => return Err(Error::Eof),
|
||||
},
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Consume the first character in the input.
|
||||
fn next_char(&mut self) -> Result<char> {
|
||||
let ch = self.peek_char()?;
|
||||
self.read_buf = self.read_buf[ch.1..].to_string();
|
||||
self.peek = None;
|
||||
Ok(ch.0)
|
||||
}
|
||||
|
||||
// Parse a string until the next '"' character.
|
||||
//
|
||||
// Makes no attempt to handle escape sequences. What did you expect? This is
|
||||
// example code!
|
||||
fn parse_string(&mut self) -> Result<String> {
|
||||
if self.next_char()? != '"' {
|
||||
return Err(Error::ExpectedString);
|
||||
}
|
||||
loop {
|
||||
match self.read_buf.find('"') {
|
||||
Some(len) => {
|
||||
let out = self.read_buf[..len].to_string();
|
||||
self.read_buf = self.read_buf[len + 1..].to_string();
|
||||
return Ok(out);
|
||||
},
|
||||
None => match self.input.next_strict() {
|
||||
Some(e) => {
|
||||
match e {
|
||||
Ok(s) => {
|
||||
s.clone_into(&mut self.read_buf);
|
||||
},
|
||||
Err(e) => return Err(Error::UTF8(format!("{e}"))),
|
||||
};
|
||||
},
|
||||
None => return Err(Error::Eof),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> de::Deserializer<'de> for &mut Deserializer<'de> {
|
||||
type Error = Error;
|
||||
|
||||
forward_to_deserialize_any! {
|
||||
bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char bytes byte_buf option unit unit_struct
|
||||
}
|
||||
|
||||
// Look at the input data to decide what Serde data model type to
|
||||
// deserialize as. Not all data formats are able to support this operation.
|
||||
// Formats that support `deserialize_any` are known as self-describing.
|
||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match self.peek_char()?.0 {
|
||||
'"' => self.deserialize_str(visitor),
|
||||
'[' => self.deserialize_seq(visitor),
|
||||
'{' => self.deserialize_map(visitor),
|
||||
_ => Err(Error::Syntax),
|
||||
}
|
||||
}
|
||||
|
||||
// Refer to the "Understanding deserializer lifetimes" page for information
|
||||
// about the three deserialization flavors of strings in Serde.
|
||||
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_string(self.parse_string()?)
|
||||
}
|
||||
|
||||
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.deserialize_string(visitor)
|
||||
}
|
||||
|
||||
// Deserialization of compound types like sequences and maps happens by
|
||||
// passing the visitor an "Access" object that gives it the ability to
|
||||
// iterate through the data contained in the sequence.
|
||||
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
// Parse the opening bracket of the sequence.
|
||||
if self.next_char()? == '[' {
|
||||
// Give the visitor access to each element of the sequence.
|
||||
let value = visitor.visit_seq(CommaSeparated::new(self))?;
|
||||
// Parse the closing bracket of the sequence.
|
||||
if self.next_char()? == ']' {
|
||||
Ok(value)
|
||||
} else {
|
||||
Err(Error::ExpectedArrayEnd)
|
||||
}
|
||||
} else {
|
||||
Err(Error::ExpectedArray)
|
||||
}
|
||||
}
|
||||
|
||||
// Much like `deserialize_seq` but calls the visitors `visit_map` method
|
||||
// with a `MapAccess` implementation, rather than the visitor's `visit_seq`
|
||||
// method with a `SeqAccess` implementation.
|
||||
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
// Parse the opening brace of the map.
|
||||
if self.next_char()? == '{' {
|
||||
// Give the visitor access to each entry of the map.
|
||||
let value = visitor.visit_map(CommaSeparated::new(self))?;
|
||||
// Parse the closing brace of the map.
|
||||
if self.next_char()? == '}' {
|
||||
Ok(value)
|
||||
} else {
|
||||
Err(Error::ExpectedMapEnd)
|
||||
}
|
||||
} else {
|
||||
Err(Error::ExpectedMap)
|
||||
}
|
||||
}
|
||||
|
||||
// Structs look just like maps in JSON.
|
||||
//
|
||||
// Notice the `fields` parameter - a "struct" in the Serde data model means
|
||||
// that the `Deserialize` implementation is required to know what the fields
|
||||
// are before even looking at the input data. Any key-value pairing in which
|
||||
// the fields cannot be known ahead of time is probably a map.
|
||||
fn deserialize_struct<V>(
|
||||
self,
|
||||
_name: &'static str,
|
||||
_fields: &'static [&'static str],
|
||||
visitor: V,
|
||||
) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.deserialize_map(visitor)
|
||||
}
|
||||
|
||||
// An identifier in Serde is the type that identifies a field of a struct or
|
||||
// the variant of an enum. In JSON, struct fields and enum variants are
|
||||
// represented as strings. In other formats they may be represented as
|
||||
// numeric indices.
|
||||
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.deserialize_str(visitor)
|
||||
}
|
||||
|
||||
// Tuples look just like sequences in JSON. Some formats may be able to
|
||||
// represent tuples more efficiently.
|
||||
//
|
||||
// As indicated by the length parameter, the `Deserialize` implementation
|
||||
// for a tuple in the Serde data model is required to know the length of the
|
||||
// tuple before even looking at the input data.
|
||||
fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.deserialize_seq(visitor)
|
||||
}
|
||||
|
||||
// Tuple structs look just like sequences in JSON.
|
||||
fn deserialize_tuple_struct<V>(
|
||||
self,
|
||||
_name: &'static str,
|
||||
_len: usize,
|
||||
visitor: V,
|
||||
) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.deserialize_seq(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_enum<V>(
|
||||
self,
|
||||
_name: &'static str,
|
||||
_variants: &'static [&'static str],
|
||||
visitor: V,
|
||||
) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
if self.peek_char()?.0 == '"' {
|
||||
// Visit a unit variant.
|
||||
visitor.visit_enum(self.parse_string()?.into_deserializer())
|
||||
} else if self.next_char()? == '{' {
|
||||
// Visit a newtype variant, tuple variant, or struct variant.
|
||||
let value = visitor.visit_enum(Enum::new(self))?;
|
||||
// Parse the matching close brace.
|
||||
if self.next_char()? == '}' {
|
||||
Ok(value)
|
||||
} else {
|
||||
Err(Error::ExpectedMapEnd)
|
||||
}
|
||||
} else {
|
||||
Err(Error::ExpectedEnum)
|
||||
}
|
||||
}
|
||||
|
||||
// As is done here, serializers are encouraged to treat newtype structs as
|
||||
// insignificant wrappers around the data they contain. That means not
|
||||
// parsing anything other than the contained value.
|
||||
fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_newtype_struct(self)
|
||||
}
|
||||
|
||||
// Like `deserialize_any` but indicates to the `Deserializer` that it makes
|
||||
// no difference which `Visitor` method is called because the data is
|
||||
// ignored.
|
||||
//
|
||||
// Some deserializers are able to implement this more efficiently than
|
||||
// `deserialize_any`, for example by rapidly skipping over matched
|
||||
// delimiters without paying close attention to the data in between.
|
||||
//
|
||||
// Some formats are not able to implement this at all. Formats that can
|
||||
// implement `deserialize_any` and `deserialize_ignored_any` are known as
|
||||
// self-describing.
|
||||
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
self.deserialize_any(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
// In order to handle commas correctly when deserializing a JSON array or map,
|
||||
// we need to track whether we are on the first element or past the first
|
||||
// element.
|
||||
struct CommaSeparated<'a, 'de: 'a> {
|
||||
de: &'a mut Deserializer<'de>,
|
||||
}
|
||||
|
||||
impl<'a, 'de> CommaSeparated<'a, 'de> {
|
||||
fn new(de: &'a mut Deserializer<'de>) -> Self {
|
||||
CommaSeparated { de }
|
||||
}
|
||||
}
|
||||
|
||||
// `SeqAccess` is provided to the `Visitor` to give it the ability to iterate
|
||||
// through elements of the sequence.
|
||||
impl<'de> SeqAccess<'de> for CommaSeparated<'_, 'de> {
|
||||
type Error = Error;
|
||||
|
||||
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
|
||||
where
|
||||
T: DeserializeSeed<'de>,
|
||||
{
|
||||
// Check if there are no more elements.
|
||||
if self.de.peek_char()?.0 == ']' {
|
||||
return Ok(None);
|
||||
}
|
||||
// Deserialize an array element.
|
||||
seed.deserialize(&mut *self.de).map(Some)
|
||||
}
|
||||
}
|
||||
|
||||
// `MapAccess` is provided to the `Visitor` to give it the ability to iterate
|
||||
// through entries of the map.
|
||||
impl<'de> MapAccess<'de> for CommaSeparated<'_, 'de> {
|
||||
type Error = Error;
|
||||
|
||||
fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
|
||||
where
|
||||
K: DeserializeSeed<'de>,
|
||||
{
|
||||
// Check if there are no more entries.
|
||||
if self.de.peek_char()?.0 == '}' {
|
||||
return Ok(None);
|
||||
}
|
||||
// Deserialize a map key.
|
||||
seed.deserialize(&mut *self.de).map(Some)
|
||||
}
|
||||
|
||||
fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
|
||||
where
|
||||
V: DeserializeSeed<'de>,
|
||||
{
|
||||
// It doesn't make a difference whether the colon is parsed at the end
|
||||
// of `next_key_seed` or at the beginning of `next_value_seed`. In this
|
||||
// case the code is a bit simpler having it here.
|
||||
if self.de.next_char()? != ':' {
|
||||
return Err(Error::ExpectedMapColon);
|
||||
}
|
||||
// Deserialize a map value.
|
||||
seed.deserialize(&mut *self.de)
|
||||
}
|
||||
}
|
||||
|
||||
struct Enum<'a, 'de: 'a> {
|
||||
de: &'a mut Deserializer<'de>,
|
||||
}
|
||||
|
||||
impl<'a, 'de> Enum<'a, 'de> {
|
||||
fn new(de: &'a mut Deserializer<'de>) -> Self {
|
||||
Enum { de }
|
||||
}
|
||||
}
|
||||
|
||||
// `EnumAccess` is provided to the `Visitor` to give it the ability to determine
|
||||
// which variant of the enum is supposed to be deserialized.
|
||||
//
|
||||
// Note that all enum deserialization methods in Serde refer exclusively to the
|
||||
// "externally tagged" enum representation.
|
||||
impl<'de> EnumAccess<'de> for Enum<'_, 'de> {
|
||||
type Error = Error;
|
||||
type Variant = Self;
|
||||
|
||||
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)>
|
||||
where
|
||||
V: DeserializeSeed<'de>,
|
||||
{
|
||||
// The `deserialize_enum` method parsed a `{` character so we are
|
||||
// currently inside of a map. The seed will be deserializing itself from
|
||||
// the key of the map.
|
||||
let val = seed.deserialize(&mut *self.de)?;
|
||||
// Parse the colon separating map key from value.
|
||||
if self.de.next_char()? == ':' {
|
||||
Ok((val, self))
|
||||
} else {
|
||||
Err(Error::ExpectedMapColon)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// `VariantAccess` is provided to the `Visitor` to give it the ability to see
|
||||
// the content of the single variant that it decided to deserialize.
|
||||
impl<'de> VariantAccess<'de> for Enum<'_, 'de> {
|
||||
type Error = Error;
|
||||
|
||||
// If the `Visitor` expected this variant to be a unit variant, the input
|
||||
// should have been the plain string case handled in `deserialize_enum`.
|
||||
fn unit_variant(self) -> Result<()> {
|
||||
Err(Error::ExpectedString)
|
||||
}
|
||||
|
||||
// Newtype variants are represented in JSON as `{ NAME: VALUE }` so
|
||||
// deserialize the value here.
|
||||
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
|
||||
where
|
||||
T: DeserializeSeed<'de>,
|
||||
{
|
||||
seed.deserialize(self.de)
|
||||
}
|
||||
|
||||
// Tuple variants are represented in JSON as `{ NAME: [DATA...] }` so
|
||||
// deserialize the sequence of data here.
|
||||
fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
de::Deserializer::deserialize_seq(self.de, visitor)
|
||||
}
|
||||
|
||||
// Struct variants are represented in JSON as `{ NAME: { K: V, ... } }` so
|
||||
// deserialize the inner map here.
|
||||
fn struct_variant<V>(self, _fields: &'static [&'static str], visitor: V) -> Result<V::Value>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
de::Deserializer::deserialize_map(self.de, visitor)
|
||||
}
|
||||
}
|
||||
+6
-195
@@ -1,14 +1,8 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
io::{Cursor, Read},
|
||||
mem,
|
||||
sync::Arc,
|
||||
};
|
||||
use std::{collections::HashMap, io::Read, sync::Arc};
|
||||
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use glam::{self, Mat2, Mat3, Mat4, Vec2, Vec3, Vec4};
|
||||
use obj::{LoadConfig, ObjData, ObjError};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use vulkano::{
|
||||
buffer::{Buffer, BufferCreateInfo, BufferUsage, Subbuffer},
|
||||
memory::allocator::{
|
||||
@@ -17,16 +11,12 @@ use vulkano::{
|
||||
pipeline::graphics::vertex_input::Vertex,
|
||||
};
|
||||
|
||||
use crate::{instruction_set::InstructionSet, mcsg_deserialise::from_reader};
|
||||
use crate::instruction_set::InstructionSet;
|
||||
|
||||
pub(crate) const PLATONIC_SOLIDS: [(&str, &[u8]); 1] = [("Buny", include_bytes!("bunny.obj"))];
|
||||
pub(crate) const CSG_SOLIDS: [(&str, &[u8]); 1] =
|
||||
[("Primitives", include_bytes!("primitive.mcsg"))];
|
||||
|
||||
// We now create a buffer that will store the shape of our triangle.
|
||||
// We use #[repr(C)] here to force rustc to not do anything funky with our data,
|
||||
// although for this particular example, it doesn't actually change the
|
||||
// in-memory representation.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod, Vertex)]
|
||||
pub(crate) struct OVertex {
|
||||
@@ -73,10 +63,10 @@ pub(crate) enum Inputs {
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct CSGPart {
|
||||
pub(crate) code: u16,
|
||||
pub(crate) opcode: InstructionSet,
|
||||
pub(crate) constants: Vec<Inputs>,
|
||||
pub(crate) material: Option<Mat4>,
|
||||
pub(crate) code: Vec<u8>,
|
||||
pub(crate) opcode: InstructionSet,
|
||||
pub(crate) inputs: Vec<u8>,
|
||||
pub(crate) material: Option<Mat4>,
|
||||
}
|
||||
|
||||
impl CSGPart {
|
||||
@@ -190,185 +180,6 @@ pub(crate) fn load_obj(
|
||||
}])
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct MCSG {
|
||||
object: Vec<MCSGObject>,
|
||||
csg: Vec<MCSGCSG>,
|
||||
}
|
||||
type MCSGObject = HashMap<String, String>;
|
||||
type MCSGCSG = Vec<MCSGCSGPart>;
|
||||
type MCSGCSGPart = HashMap<String, String>;
|
||||
|
||||
fn mat3_from_string(input: &str) -> Result<Mat3, String> {
|
||||
let vec = input
|
||||
.split(' ')
|
||||
.map(|s| s.parse::<f32>())
|
||||
.collect::<Result<Vec<f32>, _>>()
|
||||
.map_err(|_| "not floats")?;
|
||||
let array: [f32; 9] = vec.try_into().map_err(|_| "wrong number of values")?;
|
||||
let matrix = Mat3::from_cols_array(&array);
|
||||
Ok(matrix)
|
||||
}
|
||||
|
||||
fn vec3_from_string(input: &str) -> Result<Vec3, String> {
|
||||
let vec = input
|
||||
.split(' ')
|
||||
.map(|s| s.parse::<f32>())
|
||||
.collect::<Result<Vec<f32>, _>>()
|
||||
.map_err(|_| "not floats")?;
|
||||
let array: [f32; 3] = vec.try_into().map_err(|_| "wrong number of values")?;
|
||||
let vector = Vec3::from_array(array);
|
||||
Ok(vector)
|
||||
}
|
||||
struct TRS {
|
||||
translation: Vec3,
|
||||
rotation: Mat3,
|
||||
scale: Vec3,
|
||||
}
|
||||
|
||||
fn get_trs(o: &HashMap<String, String>) -> Result<TRS, String> {
|
||||
Ok(TRS {
|
||||
translation: o
|
||||
.get("t")
|
||||
.map(String::as_str)
|
||||
.map(vec3_from_string)
|
||||
.transpose()?
|
||||
.unwrap_or(Vec3::ZERO),
|
||||
rotation: o
|
||||
.get("r")
|
||||
.map(String::as_str)
|
||||
.map(mat3_from_string)
|
||||
.transpose()?
|
||||
.unwrap_or(Mat3::IDENTITY),
|
||||
scale: o
|
||||
.get("s")
|
||||
.map(String::as_str)
|
||||
.map(vec3_from_string)
|
||||
.transpose()?
|
||||
.unwrap_or(Vec3::ONE),
|
||||
})
|
||||
}
|
||||
fn get_color(o: &HashMap<String, String>) -> Result<Vec3, String> {
|
||||
Ok(o.get("color")
|
||||
.map(String::as_str)
|
||||
.map(vec3_from_string)
|
||||
.transpose()?
|
||||
.unwrap_or(Vec3::splat(255.)))
|
||||
}
|
||||
|
||||
fn get_rgb(o: &HashMap<String, String>) -> Result<Vec3, String> {
|
||||
Ok(o.get("rgb")
|
||||
.map(String::as_str)
|
||||
.map(vec3_from_string)
|
||||
.transpose()?
|
||||
.unwrap_or(Vec3::splat(255.)))
|
||||
}
|
||||
|
||||
fn get_f32(o: &HashMap<String, String>, tag: &str) -> Result<f32, String> {
|
||||
get_f32_default(o, tag, 0.)
|
||||
}
|
||||
|
||||
fn get_f32_default(o: &HashMap<String, String>, tag: &str, _default: f32) -> Result<f32, String> {
|
||||
Ok(o.get(tag)
|
||||
.map(|c| c.parse::<f32>())
|
||||
.transpose()
|
||||
.map_err(|e| e.to_string())?
|
||||
.unwrap_or_default())
|
||||
}
|
||||
|
||||
fn get_percentage(o: &HashMap<String, String>, tag: &str) -> Result<f32, String> {
|
||||
get_f32(o, tag).map(|c| c / 100.0)
|
||||
}
|
||||
|
||||
fn get_percentage_default(
|
||||
o: &HashMap<String, String>,
|
||||
tag: &str,
|
||||
default: f32,
|
||||
) -> Result<f32, String> {
|
||||
get_f32_default(o, tag, default).map(|c| c / 100.0)
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
enum Half {
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
XM,
|
||||
YM,
|
||||
ZM,
|
||||
}
|
||||
|
||||
fn get_half(o: &HashMap<String, String>) -> Result<Half, String> {
|
||||
Ok({
|
||||
let half = o
|
||||
.get("half")
|
||||
.map(|c| c.parse::<u8>())
|
||||
.transpose()
|
||||
.map_err(|e| e.to_string())?
|
||||
.unwrap_or(0);
|
||||
if half as usize >= mem::variant_count::<Half>() {
|
||||
return Err("invalid enum".to_owned());
|
||||
}
|
||||
unsafe { mem::transmute::<u8, Half>(half) }
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn load_csg(
|
||||
_memory_allocator: &Arc<StandardMemoryAllocator>,
|
||||
input: &mut dyn Read,
|
||||
name: String,
|
||||
) -> Result<Vec<CSG>, String> {
|
||||
let mcsg: MCSG =
|
||||
from_reader(&mut Cursor::new("{").chain(input).chain(Cursor::new("}"))).unwrap();
|
||||
|
||||
mcsg.object
|
||||
.iter()
|
||||
.map(|o| {
|
||||
let name = name.clone() + "_" + o.get("name").unwrap_or(&"unknown".to_owned());
|
||||
let _trs = get_trs(o)?;
|
||||
let _color = get_color(o)?;
|
||||
|
||||
let cid = o
|
||||
.get("cid")
|
||||
.map(|c| c.parse::<usize>())
|
||||
.transpose()
|
||||
.map_err(|e| e.to_string())?
|
||||
.unwrap_or(0);
|
||||
if o.get("type").map(|ty| &ty[..] != "csg").unwrap_or(false) {
|
||||
return Err("Type unknown".to_owned());
|
||||
}
|
||||
|
||||
let parts = mcsg
|
||||
.csg
|
||||
.get(cid)
|
||||
.ok_or("unknown cid")?
|
||||
.iter()
|
||||
.map(|inpart| {
|
||||
let ty = inpart.get("type").ok_or("no type!")?.as_str();
|
||||
let csgpart = CSGPart::opcode(InstructionSet::OPNop, vec![]);
|
||||
if ty == "sphere" {
|
||||
let _blend = get_f32(inpart, "blend")?;
|
||||
let _shell = get_percentage(inpart, "shell%")?;
|
||||
let _power = get_f32_default(inpart, "power", 2.)?;
|
||||
let _rgb = get_rgb(inpart)?;
|
||||
let _trs = get_trs(inpart)?;
|
||||
let _half = get_half(inpart)?;
|
||||
}
|
||||
Ok(csgpart)
|
||||
})
|
||||
.collect::<Result<Vec<CSGPart>, String>>()?;
|
||||
|
||||
Ok(CSG {
|
||||
parts,
|
||||
pos: Vec3::ZERO,
|
||||
rot: Vec3::ZERO,
|
||||
scale: Vec3::ONE,
|
||||
name,
|
||||
})
|
||||
})
|
||||
.collect::<Result<Vec<CSG>, String>>()
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Light {
|
||||
pub(crate) pos: Vec3,
|
||||
|
||||
+517
@@ -0,0 +1,517 @@
|
||||
use egui::ahash::HashMapExt;
|
||||
use foldhash::HashMap;
|
||||
use rspirv::spirv;
|
||||
|
||||
use crate::instruction_set::InstructionSet;
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
|
||||
enum SSAOpcode {
|
||||
#[default]
|
||||
SSAStop,
|
||||
SSAReturn,
|
||||
SSAPosition,
|
||||
SSAAdd,
|
||||
SSASub,
|
||||
SSAMul,
|
||||
SSADiv,
|
||||
SSAMod,
|
||||
SSARem,
|
||||
SSAPow,
|
||||
SSAAtan2,
|
||||
SSAMin,
|
||||
SSAMinMaterial,
|
||||
SSAMax,
|
||||
SSAMaxMaterial,
|
||||
SSACross,
|
||||
SSADot,
|
||||
SSALength,
|
||||
SSADistance,
|
||||
SSANormalize,
|
||||
SSANegate,
|
||||
SSARound,
|
||||
SSARoundEven,
|
||||
SSATrunc,
|
||||
SSAAbs,
|
||||
SSASign,
|
||||
SSAFloor,
|
||||
SSACeil,
|
||||
SSAFract,
|
||||
SSASin,
|
||||
SSACos,
|
||||
SSATan,
|
||||
SSAAsin,
|
||||
SSAAcos,
|
||||
SSAAtan,
|
||||
SSASinh,
|
||||
SSACosh,
|
||||
SSATanh,
|
||||
SSAAsinh,
|
||||
SSAAcosh,
|
||||
SSAAtanh,
|
||||
SSAExp,
|
||||
SSALog,
|
||||
SSAExp2,
|
||||
SSALog2,
|
||||
SSASqrt,
|
||||
SSAInverseSqrt,
|
||||
SSASquare,
|
||||
SSACube,
|
||||
SSASmoothMin,
|
||||
SSASmoothMax,
|
||||
SSASmoothMinMaterial,
|
||||
SSASmoothMaxMaterial,
|
||||
SSAClamp,
|
||||
SSAMix,
|
||||
SSAStep,
|
||||
SSASmoothStep,
|
||||
SSAFMA,
|
||||
SSASDFSphere,
|
||||
SSASDFBox,
|
||||
SSASDFTorus,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
|
||||
struct SSAOpcodeSized {
|
||||
opcode: SSAOpcode,
|
||||
size: u8,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
enum SSAInput {
|
||||
Register(u32),
|
||||
Constant(f32),
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Clone)]
|
||||
struct SSAInstruction {
|
||||
opcode: SSAOpcodeSized,
|
||||
inputs: Vec<SSAInput>,
|
||||
outputs: Vec<u32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Clone)]
|
||||
struct SSATape {
|
||||
last_output: u32,
|
||||
tape: Vec<SSAInstruction>,
|
||||
constants: Vec<f32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
|
||||
struct GPUOpcode(u8);
|
||||
|
||||
struct GPUTape {
|
||||
instructions: Vec<u8>,
|
||||
constants: Vec<f32>,
|
||||
}
|
||||
|
||||
impl SSAOpcodeSized {
|
||||
const fn output(&self) -> u8 {
|
||||
use SSAOpcode::*;
|
||||
match self.opcode {
|
||||
SSAStop => 0,
|
||||
SSAReturn => 0,
|
||||
SSAPosition => 3,
|
||||
SSAMinMaterial => 1,
|
||||
SSAMaxMaterial => 1,
|
||||
SSASmoothMinMaterial => 1,
|
||||
SSASmoothMaxMaterial => 1,
|
||||
SSACross => 3,
|
||||
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,
|
||||
SSACross => 3 + 3,
|
||||
SSASDFSphere => 3 + 1,
|
||||
SSASDFBox => 3 + 3,
|
||||
SSASDFTorus => 3 + 2,
|
||||
SSAAdd | SSASub | SSAMul | SSADiv | SSAMod | SSARem | SSAPow | SSAAtan2 | SSAMin
|
||||
| SSAMax | SSADot | SSADistance => self.size * 2,
|
||||
SSASmoothMin | SSASmoothMax | SSAClamp | SSAMix | SSAStep | SSASmoothStep | 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 | SSACross | SSASDFSphere | SSASDFBox
|
||||
| SSASDFTorus => (0, 0),
|
||||
SSAAdd | SSASub | SSAMul | SSADiv | SSAMod | SSARem | SSAPow | SSAAtan2 | SSAMin
|
||||
| SSAMax | SSADot | SSADistance => (2, 1),
|
||||
SSASmoothMin | SSASmoothMax | SSAClamp | SSAMix | SSAStep | SSASmoothStep | 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(OPStop, 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),
|
||||
SSACross => opcode_drop(OPCross, 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),
|
||||
SSARem => opcode_drop(OPRem, self.size),
|
||||
SSAPow => opcode_drop(OPPow, 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),
|
||||
SSANormalize => opcode_drop(OPNormalize, self.size),
|
||||
SSANegate => opcode_drop(OPNegate, self.size),
|
||||
SSARound => opcode_drop(OPRound, self.size),
|
||||
SSARoundEven => opcode_drop(OPRoundEven, self.size),
|
||||
SSATrunc => opcode_drop(OPTrunc, self.size),
|
||||
SSAAbs => opcode_drop(OPAbs, self.size),
|
||||
SSASign => opcode_drop(OPSign, 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),
|
||||
SSASinh => opcode_drop(OPSinh, self.size),
|
||||
SSACosh => opcode_drop(OPCosh, self.size),
|
||||
SSATanh => opcode_drop(OPTanh, self.size),
|
||||
SSAAsinh => opcode_drop(OPAsinh, self.size),
|
||||
SSAAcosh => opcode_drop(OPAcosh, self.size),
|
||||
SSAAtanh => opcode_drop(OPAtanh, self.size),
|
||||
SSAExp => opcode_drop(OPExp, self.size),
|
||||
SSALog => opcode_drop(OPLog, self.size),
|
||||
SSAExp2 => opcode_drop(OPExp2, self.size),
|
||||
SSALog2 => opcode_drop(OPLog2, self.size),
|
||||
SSASqrt => opcode_drop(OPSqrt, self.size),
|
||||
SSAInverseSqrt => opcode_drop(OPInverseSqrt, 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),
|
||||
SSAStep => opcode_drop(OPStep, self.size),
|
||||
SSASmoothStep => opcode_drop(OPSmoothStep, self.size),
|
||||
SSAFMA => opcode_drop(OPFMA, self.size),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SSATape {
|
||||
fn push_instruction(&mut self, opcode: SSAOpcodeSized, inputs: Vec<SSAInput>) -> Vec<u32> {
|
||||
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>>();
|
||||
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: outputs.clone(),
|
||||
});
|
||||
return outputs;
|
||||
}
|
||||
|
||||
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 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![],
|
||||
constants: self.constants.clone(),
|
||||
};
|
||||
|
||||
for SSAInstruction {
|
||||
opcode,
|
||||
inputs,
|
||||
outputs,
|
||||
} in self.tape.iter()
|
||||
{
|
||||
let code = opcode.to_raw_opcode();
|
||||
gpu_tape.instructions.push(code.0);
|
||||
|
||||
let mut low_nibble = true;
|
||||
let mut staging_byte = 0u8;
|
||||
|
||||
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.instructions.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.instructions.push(staging_byte);
|
||||
}
|
||||
|
||||
low_nibble = !low_nibble;
|
||||
}
|
||||
|
||||
if !low_nibble {
|
||||
gpu_tape.instructions.push(staging_byte);
|
||||
}
|
||||
}
|
||||
gpu_tape
|
||||
}
|
||||
|
||||
fn compile_to_spirv(&self) {
|
||||
let mut b = rspirv::dr::Builder::new();
|
||||
b.set_version(1, 5);
|
||||
b.memory_model(spirv::AddressingModel::Logical, spirv::MemoryModel::GLSL450);
|
||||
let void = b.type_void();
|
||||
let float = b.type_float(32);
|
||||
let vec1 = b.type_vector(float, 1);
|
||||
let vec2 = b.type_vector(float, 2);
|
||||
let vec3 = b.type_vector(float, 3);
|
||||
let vec4 = b.type_vector(float, 4);
|
||||
let scene_fn_type = b.type_function(float, vec![vec3]);
|
||||
|
||||
let scene = b
|
||||
.begin_function(
|
||||
float,
|
||||
None,
|
||||
spirv::FunctionControl::DONT_INLINE
|
||||
| spirv::FunctionControl::PURE
|
||||
| spirv::FunctionControl::CONST,
|
||||
scene_fn_type,
|
||||
)
|
||||
.unwrap();
|
||||
let pos = b.function_parameter(vec3).unwrap();
|
||||
|
||||
let mut mapping = HashMap::<u32,u32>::new();
|
||||
|
||||
for instruction in self.tape.iter() {
|
||||
use SSAOpcode::*;
|
||||
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() {
|
||||
todo!();
|
||||
}
|
||||
match instruction.opcode.opcode {
|
||||
SSAStop => {
|
||||
b.ret().unwrap();
|
||||
},
|
||||
SSAReturn =>
|
||||
{
|
||||
let value = input_resolve(float, &mut b, &mapping, instruction.inputs[0]);
|
||||
b.ret_value(value).unwrap();
|
||||
},
|
||||
SSAPosition => {
|
||||
mapping.insert(instruction.outputs[0], b.composite_extract(float, None, pos, [0]).unwrap());
|
||||
mapping.insert(instruction.outputs[1], b.composite_extract(float, None, pos, [1]).unwrap());
|
||||
mapping.insert(instruction.outputs[2], b.composite_extract(float, None, pos, [2]).unwrap());
|
||||
},
|
||||
SSAAdd => {
|
||||
for i in 0..instruction.opcode.size as usize {
|
||||
let val_a = input_resolve(float, &mut b, &mapping, instruction.inputs[i]);
|
||||
let val_b = input_resolve(float, &mut b, &mapping, instruction.inputs[i+instruction.opcode.size as usize]);
|
||||
mapping.insert(instruction.outputs[i], b.f_add(float, None, val_a, val_b).unwrap());
|
||||
}
|
||||
},
|
||||
SSASub => todo!(),
|
||||
SSAMul => todo!(),
|
||||
SSADiv => todo!(),
|
||||
SSAMod => todo!(),
|
||||
SSARem => todo!(),
|
||||
SSAPow => todo!(),
|
||||
SSAAtan2 => todo!(),
|
||||
SSAMin => todo!(),
|
||||
SSAMinMaterial => todo!(),
|
||||
SSAMax => todo!(),
|
||||
SSAMaxMaterial => todo!(),
|
||||
SSACross => todo!(),
|
||||
SSADot => todo!(),
|
||||
SSALength => todo!(),
|
||||
SSADistance => todo!(),
|
||||
SSANormalize => todo!(),
|
||||
SSANegate => todo!(),
|
||||
SSARound => todo!(),
|
||||
SSARoundEven => todo!(),
|
||||
SSATrunc => todo!(),
|
||||
SSAAbs => todo!(),
|
||||
SSASign => todo!(),
|
||||
SSAFloor => todo!(),
|
||||
SSACeil => todo!(),
|
||||
SSAFract => todo!(),
|
||||
SSASin => todo!(),
|
||||
SSACos => todo!(),
|
||||
SSATan => todo!(),
|
||||
SSAAsin => todo!(),
|
||||
SSAAcos => todo!(),
|
||||
SSAAtan => todo!(),
|
||||
SSASinh => todo!(),
|
||||
SSACosh => todo!(),
|
||||
SSATanh => todo!(),
|
||||
SSAAsinh => todo!(),
|
||||
SSAAcosh => todo!(),
|
||||
SSAAtanh => todo!(),
|
||||
SSAExp => todo!(),
|
||||
SSALog => todo!(),
|
||||
SSAExp2 => todo!(),
|
||||
SSALog2 => todo!(),
|
||||
SSASqrt => todo!(),
|
||||
SSAInverseSqrt => todo!(),
|
||||
SSASquare => todo!(),
|
||||
SSACube => todo!(),
|
||||
SSASmoothMin => todo!(),
|
||||
SSASmoothMax => todo!(),
|
||||
SSASmoothMinMaterial => todo!(),
|
||||
SSASmoothMaxMaterial => todo!(),
|
||||
SSAClamp => todo!(),
|
||||
SSAMix => todo!(),
|
||||
SSAStep => todo!(),
|
||||
SSASmoothStep => todo!(),
|
||||
SSAFMA => todo!(),
|
||||
SSASDFSphere => todo!(),
|
||||
SSASDFBox => todo!(),
|
||||
SSASDFTorus => todo!(),
|
||||
}
|
||||
}
|
||||
b.end_function().unwrap();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user