mew/texture.rs
1pub mod sample_type {
2 //! Texture binding sample types. Enums exploded into `const`s because
3 //! `Float` has a useless `filterable` property which is annoying to write out.
4
5 /// <code>[wgpu::TextureSampleType::Float](https://docs.rs/wgpu/latest/wgpu/enum.TextureSampleType.html#variant.Float) { filterable: true, }</code>
6 pub const FLOAT: wgpu::TextureSampleType = wgpu::TextureSampleType::Float { filterable: true, };
7 /// <code>[wgpu::TextureSampleType::Float](https://docs.rs/wgpu/latest/wgpu/enum.TextureSampleType.html#variant.Float) { filterable: false, } // wtf why</code>
8 pub const FLOAT_FILTERABLE_FALSE_IF_YOU_REALLY_CARE_LIKE_WHATS_THE_POINT_YOU_CAN_SET_FILTERABLE_TRUE_AND_STILL_USE_IT_WITH_A_NON_FILTERING_SAMPLER: wgpu::TextureSampleType = wgpu::TextureSampleType::Float { filterable: false, }; // wtf why
9 /// [`wgpu::TextureSampleType::Depth`](https://docs.rs/wgpu/latest/wgpu/enum.TextureSampleType.html#variant.Depth)
10 pub const DEPTH: wgpu::TextureSampleType = wgpu::TextureSampleType::Depth;
11 /// [`wgpu::TextureSampleType::Sint`](https://docs.rs/wgpu/latest/wgpu/enum.TextureSampleType.html#variant.Sint)
12 pub const SINT: wgpu::TextureSampleType = wgpu::TextureSampleType::Sint;
13 /// [`wgpu::TextureSampleType::Uint`](https://docs.rs/wgpu/latest/wgpu/enum.TextureSampleType.html#variant.Uint)
14 pub const UINT: wgpu::TextureSampleType = wgpu::TextureSampleType::Uint;
15}
16
17/// Define a type of texture - not its size or format, but a set of properties.
18///
19/// More specifically, its
20/// [`wgpu::TextureUsages`](https://docs.rs/wgpu/latest/wgpu/struct.TextureUsages.html),
21/// [`wgpu::TextureViewDimension`](https://docs.rs/wgpu/latest/wgpu/enum.TextureViewDimension.html),
22/// & the binding's
23/// [`wgpu::TextureSampleType`](https://docs.rs/wgpu/latest/wgpu/enum.TextureSampleType.html)
24/// as simplified under [`sample_type`].
25/// The texture's size & format are defined on creation of the texture dynamically.
26///
27/// This struct also comes with a view of all layers, so you can bind to it
28/// directly.
29///
30/// ```
31/// texture! { Texture {
32/// usage: COPY_DST | TEXTURE_BINDING,
33/// dimension: D2,
34/// sample_type: FLOAT,
35/// } }
36///
37/// let texture: Texture = context.new_texture((64, 64, 1), wgpu::TextureFormat::Rgba8Unorm);
38/// ```
39///
40/// The texture is made with 1 mip level and sample count, this will probably
41/// eventually be customizable but I haven't made anything complex enough yet to
42/// figure out how that works.
43#[macro_export]
44macro_rules! texture {
45 { $struct:ident {
46 usage: $( $usage:ident )|+ ,
47 dimension: $dimension:ident,
48 sample_type: $sample:ident,
49 } } => {
50 #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
51 pub struct $struct {
52 pub texture: $crate::wgpu::Texture,
53 pub view: $crate::wgpu::TextureView,
54 }
55
56 impl ::std::ops::Deref for $struct {
57 type Target = $crate::wgpu::Texture;
58 fn deref(&self) -> &Self::Target {
59 &self.texture
60 }
61 }
62
63 impl $crate::texture::MewTexture for $struct {
64 fn new(texture: $crate::wgpu::Texture) -> Self {
65 let view = texture.create_view(&$crate::wgpu::TextureViewDescriptor {
66 label: Some(concat!(stringify!($struct), " Texture View")),
67 format: Some(texture.format()),
68 dimension: Some($crate::wgpu::TextureViewDimension::$dimension),
69 usage: Some($( $crate::wgpu::TextureUsages::$usage )|+),
70 aspect: $crate::wgpu::TextureAspect::All,
71 base_mip_level: 0,
72 mip_level_count: None,
73 base_array_layer: 0,
74 array_layer_count: None,
75 });
76 Self {
77 texture,
78 view,
79 }
80 }
81
82 fn binding_type() -> $crate::wgpu::BindingType {
83 $crate::wgpu::BindingType::Texture {
84 sample_type: $crate::texture::sample_type::$sample,
85 view_dimension: $crate::wgpu::TextureViewDimension::$dimension,
86 multisampled: false,
87 }
88 }
89
90 fn buffer_desc(inner_size: (u32, u32, u32), format: $crate::wgpu::TextureFormat) -> $crate::wgpu::TextureDescriptor<'static> {
91 $crate::wgpu::TextureDescriptor {
92 label: Some(concat!(stringify!($struct), " Texture")),
93 size: $crate::wgpu::Extent3d {
94 width: inner_size.0,
95 height: inner_size.1,
96 depth_or_array_layers: inner_size.2,
97 },
98 mip_level_count: 1,
99 sample_count: 1,
100 dimension: $crate::wgpu::TextureViewDimension::$dimension.compatible_texture_dimension(),
101 format,
102 usage: $( $crate::wgpu::TextureUsages::$usage )|+,
103 view_formats: &[],
104 }
105 }
106
107 fn as_binding<'a>(&'a self) -> $crate::wgpu::BindingResource<'a> {
108 $crate::wgpu::BindingResource::TextureView(&self.view)
109 }
110
111 fn as_colour_attachment<'a>(&'a self, clear: Option<$crate::wgpu::Color>, depth_slice: Option<u32>) -> $crate::wgpu::RenderPassColorAttachment<'a> {
112 $crate::wgpu::RenderPassColorAttachment {
113 view: &self.view,
114 depth_slice,
115 resolve_target: None, // ???
116 ops: $crate::wgpu::Operations {
117 load: clear.map(|colour| $crate::wgpu::LoadOp::Clear(colour)).unwrap_or($crate::wgpu::LoadOp::Load),
118 store: $crate::wgpu::StoreOp::Store,
119 },
120 }
121 }
122
123 fn as_depth_attachment<'a>(&'a self) -> $crate::wgpu::RenderPassDepthStencilAttachment<'a> {
124 $crate::wgpu::RenderPassDepthStencilAttachment {
125 view: &self.view,
126 depth_ops: Some($crate::wgpu::Operations {
127 load: $crate::wgpu::LoadOp::Clear(1.0),
128 store: $crate::wgpu::StoreOp::Store,
129 }),
130 stencil_ops: None,
131 }
132 }
133
134 fn memory_estimate(&self) -> u64 {
135 self.texture.format().theoretical_memory_footprint($crate::wgpu::Extent3d {
136 width: self.texture.width(),
137 height: self.texture.height(),
138 depth_or_array_layers: self.texture.depth_or_array_layers(),
139 })
140 }
141
142 fn texel_layout(&self) -> $crate::wgpu::TexelCopyBufferLayout {
143 $crate::wgpu::TexelCopyBufferLayout {
144 offset: 0,
145 bytes_per_row: Some(self.texture.format().components() as u32 * self.texture.width()),
146 rows_per_image: Some(self.texture.height())
147 }
148 }
149 }
150 }
151}
152pub use texture;
153
154
155/// Trait for internal use to work with texture bindings.
156pub trait MewTexture {
157 /// Build this texture type from a
158 /// [`wgpu::Texture`](https://docs.rs/wgpu/latest/wgpu/struct.Texture.html).
159 fn new(buffer: wgpu::Texture) -> Self;
160 /// Get a [`wgpu::BindingType`](https://docs.rs/wgpu/latest/wgpu/enum.BindingType.html)
161 /// to use for this type of texture.
162 fn binding_type() -> wgpu::BindingType;
163 /// Get a [`wgpu::TextureDescriptor`](https://docs.rs/wgpu/latest/wgpu/type.TextureDescriptor.html)
164 /// to build this type of texture with the given size &
165 /// [`wgpu::TextureFormat`](https://docs.rs/wgpu/latest/wgpu/enum.TextureFormat.html).
166 fn buffer_desc(inner_size: (u32, u32, u32), format: wgpu::TextureFormat) -> wgpu::TextureDescriptor<'static>;
167 /// Get this texture's [`wgpu::BindingResource`](https://docs.rs/wgpu/latest/wgpu/enum.BindingResource.html)
168 /// to bind it in a bind group.
169 fn as_binding<'a>(&'a self) -> wgpu::BindingResource<'a>;
170 /// Get a [`wgpu::RenderPassColorAttachment`](https://docs.rs/wgpu/latest/wgpu/struct.RenderPassColorAttachment.html)
171 /// to attach this texture to a render pass, to draw to it using a specified clear
172 /// colour on a 2D depth slice (set to `None` if it's a regular 2D texture).
173 fn as_colour_attachment<'a>(&'a self, clear: Option<wgpu::Color>, depth_slice: Option<u32>) -> wgpu::RenderPassColorAttachment<'a>;
174 /// Get a [`wgpu::RenderPassDepthStencilAttachment`](https://docs.rs/wgpu/latest/wgpu/struct.RenderPassDepthStencilAttachment.html)
175 /// to attach this texture to a render pass, to use as a depth stencil.
176 fn as_depth_attachment<'a>(&'a self) -> wgpu::RenderPassDepthStencilAttachment<'a>;
177 /// Get the estimated size of this texture. Default implementation just uses
178 /// [wgpu::TextureFormat::theoretical_memory_footprint](https://docs.rs/wgpu/latest/wgpu/enum.TextureFormat.html#method.theoretical_memory_footprint).
179 fn memory_estimate(&self) -> u64;
180 /// Get the [`wgpu::TexelCopyBufferLayout`](https://docs.rs/wgpu/latest/wgpu/struct.TexelCopyBufferLayout.html)
181 /// for this texture. Required by the queue to write any data to the texture.
182 fn texel_layout(&self) -> wgpu::TexelCopyBufferLayout;
183}