Skip to content

Commit

Permalink
Use instance in shader
Browse files Browse the repository at this point in the history
  • Loading branch information
nanoqsh committed Jan 12, 2024
1 parent 3be719e commit 7189aa4
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 74 deletions.
86 changes: 50 additions & 36 deletions dunge/src/shader.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use {
crate::{
bind::TypedGroup,
sl::{Info, IntoModule, Module, Stages},
sl::{InstInfo, IntoModule, Module, Stages, VertInfo},
state::State,
types::{MemberType, VectorType},
},
std::marker::PhantomData,
wgpu::{PipelineLayout, ShaderModule, VertexAttribute, VertexBufferLayout},
wgpu::{BufferAddress, PipelineLayout, ShaderModule, VertexAttribute, VertexBufferLayout},
};

pub struct Shader<V> {
Expand Down Expand Up @@ -42,7 +42,7 @@ impl<V> Shader<V> {

fn layout(Vertex { size, attributes }: &Vertex) -> VertexBufferLayout {
VertexBufferLayout {
array_stride: *size as BufferAddress,
array_stride: *size,
step_mode: VertexStepMode::Vertex,
attributes,
}
Expand All @@ -57,7 +57,7 @@ impl<V> Shader<V> {
}

struct Vertex {
size: usize,
size: BufferAddress,
attributes: Box<[VertexAttribute]>,
}

Expand Down Expand Up @@ -152,48 +152,62 @@ impl Inner {
state.device().create_pipeline_layout(&desc)
};

let vertex = {
let vert = |info: Info| {
let mut offset = 0;
let mut shader_location = 0;
let attr = |vecty| {
let format = match vecty {
VectorType::Vec2f => VertexFormat::Float32x2,
VectorType::Vec3f => VertexFormat::Float32x3,
VectorType::Vec4f => VertexFormat::Float32x4,
VectorType::Vec2u => VertexFormat::Uint32x2,
VectorType::Vec3u => VertexFormat::Uint32x3,
VectorType::Vec4u => VertexFormat::Uint32x4,
VectorType::Vec2i => VertexFormat::Sint32x2,
VectorType::Vec3i => VertexFormat::Sint32x3,
VectorType::Vec4i => VertexFormat::Sint32x4,
};

let attr = VertexAttribute {
format,
offset,
shader_location,
};

offset += format.size();
shader_location += 1;
attr
let to_format = |vecty| match vecty {
VectorType::Vec2f => VertexFormat::Float32x2,
VectorType::Vec3f => VertexFormat::Float32x3,
VectorType::Vec4f => VertexFormat::Float32x4,
VectorType::Vec2u => VertexFormat::Uint32x2,
VectorType::Vec3u => VertexFormat::Uint32x3,
VectorType::Vec4u => VertexFormat::Uint32x4,
VectorType::Vec2i => VertexFormat::Sint32x2,
VectorType::Vec3i => VertexFormat::Sint32x3,
VectorType::Vec4i => VertexFormat::Sint32x4,
};

let mut vertex = Vec::with_capacity(cx.count_verts());
let vert = |info: VertInfo| {
let mut offset = 0;
let mut location = info.start_location;
let attr = |vecty| {
let format = to_format(vecty);
let attr = VertexAttribute {
format,
offset,
shader_location: location,
};

Vertex {
size: info.size,
attributes: info.def.into_iter().map(attr).collect(),
}
offset += format.size();
location += 1;
attr
};

Vertex {
size: info.size as BufferAddress,
attributes: info.def.into_iter().map(attr).collect(),
}
};

vertex.extend(cx.verts().map(vert));
let inst = |info: InstInfo| {
let format = to_format(info.vecty);
let attr = VertexAttribute {
format,
offset: 0,
shader_location: info.location,
};

cx.verts().map(vert).collect()
Vertex {
size: format.size(),
attributes: Box::from([attr]),
}
};

vertex.extend(cx.insts().map(inst));
Self {
id: state.next_shader_id(),
module,
layout,
vertex,
vertex: Box::from(vertex),
groups,
}
}
Expand Down
68 changes: 56 additions & 12 deletions dunge_shader/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,26 +33,39 @@ impl Stages {
}
}

#[derive(Clone, Copy)]
pub(crate) enum InputInfo {
Vert(Info),
Inst(Info),
Vert(VertInfo),
Inst(InstInfo),
Index,
}

impl InputInfo {
fn into_vert(self) -> Option<Info> {
fn as_vert(&self) -> Option<VertInfo> {
match self {
Self::Vert(info) => Some(*info),
_ => None,
}
}

fn as_inst(&self) -> Option<InstInfo> {
match self {
Self::Vert(info) => Some(info),
Self::Inst(info) => Some(*info),
_ => None,
}
}
}

#[derive(Clone, Copy)]
pub struct Info {
pub struct VertInfo {
pub def: Define<VectorType>,
pub size: usize,
pub start_location: u32,
}

#[derive(Clone, Copy)]
pub struct InstInfo {
pub vecty: VectorType,
pub location: u32,
}

pub(crate) struct GroupEntry {
Expand Down Expand Up @@ -84,6 +97,7 @@ fn countdown(v: &mut u8, msg: &str) {
pub struct Context {
pub(crate) inputs: Vec<InputInfo>,
pub(crate) groups: Vec<GroupEntry>,
location: u32,
limits: Limits,
}

Expand All @@ -92,6 +106,7 @@ impl Context {
Self {
inputs: vec![],
groups: vec![],
location: 0,
limits: Limits {
index: 1,
verts: 1,
Expand All @@ -111,15 +126,26 @@ impl Context {
fn add_vertex(&mut self, def: Define<VectorType>, size: usize) -> u32 {
countdown(&mut self.limits.verts, "too many vertices in the shader");
let id = self.inputs.len() as u32;
let info = Info { def, size };
let info = VertInfo {
def,
size,
start_location: self.location,
};

self.location += def.len() as u32;
self.inputs.push(InputInfo::Vert(info));
id
}

fn add_instance(&mut self, def: Define<VectorType>, size: usize) -> u32 {
fn add_instance(&mut self, vec: VectorType) -> u32 {
countdown(&mut self.limits.insts, "too many instances in the shader");
let id = self.inputs.len() as u32;
let info = Info { def, size };
let info = InstInfo {
vecty: vec,
location: self.location,
};

self.location += 1;
self.inputs.push(InputInfo::Inst(info));
id
}
Expand All @@ -139,8 +165,21 @@ impl Context {
}

#[doc(hidden)]
pub fn verts(&self) -> impl Iterator<Item = Info> + '_ {
self.inputs.iter().copied().filter_map(InputInfo::into_vert)
pub fn count_verts(&self) -> usize {
self.inputs
.iter()
.filter(|info| matches!(info, InputInfo::Vert(_) | InputInfo::Inst(_)))
.count()
}

#[doc(hidden)]
pub fn verts(&self) -> impl Iterator<Item = VertInfo> + '_ {
self.inputs.iter().filter_map(InputInfo::as_vert)
}

#[doc(hidden)]
pub fn insts(&self) -> impl Iterator<Item = InstInfo> + '_ {
self.inputs.iter().filter_map(InputInfo::as_inst)
}

#[doc(hidden)]
Expand Down Expand Up @@ -222,7 +261,12 @@ where
type Instance = I;

fn from_context_input(cx: &mut Context) -> Self {
let id = cx.add_instance(I::DEF, mem::size_of::<I>());
let mut id = None;
for vec in I::DEF {
id.get_or_insert(cx.add_instance(vec));
}

let id = id.expect("the instance must have at least one field");
Self(instance::Projection::projection(id))
}
}
Expand Down
8 changes: 8 additions & 0 deletions dunge_shader/src/define.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ impl<T> Define<T> {
pub const fn new(s: &'static [T]) -> Self {
Self(s)
}

pub const fn len(&self) -> usize {
self.0.len()
}

pub const fn is_empty(&self) -> bool {
self.0.is_empty()
}
}

impl<T> Clone for Define<T> {
Expand Down
Loading

0 comments on commit 7189aa4

Please sign in to comment.