diff --git a/dunge/tests/shader.rs b/dunge/tests/shader.rs index b7edb97..3064641 100644 --- a/dunge/tests/shader.rs +++ b/dunge/tests/shader.rs @@ -11,12 +11,12 @@ fn shader_calc() -> Result<(), Error> { let compute = || { let m = -sl::mat2(sl::vec2(1., 0.), sl::vec2(0., 1.)); - let [m0, m1, m3] = sl::thunk(m); - let v = m0.x() + m1.y(); + let mt = sl::thunk(m); + let v = mt.clone().x() + mt.clone().y(); let z = sl::splat_vec3(1.).z(); Out { - place: sl::vec4_concat(m3.x(), v) * sl::f32(1) * z, + place: sl::vec4_concat(mt.x(), v) * sl::f32(1) * z, color: sl::vec4(0., 0., 1., 1.) + Vec4::splat(0.), } }; diff --git a/dunge/tests/triangle_index.rs b/dunge/tests/triangle_index.rs index e102b2a..70975cf 100644 --- a/dunge/tests/triangle_index.rs +++ b/dunge/tests/triangle_index.rs @@ -23,9 +23,9 @@ fn render() -> Result<(), Error> { const Y_OFFSET: f32 = 0.25; let triangle = |Index(index): Index| { - let [x, y] = sl::thunk(sl::f32(index) * THIRD + R_OFFSET); + let i = sl::thunk(sl::f32(index) * THIRD + R_OFFSET); Out { - place: sl::vec4(sl::cos(x), sl::sin(y) + Y_OFFSET, 0., 1.), + place: sl::vec4(sl::cos(i.clone()), sl::sin(i) + Y_OFFSET, 0., 1.), color: COLOR, } }; diff --git a/dunge/tests/triangle_instance.rs b/dunge/tests/triangle_instance.rs index 31cf2ee..89662da 100644 --- a/dunge/tests/triangle_instance.rs +++ b/dunge/tests/triangle_instance.rs @@ -26,8 +26,8 @@ fn render() -> Result<(), Error> { struct Transform(Row<[f32; 2]>, Row<[f32; 3]>); let triangle = |t: InInstance, Index(index): Index| { - let [x, y] = sl::thunk(sl::f32(index) * THIRD + R_OFFSET); - let p = sl::vec2(sl::cos(x), sl::sin(y)) * TRIANGLE_SIZE + t.0; + let i = sl::thunk(sl::f32(index) * THIRD + R_OFFSET); + let p = sl::vec2(sl::cos(i.clone()), sl::sin(i)) * TRIANGLE_SIZE + t.0; Out { place: sl::vec4_concat(p, Vec2::new(0., 1.)), color: sl::vec4_with(sl::fragment(t.1), 1.), diff --git a/dunge_shader/src/eval.rs b/dunge_shader/src/eval.rs index a07b040..bf01d17 100644 --- a/dunge_shader/src/eval.rs +++ b/dunge_shader/src/eval.rs @@ -2,17 +2,18 @@ use { crate::{ context::{Context, InputInfo, InstInfo, Stages, VertInfo}, define::Define, + math::Func, module::{Module, Out, Output}, - ret::Ret, + ret::{Bi, Ret, Un}, + texture::Sampled, types::{self, MemberType, ScalarType, ValueType, VectorType}, }, naga::{ - AddressSpace, Arena, BinaryOperator, Binding, BuiltIn, EntryPoint, Expression, Function, - FunctionArgument, FunctionResult, GlobalVariable, Handle, Literal, LocalVariable, Range, - ResourceBinding, SampleLevel, ShaderStage, Span, Statement, StructMember, Type, TypeInner, - UnaryOperator, UniqueArena, + AddressSpace, Arena, Binding, BuiltIn, EntryPoint, Expression, Function, FunctionArgument, + FunctionResult, GlobalVariable, Handle, Literal, LocalVariable, Range, ResourceBinding, + ShaderStage, Span, Statement, StructMember, Type, TypeInner, UniqueArena, }, - std::{array, cell::Cell, collections::HashMap, iter, marker::PhantomData, mem, rc::Rc}, + std::{cell::Cell, collections::HashMap, iter, marker::PhantomData, mem, rc::Rc}, }; pub(crate) fn make(cx: Context, output: O) -> Module @@ -173,13 +174,13 @@ pub struct ReadVertex { } impl ReadVertex { - pub const fn new(id: u32, index: u32) -> Ret { + pub const fn new(id: u32, index: u32) -> Ret { Ret::new(Self { id, index }) } } -impl Eval for Ret { - type Out = T; +impl Eval for Ret { + type Out = O; fn eval(self, en: &mut Vs) -> Expr { let en = &mut en.inner; @@ -194,24 +195,24 @@ pub struct ReadInstance { } impl ReadInstance { - pub const fn new(id: u32) -> Ret { + pub const fn new(id: u32) -> Ret { Ret::new(Self { id }) } } -impl Eval for Ret +impl Eval for Ret where - T: types::Value, + O: types::Value, { - type Out = T; + type Out = O; fn eval(self, en: &mut Vs) -> Expr { let en = &mut en.inner; let id = self.get().id; - match T::VALUE_TYPE { + match O::VALUE_TYPE { ValueType::Scalar(_) | ValueType::Vector(_) => en.argument(id), ValueType::Matrix(mat) => { - let ty = en.new_type(T::VALUE_TYPE.ty()); + let ty = en.new_type(O::VALUE_TYPE.ty()); let arg = en.argument(id); let exprs = (0..mat.dims()) .map(|index| en.access_index(arg, index)) @@ -255,11 +256,11 @@ impl ReadGlobal { } } -impl Eval for Ret +impl Eval for Ret where E: GetEntry, { - type Out = T; + type Out = O; fn eval(self, en: &mut E) -> Expr { let ReadGlobal { @@ -308,14 +309,11 @@ where } } -pub fn thunk(a: A) -> [Ret, A::Out>; N] +pub fn thunk(a: A) -> Ret, A::Out> where A: Eval, { - let state = State::Eval(a); - let inner = Rc::new(Cell::new(state)); - let thunk = Thunk::new(Rc::clone(&inner)); - array::from_fn(|_| Ret::new(thunk.clone())) + Ret::new(Thunk::new(a)) } pub struct Thunk { @@ -324,9 +322,9 @@ pub struct Thunk { } impl Thunk { - fn new(a: Rc>>) -> Self { + fn new(a: A) -> Self { Self { - s: a, + s: Rc::new(Cell::new(State::Eval(a))), e: PhantomData, } } @@ -334,7 +332,10 @@ impl Thunk { impl Clone for Thunk { fn clone(&self) -> Self { - Self::new(self.s.clone()) + Self { + s: Rc::clone(&self.s), + e: PhantomData, + } } } @@ -607,92 +608,6 @@ impl Argument { } } -pub(crate) enum Un { - Neg, -} - -impl Un { - fn operator(self) -> UnaryOperator { - match self { - Self::Neg => UnaryOperator::Negate, - } - } -} - -pub(crate) enum Bi { - Add, - Sub, - Mul, - Div, - Rem, -} - -impl Bi { - fn operator(self) -> BinaryOperator { - match self { - Self::Add => BinaryOperator::Add, - Self::Sub => BinaryOperator::Subtract, - Self::Mul => BinaryOperator::Multiply, - Self::Div => BinaryOperator::Divide, - Self::Rem => BinaryOperator::Modulo, - } - } -} - -pub(crate) enum Func { - Cos, - Cosh, - Sin, - Sinh, - Tan, - Tanh, -} - -impl Func { - fn expr(self, ev: Evaluated) -> Expression { - use naga::MathFunction; - - let fun = match self { - Self::Cos => MathFunction::Cos, - Self::Cosh => MathFunction::Cosh, - Self::Sin => MathFunction::Sin, - Self::Sinh => MathFunction::Sinh, - Self::Tan => MathFunction::Tan, - Self::Tanh => MathFunction::Tanh, - }; - - let mut exprs = ev.into_iter().map(Expr::get); - Expression::Math { - fun, - arg: exprs.next().expect("first argument"), - arg1: exprs.next(), - arg2: exprs.next(), - arg3: exprs.next(), - } - } -} - -pub(crate) struct Sampled { - pub tex: Expr, - pub sam: Expr, - pub crd: Expr, -} - -impl Sampled { - fn expr(self) -> Expression { - Expression::ImageSample { - image: self.tex.0, - sampler: self.sam.0, - gather: None, - coordinate: self.crd.0, - array_index: None, - offset: None, - level: SampleLevel::Auto, - depth_ref: None, - } - } -} - pub struct Entry { compl: Compiler, locls: Arena, diff --git a/dunge_shader/src/math.rs b/dunge_shader/src/math.rs index a24f918..a5b0f6d 100644 --- a/dunge_shader/src/math.rs +++ b/dunge_shader/src/math.rs @@ -1,8 +1,9 @@ use { crate::{ - eval::{Eval, EvalTuple, Evaluated, Expr, Func, GetEntry}, + eval::{Eval, EvalTuple, Evaluated, Expr, GetEntry}, ret::Ret, }, + naga::{Expression, MathFunction}, std::marker::PhantomData, }; @@ -78,3 +79,34 @@ where en.get_entry().math(func, o) } } + +pub(crate) enum Func { + Cos, + Cosh, + Sin, + Sinh, + Tan, + Tanh, +} + +impl Func { + pub fn expr(self, ev: Evaluated) -> Expression { + let fun = match self { + Self::Cos => MathFunction::Cos, + Self::Cosh => MathFunction::Cosh, + Self::Sin => MathFunction::Sin, + Self::Sinh => MathFunction::Sinh, + Self::Tan => MathFunction::Tan, + Self::Tanh => MathFunction::Tanh, + }; + + let mut exprs = ev.into_iter().map(Expr::get); + Expression::Math { + fun, + arg: exprs.next().expect("first argument"), + arg1: exprs.next(), + arg2: exprs.next(), + arg3: exprs.next(), + } + } +} diff --git a/dunge_shader/src/ret.rs b/dunge_shader/src/ret.rs index 958dc27..061d930 100644 --- a/dunge_shader/src/ret.rs +++ b/dunge_shader/src/ret.rs @@ -1,11 +1,12 @@ use { - crate::eval::{Bi, Eval, Expr, GetEntry, Un, Vs}, + crate::eval::{Eval, Expr, GetEntry, Vs}, + naga::{BinaryOperator, UnaryOperator}, std::{marker::PhantomData, ops}, }; -pub struct Ret { +pub struct Ret { a: A, - t: PhantomData, + t: PhantomData, } impl Ret { @@ -18,7 +19,7 @@ impl Ret { } } -impl Clone for Ret +impl Clone for Ret where A: Clone, { @@ -27,7 +28,7 @@ where } } -impl Copy for Ret where A: Copy {} +impl Copy for Ret where A: Copy {} type Operand = Ret>::Out>; @@ -179,3 +180,35 @@ impl_binary!(Mul::mul(f32, glam::Mat4) -> glam::Mat4); impl_binary!(Mul::mul(glam::Mat2, glam::Vec2) -> glam::Vec2); impl_binary!(Mul::mul(glam::Mat3, glam::Vec3) -> glam::Vec3); impl_binary!(Mul::mul(glam::Mat4, glam::Vec4) -> glam::Vec4); + +pub(crate) enum Un { + Neg, +} + +impl Un { + pub fn operator(self) -> UnaryOperator { + match self { + Self::Neg => UnaryOperator::Negate, + } + } +} + +pub(crate) enum Bi { + Add, + Sub, + Mul, + Div, + Rem, +} + +impl Bi { + pub fn operator(self) -> BinaryOperator { + match self { + Self::Add => BinaryOperator::Add, + Self::Sub => BinaryOperator::Subtract, + Self::Mul => BinaryOperator::Multiply, + Self::Div => BinaryOperator::Divide, + Self::Rem => BinaryOperator::Modulo, + } + } +} diff --git a/dunge_shader/src/texture.rs b/dunge_shader/src/texture.rs index 3ee1444..1cea441 100644 --- a/dunge_shader/src/texture.rs +++ b/dunge_shader/src/texture.rs @@ -1,13 +1,14 @@ use { crate::{ - eval::{Eval, Expr, GetEntry, Sampled}, + eval::{Eval, Expr, GetEntry}, ret::Ret, types, }, + naga::{Expression, SampleLevel}, std::marker::PhantomData, }; -type Tex = Ret, types::Vec4>; +type Tex = Ret, types::Vec4>; pub const fn texture_sample(tex: T, sam: S, crd: C) -> Tex where @@ -15,7 +16,7 @@ where S: Eval, C: Eval>, { - Ret::new(Sample { + Ret::new(Samp { tex, sam, crd, @@ -23,14 +24,14 @@ where }) } -pub struct Sample { +pub struct Samp { tex: T, sam: S, crd: C, e: PhantomData, } -impl Eval for Ret, types::Vec4> +impl Eval for Ret, types::Vec4> where T: Eval>, S: Eval, @@ -40,7 +41,7 @@ where type Out = types::Vec4; fn eval(self, en: &mut E) -> Expr { - let Sample { tex, sam, crd, .. } = self.get(); + let Samp { tex, sam, crd, .. } = self.get(); let ex = Sampled { tex: tex.eval(en), sam: sam.eval(en), @@ -50,3 +51,24 @@ where en.get_entry().sample(ex) } } + +pub(crate) struct Sampled { + tex: Expr, + sam: Expr, + crd: Expr, +} + +impl Sampled { + pub fn expr(self) -> Expression { + Expression::ImageSample { + image: self.tex.get(), + sampler: self.sam.get(), + gather: None, + coordinate: self.crd.get(), + array_index: None, + offset: None, + level: SampleLevel::Auto, + depth_ref: None, + } + } +} diff --git a/examples/ssaa/src/lib.rs b/examples/ssaa/src/lib.rs index 62b2860..5af5fed 100644 --- a/examples/ssaa/src/lib.rs +++ b/examples/ssaa/src/lib.rs @@ -25,9 +25,9 @@ pub fn run(window: dunge::window::Window) -> Result<(), Error> { struct Offset<'a>(&'a Uniform); let triangle = |Index(idx): Index, Groups(offset): Groups| { - let [x, y] = sl::thunk(sl::f32(idx) * THIRD + offset.0); + let i = sl::thunk(sl::f32(idx) * THIRD + offset.0); Out { - place: sl::vec4(sl::cos(x), sl::sin(y), 0., 1.), + place: sl::vec4(sl::cos(i.clone()), sl::sin(i), 0., 1.), color: COLOR, } }; @@ -46,7 +46,7 @@ pub fn run(window: dunge::window::Window) -> Result<(), Error> { let screen = |vert: InVertex, Groups(map): Groups| Out { place: sl::vec4_concat(vert.0, Vec2::new(0., 1.)), color: { - let [s0, s1, s2, s3] = sl::thunk(sl::fragment(vert.1)); + let s = sl::thunk(sl::fragment(vert.1)); let tex = || map.tex.clone(); let sam = || map.sam.clone(); let stp = || map.stp.clone(); @@ -54,10 +54,10 @@ pub fn run(window: dunge::window::Window) -> Result<(), Error> { let d1 = sl::vec2(stp().x(), -stp().y()); let d2 = sl::vec2(-stp().x(), stp().y()); let d3 = sl::vec2(-stp().x(), -stp().y()); - (sl::texture_sample(tex(), sam(), s0 + d0) - + sl::texture_sample(tex(), sam(), s1 + d1) - + sl::texture_sample(tex(), sam(), s2 + d2) - + sl::texture_sample(tex(), sam(), s3 + d3)) + (sl::texture_sample(tex(), sam(), s.clone() + d0) + + sl::texture_sample(tex(), sam(), s.clone() + d1) + + sl::texture_sample(tex(), sam(), s.clone() + d2) + + sl::texture_sample(tex(), sam(), s + d3)) * 0.25 }, }; diff --git a/examples/triangle/src/lib.rs b/examples/triangle/src/lib.rs index 15813c8..ba141c1 100644 --- a/examples/triangle/src/lib.rs +++ b/examples/triangle/src/lib.rs @@ -19,9 +19,9 @@ pub fn run(window: dunge::window::Window) -> Result<(), Error> { struct Offset<'a>(&'a Uniform); let triangle = |Index(idx): Index, Groups(offset): Groups| { - let [x, y] = sl::thunk(sl::f32(idx) * THIRD + offset.0); + let i = sl::thunk(sl::f32(idx) * THIRD + offset.0); Out { - place: sl::vec4(sl::cos(x), sl::sin(y), 0., 1.), + place: sl::vec4(sl::cos(i.clone()), sl::sin(i), 0., 1.), color: COLOR, } };