Skip to content

Commit

Permalink
Unit structs in derive
Browse files Browse the repository at this point in the history
  • Loading branch information
nanoqsh committed Jan 15, 2024
1 parent 2e5284d commit bfac8c8
Show file tree
Hide file tree
Showing 11 changed files with 169 additions and 90 deletions.
16 changes: 2 additions & 14 deletions dunge/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
use {
crate::{
bind::{self, Binder, GroupHandler, UniqueBinding, Update, Visit},
draw::Draw,
format::Format,
instance::Row,
layer::Layer,
mesh::{self, Mesh},
shader::Shader,
sl::IntoModule,
state::{Render, State},
texture::{
self, CopyBuffer, CopyBufferView, DrawTexture, Filter, Make, MapResult, Mapped, Sampler,
},
state::State,
texture::{self, CopyBuffer, CopyBufferView, Filter, Make, MapResult, Mapped, Sampler},
uniform::{Uniform, Value},
Vertex,
},
Expand Down Expand Up @@ -90,15 +87,6 @@ impl Context {
view.map(&self.0, tx, rx).await
}

pub fn draw_to_texture<T, D>(&self, render: &mut Render, texture: &T, draw: D)
where
T: DrawTexture,
D: Draw,
{
let view = texture.draw_texture().render_view();
self.0.draw(render, view, draw);
}

pub fn update_group<G>(
&self,
uni: &mut UniqueBinding,
Expand Down
33 changes: 31 additions & 2 deletions dunge/src/instance.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
use {
crate::{
context::Context,
sl::{ReadInstance, Ret},
state::State,
types::{self, VectorType},
uniform::{self, Value},
Instance,
},
std::marker::PhantomData,
std::{error, fmt, marker::PhantomData},
wgpu::{Buffer, RenderPass},
};

pub use dunge_shader::instance::Projection;

/// Describes a group member type projection.
/// Describes an instance member type projection.
///
/// The trait is sealed because the derive macro relies on no new types being used.
pub trait MemberProjection: private::Sealed {
Expand Down Expand Up @@ -135,8 +136,36 @@ impl<U> Row<U> {
ty: PhantomData,
}
}

pub fn update(&self, cx: &Context, data: &[U]) -> Result<(), UpdateError>
where
U: Value,
{
if data.len() != self.len as usize {
return Err(UpdateError);
}

let queue = cx.state().queue();
let data = uniform::values_as_bytes(data);
queue.write_buffer(&self.buf, 0, data.as_ref());
Ok(())
}
}

/// An error returned from the [update](crate::instance::Row::update) function.
///
/// Returned when passed data size is invalid.
#[derive(Debug)]
pub struct UpdateError;

impl fmt::Display for UpdateError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "update error: the data size is invalid")
}
}

impl error::Error for UpdateError {}

