diff --git a/dunge/tests/shader.rs b/dunge/tests/shader.rs index 8e64554..313c2c3 100644 --- a/dunge/tests/shader.rs +++ b/dunge/tests/shader.rs @@ -13,9 +13,9 @@ type Error = Box; #[test] fn render() -> Result<(), Error> { let compute = || { - let m = sl::mat2(sl::vec2(1., 0.), sl::vec2(0., 1.)); + 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 v = m0.x() + (-m1.y()); let z = sl::splat_vec3(1.).z(); Out { diff --git a/dunge/tests/shader.wgsl b/dunge/tests/shader.wgsl index 74e33ee..59541fe 100644 --- a/dunge/tests/shader.wgsl +++ b/dunge/tests/shader.wgsl @@ -4,8 +4,8 @@ struct VertexOutput { @vertex fn vs() -> VertexOutput { - let _e6: mat2x2 = mat2x2(vec2(1f, 0f), vec2(0f, 1f)); - return VertexOutput(((vec4(_e6[0], (_e6[0] + _e6[1])) * f32(1i)) * vec3(1f, 1f, 1f).z)); + let _e7: mat2x2 = -(mat2x2(vec2(1f, 0f), vec2(0f, 1f))); + return VertexOutput(((vec4(_e7[0], (_e7[0] + -(_e7[1]))) * f32(1i)) * vec3(1f, 1f, 1f).z)); } @fragment diff --git a/dunge_shader/src/eval.rs b/dunge_shader/src/eval.rs index 40f09b0..565d8b0 100644 --- a/dunge_shader/src/eval.rs +++ b/dunge_shader/src/eval.rs @@ -1,4 +1,3 @@ -use std::marker::PhantomData; use { crate::{ context::{Context, InputInfo, InstInfo, Stages, VertInfo}, @@ -11,9 +10,9 @@ use { AddressSpace, Arena, BinaryOperator, Binding, Block, BuiltIn, EntryPoint, Expression, Function, FunctionArgument, FunctionResult, GlobalVariable, Handle, Literal, Range, ResourceBinding, SampleLevel, ShaderStage, Span, Statement, StructMember, Type, TypeInner, - UniqueArena, + UnaryOperator, UniqueArena, }, - std::{array, cell::Cell, collections::HashMap, iter, mem, rc::Rc}, + std::{array, cell::Cell, collections::HashMap, iter, marker::PhantomData, mem, rc::Rc}, }; pub(crate) fn make(cx: Context, output: O) -> Module @@ -564,7 +563,19 @@ impl Argument { } } -pub(crate) enum Op { +pub(crate) enum Un { + Neg, +} + +impl Un { + fn operator(self) -> UnaryOperator { + match self { + Self::Neg => UnaryOperator::Negate, + } + } +} + +pub(crate) enum Bi { Add, Sub, Mul, @@ -572,7 +583,7 @@ pub(crate) enum Op { Rem, } -impl Op { +impl Bi { fn operator(self) -> BinaryOperator { match self { Self::Add => BinaryOperator::Add, @@ -714,7 +725,19 @@ impl Entry { Expr(handle) } - pub(crate) fn binary(&mut self, op: Op, a: Expr, b: Expr) -> Expr { + pub(crate) fn unary(&mut self, op: Un, a: Expr) -> Expr { + let ex = Expression::Unary { + op: op.operator(), + expr: a.0, + }; + + let handle = self.exprs.append(ex, Span::UNDEFINED); + let st = Statement::Emit(Range::new_from_bounds(handle, handle)); + self.stats.push(st, &self.exprs); + Expr(handle) + } + + pub(crate) fn binary(&mut self, op: Bi, a: Expr, b: Expr) -> Expr { let ex = Expression::Binary { op: op.operator(), left: a.0, diff --git a/dunge_shader/src/ret.rs b/dunge_shader/src/ret.rs index c496763..958dc27 100644 --- a/dunge_shader/src/ret.rs +++ b/dunge_shader/src/ret.rs @@ -1,5 +1,5 @@ use { - crate::eval::{Eval, Expr, GetEntry, Op, Vs}, + crate::eval::{Bi, Eval, Expr, GetEntry, Un, Vs}, std::{marker::PhantomData, ops}, }; @@ -29,10 +29,54 @@ where impl Copy for Ret where A: Copy {} +type Operand = Ret>::Out>; + +pub struct Unary { + a: A, + op: Un, +} + +impl Eval for Ret, O> +where + A: Eval, + E: GetEntry, +{ + type Out = O; + + fn eval(self, en: &mut E) -> Expr { + let Unary { a, op } = self.get(); + let x = a.eval(en); + en.get_entry().unary(op, x) + } +} + +macro_rules! impl_unary { + ($o:ident :: $f:ident ( $a:ty ) -> $r:ty) => { + impl ops::$o for Operand { + type Output = Operand, $r>; + + fn $f(self) -> Self::Output { + Ret::new(Unary { + a: self, + op: Un::$o, + }) + } + } + }; +} + +impl_unary!(Neg::neg(f32) -> f32); +impl_unary!(Neg::neg(glam::Vec2) -> glam::Vec2); +impl_unary!(Neg::neg(glam::Vec3) -> glam::Vec3); +impl_unary!(Neg::neg(glam::Vec4) -> glam::Vec4); +impl_unary!(Neg::neg(glam::Mat2) -> glam::Mat2); +impl_unary!(Neg::neg(glam::Mat3) -> glam::Mat3); +impl_unary!(Neg::neg(glam::Mat4) -> glam::Mat4); + pub struct Binary { a: A, b: B, - op: Op, + op: Bi, } impl Eval for Ret, O> @@ -51,89 +95,87 @@ where } } -type Operands = Ret>::Out>; - -macro_rules! impl_op { +macro_rules! impl_binary { ($o:ident :: $f:ident ( $a:ty, $b:ty ) -> $r:ty) => { - impl ops::$o> for $a { - type Output = Operands>, $r>; + impl ops::$o> for $a { + type Output = Operand>, $r>; - fn $f(self, b: Operands) -> Self::Output { + fn $f(self, b: Operand) -> Self::Output { Ret::new(Binary { a: self, b, - op: Op::$o, + op: Bi::$o, }) } } - impl ops::$o<$a> for Operands { - type Output = Operands, $r>; + impl ops::$o<$a> for Operand { + type Output = Operand, $r>; fn $f(self, b: $a) -> Self::Output { Ret::new(Binary { a: self, b, - op: Op::$o, + op: Bi::$o, }) } } - impl ops::$o> for Operands { - type Output = Operands>, $r>; + impl ops::$o> for Operand { + type Output = Operand>, $r>; - fn $f(self, b: Operands) -> Self::Output { + fn $f(self, b: Operand) -> Self::Output { Ret::new(Binary { a: self, b, - op: Op::$o, + op: Bi::$o, }) } } }; } -impl_op!(Add::add(f32, f32) -> f32); -impl_op!(Sub::sub(f32, f32) -> f32); -impl_op!(Mul::mul(f32, f32) -> f32); -impl_op!(Div::div(f32, f32) -> f32); -impl_op!(Rem::rem(f32, f32) -> f32); -impl_op!(Add::add(i32, i32) -> i32); -impl_op!(Sub::sub(i32, i32) -> i32); -impl_op!(Mul::mul(i32, i32) -> i32); -impl_op!(Div::div(i32, i32) -> i32); -impl_op!(Rem::rem(i32, i32) -> i32); -impl_op!(Add::add(u32, u32) -> u32); -impl_op!(Sub::sub(u32, u32) -> u32); -impl_op!(Mul::mul(u32, u32) -> u32); -impl_op!(Div::div(u32, u32) -> u32); -impl_op!(Rem::rem(u32, u32) -> u32); - -impl_op!(Add::add(glam::Vec2, glam::Vec2) -> glam::Vec2); -impl_op!(Add::add(glam::Vec3, glam::Vec3) -> glam::Vec3); -impl_op!(Add::add(glam::Vec4, glam::Vec4) -> glam::Vec4); -impl_op!(Sub::sub(glam::Vec2, glam::Vec2) -> glam::Vec2); -impl_op!(Sub::sub(glam::Vec3, glam::Vec3) -> glam::Vec3); -impl_op!(Sub::sub(glam::Vec4, glam::Vec4) -> glam::Vec4); -impl_op!(Mul::mul(f32, glam::Vec2) -> glam::Vec2); -impl_op!(Mul::mul(glam::Vec2, f32) -> glam::Vec2); -impl_op!(Mul::mul(f32, glam::Vec3) -> glam::Vec3); -impl_op!(Mul::mul(glam::Vec3, f32) -> glam::Vec3); -impl_op!(Mul::mul(f32, glam::Vec4) -> glam::Vec4); -impl_op!(Mul::mul(glam::Vec4, f32) -> glam::Vec4); - -impl_op!(Add::add(glam::Mat2, glam::Mat2) -> glam::Mat2); -impl_op!(Add::add(glam::Mat3, glam::Mat3) -> glam::Mat3); -impl_op!(Add::add(glam::Mat4, glam::Mat4) -> glam::Mat4); -impl_op!(Sub::sub(glam::Mat2, glam::Mat2) -> glam::Mat2); -impl_op!(Sub::sub(glam::Mat3, glam::Mat3) -> glam::Mat3); -impl_op!(Sub::sub(glam::Mat4, glam::Mat4) -> glam::Mat4); -impl_op!(Mul::mul(glam::Mat2, glam::Mat2) -> glam::Mat2); -impl_op!(Mul::mul(glam::Mat3, glam::Mat3) -> glam::Mat3); -impl_op!(Mul::mul(glam::Mat4, glam::Mat4) -> glam::Mat4); -impl_op!(Mul::mul(f32, glam::Mat2) -> glam::Mat2); -impl_op!(Mul::mul(f32, glam::Mat3) -> glam::Mat3); -impl_op!(Mul::mul(f32, glam::Mat4) -> glam::Mat4); -impl_op!(Mul::mul(glam::Mat2, glam::Vec2) -> glam::Vec2); -impl_op!(Mul::mul(glam::Mat3, glam::Vec3) -> glam::Vec3); -impl_op!(Mul::mul(glam::Mat4, glam::Vec4) -> glam::Vec4); +impl_binary!(Add::add(f32, f32) -> f32); +impl_binary!(Sub::sub(f32, f32) -> f32); +impl_binary!(Mul::mul(f32, f32) -> f32); +impl_binary!(Div::div(f32, f32) -> f32); +impl_binary!(Rem::rem(f32, f32) -> f32); +impl_binary!(Add::add(i32, i32) -> i32); +impl_binary!(Sub::sub(i32, i32) -> i32); +impl_binary!(Mul::mul(i32, i32) -> i32); +impl_binary!(Div::div(i32, i32) -> i32); +impl_binary!(Rem::rem(i32, i32) -> i32); +impl_binary!(Add::add(u32, u32) -> u32); +impl_binary!(Sub::sub(u32, u32) -> u32); +impl_binary!(Mul::mul(u32, u32) -> u32); +impl_binary!(Div::div(u32, u32) -> u32); +impl_binary!(Rem::rem(u32, u32) -> u32); + +impl_binary!(Add::add(glam::Vec2, glam::Vec2) -> glam::Vec2); +impl_binary!(Add::add(glam::Vec3, glam::Vec3) -> glam::Vec3); +impl_binary!(Add::add(glam::Vec4, glam::Vec4) -> glam::Vec4); +impl_binary!(Sub::sub(glam::Vec2, glam::Vec2) -> glam::Vec2); +impl_binary!(Sub::sub(glam::Vec3, glam::Vec3) -> glam::Vec3); +impl_binary!(Sub::sub(glam::Vec4, glam::Vec4) -> glam::Vec4); +impl_binary!(Mul::mul(f32, glam::Vec2) -> glam::Vec2); +impl_binary!(Mul::mul(glam::Vec2, f32) -> glam::Vec2); +impl_binary!(Mul::mul(f32, glam::Vec3) -> glam::Vec3); +impl_binary!(Mul::mul(glam::Vec3, f32) -> glam::Vec3); +impl_binary!(Mul::mul(f32, glam::Vec4) -> glam::Vec4); +impl_binary!(Mul::mul(glam::Vec4, f32) -> glam::Vec4); + +impl_binary!(Add::add(glam::Mat2, glam::Mat2) -> glam::Mat2); +impl_binary!(Add::add(glam::Mat3, glam::Mat3) -> glam::Mat3); +impl_binary!(Add::add(glam::Mat4, glam::Mat4) -> glam::Mat4); +impl_binary!(Sub::sub(glam::Mat2, glam::Mat2) -> glam::Mat2); +impl_binary!(Sub::sub(glam::Mat3, glam::Mat3) -> glam::Mat3); +impl_binary!(Sub::sub(glam::Mat4, glam::Mat4) -> glam::Mat4); +impl_binary!(Mul::mul(glam::Mat2, glam::Mat2) -> glam::Mat2); +impl_binary!(Mul::mul(glam::Mat3, glam::Mat3) -> glam::Mat3); +impl_binary!(Mul::mul(glam::Mat4, glam::Mat4) -> glam::Mat4); +impl_binary!(Mul::mul(f32, glam::Mat2) -> glam::Mat2); +impl_binary!(Mul::mul(f32, glam::Mat3) -> glam::Mat3); +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); diff --git a/examples/cube/src/main.rs b/examples/cube/src/main.rs index d512d72..81069cb 100644 --- a/examples/cube/src/main.rs +++ b/examples/cube/src/main.rs @@ -45,21 +45,24 @@ async fn run() -> Result<(), Error> { struct Map<'a> { tex: BoundTexture<'a>, sam: &'a Sampler, - step: &'a Uniform<[f32; 2]>, - // TODO: fix frame size alignment + stp: &'a Uniform<[f32; 2]>, } let screen = |vert: InVertex, Groups(map): Groups| Out { place: sl::vec4_concat(vert.0, Vec2::new(0., 1.)), color: { - let [st] = sl::thunk(sl::fragment(vert.1)); - let d1 = sl::vec2(0., map.step.clone().y()); - let d2 = sl::vec2(map.step.clone().x(), 0.); - let d3 = sl::vec2(map.step.clone().x(), map.step.y()); - (sl::texture_sample(map.tex.clone(), map.sam.clone(), st.clone()) - + sl::texture_sample(map.tex.clone(), map.sam.clone(), st.clone() + d1) - + sl::texture_sample(map.tex.clone(), map.sam.clone(), st.clone() + d2) - + sl::texture_sample(map.tex, map.sam, st + d3)) + let [s0, s1, s2, s3] = sl::thunk(sl::fragment(vert.1)); + let tex = || map.tex.clone(); + let sam = || map.sam.clone(); + let stp = || map.stp.clone(); + let d0 = sl::vec2(stp().x(), stp().y()); + 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)) * 0.25 }, }; @@ -94,8 +97,14 @@ async fn run() -> Result<(), Error> { binder.into_binding() }; + const SCREEN_FACTOR: u32 = 2; + let make_render_buf = |cx: &Context, (width, height)| { - let size = (u32::max(width * 2, 1), u32::max(height * 2, 1)); + let size = ( + u32::max(width, 1) * SCREEN_FACTOR, + u32::max(height, 1) * SCREEN_FACTOR, + ); + let color = { let data = TextureData::empty(size, Format::RgbAlpha) .expect("non-zero size") @@ -119,14 +128,19 @@ async fn run() -> Result<(), Error> { let mut render_buf = make_render_buf(&cx, window.size()); let sam = cx.make_sampler(Filter::Nearest); - let step_value = |size| <[u32; 2]>::from(size).map(|v| 0.5 / v as f32); - let step = cx.make_uniform(step_value(render_buf.size())); + let make_stp = |size| { + const SCREEN_INV: f32 = 1. / SCREEN_FACTOR as f32; + + <[u32; 2]>::from(size).map(|v| SCREEN_INV / v as f32) + }; + + let stp = cx.make_uniform(make_stp(render_buf.size())); let (bind_map, handler) = { let map = Map { tex: BoundTexture::new(render_buf.color()), sam: &sam, - step: &step, + stp: &stp, }; let mut binder = cx.make_binder(&screen_shader); @@ -217,13 +231,12 @@ async fn run() -> Result<(), Error> { if let Some(size) = ctrl.resized() { *state.render_buf = make_render_buf(&cx, size); - let v = step_value(state.render_buf.size()); - step.update(&cx, v); + stp.update(&cx, make_stp(state.render_buf.size())); let map = Map { tex: BoundTexture::new(state.render_buf.color()), sam: &sam, - step: &step, + stp: &stp, }; dunge::then!(cx.update_group(&mut state.bind_map, &handler, &map));