1use std::{
2 any::TypeId,
3 marker::PhantomData,
4 ops::Deref,
5};
6
7
8#[macro_export]
34macro_rules! pipeline {
35 { @texturefmt $var:ident , SURFACE } => {
36 $var
37 };
38 { @texturefmt $var:ident , $fragmentfmt:ident } => {
39 Some($crate::wgpu::TextureFormat::$fragmentfmt)
40 };
41
42 { $struct:ident {
43 bind_groups : [
44 $( $bindgroupnum:tt => $bindgroup:ty ),* $(,)?
45 ],
46 vertex_types: [
47 $( $vertexnum:tt => $vertexty:ty ),* $(,)?
48 ],
49 fragment_targets: [
50 $( $fragmentnum:tt => $blend:ident $mask:ident as $fragmentfmt:ident ),* $(,)?
51 ],
52 push_constants: [
53 $( $pushfrom:literal .. $pushto:literal @ $pushshaderstage:ident ),* $(,)?
54 ],
55 depth: $depthfmt:expr,
56 cull: $cull:expr,
57 } } => {
58 #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
59 pub struct $struct {
60 pipeline: $crate::wgpu::RenderPipeline,
61 }
62
63 impl ::std::ops::Deref for $struct {
64 type Target = $crate::wgpu::RenderPipeline;
65 fn deref(&self) -> &Self::Target {
66 &self.pipeline
67 }
68 }
69
70 impl $crate::pipeline::MewPipeline for $struct {
85 type BindGroupSet = ( $( $bindgroup , )* );
86 type BindGroupArray<T> = [T; $crate::len! { $( $bindgroupnum )* }];
88 type VertexArray<T> = [T; $crate::len! { $( $vertexnum )* }];
89 type FragmentArray<T> = [T; $crate::len! { $( $fragmentnum )* }];
90
91 fn new(pipeline: $crate::wgpu::RenderPipeline) -> Self {
92 Self {
93 pipeline,
94 }
95 }
96
97 fn bind_group_layout_types_array() -> Self::BindGroupArray<(::std::any::TypeId, $crate::wgpu::BindGroupLayoutDescriptor<'static>)> {
111 use $crate::bindgroup::MewBindGroup;
112 [ $( (
113 ::std::any::TypeId::of::<$bindgroup>(),
114 <$bindgroup>::layout_desc(),
115 ), )* ]
116 }
117
118 fn map_bind_group_array<A, B, F: FnMut(A) -> B>(array: Self::BindGroupArray<A>, f: F) -> Self::BindGroupArray<B> {
119 array.map(f)
120 }
121
122 fn bind_group_ref_array(layout_array: &Self::BindGroupArray<$crate::wgpu::BindGroupLayout>) -> Self::BindGroupArray<&$crate::wgpu::BindGroupLayout> {
123 layout_array.each_ref()
124 }
125
126 fn layout_desc<'a, 'b>(bind_group_layouts: &'a Self::BindGroupArray<&'b $crate::wgpu::BindGroupLayout>) -> $crate::wgpu::PipelineLayoutDescriptor<'a> {
127 $crate::wgpu::PipelineLayoutDescriptor {
128 label: Some(concat!(stringify!($struct), " Layout Descriptor")),
129 bind_group_layouts,
130 push_constant_ranges: &[ $(
131 $crate::wgpu::PushConstantRange {
132 stages: $crate::wgpu::ShaderStages::$pushshaderstage,
133 range: $pushfrom..$pushto,
134 },
135 )* ],
136 }
137 }
138
139 fn fragment_targets<'a>(surface_fmt: Option<$crate::wgpu::TextureFormat>) -> Self::FragmentArray<Option<$crate::wgpu::ColorTargetState>> {
140 [ $( $crate::pipeline! { @texturefmt surface_fmt, $fragmentfmt }.map(|format| $crate::wgpu::ColorTargetState {
141 format,
142 blend: Some($crate::wgpu::BlendState::$blend),
143 write_mask: $crate::wgpu::ColorWrites::$mask,
144 }), )* ]
145 }
146
147 fn pipeline_desc<'a>(
148 layout: &'a $crate::pipeline::MewPipelineLayout<Self>,
149 shader: &'a $crate::wgpu::ShaderModule,
150 vertex_entry: Option<&'a str>,
151 fragment_entry: Option<&'a str>,
152 fragment_targets: &'a Self::FragmentArray<Option<$crate::wgpu::ColorTargetState>>,
153 ) -> $crate::wgpu::RenderPipelineDescriptor<'a> {
154 use ::std::sync::LazyLock;
155 #[allow(unused_imports)]
156 use $crate::wgpu::{
157 Face::*,
158 TextureFormat::*,
159 };
160
161 static VERTICES: LazyLock<<$struct as $crate::pipeline::MewPipeline>::VertexArray<$crate::wgpu::VertexBufferLayout<'static>>> = LazyLock::new(|| {
162 #[allow(unused_imports)]
163 use $crate::vertexstruct::MewVertexStruct;
164 [ $( <$vertexty>::vertex_layout(), )* ]
165 });
166
167 $crate::wgpu::RenderPipelineDescriptor {
168 label: Some(concat!(stringify!($struct), " Descriptor")),
169 layout: Some(layout),
170 vertex: $crate::wgpu::VertexState {
171 module: shader,
172 entry_point: vertex_entry,
173 compilation_options: Default::default(),
174 buffers: &*VERTICES,
175 },
176 fragment: Some($crate::wgpu::FragmentState {
177 module: shader,
178 entry_point: fragment_entry,
179 compilation_options: Default::default(),
180 targets: fragment_targets,
181 }),
182 primitive: $crate::wgpu::PrimitiveState {
183 topology: $crate::wgpu::PrimitiveTopology::TriangleList,
184 strip_index_format: None,
185 front_face: $crate::wgpu::FrontFace::Ccw,
186 cull_mode: $cull,
187 polygon_mode: $crate::wgpu::PolygonMode::Fill,
188 unclipped_depth: false,
189 conservative: false,
190 },
191 depth_stencil: $depthfmt.map(|format| $crate::wgpu::DepthStencilState {
192 format,
193 depth_write_enabled: true,
194 depth_compare: $crate::wgpu::CompareFunction::Less,
195 stencil: Default::default(),
196 bias: Default::default(),
197 }),
198 multisample: $crate::wgpu::MultisampleState {
199 count: 1,
200 mask: !0,
201 alpha_to_coverage_enabled: true,
202 },
203 multiview: None,
204 cache: None,
205 }
206 }
207 }
208 };
209}
210pub use pipeline;
211
212
213pub trait MewPipeline {
222 type BindGroupSet;
224 type BindGroupArray<T>;
229 type VertexArray<T>;
232 type FragmentArray<T>;
235
236 fn new(pipeline: wgpu::RenderPipeline) -> Self;
238
239 fn bind_group_layout_types_array() -> Self::BindGroupArray<(TypeId, wgpu::BindGroupLayoutDescriptor<'static>)>;
241 fn map_bind_group_array<A, B, F: FnMut(A) -> B>(array: Self::BindGroupArray<A>, f: F) -> Self::BindGroupArray<B>;
242
243 fn bind_group_ref_array(layout_array: &Self::BindGroupArray<wgpu::BindGroupLayout>) -> Self::BindGroupArray<&wgpu::BindGroupLayout>;
244
245 fn layout_desc<'a, 'b>(bind_group_layouts: &'a Self::BindGroupArray<&'b wgpu::BindGroupLayout>) -> wgpu::PipelineLayoutDescriptor<'a>;
249
250 fn fragment_targets<'a>(surface_fmt: Option<wgpu::TextureFormat>) -> Self::FragmentArray<Option<wgpu::ColorTargetState>>;
251
252 fn pipeline_desc<'a>(
253 layout: &'a MewPipelineLayout<Self>,
254 shader: &'a wgpu::ShaderModule,
255 vertex_entry: Option<&'a str>,
256 fragment_entry: Option<&'a str>,
257 fragment_targets: &'a Self::FragmentArray<Option<wgpu::ColorTargetState>>,
258 ) -> wgpu::RenderPipelineDescriptor<'a>;
259}
260
261
262pub struct MewPipelineLayout<PIPE: ?Sized> {
265 layout: wgpu::PipelineLayout,
266 _marker: PhantomData<PIPE>,
267}
268impl<PIPE: ?Sized> Deref for MewPipelineLayout<PIPE> {
269 type Target = wgpu::PipelineLayout;
270 fn deref(&self) -> &Self::Target {
271 &self.layout
272 }
273}
274impl<PIPE: ?Sized> MewPipelineLayout<PIPE> {
275 pub fn new(layout: wgpu::PipelineLayout) -> Self {
277 Self {
278 layout,
279 _marker: PhantomData,
280 }
281 }
282}