mod private {
pub trait Sealed {}
}
13 changes: 12 additions & 1 deletion dunge/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use {
crate::{
color::Rgba,
context::Error,
context::{Context, Error},
draw::Draw,
format::Format,
layer::{Layer, SetLayer},
Expand Down Expand Up @@ -99,6 +99,17 @@ impl State {
#[derive(Default)]
pub struct Render(Encoders);

impl Render {
pub fn draw_to<T, D>(&mut self, cx: &Context, texture: &T, draw: D)
where
T: DrawTexture,
D: Draw,
{
let view = texture.draw_texture().render_view();
cx.state().draw(self, view, draw);
}
}

#[derive(Clone, Copy, Default)]
pub struct Options {
clear: Option<Rgba>,
Expand Down
4 changes: 1 addition & 3 deletions dunge/tests/triangle_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,7 @@ fn render() -> Result<(), Error> {
frame.copy_texture(&buffer, &view);
});

let mut render = Render::default();
cx.draw_to_texture(&mut render, &view, draw);

Render::default().draw_to(&cx, &view, draw);
let mapped = helpers::block_on({
let (tx, rx) = helpers::oneshot();
cx.map_view(buffer.view(), tx, rx)
Expand Down
4 changes: 1 addition & 3 deletions dunge/tests/triangle_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,7 @@ fn render() -> Result<(), Error> {
frame.copy_texture(&buffer, &view);
});

let mut render = Render::default();
cx.draw_to_texture(&mut render, &view, draw);

Render::default().draw_to(&cx, &view, draw);
let mapped = helpers::block_on({
let (tx, rx) = helpers::oneshot();
cx.map_view(buffer.view(), tx, rx)
Expand Down
18 changes: 5 additions & 13 deletions dunge/tests/triangle_instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,14 @@ fn render() -> Result<(), Error> {
const R_OFFSET: f32 = -consts::TAU / 4.;

#[derive(Instance)]
struct Transform {
pos: Row<[f32; 2]>,
col: Row<[f32; 3]>,
}
struct Transform(Row<[f32; 2]>, Row<[f32; 3]>);

let triangle = |t: InInstance<Transform>, 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.pos;
let p = sl::vec2(sl::cos(x), sl::sin(y)) * TRIANGLE_SIZE + t.0;
Out {
place: sl::concat(p, Vec2::new(0., 1.)),
color: sl::vec4_with(sl::fragment(t.col), 1.),
color: sl::vec4_with(sl::fragment(t.1), 1.),
}
};

Expand All @@ -53,10 +50,7 @@ fn render() -> Result<(), Error> {
const POS: [[f32; 2]; 3] = [[0.0, -0.375], [0.433, 0.375], [-0.433, 0.375]];
const COL: [[f32; 3]; 3] = [[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]];

Transform {
pos: cx.make_row(&POS),
col: cx.make_row(&COL),
}
Transform(cx.make_row(&POS), cx.make_row(&COL))
};

let buffer = cx.make_copy_buffer(SIZE);
Expand All @@ -71,9 +65,7 @@ fn render() -> Result<(), Error> {
frame.copy_texture(&buffer, &view);
});

let mut render = Render::default();
cx.draw_to_texture(&mut render, &view, draw);

Render::default().draw_to(&cx, &view, draw);
let mapped = helpers::block_on({
let (tx, rx) = helpers::oneshot();
cx.map_view(buffer.view(), tx, rx)
Expand Down
28 changes: 7 additions & 21 deletions dunge/tests/triangle_vertex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,11 @@ fn render() -> Result<(), Error> {

#[repr(C)]
#[derive(Vertex)]
struct Vert {
pos: [f32; 2],
col: [f32; 3],
}
struct Vert([f32; 2], [f32; 3]);

let triangle = |vert: InVertex<Vert>| Out {
place: sl::concat(vert.pos, Vec2::new(0., 1.)),
color: sl::vec4_with(sl::fragment(vert.col), 1.),
place: sl::concat(vert.0, Vec2::new(0., 1.)),
color: sl::vec4_with(sl::fragment(vert.1), 1.),
};

let cx = helpers::block_on(dunge::context())?;
Expand All @@ -47,18 +44,9 @@ fn render() -> Result<(), Error> {
use mesh::Data;

const VERTS: [Vert; 3] = [
Vert {
pos: [0., -0.75],
col: [1., 0., 0.],
},
Vert {
pos: [0.866, 0.75],
col: [0., 1., 0.],
},
Vert {
pos: [-0.866, 0.75],
col: [0., 0., 1.],
},
Vert([0., -0.75], [1., 0., 0.]),
Vert([0.866, 0.75], [0., 1., 0.]),
Vert([-0.866, 0.75], [0., 0., 1.]),
];

let data = Data::from_verts(&VERTS);
Expand All @@ -72,9 +60,7 @@ fn render() -> Result<(), Error> {
frame.copy_texture(&buffer, &view);
});

let mut render = Render::default();
cx.draw_to_texture(&mut render, &view, draw);

Render::default().draw_to(&cx, &view, draw);
let mapped = helpers::block_on({
let (tx, rx) = helpers::oneshot();
cx.map_view(buffer.view(), tx, rx)
Expand Down
45 changes: 35 additions & 10 deletions dunge_macros/src/group.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use {
crate::member,
proc_macro2::{Span, TokenStream},
syn::{spanned::Spanned, Data, DataStruct, DeriveInput, GenericParam, Ident, Lifetime},
syn::{spanned::Spanned, Data, DataStruct, DeriveInput, Fields, GenericParam, Ident, Lifetime},
};

pub(crate) fn derive(input: DeriveInput) -> TokenStream {
Expand All @@ -13,6 +13,16 @@ pub(crate) fn derive(input: DeriveInput) -> TokenStream {
};
};

let named = match &fields {
Fields::Named(_) => true,
Fields::Unnamed(_) => false,
Fields::Unit => {
return quote::quote_spanned! { input.ident.span() =>
::std::compile_error!("the group type cannot be a unit struct");
}
}
};

let mut lts = Vec::with_capacity(input.generics.params.len());
for param in input.generics.params {
let GenericParam::Lifetime(param) = param else {
Expand Down Expand Up @@ -48,7 +58,6 @@ pub(crate) fn derive(input: DeriveInput) -> TokenStream {
};

let static_lts = lts.iter().map(|_| &static_lt);

let anon_lt = Lifetime {
apostrophe: Span::call_site(),
ident: Ident::new("_", Span::call_site()),
Expand All @@ -73,7 +82,11 @@ pub(crate) fn derive(input: DeriveInput) -> TokenStream {
let group_fields = iter::zip(0.., &fields).map(|(index, field)| {
let ident = member::make(index, field.ident.clone());
let ty = &field.ty;
quote::quote! { #ident: <#ty as ::dunge::group::MemberProjection>::Field }
if named {
quote::quote! { #ident: <#ty as ::dunge::group::MemberProjection>::Field }
} else {
quote::quote! { <#ty as ::dunge::group::MemberProjection>::Field }
}
});

let group_member_projections = iter::zip(0.., &fields).map(|(index, field)| {
Expand All @@ -82,6 +95,20 @@ pub(crate) fn derive(input: DeriveInput) -> TokenStream {
quote::quote! { #ident: <#ty as ::dunge::group::MemberProjection>::member_projection(id, #index, out.clone()) }
});

let projection = if named {
quote::quote! {
struct #projection_name<#(#lts),*> {
#(#group_fields),*,
}
}
} else {
quote::quote! {
struct #projection_name<#(#lts),*>(
#(#group_fields),*,
);
}
};

quote::quote! {
impl<#(#lts),*> ::dunge::Group for #name<#(#lts),*> {
type Projection = #projection_name<#(#static_lts),*>;
Expand All @@ -96,9 +123,7 @@ pub(crate) fn derive(input: DeriveInput) -> TokenStream {
}
}

struct #projection_name<#(#lts),*> {
#(#group_fields),*,
}
#projection

impl<#(#lts),*> ::dunge::group::Projection for #projection_name<#(#lts),*> {
fn projection(id: ::core::primitive::u32, out: ::dunge::sl::GlobalOut) -> Self {
Expand Down Expand Up @@ -183,10 +208,10 @@ mod tests {
}
}

struct MapProjection<'a> {
0: <BoundTexture<'a> as ::dunge::group::MemberProjection>::Field,
1: <&'a Sampler as ::dunge::group::MemberProjection>::Field,
}
struct MapProjection<'a>(
<BoundTexture<'a> as ::dunge::group::MemberProjection>::Field,
<&'a Sampler as ::dunge::group::MemberProjection>::Field,
);
impl<'a> ::dunge::group::Projection for MapProjection<'a> {
fn projection(id: ::core::primitive::u32, out: ::dunge::sl::GlobalOut) -> Self {
Expand Down
Loading

0 comments on commit bfac8c8

Please sign in to comment.