1use core::marker::PhantomData;
2use core::num::NonZeroU32;
3
4use crate::{Scalar, Vec2, Vec3, Vec4};
5
6pub struct Sampler;
12
13pub const ONE: NonZeroU32 = NonZeroU32::MIN;
17
18#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
25pub struct Texture1d<T: ?Sized> {
26 pub dimensions: Scalar<NonZeroU32>,
27 pub mip_levels: NonZeroU32,
28 pub data: T,
29}
30
31#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
36pub struct Texture2d<T: ?Sized> {
37 pub dimensions: Vec2<NonZeroU32>,
38 pub mip_levels: NonZeroU32,
39 pub data: T,
40}
41
42#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
47pub struct Texture2dArray<T: ?Sized> {
48 pub dimensions: Vec2<NonZeroU32>,
49 pub array_layers: NonZeroU32,
50 pub mip_levels: NonZeroU32,
51 pub data: T,
52}
53
54#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
59pub struct Texture3d<T: ?Sized> {
60 pub dimensions: Vec3<NonZeroU32>,
61 pub mip_levels: NonZeroU32,
62 pub data: T,
63}
64
65#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
70pub struct TextureCube<T: ?Sized> {
71 pub dimensions: Vec2<NonZeroU32>,
72 pub mip_levels: NonZeroU32,
73 pub data: T,
74}
75
76#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
81pub struct TextureCubeArray<T: ?Sized> {
82 pub dimensions: Vec2<NonZeroU32>,
83 pub array_layers: NonZeroU32,
84 pub mip_levels: NonZeroU32,
85 pub data: T,
86}
87
88#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
93pub struct TextureMultisampled2d<T: ?Sized> {
94 pub dimensions: Vec2<NonZeroU32>,
95 pub samples: NonZeroU32,
96 pub data: T,
97}
98
99impl<'d, C: Component> Texture1d<&'d dyn Read<Coordinates = Scalar<i32>, Component = C>> {
106 pub fn one_texel(texel: &'d Constant<Scalar<i32>, C>) -> Self {
107 Self {
108 dimensions: Scalar::new(ONE),
109 mip_levels: ONE,
110 data: texel,
111 }
112 }
113}
114
115impl<'d, C: Component> Texture2d<&'d dyn Read<Coordinates = Vec2<i32>, Component = C>> {
116 pub fn one_texel(texel: &'d Constant<Vec2<i32>, C>) -> Self {
117 Self {
118 dimensions: Vec2::splat(ONE),
119 mip_levels: ONE,
120 data: texel,
121 }
122 }
123}
124
125pub trait Read {
134 type Coordinates: Copy + 'static;
135 type Component: Component;
136
137 fn read_texel(
142 &self,
143 coordinates: Self::Coordinates,
144 array_layer: i32,
145 sample: i32,
146 mip_level: i32,
147 ) -> Vec4<Self::Component>;
148}
149
150pub trait Query {
154 type Dimensions: Dimensions;
157
158 type Component: Component;
163
164 fn base_dimensions(&self) -> Self::Dimensions;
166
167 fn array_layers(&self) -> NonZeroU32 {
171 ONE
172 }
173
174 fn mip_levels(&self) -> NonZeroU32 {
176 ONE
177 }
178
179 fn samples(&self) -> NonZeroU32 {
183 ONE
184 }
185}
186
187pub trait Component: Copy + 'static {}
189impl Component for u32 {}
190impl Component for i32 {}
191impl Component for f32 {}
192
193macro_rules! impl_read_forwarder_struct {
196 ($texture_type:ident) => {
197 impl<T: ?Sized + Read> Read for $texture_type<T> {
198 type Coordinates = T::Coordinates;
199 type Component = T::Component;
200
201 fn read_texel(
202 &self,
203 coordinates: Self::Coordinates,
204 array_layer: i32,
205 sample: i32,
206 mip_level: i32,
207 ) -> Vec4<Self::Component> {
208 self.data
209 .read_texel(coordinates, array_layer, sample, mip_level)
210 }
211 }
212 };
213}
214
215impl_read_forwarder_struct!(Texture1d);
216impl_read_forwarder_struct!(Texture2d);
217impl_read_forwarder_struct!(Texture2dArray);
218impl_read_forwarder_struct!(Texture3d);
219impl_read_forwarder_struct!(TextureCube);
220impl_read_forwarder_struct!(TextureCubeArray);
221impl_read_forwarder_struct!(TextureMultisampled2d);
222
223macro_rules! impl_read_forwarder_deref {
224 ($($ty:tt)*) => {
225 impl<T: ?Sized + Read> Read for $($ty)* {
226 type Coordinates = T::Coordinates;
227 type Component = T::Component;
228
229 fn read_texel(
230 &self,
231 coordinates: Self::Coordinates,
232 array_layer: i32,
233 sample: i32,
234 mip_level: i32,
235 ) -> Vec4<Self::Component> {
236 T::read_texel(&**self, coordinates, array_layer, sample, mip_level)
237 }
238 }
239 };
240}
241
242impl_read_forwarder_deref!(&T);
243impl_read_forwarder_deref!(&mut T);
244#[cfg(feature = "alloc")]
245impl_read_forwarder_deref!(alloc::boxed::Box<T>);
246#[cfg(feature = "alloc")]
247impl_read_forwarder_deref!(alloc::rc::Rc<T>);
248#[cfg(feature = "alloc")]
249impl_read_forwarder_deref!(alloc::sync::Arc<T>);
250
251macro_rules! query_common {
254 () => {
255 type Component = T::Component;
256 fn base_dimensions(&self) -> Self::Dimensions {
257 self.dimensions
258 }
259 };
260}
261
262macro_rules! query_mip {
263 () => {
264 fn mip_levels(&self) -> NonZeroU32 {
265 self.mip_levels
266 }
267 };
268}
269
270impl<T: ?Sized + Read> Query for Texture1d<T> {
271 type Dimensions = Scalar<NonZeroU32>;
272 query_common!();
273 query_mip!();
274}
275
276impl<T: ?Sized + Read> Query for Texture2d<T> {
277 type Dimensions = Vec2<NonZeroU32>;
278 query_common!();
279 query_mip!();
280}
281
282impl<T: ?Sized + Read> Query for Texture2dArray<T> {
283 type Dimensions = Vec2<NonZeroU32>;
284 query_common!();
285 query_mip!();
286 fn array_layers(&self) -> NonZeroU32 {
287 self.array_layers
288 }
289}
290
291impl<T: ?Sized + Read> Query for Texture3d<T> {
292 type Dimensions = Vec3<NonZeroU32>;
293 query_common!();
294 query_mip!();
295}
296
297impl<T: ?Sized + Read> Query for TextureCube<T> {
298 type Dimensions = Vec2<NonZeroU32>;
299 query_common!();
300 query_mip!();
301}
302
303impl<T: ?Sized + Read> Query for TextureCubeArray<T> {
304 type Dimensions = Vec2<NonZeroU32>;
305 query_common!();
306 query_mip!();
307 fn array_layers(&self) -> NonZeroU32 {
308 self.array_layers
309 }
310}
311
312impl<T: ?Sized + Read> Query for TextureMultisampled2d<T> {
313 type Dimensions = Vec2<NonZeroU32>;
314 query_common!();
315 fn samples(&self) -> NonZeroU32 {
316 self.samples
317 }
318}
319
320#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub struct Constant<C, T> {
325 pub texel: Vec4<T>,
326 _phantom: PhantomData<fn(C)>,
327}
328
329impl<C: Copy + 'static, T: Component> Constant<C, T> {
330 pub const fn new(texel: Vec4<T>) -> Self {
331 Self {
332 texel,
333 _phantom: PhantomData,
334 }
335 }
336}
337
338impl<C: Copy + 'static, T: Component> Read for Constant<C, T> {
339 type Coordinates = C;
340 type Component = T;
341
342 fn read_texel(
343 &self,
344 _coordinates: Self::Coordinates,
345 _array_layer: i32,
346 _sample: i32,
347 _mip_level: i32,
348 ) -> Vec4<Self::Component> {
349 self.texel
350 }
351}
352
353pub fn dimensions<Q>(texture: &Q, mip_level: i32) -> <Q::Dimensions as Dimensions>::Plain
364where
365 Q: ?Sized + Query,
366{
367 Dimensions::at_mip_level(texture.base_dimensions(), mip_level as u32)
368}
369
370#[doc(hidden)]
374pub fn non_zero_to_scalar(input: NonZeroU32) -> Scalar<u32> {
375 Scalar(input.get())
376}
377
378use dim::Dimensions;
379mod dim {
380 use super::*;
381
382 pub trait Dimensions: Copy + 'static {
385 type Plain;
387
388 fn at_mip_level(self, mip_level: u32) -> Self::Plain;
389 }
390
391 impl Dimensions for Scalar<NonZeroU32> {
392 type Plain = Scalar<u32>;
393 fn at_mip_level(self, mip_level: u32) -> Self::Plain {
394 Scalar::new(mip_divide_size(self.0, mip_level))
395 }
396 }
397 impl Dimensions for Vec2<NonZeroU32> {
398 type Plain = Vec2<u32>;
399 fn at_mip_level(self, mip_level: u32) -> Self::Plain {
400 Vec2::new(
401 mip_divide_size(self.x, mip_level),
402 mip_divide_size(self.y, mip_level),
403 )
404 }
405 }
406 impl Dimensions for Vec3<NonZeroU32> {
407 type Plain = Vec3<u32>;
408 fn at_mip_level(self, mip_level: u32) -> Self::Plain {
409 Vec3::new(
410 mip_divide_size(self.x, mip_level),
411 mip_divide_size(self.y, mip_level),
412 mip_divide_size(self.z, mip_level),
413 )
414 }
415 }
416
417 fn mip_divide_size(size: NonZeroU32, mip_level: u32) -> u32 {
420 (size.get() >> mip_level).max(1)
422 }
423}