Skip to content

Commit

Permalink
Unary operator
Browse files Browse the repository at this point in the history
  • Loading branch information
nanoqsh committed Feb 5, 2024
1 parent beaa98f commit 412c785
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 87 deletions.
4 changes: 2 additions & 2 deletions dunge/tests/shader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ type Error = Box<dyn error::Error>;
#[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 {
Expand Down
4 changes: 2 additions & 2 deletions dunge/tests/shader.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ struct VertexOutput {

@vertex
fn vs() -> VertexOutput {
let _e6: mat2x2<f32> = mat2x2<f32>(vec2<f32>(1f, 0f), vec2<f32>(0f, 1f));
return VertexOutput(((vec4<f32>(_e6[0], (_e6[0] + _e6[1])) * f32(1i)) * vec3<f32>(1f, 1f, 1f).z));
let _e7: mat2x2<f32> = -(mat2x2<f32>(vec2<f32>(1f, 0f), vec2<f32>(0f, 1f)));
return VertexOutput(((vec4<f32>(_e7[0], (_e7[0] + -(_e7[1]))) * f32(1i)) * vec3<f32>(1f, 1f, 1f).z));
}

@fragment
Expand Down
35 changes: 29 additions & 6 deletions dunge_shader/src/eval.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::marker::PhantomData;
use {
crate::{
context::{Context, InputInfo, InstInfo, Stages, VertInfo},
Expand All @@ -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<O>(cx: Context, output: O) -> Module
Expand Down Expand Up @@ -564,15 +563,27 @@ 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,
Div,
Rem,
}

impl Op {
impl Bi {
fn operator(self) -> BinaryOperator {
match self {
Self::Add => BinaryOperator::Add,
Expand Down Expand Up @@ -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,
Expand Down
162 changes: 102 additions & 60 deletions dunge_shader/src/ret.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use {
crate::eval::{Eval, Expr, GetEntry, Op, Vs},
crate::eval::{Bi, Eval, Expr, GetEntry, Un, Vs},
std::{marker::PhantomData, ops},
};

Expand Down Expand Up @@ -29,10 +29,54 @@ where

impl<A, T> Copy for Ret<A, T> where A: Copy {}

type Operand<A, B> = Ret<A, <B as Eval<Vs>>::Out>;

pub struct Unary<A> {
a: A,
op: Un,
}

impl<A, O, E> Eval<E> for Ret<Unary<A>, O>
where
A: Eval<E>,
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<A> ops::$o for Operand<A, $a> {
type Output = Operand<Unary<Self>, $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, B> {
a: A,
b: B,
op: Op,
op: Bi,
}

impl<A, B, O, E> Eval<E> for Ret<Binary<A, B>, O>
Expand All @@ -51,89 +95,87 @@ where
}
}

type Operands<A, B> = Ret<A, <B as Eval<Vs>>::Out>;

macro_rules! impl_op {
macro_rules! impl_binary {
($o:ident :: $f:ident ( $a:ty, $b:ty ) -> $r:ty) => {
impl<A> ops::$o<Operands<A, $b>> for $a {
type Output = Operands<Binary<Self, Operands<A, $b>>, $r>;
impl<A> ops::$o<Operand<A, $b>> for $a {
type Output = Operand<Binary<Self, Operand<A, $b>>, $r>;

fn $f(self, b: Operands<A, $b>) -> Self::Output {
fn $f(self, b: Operand<A, $b>) -> Self::Output {
Ret::new(Binary {
a: self,
b,
op: Op::$o,
op: Bi::$o,
})
}
}

impl<A> ops::$o<$a> for Operands<A, $b> {
type Output = Operands<Binary<Self, $a>, $r>;
impl<A> ops::$o<$a> for Operand<A, $b> {
type Output = Operand<Binary<Self, $a>, $r>;

fn $f(self, b: $a) -> Self::Output {
Ret::new(Binary {
a: self,
b,
op: Op::$o,
op: Bi::$o,
})
}
}

impl<A, B> ops::$o<Operands<B, $b>> for Operands<A, $a> {
type Output = Operands<Binary<Self, Operands<B, $b>>, $r>;
impl<A, B> ops::$o<Operand<B, $b>> for Operand<A, $a> {
type Output = Operand<Binary<Self, Operand<B, $b>>, $r>;

fn $f(self, b: Operands<B, $b>) -> Self::Output {
fn $f(self, b: Operand<B, $b>) -> 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);
47 changes: 30 additions & 17 deletions examples/cube/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Screen>, Groups(map): Groups<Map>| 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
},
};
Expand Down Expand Up @@ -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")
Expand All @@ -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);
Expand Down Expand Up @@ -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));
Expand Down

0 comments on commit 412c785

Please sign in to comment.