1#![doc(html_logo_url = "https://64-tesseract.ftp.sh/tesseract.gif", html_favicon_url = "https://64-tesseract.ftp.sh/tesseract.gif")]
2#![doc = include_str!("../README.md")]
3
4pub use wgpu;
5#[cfg(feature = "sync")]
6pub use pollster;
7#[cfg(feature = "winit")]
8pub use winit;
9
10mod macromath;
11pub mod bindgroup;
12pub mod buffer;
13pub mod pipeline;
14pub mod sampler;
15pub mod shaderprimitive;
16pub mod shaderstruct;
17pub mod texture;
18pub mod typemap;
19pub mod vertexformat;
20pub mod vertexstruct;
21#[cfg(feature = "winit")]
22pub mod winitutils;
23
24pub mod prelude {
25 pub use crate::{
26 bindgroup::*,
27 buffer::*,
28 pipeline::*,
29 sampler::*,
30 shaderprimitive,
31 shaderstruct::*,
32 texture::*,
33 vertexformat,
34 vertexstruct::*,
35 *,
36 };
37 #[cfg(feature = "winit")]
38 pub use crate::winitutils::*;
39}
40
41
42#[macro_export]
78macro_rules! render_context {
79 { $struct:ident {
80 features: [
81 $( $feature:ident ),* $(,)?
82 ],
83 limits: {
84 $( $limit:ident : $limitval:expr ),* $(,)?
85 },
86 bind_groups: [
87 $( $bindgroupnum:tt => $bindgroup:ty ),* $(,)?
88 ],
89 pipelines: [
90 $( $pipelinenum:tt => $pipeline:ty ),* $(,)?
91 ] $(,)?
92 } } => {
93 typemap! { BindGroupLayoutTypes [
94 $( $bindgroupnum => $crate::bindgroup::MewBindGroupLayout<$bindgroup> , )*
95 ] }
96
97 typemap! { PipelineLayoutTypes [
98 $( $pipelinenum => $crate::pipeline::MewPipelineLayout<$pipeline> , )*
99 ] }
100
101 pub struct $struct {
102 pub instance: $crate::wgpu::Instance,
103 pub adapter: $crate::wgpu::Adapter,
104 pub device: $crate::wgpu::Device,
105 pub queue: $crate::wgpu::Queue,
106 bind_group_layouts: BindGroupLayoutTypes,
107 pipeline_layouts: PipelineLayoutTypes,
108 }
109
110 $crate::render_context_sync! { $struct }
111
112 impl $struct {
113 pub async fn new(backends: $crate::wgpu::Backends) -> Result<Self, Box<dyn ::std::error::Error>> {
114 let instance = $crate::wgpu::Instance::new(&wgpu::InstanceDescriptor {
115 backends,
116 flags: $crate::wgpu::InstanceFlags::empty(),
117 ..Default::default()
118 });
119
120 let adapter = instance.request_adapter(
121 &$crate::wgpu::RequestAdapterOptions {
122 power_preference: $crate::wgpu::PowerPreference::default(),
123 compatible_surface: None,
124 force_fallback_adapter: false,
125 },
126 ).await.inspect_err(|e| eprintln!("Could not get display adapter: {e}"))?;
127
128 let (device, queue) = adapter.request_device(
129 &$crate::wgpu::DeviceDescriptor {
130 label: Some("Device"),
131 required_features: $crate::wgpu::Features::empty() $( | $crate::wgpu::Features::$feature )*,
132 required_limits: $crate::wgpu::Limits {
133 $( $limit: $limitval, )*
134 ..Default::default()
135 },
136 memory_hints: Default::default(),
137 trace: $crate::wgpu::Trace::Off,
138 }
139 ).await.inspect_err(|e| eprintln!("Could not get display device: {e}"))?;
140
141 let bind_group_layouts = BindGroupLayoutTypes (
142 $( {
143 let desc = <$bindgroup>::layout_desc();
144 let layout = device.create_bind_group_layout(&desc);
145 $crate::bindgroup::MewBindGroupLayout::new(layout)
146 }, )*
147 );
148
149 let pipeline_layouts = PipelineLayoutTypes (
150 $( {
151 let bind_groups = <$pipeline>::get_layouts_from_refs(&bind_group_layouts);
152 let bind_groups_arr = <$pipeline>::bind_group_layouts(&bind_groups);
153 let desc = <$pipeline>::layout_desc(&bind_groups_arr);
154 let layout = device.create_pipeline_layout(&desc);
155 $crate::pipeline::MewPipelineLayout::new(layout)
156 }, )*
157 );
158
159 Ok(Self {
160 instance,
161 adapter,
162 device,
163 queue,
164 bind_group_layouts,
165 pipeline_layouts,
166 })
167 }
168
169 pub fn new_buffer<BUFFER: $crate::buffer::MewBuffer>(&self, inner_size: u64) -> BUFFER {
170 let raw_buffer = self.device.create_buffer(&BUFFER::buffer_desc(inner_size));
171 BUFFER::new(raw_buffer)
172 }
173
174 pub fn new_sampler<SAMPLER: $crate::sampler::MewSampler>(&self) -> SAMPLER {
175 let raw_sampler = self.device.create_sampler(&SAMPLER::buffer_desc());
176 SAMPLER::new(raw_sampler)
177 }
178
179 pub fn new_texture<TEXTURE: $crate::texture::MewTexture>(&self, inner_size: (u32, u32, u32)) -> TEXTURE {
180 let raw_texture = self.device.create_texture(&TEXTURE::buffer_desc(inner_size));
181 TEXTURE::new(raw_texture)
182 }
183
184 pub fn new_bind_group<BIND: $crate::bindgroup::MewBindGroup>(&self, buffers: BIND::BufferSet) -> BIND
185 where
186 BindGroupLayoutTypes: AsRef<$crate::bindgroup::MewBindGroupLayout<BIND>>
187 {
188 let raw_bind_group = {
189 let layout: &$crate::bindgroup::MewBindGroupLayout<BIND> = self.bind_group_layouts.as_ref();
190 let entries = BIND::bind_group_entries(&buffers);
191 let desc = BIND::bind_group_desc(layout, &entries);
192 self.device.create_bind_group(&desc)
193 };
194 BIND::new(raw_bind_group, buffers)
195 }
196
197 pub fn new_pipeline<PIPE: $crate::pipeline::MewPipeline>(
198 &self,
199 surface_fmt: Option<$crate::wgpu::TextureFormat>,
200 shader: &$crate::wgpu::ShaderModule,
201 vertex_entry: Option<&str>,
202 fragment_entry: Option<&str>,
203 ) -> PIPE
204 where
205 PipelineLayoutTypes: AsRef<$crate::pipeline::MewPipelineLayout<PIPE>>
206 {
207 let raw_pipeline = {
208 let layout: &$crate::pipeline::MewPipelineLayout<PIPE> = self.pipeline_layouts.as_ref();
209 let targets = PIPE::fragment_targets(surface_fmt);
210 let desc = &PIPE::pipeline_desc(layout, shader, vertex_entry, fragment_entry, &targets);
211 self.device.create_render_pipeline(desc)
212 };
213 PIPE::new(raw_pipeline)
214 }
215 }
216
217 impl $crate::MewRenderContext for $struct {
218 fn instance(&self) -> &wgpu::Instance {
219 &self.instance
220 }
221
222 fn adapter(&self) -> &wgpu::Adapter {
223 &self.adapter
224 }
225
226 fn device(&self) -> &wgpu::Device {
227 &self.device
228 }
229
230 fn queue(&self) -> &wgpu::Queue {
231 &self.queue
232 }
233 }
234 };
235}
236
237#[cfg(feature = "sync")]
238#[macro_export]
239macro_rules! render_context_sync {
240 { $struct:ident } => {
241 impl $struct {
242 pub fn poll_new(backends: $crate::wgpu::Backends) -> Result<Self, Box<dyn ::std::error::Error>> {
243 $crate::pollster::block_on(Self::new(backends))
244 }
245 }
246 };
247}
248
249#[cfg(not(feature = "sync"))]
250#[macro_export]
251macro_rules! render_context_sync {
252 { $struct:ident } => {};
253}
254
255
256
257
258pub trait MewRenderContext {
259 fn instance(&self) -> &wgpu::Instance;
260 fn adapter(&self) -> &wgpu::Adapter;
261 fn device(&self) -> &wgpu::Device;
262 fn queue(&self) -> &wgpu::Queue;
263}