spirv_std/
image.rs

1//! Image types
2
3pub use self::params::{ImageCoordinate, ImageCoordinateSubpassData, ImageSizeQuery, SampleType};
4#[cfg(target_arch = "spirv")]
5use crate::VectorTruncateInto;
6pub use crate::macros::Image;
7use crate::{Float, Integer, Sampler};
8#[cfg(target_arch = "spirv")]
9use core::arch::asm;
10use sample_with::{NoneTy, SampleParams, SomeTy};
11pub use spirv_std_types::image_params::{
12    AccessQualifier, Arrayed, Dimensionality, ImageDepth, ImageFormat, Multisampled, Sampled,
13};
14
15mod params;
16
17/// Contains extra image operands
18pub mod sample_with;
19
20/// Re-export of primitive types to ensure the `Image` proc macro always points
21/// to the right type.
22#[doc(hidden)]
23pub mod __private {
24    pub use {f32, f64, i8, i16, i32, i64, u8, u16, u32, u64};
25}
26
27/// A 1d image used with a sampler.
28pub type Image1d = crate::Image!(1D, type=f32, sampled, __crate_root=crate);
29/// A 2d image used with a sampler. This is pretty typical and probably what you want.
30pub type Image2d = crate::Image!(2D, type=f32, sampled, __crate_root=crate);
31/// A 3d image used with a sampler.
32pub type Image3d = crate::Image!(3D, type=f32, sampled, __crate_root=crate);
33/// A 1d image used with a sampler, containing unsigned integer data.
34pub type Image1dU = crate::Image!(1D, type=u32, sampled, __crate_root=crate);
35/// A 2d image used with a sampler, containing unsigned integer data.
36pub type Image2dU = crate::Image!(2D, type=u32, sampled, __crate_root=crate);
37/// A 3d image used with a sampler, containing unsigned integer data.
38pub type Image3dU = crate::Image!(3D, type=u32, sampled, __crate_root=crate);
39/// A 1d image used with a sampler, containing signed integer data.
40pub type Image1dI = crate::Image!(1D, type=i32, sampled, __crate_root=crate);
41/// A 2d image used with a sampler, containing signed integer data.
42pub type Image2dI = crate::Image!(2D, type=i32, sampled, __crate_root=crate);
43/// A 3d image used with a sampler, containing signed integer data.
44pub type Image3dI = crate::Image!(3D, type=i32, sampled, __crate_root=crate);
45
46/// An array of 1d images, used with a sampler.
47pub type Image1dArray = crate::Image!(1D, type=f32, sampled, arrayed, __crate_root=crate);
48/// An array of 2d images, used with a sampler.
49pub type Image2dArray = crate::Image!(2D, type=f32, sampled, arrayed, __crate_root=crate);
50/// An array of 3d images, used with a sampler.
51pub type Image3dArray = crate::Image!(3D, type=f32, sampled, arrayed, __crate_root=crate);
52/// An array of 1d images, used with a sampler, each containing unsigned integer data.
53pub type Image1dUArray = crate::Image!(1D, type=u32, sampled, arrayed, __crate_root=crate);
54/// An array of 2d images, used with a sampler, each containing unsigned integer data.
55pub type Image2dUArray = crate::Image!(2D, type=u32, sampled, arrayed, __crate_root=crate);
56/// An array of 3d images, used with a sampler, each containing unsigned integer data.
57pub type Image3dUArray = crate::Image!(3D, type=u32, sampled, arrayed, __crate_root=crate);
58/// An array of 1d images, used with a sampler, each containing signed integer data.
59pub type Image1dIArray = crate::Image!(1D, type=i32, sampled, arrayed, __crate_root=crate);
60/// An array of 2d images, used with a sampler, each containing signed integer data.
61pub type Image2dIArray = crate::Image!(2D, type=i32, sampled, arrayed, __crate_root=crate);
62/// An array of 3d images, used with a sampler, each containing signed integer data.
63pub type Image3dIArray = crate::Image!(3D, type=i32, sampled, arrayed, __crate_root=crate);
64
65/// A 1d storage image, directly accessed, without using a sampler.
66pub type StorageImage1d = crate::Image!(1D, type=f32, sampled=false, __crate_root=crate);
67/// A 2d storage image, directly accessed, without using a sampler.
68pub type StorageImage2d = crate::Image!(2D, type=f32, sampled=false, __crate_root=crate);
69/// A 3d storage image, directly accessed, without using a sampler.
70pub type StorageImage3d = crate::Image!(3D, type=f32, sampled=false, __crate_root=crate);
71/// A 1d storage image, directly accessed without a sampler, containing unsigned integer data.
72pub type StorageImage1dU = crate::Image!(1D, type=u32, sampled=false, __crate_root=crate);
73/// A 2d storage image, directly accessed without a sampler, containing unsigned integer data.
74pub type StorageImage2dU = crate::Image!(2D, type=u32, sampled=false, __crate_root=crate);
75/// A 3d storage image, directly accessed without a sampler, containing unsigned integer data.
76pub type StorageImage3dU = crate::Image!(3D, type=u32, sampled=false, __crate_root=crate);
77/// A 1d storage image, directly accessed without a sampler, containing signed integer data.
78pub type StorageImage1dI = crate::Image!(1D, type=i32, sampled=false, __crate_root=crate);
79/// A 2d storage image, directly accessed without a sampler, containing signed integer data.
80pub type StorageImage2dI = crate::Image!(2D, type=i32, sampled=false, __crate_root=crate);
81/// A 3d storage image, directly accessed without a sampler, containing signed integer data.
82pub type StorageImage3dI = crate::Image!(3D, type=i32, sampled=false, __crate_root=crate);
83
84/// A cubemap, i.e. a cube of 6 textures, sampled using a direction rather than image coordinates.
85pub type Cubemap = crate::Image!(cube, type=f32, sampled, __crate_root=crate);
86
87// TODO: Migrate Image parameters back to their enum values once #![feature(adt_const_params)] is
88// stabilized.
89
90/// An opaque image type. Corresponds to `OpTypeImage`.
91///
92/// You likely want to write this type using the [`crate::Image!`] macro helper, as the generic
93/// arguments here can get extremely verbose.
94///
95/// See SPIR-V `OpTypeImage` specification for the meaning of integer parameters.
96#[spirv(generic_image_type)]
97#[derive(Copy, Clone)]
98// HACK(eddyb) avoids "transparent newtype of `_anti_zst_padding`" misinterpretation.
99#[repr(C)]
100pub struct Image<
101    SampledType: SampleType<FORMAT, COMPONENTS>,
102    const DIM: u32,          // Dimensionality,
103    const DEPTH: u32,        // ImageDepth,
104    const ARRAYED: u32,      // Arrayed,
105    const MULTISAMPLED: u32, // Multisampled,
106    const SAMPLED: u32,      // Sampled,
107    const FORMAT: u32,       // ImageFormat,
108    const COMPONENTS: u32,   // NumberOfComponents,
109> {
110    // HACK(eddyb) avoids the layout becoming ZST (and being elided in one way
111    // or another, before `#[spirv(generic_image_type)]` can special-case it).
112    _anti_zst_padding: core::mem::MaybeUninit<u32>,
113    _marker: core::marker::PhantomData<SampledType>,
114}
115
116impl<
117    SampledType: SampleType<FORMAT, COMPONENTS>,
118    const DIM: u32,
119    const DEPTH: u32,
120    const ARRAYED: u32,
121    const MULTISAMPLED: u32,
122    const FORMAT: u32,
123    const COMPONENTS: u32,
124>
125    Image<
126        SampledType,
127        DIM,
128        DEPTH,
129        ARRAYED,
130        MULTISAMPLED,
131        { Sampled::Yes as u32 },
132        FORMAT,
133        COMPONENTS,
134    >
135{
136    /// Fetch a single texel with a sampler set at compile time
137    #[crate::macros::gpu_only]
138    #[doc(alias = "OpImageFetch")]
139    #[inline]
140    pub fn fetch<I>(
141        &self,
142        coordinate: impl ImageCoordinate<I, DIM, ARRAYED>,
143    ) -> SampledType::SampleResult
144    where
145        I: Integer,
146    {
147        let mut result = SampledType::Vec4::default();
148        unsafe {
149            asm! {
150                "OpDecorate %image NonUniform",
151                "OpDecorate %result NonUniform",
152                "%image = OpLoad _ {this}",
153                "%coordinate = OpLoad _ {coordinate}",
154                "%result = OpImageFetch typeof*{result} %image %coordinate",
155                "OpStore {result} %result",
156                result = in(reg) &mut result,
157                this = in(reg) self,
158                coordinate = in(reg) &coordinate,
159            }
160        }
161        result.truncate_into()
162    }
163
164    /// Fetch a single texel at a mipmap `lod` with a sampler set at compile time
165    ///
166    /// `lod` is also known as `level` in WGSL's `textureLoad`
167    #[crate::macros::gpu_only]
168    #[doc(alias = "OpImageFetch")]
169    #[inline]
170    pub fn fetch_with_lod<I>(
171        &self,
172        coordinate: impl ImageCoordinate<I, DIM, ARRAYED>,
173        lod: u32,
174    ) -> SampledType::SampleResult
175    where
176        I: Integer,
177    {
178        self.fetch_with(coordinate, sample_with::lod(lod))
179    }
180}
181
182impl<
183    SampledType: SampleType<FORMAT, COMPONENTS>,
184    const DIM: u32,
185    const DEPTH: u32,
186    const FORMAT: u32,
187    const ARRAYED: u32,
188    const SAMPLED: u32,
189    const COMPONENTS: u32,
190>
191    Image<
192        SampledType,
193        DIM,
194        DEPTH,
195        ARRAYED,
196        { Multisampled::False as u32 },
197        SAMPLED,
198        FORMAT,
199        COMPONENTS,
200    >
201{
202    // Note: #[inline] is needed because in vulkan, the component must be a constant expression.
203    /// Gathers the requested component from four texels.
204    #[crate::macros::gpu_only]
205    #[doc(alias = "OpImageGather")]
206    #[inline]
207    pub fn gather<F>(
208        &self,
209        sampler: Sampler,
210        coordinate: impl ImageCoordinate<F, DIM, ARRAYED>,
211        component: u32,
212    ) -> SampledType::Vec4
213    where
214        Self: HasGather,
215        F: Float,
216    {
217        let mut result = SampledType::Vec4::default();
218        unsafe {
219            asm! {
220                "OpDecorate %image NonUniform",
221                "OpDecorate %sampler NonUniform",
222                "OpDecorate %sampledImage NonUniform",
223                "OpDecorate %result NonUniform",
224                "%typeSampledImage = OpTypeSampledImage typeof*{this}",
225                "%image = OpLoad _ {this}",
226                "%sampler = OpLoad _ {sampler}",
227                "%coordinate = OpLoad _ {coordinate}",
228                "%sampledImage = OpSampledImage %typeSampledImage %image %sampler",
229                "%result = OpImageGather typeof*{result} %sampledImage %coordinate {component}",
230                "OpStore {result} %result",
231                result = in(reg) &mut result,
232                this = in(reg) self,
233                sampler = in(reg) &sampler,
234                coordinate = in(reg) &coordinate,
235                component = in(reg) component,
236            }
237        }
238        result
239    }
240
241    /// Sample texels at `coord` from the image using `sampler`.
242    #[crate::macros::gpu_only]
243    #[inline]
244    pub fn sample<F>(
245        &self,
246        sampler: Sampler,
247        coord: impl ImageCoordinate<F, DIM, ARRAYED>,
248    ) -> SampledType::SampleResult
249    where
250        F: Float,
251    {
252        unsafe {
253            let mut result = SampledType::Vec4::default();
254            asm!(
255                "OpDecorate %image NonUniform",
256                "OpDecorate %sampler NonUniform",
257                "OpDecorate %sampledImage NonUniform",
258                "OpDecorate %result NonUniform",
259                "%typeSampledImage = OpTypeSampledImage typeof*{1}",
260                "%image = OpLoad typeof*{1} {1}",
261                "%sampler = OpLoad typeof*{2} {2}",
262                "%coord = OpLoad typeof*{3} {3}",
263                "%sampledImage = OpSampledImage %typeSampledImage %image %sampler",
264                "%result = OpImageSampleImplicitLod typeof*{0} %sampledImage %coord",
265                "OpStore {0} %result",
266                in(reg) &mut result,
267                in(reg) self,
268                in(reg) &sampler,
269                in(reg) &coord
270            );
271            result.truncate_into()
272        }
273    }
274
275    /// Sample texels at `coord` from the image using `sampler`, after adding the input bias to the
276    /// implicit level of detail.
277    #[crate::macros::gpu_only]
278    #[inline]
279    pub fn sample_bias<F>(
280        &self,
281        sampler: Sampler,
282        coord: impl ImageCoordinate<F, DIM, ARRAYED>,
283        bias: f32,
284    ) -> SampledType::SampleResult
285    where
286        F: Float,
287    {
288        unsafe {
289            let mut result = SampledType::Vec4::default();
290
291            asm!(
292                "OpDecorate %image NonUniform",
293                "OpDecorate %sampler NonUniform",
294                "OpDecorate %sampledImage NonUniform",
295                "OpDecorate %result NonUniform",
296                "%typeSampledImage = OpTypeSampledImage typeof*{1}",
297                "%image = OpLoad typeof*{1} {1}",
298                "%sampler = OpLoad typeof*{2} {2}",
299                "%coord = OpLoad typeof*{3} {3}",
300                "%sampledImage = OpSampledImage %typeSampledImage %image %sampler",
301                "%result = OpImageSampleImplicitLod typeof*{0} %sampledImage %coord Bias {4}",
302                "OpStore {0} %result",
303                in(reg) &mut result,
304                in(reg) self,
305                in(reg) &sampler,
306                in(reg) &coord,
307                in(reg) bias,
308            );
309            result.truncate_into()
310        }
311    }
312
313    /// Fetch a single texel with a sampler set at compile time
314    #[crate::macros::gpu_only]
315    #[doc(alias = "OpImageSampleExplicitLod")]
316    /// Sample the image at a coordinate by a lod
317    #[inline]
318    pub fn sample_by_lod<F>(
319        &self,
320        sampler: Sampler,
321        coordinate: impl ImageCoordinate<F, DIM, ARRAYED>,
322        lod: f32,
323    ) -> SampledType::SampleResult
324    where
325        F: Float,
326    {
327        let mut result = SampledType::Vec4::default();
328        unsafe {
329            asm!(
330                "OpDecorate %image NonUniform",
331                "OpDecorate %sampler NonUniform",
332                "OpDecorate %sampledImage NonUniform",
333                "OpDecorate %result NonUniform",
334                "%image = OpLoad _ {this}",
335                "%sampler = OpLoad _ {sampler}",
336                "%coordinate = OpLoad _ {coordinate}",
337                "%lod = OpLoad _ {lod}",
338                "%sampledImage = OpSampledImage _ %image %sampler",
339                "%result = OpImageSampleExplicitLod typeof*{result} %sampledImage %coordinate Lod %lod",
340                "OpStore {result} %result",
341                result = in(reg) &mut result,
342                this = in(reg) self,
343                sampler = in(reg) &sampler,
344                coordinate = in(reg) &coordinate,
345                lod = in(reg) &lod
346            );
347        }
348        result.truncate_into()
349    }
350
351    #[crate::macros::gpu_only]
352    #[doc(alias = "OpImageSampleExplicitLod")]
353    /// Sample the image based on a gradient formed by (dx, dy). Specifically, ([du/dx, dv/dx], [du/dy, dv/dy])
354    #[inline]
355    pub fn sample_by_gradient<F>(
356        &self,
357        sampler: Sampler,
358        coordinate: impl ImageCoordinate<F, DIM, ARRAYED>,
359        gradient_dx: impl ImageCoordinate<F, DIM, { Arrayed::False as u32 }>,
360        gradient_dy: impl ImageCoordinate<F, DIM, { Arrayed::False as u32 }>,
361    ) -> SampledType::SampleResult
362    where
363        F: Float,
364    {
365        let mut result = SampledType::Vec4::default();
366        unsafe {
367            asm!(
368                "OpDecorate %image NonUniform",
369                "OpDecorate %sampler NonUniform",
370                "OpDecorate %sampledImage NonUniform",
371                "OpDecorate %result NonUniform",
372                "%image = OpLoad _ {this}",
373                "%sampler = OpLoad _ {sampler}",
374                "%coordinate = OpLoad _ {coordinate}",
375                "%gradient_dx = OpLoad _ {gradient_dx}",
376                "%gradient_dy = OpLoad _ {gradient_dy}",
377                "%sampledImage = OpSampledImage _ %image %sampler",
378                "%result = OpImageSampleExplicitLod typeof*{result} %sampledImage %coordinate Grad %gradient_dx %gradient_dy",
379                "OpStore {result} %result",
380                result = in(reg) &mut result,
381                this = in(reg) self,
382                sampler = in(reg) &sampler,
383                coordinate = in(reg) &coordinate,
384                gradient_dx = in(reg) &gradient_dx,
385                gradient_dy = in(reg) &gradient_dy,
386            );
387        }
388        result.truncate_into()
389    }
390
391    #[crate::macros::gpu_only]
392    #[doc(alias = "OpImageSampleDrefImplicitLod")]
393    /// Sample the image's depth reference
394    #[inline]
395    pub fn sample_depth_reference<F>(
396        &self,
397        sampler: Sampler,
398        coordinate: impl ImageCoordinate<F, DIM, ARRAYED>,
399        depth_reference: f32,
400    ) -> SampledType
401    where
402        F: Float,
403    {
404        let mut result = Default::default();
405        unsafe {
406            asm!(
407                "OpDecorate %image NonUniform",
408                "OpDecorate %sampler NonUniform",
409                "OpDecorate %sampledImage NonUniform",
410                "OpDecorate %result NonUniform",
411                "%image = OpLoad _ {this}",
412                "%sampler = OpLoad _ {sampler}",
413                "%coordinate = OpLoad _ {coordinate}",
414                "%depth_reference = OpLoad _ {depth_reference}", // not required to do this way, but done for consistency
415                "%sampledImage = OpSampledImage _ %image %sampler",
416                "%result = OpImageSampleDrefImplicitLod typeof*{result} %sampledImage %coordinate %depth_reference",
417                "OpStore {result} %result",
418                result = in(reg) &mut result,
419                this = in(reg) self,
420                sampler = in(reg) &sampler,
421                coordinate = in(reg) &coordinate,
422                depth_reference = in(reg) &depth_reference,
423            );
424        }
425        result
426    }
427
428    #[crate::macros::gpu_only]
429    #[doc(alias = "OpImageSampleDrefExplicitLod")]
430    /// Sample the image's depth reference based on an explicit lod
431    #[inline]
432    pub fn sample_depth_reference_by_lod<F>(
433        &self,
434        sampler: Sampler,
435        coordinate: impl ImageCoordinate<F, DIM, ARRAYED>,
436        depth_reference: f32,
437        lod: f32,
438    ) -> SampledType
439    where
440        F: Float,
441    {
442        let mut result = Default::default();
443        unsafe {
444            asm!(
445                "OpDecorate %image NonUniform",
446                "OpDecorate %sampler NonUniform",
447                "OpDecorate %sampledImage NonUniform",
448                "OpDecorate %result NonUniform",
449                "%image = OpLoad _ {this}",
450                "%sampler = OpLoad _ {sampler}",
451                "%coordinate = OpLoad _ {coordinate}",
452                "%depth_reference = OpLoad _ {depth_reference}",
453                "%lod = OpLoad _ {lod}",
454                "%sampledImage = OpSampledImage _ %image %sampler",
455                "%result = OpImageSampleDrefExplicitLod typeof*{result} %sampledImage %coordinate %depth_reference Lod %lod",
456                "OpStore {result} %result",
457                result = in(reg) &mut result,
458                this = in(reg) self,
459                sampler = in(reg) &sampler,
460                coordinate = in(reg) &coordinate,
461                depth_reference = in(reg) &depth_reference,
462                lod = in(reg) &lod,
463            )
464        }
465        result
466    }
467
468    #[crate::macros::gpu_only]
469    #[doc(alias = "OpImageSampleDrefExplicitLod")]
470    /// Sample the image's depth reference based on a gradient formed by (dx, dy).
471    /// Specifically, ([du/dx, dv/dx], [du/dy, dv/dy])
472    #[inline]
473    pub fn sample_depth_reference_by_gradient<F>(
474        &self,
475        sampler: Sampler,
476        coordinate: impl ImageCoordinate<F, DIM, ARRAYED>,
477        depth_reference: f32,
478        gradient_dx: impl ImageCoordinate<F, DIM, { Arrayed::False as u32 }>,
479        gradient_dy: impl ImageCoordinate<F, DIM, { Arrayed::False as u32 }>,
480    ) -> SampledType
481    where
482        F: Float,
483    {
484        let mut result = Default::default();
485        unsafe {
486            asm!(
487                "OpDecorate %image NonUniform",
488                "OpDecorate %sampler NonUniform",
489                "OpDecorate %sampledImage NonUniform",
490                "OpDecorate %result NonUniform",
491                "%image = OpLoad _ {this}",
492                "%sampler = OpLoad _ {sampler}",
493                "%coordinate = OpLoad _ {coordinate}",
494                "%depth_reference = OpLoad _ {depth_reference}",
495                "%gradient_dx = OpLoad _ {gradient_dx}",
496                "%gradient_dy = OpLoad _ {gradient_dy}",
497                "%sampledImage = OpSampledImage _ %image %sampler",
498                "%result = OpImageSampleDrefExplicitLod typeof*{result} %sampledImage %coordinate %depth_reference Grad %gradient_dx %gradient_dy",
499                "OpStore {result} %result",
500                result = in(reg) &mut result,
501                this = in(reg) self,
502                sampler = in(reg) &sampler,
503                coordinate = in(reg) &coordinate,
504                depth_reference = in(reg) &depth_reference,
505                gradient_dx = in(reg) &gradient_dx,
506                gradient_dy = in(reg) &gradient_dy,
507            );
508        }
509        result
510    }
511}
512
513impl<
514    SampledType: SampleType<FORMAT, COMPONENTS>,
515    const DIM: u32,
516    const DEPTH: u32,
517    const SAMPLED: u32,
518    const FORMAT: u32,
519    const COMPONENTS: u32,
520>
521    Image<
522        SampledType,
523        DIM,
524        DEPTH,
525        { Arrayed::False as u32 },
526        { Multisampled::False as u32 },
527        SAMPLED,
528        FORMAT,
529        COMPONENTS,
530    >
531{
532    /// Sample the image with a project coordinate
533    #[crate::macros::gpu_only]
534    #[doc(alias = "OpImageSampleProjImplicitLod")]
535    #[inline]
536    pub fn sample_with_project_coordinate<F>(
537        &self,
538        sampler: Sampler,
539        project_coordinate: impl ImageCoordinate<F, DIM, { Arrayed::True as u32 }>,
540    ) -> SampledType::SampleResult
541    where
542        F: Float,
543    {
544        unsafe {
545            let mut result = SampledType::Vec4::default();
546            asm!(
547                "OpDecorate %image NonUniform",
548                "OpDecorate %sampler NonUniform",
549                "OpDecorate %sampledImage NonUniform",
550                "OpDecorate %result NonUniform",
551                "%image = OpLoad _ {this}",
552                "%sampler = OpLoad _ {sampler}",
553                "%project_coordinate = OpLoad _ {project_coordinate}",
554                "%sampledImage = OpSampledImage _ %image %sampler",
555                "%result = OpImageSampleProjImplicitLod typeof*{result} %sampledImage %project_coordinate",
556                "OpStore {result} %result",
557                result = in(reg) &mut result,
558                this = in(reg) self,
559                sampler = in(reg) &sampler,
560                project_coordinate = in(reg) &project_coordinate,
561            );
562            result.truncate_into()
563        }
564    }
565
566    #[crate::macros::gpu_only]
567    #[doc(alias = "OpImageSampleProjExplicitLod")]
568    /// Sample the image with a project coordinate by a lod
569    #[inline]
570    pub fn sample_with_project_coordinate_by_lod<F>(
571        &self,
572        sampler: Sampler,
573        project_coordinate: impl ImageCoordinate<F, DIM, { Arrayed::True as u32 }>,
574        lod: f32,
575    ) -> SampledType::Vec4
576    where
577        F: Float,
578    {
579        let mut result = Default::default();
580        unsafe {
581            asm!(
582                "OpDecorate %image NonUniform",
583                "OpDecorate %sampler NonUniform",
584                "OpDecorate %sampledImage NonUniform",
585                "OpDecorate %result NonUniform",
586                "%image = OpLoad _ {this}",
587                "%sampler = OpLoad _ {sampler}",
588                "%project_coordinate = OpLoad _ {project_coordinate}",
589                "%lod = OpLoad _ {lod}",
590                "%sampledImage = OpSampledImage _ %image %sampler",
591                "%result = OpImageSampleProjExplicitLod typeof*{result} %sampledImage %project_coordinate Lod %lod",
592                "OpStore {result} %result",
593                result = in(reg) &mut result,
594                this = in(reg) self,
595                sampler = in(reg) &sampler,
596                project_coordinate = in(reg) &project_coordinate,
597                lod = in(reg) &lod
598            );
599        }
600        result
601    }
602
603    #[crate::macros::gpu_only]
604    #[doc(alias = "OpImageSampleProjExplicitLod")]
605    /// Sample the image with a project coordinate based on a gradient formed by (dx, dy). Specifically, ([du/dx, dv/dx], [du/dy, dv/dy])
606    #[inline]
607    pub fn sample_with_project_coordinate_by_gradient<F>(
608        &self,
609        sampler: Sampler,
610        project_coordinate: impl ImageCoordinate<F, DIM, { Arrayed::True as u32 }>,
611        gradient_dx: impl ImageCoordinate<F, DIM, { Arrayed::False as u32 }>,
612        gradient_dy: impl ImageCoordinate<F, DIM, { Arrayed::False as u32 }>,
613    ) -> SampledType::Vec4
614    where
615        F: Float,
616    {
617        let mut result = Default::default();
618        unsafe {
619            asm!(
620                "OpDecorate %image NonUniform",
621                "OpDecorate %sampler NonUniform",
622                "OpDecorate %sampledImage NonUniform",
623                "OpDecorate %result NonUniform",
624                "%image = OpLoad _ {this}",
625                "%sampler = OpLoad _ {sampler}",
626                "%project_coordinate = OpLoad _ {project_coordinate}",
627                "%gradient_dx = OpLoad _ {gradient_dx}",
628                "%gradient_dy = OpLoad _ {gradient_dy}",
629                "%sampledImage = OpSampledImage _ %image %sampler",
630                "%result = OpImageSampleProjExplicitLod typeof*{result} %sampledImage %project_coordinate Grad %gradient_dx %gradient_dy",
631                "OpStore {result} %result",
632                result = in(reg) &mut result,
633                this = in(reg) self,
634                sampler = in(reg) &sampler,
635                project_coordinate = in(reg) &project_coordinate,
636                gradient_dx = in(reg) &gradient_dx,
637                gradient_dy = in(reg) &gradient_dy,
638            );
639        }
640        result
641    }
642
643    #[crate::macros::gpu_only]
644    #[doc(alias = "OpImageSampleProjDrefImplicitLod")]
645    /// Sample the image's depth reference with the project coordinate
646    #[inline]
647    pub fn sample_depth_reference_with_project_coordinate<F>(
648        &self,
649        sampler: Sampler,
650        project_coordinate: impl ImageCoordinate<F, DIM, { Arrayed::True as u32 }>,
651        depth_reference: f32,
652    ) -> SampledType
653    where
654        F: Float,
655    {
656        let mut result = Default::default();
657        unsafe {
658            asm!(
659                "OpDecorate %image NonUniform",
660                "OpDecorate %sampler NonUniform",
661                "OpDecorate %sampledImage NonUniform",
662                "OpDecorate %result NonUniform",
663                "%image = OpLoad _ {this}",
664                "%sampler = OpLoad _ {sampler}",
665                "%project_coordinate = OpLoad _ {project_coordinate}",
666                "%depth_reference = OpLoad _ {depth_reference}", // not required to do this way, but done for consistency
667                "%sampledImage = OpSampledImage _ %image %sampler",
668                "%result = OpImageSampleProjDrefImplicitLod typeof*{result} %sampledImage %project_coordinate %depth_reference",
669                "OpStore {result} %result",
670                result = in(reg) &mut result,
671                this = in(reg) self,
672                sampler = in(reg) &sampler,
673                project_coordinate = in(reg) &project_coordinate,
674                depth_reference = in(reg) &depth_reference,
675            );
676        }
677        result
678    }
679
680    #[crate::macros::gpu_only]
681    #[doc(alias = "OpImageSampleProjDrefExplicitLod")]
682    /// Sample the image's depth reference with the project coordinate based on an explicit lod
683    #[inline]
684    pub fn sample_depth_reference_with_project_coordinate_by_lod<F>(
685        &self,
686        sampler: Sampler,
687        coordinate: impl ImageCoordinate<F, DIM, { Arrayed::True as u32 }>,
688        depth_reference: f32,
689        lod: f32,
690    ) -> SampledType
691    where
692        F: Float,
693    {
694        let mut result = Default::default();
695        unsafe {
696            asm!(
697                "OpDecorate %image NonUniform",
698                "OpDecorate %sampler NonUniform",
699                "OpDecorate %sampledImage NonUniform",
700                "OpDecorate %result NonUniform",
701                "%image = OpLoad _ {this}",
702                "%sampler = OpLoad _ {sampler}",
703                "%coordinate = OpLoad _ {coordinate}",
704                "%depth_reference = OpLoad _ {depth_reference}",
705                "%lod = OpLoad _ {lod}",
706                "%sampledImage = OpSampledImage _ %image %sampler",
707                "%result = OpImageSampleProjDrefExplicitLod typeof*{result} %sampledImage %coordinate %depth_reference Lod %lod",
708                "OpStore {result} %result",
709                result = in(reg) &mut result,
710                this = in(reg) self,
711                sampler = in(reg) &sampler,
712                coordinate = in(reg) &coordinate,
713                depth_reference = in(reg) &depth_reference,
714                lod = in(reg) &lod,
715            )
716        }
717        result
718    }
719
720    #[crate::macros::gpu_only]
721    #[doc(alias = "OpImageSampleProjDrefExplicitLod")]
722    /// Sample the image's depth reference with the project coordinate based on a gradient formed by (dx, dy).
723    /// Specifically, ([du/dx, dv/dx], [du/dy, dv/dy])
724    #[inline]
725    pub fn sample_depth_reference_with_project_coordinate_by_gradient<F>(
726        &self,
727        sampler: Sampler,
728        coordinate: impl ImageCoordinate<F, DIM, { Arrayed::True as u32 }>,
729        depth_reference: f32,
730        gradient_dx: impl ImageCoordinate<F, DIM, { Arrayed::False as u32 }>,
731        gradient_dy: impl ImageCoordinate<F, DIM, { Arrayed::False as u32 }>,
732    ) -> SampledType
733    where
734        F: Float,
735    {
736        let mut result = Default::default();
737        unsafe {
738            asm!(
739                "OpDecorate %image NonUniform",
740                "OpDecorate %sampler NonUniform",
741                "OpDecorate %sampledImage NonUniform",
742                "OpDecorate %result NonUniform",
743                "%image = OpLoad _ {this}",
744                "%sampler = OpLoad _ {sampler}",
745                "%coordinate = OpLoad _ {coordinate}",
746                "%depth_reference = OpLoad _ {depth_reference}",
747                "%gradient_dx = OpLoad _ {gradient_dx}",
748                "%gradient_dy = OpLoad _ {gradient_dy}",
749                "%sampledImage = OpSampledImage _ %image %sampler",
750                "%result = OpImageSampleProjDrefExplicitLod typeof*{result} %sampledImage %coordinate %depth_reference Grad %gradient_dx %gradient_dy",
751                "OpStore {result} %result",
752                result = in(reg) &mut result,
753                this = in(reg) self,
754                sampler = in(reg) &sampler,
755                coordinate = in(reg) &coordinate,
756                depth_reference = in(reg) &depth_reference,
757                gradient_dx = in(reg) &gradient_dx,
758                gradient_dy = in(reg) &gradient_dy,
759            );
760        }
761        result
762    }
763}
764
765impl<
766    SampledType: SampleType<FORMAT, COMPONENTS>,
767    const DIM: u32,
768    const DEPTH: u32,
769    const ARRAYED: u32,
770    const MULTISAMPLED: u32,
771    const FORMAT: u32,
772    const COMPONENTS: u32,
773>
774    Image<
775        SampledType,
776        DIM,
777        DEPTH,
778        ARRAYED,
779        MULTISAMPLED,
780        { Sampled::No as u32 },
781        FORMAT,
782        COMPONENTS,
783    >
784{
785    /// Read a texel from an image without a sampler.
786    #[crate::macros::gpu_only]
787    #[doc(alias = "OpImageRead")]
788    #[inline]
789    pub fn read<I>(
790        &self,
791        coordinate: impl ImageCoordinate<I, DIM, ARRAYED>,
792    ) -> SampledType::SampleResult
793    where
794        I: Integer,
795    {
796        let mut result = SampledType::Vec4::default();
797
798        unsafe {
799            asm! {
800                "OpDecorate %image NonUniform",
801                "OpDecorate %result NonUniform",
802                "%image = OpLoad _ {this}",
803                "%coordinate = OpLoad _ {coordinate}",
804                "%result = OpImageRead typeof*{result} %image %coordinate",
805                "OpStore {result} %result",
806                this = in(reg) self,
807                coordinate = in(reg) &coordinate,
808                result = in(reg) &mut result,
809            }
810        }
811
812        result.truncate_into()
813    }
814
815    /// Write a texel to an image without a sampler.
816    #[crate::macros::gpu_only]
817    #[doc(alias = "OpImageWrite")]
818    #[inline]
819    pub unsafe fn write<I>(
820        &self,
821        coordinate: impl ImageCoordinate<I, DIM, ARRAYED>,
822        texels: SampledType::SampleResult,
823    ) where
824        I: Integer,
825    {
826        unsafe {
827            asm! {
828                "OpDecorate %image NonUniform",
829                "%image = OpLoad _ {this}",
830                "%coordinate = OpLoad _ {coordinate}",
831                "%texels = OpLoad _ {texels}",
832                "OpImageWrite %image %coordinate %texels",
833                this = in(reg) self,
834                coordinate = in(reg) &coordinate,
835                texels = in(reg) &texels,
836            }
837        }
838    }
839}
840
841impl<
842    SampledType: SampleType<FORMAT, COMPONENTS>,
843    const DIM: u32,
844    const DEPTH: u32,
845    const FORMAT: u32,
846    const ARRAYED: u32,
847    const MULTISAMPLED: u32,
848    const COMPONENTS: u32,
849>
850    Image<
851        SampledType,
852        DIM,
853        DEPTH,
854        ARRAYED,
855        MULTISAMPLED,
856        { Sampled::Unknown as u32 },
857        FORMAT,
858        COMPONENTS,
859    >
860{
861    /// Read a texel from an image without a sampler.
862    #[crate::macros::gpu_only]
863    #[doc(alias = "OpImageRead")]
864    #[inline]
865    pub fn read<I>(
866        &self,
867        coordinate: impl ImageCoordinate<I, DIM, ARRAYED>,
868    ) -> SampledType::SampleResult
869    where
870        I: Integer,
871    {
872        let mut result = SampledType::Vec4::default();
873
874        unsafe {
875            asm! {
876                "OpDecorate %image NonUniform",
877                "OpDecorate %result NonUniform",
878                "%image = OpLoad _ {this}",
879                "%coordinate = OpLoad _ {coordinate}",
880                "%result = OpImageRead typeof*{result} %image %coordinate",
881                "OpStore {result} %result",
882                this = in(reg) self,
883                coordinate = in(reg) &coordinate,
884                result = in(reg) &mut result,
885            }
886        }
887
888        result.truncate_into()
889    }
890
891    /// Write a texel to an image without a sampler.
892    #[crate::macros::gpu_only]
893    #[doc(alias = "OpImageWrite")]
894    #[inline]
895    pub unsafe fn write<I>(
896        &self,
897        coordinate: impl ImageCoordinate<I, DIM, ARRAYED>,
898        texels: SampledType::SampleResult,
899    ) where
900        I: Integer,
901    {
902        unsafe {
903            asm! {
904                "OpDecorate %image NonUniform",
905                "%image = OpLoad _ {this}",
906                "%coordinate = OpLoad _ {coordinate}",
907                "%texels = OpLoad _ {texels}",
908                "OpImageWrite %image %coordinate %texels",
909                this = in(reg) self,
910                coordinate = in(reg) &coordinate,
911                texels = in(reg) &texels,
912            }
913        }
914    }
915}
916
917impl<
918    SampledType: SampleType<FORMAT, COMPONENTS>,
919    const DEPTH: u32,
920    const ARRAYED: u32,
921    const MULTISAMPLED: u32,
922    const FORMAT: u32,
923    const COMPONENTS: u32,
924>
925    Image<
926        SampledType,
927        { Dimensionality::SubpassData as u32 },
928        DEPTH,
929        ARRAYED,
930        MULTISAMPLED,
931        { Sampled::No as u32 },
932        FORMAT,
933        COMPONENTS,
934    >
935{
936    /// Read a texel from subpass input attachment.
937    /// Note: Vulkan only allows the read if the first two components of the coordinate are zero.
938    #[crate::macros::gpu_only]
939    #[doc(alias = "OpImageRead")]
940    #[inline]
941    pub fn read_subpass<I>(
942        &self,
943        coordinate: impl ImageCoordinateSubpassData<I, ARRAYED>,
944    ) -> SampledType::SampleResult
945    where
946        I: Integer,
947    {
948        let mut result = SampledType::Vec4::default();
949
950        unsafe {
951            asm! {
952                "OpDecorate %image NonUniform",
953                "OpDecorate %result NonUniform",
954                "%image = OpLoad _ {this}",
955                "%coordinate = OpLoad _ {coordinate}",
956                "%result = OpImageRead typeof*{result} %image %coordinate",
957                "OpStore {result} %result",
958                this = in(reg) self,
959                coordinate = in(reg) &coordinate,
960                result = in(reg) &mut result,
961            }
962        }
963
964        result.truncate_into()
965    }
966}
967
968impl<
969    SampledType: SampleType<FORMAT, COMPONENTS>,
970    const DIM: u32,
971    const DEPTH: u32,
972    const ARRAYED: u32,
973    const MULTISAMPLED: u32,
974    const SAMPLED: u32,
975    const FORMAT: u32,
976    const COMPONENTS: u32,
977> Image<SampledType, DIM, DEPTH, ARRAYED, MULTISAMPLED, SAMPLED, FORMAT, COMPONENTS>
978{
979    /// Query the number of mipmap levels.
980    #[crate::macros::gpu_only]
981    #[doc(alias = "OpImageQueryLevels")]
982    #[inline]
983    pub fn query_levels(&self) -> u32
984    where
985        Self: HasQueryLevels,
986    {
987        let mut result = Default::default();
988        unsafe {
989            asm! {
990                "OpDecorate %image NonUniform",
991                "OpDecorate %result NonUniform",
992                "%image = OpLoad _ {this}",
993                "%result = OpImageQueryLevels typeof*{result} %image",
994                "OpStore {result} %result",
995                this = in(reg) self,
996                result = in(reg) &mut result,
997            }
998        }
999        result
1000    }
1001
1002    /// Query the mipmap level and the level of detail for a hypothetical sampling of Image at
1003    /// Coordinate using an implicit level of detail. The first component of the result contains
1004    /// the mipmap array layer. The second component of the result contains the implicit level of
1005    /// detail relative to the base level.
1006    #[crate::macros::gpu_only]
1007    #[doc(alias = "OpImageQueryLod")]
1008    #[inline]
1009    pub fn query_lod(
1010        &self,
1011        sampler: Sampler,
1012        coord: impl ImageCoordinate<f32, DIM, { Arrayed::False as u32 }>,
1013    ) -> SampledType::Vec2
1014    where
1015        Self: HasQueryLevels,
1016    {
1017        // Note: Arrayed::False isn't a typo in the ImageCoordinate, the spec states:
1018        // Coordinate must be a scalar or vector of floating-point type or integer type. It
1019        // contains (u[, v] ... ) as needed by the definition of Sampled Image, **not including any
1020        // array layer index**. Unless the Kernel capability is being used, it must be floating
1021        // point.
1022        let mut result = Default::default();
1023        unsafe {
1024            asm! {
1025                "OpDecorate %image NonUniform",
1026                "OpDecorate %sampler NonUniform",
1027                "OpDecorate %sampledImage NonUniform",
1028                "OpDecorate %result NonUniform",
1029                "%typeSampledImage = OpTypeSampledImage typeof*{this}",
1030                "%image = OpLoad _ {this}",
1031                "%sampler = OpLoad _ {sampler}",
1032                "%coord = OpLoad _ {coord}",
1033                "%sampledImage = OpSampledImage %typeSampledImage %image %sampler",
1034                "%result = OpImageQueryLod typeof*{result} %sampledImage %coord",
1035                "OpStore {result} %result",
1036                result = in(reg) &mut result,
1037                this = in(reg) self,
1038                sampler = in(reg) &sampler,
1039                coord = in(reg) &coord
1040            }
1041        }
1042        result
1043    }
1044
1045    /// Query the dimensions of Image, with no level of detail.
1046    #[crate::macros::gpu_only]
1047    #[doc(alias = "OpImageQuerySize")]
1048    #[inline]
1049    pub fn query_size<Size: ImageSizeQuery<u32, DIM, ARRAYED> + Default>(&self) -> Size
1050    where
1051        Self: HasQuerySize,
1052    {
1053        let mut result: Size = Default::default();
1054        unsafe {
1055            asm! {
1056                "OpDecorate %image NonUniform",
1057                "OpDecorate %result NonUniform",
1058                "%image = OpLoad _ {this}",
1059                "%result = OpImageQuerySize typeof*{result} %image",
1060                "OpStore {result} %result",
1061                this = in(reg) self,
1062                result = in(reg) &mut result,
1063            }
1064        }
1065        result
1066    }
1067}
1068
1069impl<
1070    SampledType: SampleType<FORMAT, COMPONENTS>,
1071    const DIM: u32,
1072    const DEPTH: u32,
1073    const ARRAYED: u32,
1074    const SAMPLED: u32,
1075    const FORMAT: u32,
1076    const COMPONENTS: u32,
1077>
1078    Image<
1079        SampledType,
1080        DIM,
1081        DEPTH,
1082        ARRAYED,
1083        { Multisampled::False as u32 },
1084        SAMPLED,
1085        FORMAT,
1086        COMPONENTS,
1087    >
1088{
1089    /// Query the dimensions of Image at a specific level of detail.
1090    #[crate::macros::gpu_only]
1091    #[doc(alias = "OpImageQuerySizeLod")]
1092    #[inline]
1093    pub fn query_size_lod<Size: ImageSizeQuery<u32, DIM, ARRAYED> + Default>(
1094        &self,
1095        lod: u32,
1096    ) -> Size
1097    where
1098        Self: HasQuerySizeLod,
1099    {
1100        let mut result: Size = Default::default();
1101        unsafe {
1102            asm! {
1103                "OpDecorate %image NonUniform",
1104                "OpDecorate %result NonUniform",
1105                "%image = OpLoad _ {this}",
1106                "%result = OpImageQuerySizeLod typeof*{result} %image {lod}",
1107                "OpStore {result} %result",
1108                this = in(reg) self,
1109                lod = in(reg) lod,
1110                result = in(reg) &mut result,
1111            }
1112        }
1113        result
1114    }
1115}
1116
1117impl<
1118    SampledType: SampleType<FORMAT, COMPONENTS>,
1119    const DEPTH: u32,
1120    const ARRAYED: u32,
1121    const SAMPLED: u32,
1122    const FORMAT: u32,
1123    const COMPONENTS: u32,
1124>
1125    Image<
1126        SampledType,
1127        { Dimensionality::TwoD as u32 },
1128        DEPTH,
1129        ARRAYED,
1130        { Multisampled::True as u32 },
1131        SAMPLED,
1132        FORMAT,
1133        COMPONENTS,
1134    >
1135{
1136    /// Query the number of samples available per texel fetch in a multisample image.
1137    #[crate::macros::gpu_only]
1138    #[doc(alias = "OpImageQuerySamples")]
1139    #[inline]
1140    pub fn query_samples(&self) -> u32 {
1141        let mut result = Default::default();
1142        unsafe {
1143            asm! {
1144                "OpDecorate %image NonUniform",
1145                "OpDecorate %result NonUniform",
1146                "%image = OpLoad _ {this}",
1147                "%result = OpImageQuerySamples typeof*{result} %image",
1148                "OpStore {result} %result",
1149                this = in(reg) self,
1150                result = in(reg) &mut result,
1151            }
1152        }
1153        result
1154    }
1155}
1156
1157/// An image combined with a sampler in a single value, enabling filtered accesses of the image's
1158/// contents. Corresponds to `OpTypeSampledImage`.
1159///
1160/// The generic type parameter is the underlying image type, written like
1161/// `SampledImage<Image!(...)>`.
1162#[spirv(sampled_image)]
1163#[derive(Copy, Clone)]
1164// HACK(eddyb) false positive due to `rustc` not understanding e.g. entry-points.
1165#[allow(dead_code)]
1166pub struct SampledImage<I> {
1167    _image: I,
1168}
1169
1170impl<
1171    SampledType: SampleType<FORMAT, COMPONENTS>,
1172    const DIM: u32,
1173    const DEPTH: u32,
1174    const ARRAYED: u32,
1175    const SAMPLED: u32,
1176    const FORMAT: u32,
1177    const COMPONENTS: u32,
1178>
1179    SampledImage<
1180        Image<
1181            SampledType,
1182            DIM,
1183            DEPTH,
1184            ARRAYED,
1185            { Multisampled::False as u32 },
1186            SAMPLED,
1187            FORMAT,
1188            COMPONENTS,
1189        >,
1190    >
1191{
1192    /// Sample texels at `coord` from the sampled image with an implicit lod.
1193    #[crate::macros::gpu_only]
1194    #[inline]
1195    pub fn sample<F>(
1196        &self,
1197        coord: impl ImageCoordinate<F, DIM, ARRAYED>,
1198    ) -> SampledType::SampleResult
1199    where
1200        F: Float,
1201    {
1202        let mut result = SampledType::Vec4::default();
1203        unsafe {
1204            asm!(
1205                "OpDecorate %sampledImage NonUniform",
1206                "OpDecorate %result NonUniform",
1207                "%sampledImage = OpLoad typeof*{1} {1}",
1208                "%coord = OpLoad typeof*{2} {2}",
1209                "%result = OpImageSampleImplicitLod typeof*{0} %sampledImage %coord",
1210                "OpStore {0} %result",
1211                in(reg) &mut result,
1212                in(reg) self,
1213                in(reg) &coord
1214            );
1215        }
1216        result.truncate_into()
1217    }
1218
1219    /// Sample texels at `coord` from the sampled image with an explicit lod.
1220    #[crate::macros::gpu_only]
1221    #[inline]
1222    pub fn sample_by_lod<F>(
1223        &self,
1224        coord: impl ImageCoordinate<F, DIM, ARRAYED>,
1225        lod: f32,
1226    ) -> SampledType::SampleResult
1227    where
1228        F: Float,
1229    {
1230        let mut result = SampledType::Vec4::default();
1231        unsafe {
1232            asm!(
1233                "OpDecorate %sampledImage NonUniform",
1234                "OpDecorate %result NonUniform",
1235                "%sampledImage = OpLoad typeof*{1} {1}",
1236                "%coord = OpLoad typeof*{2} {2}",
1237                "%lod = OpLoad typeof*{3} {3}",
1238                "%result = OpImageSampleExplicitLod typeof*{0} %sampledImage %coord Lod %lod",
1239                "OpStore {0} %result",
1240                in(reg) &mut result,
1241                in(reg) self,
1242                in(reg) &coord,
1243                in(reg) &lod,
1244            );
1245        }
1246        result.truncate_into()
1247    }
1248
1249    /// Query the dimensions of the image at the specified level of detail.
1250    #[crate::macros::gpu_only]
1251    #[doc(alias = "OpImageQuerySizeLod")]
1252    #[inline]
1253    pub fn query_size_lod<Size: ImageSizeQuery<u32, DIM, ARRAYED> + Default>(
1254        &self,
1255        lod: u32,
1256    ) -> Size
1257    where
1258        Image<
1259            SampledType,
1260            DIM,
1261            DEPTH,
1262            ARRAYED,
1263            { Multisampled::False as u32 },
1264            SAMPLED,
1265            FORMAT,
1266            COMPONENTS,
1267        >: HasQuerySizeLod,
1268    {
1269        let mut result: Size = Default::default();
1270        unsafe {
1271            asm! {
1272                "%sampledImage = OpLoad _ {this}",
1273                "%image = OpImage _ %sampledImage",
1274                "%result = OpImageQuerySizeLod typeof*{result} %image {lod}",
1275                "OpStore {result} %result",
1276                this = in(reg) self,
1277                lod = in(reg) lod,
1278                result = in(reg) &mut result,
1279            }
1280        }
1281        result
1282    }
1283}
1284
1285impl<
1286    SampledType: SampleType<FORMAT, COMPONENTS>,
1287    const DIM: u32,
1288    const DEPTH: u32,
1289    const ARRAYED: u32,
1290    const SAMPLED: u32,
1291    const FORMAT: u32,
1292    const COMPONENTS: u32,
1293>
1294    SampledImage<
1295        Image<
1296            SampledType,
1297            DIM,
1298            DEPTH,
1299            ARRAYED,
1300            { Multisampled::True as u32 },
1301            SAMPLED,
1302            FORMAT,
1303            COMPONENTS,
1304        >,
1305    >
1306{
1307    /// Query the dimensions of the image, with no level of detail.
1308    /// Available only for multisampled images.
1309    #[crate::macros::gpu_only]
1310    #[doc(alias = "OpImageQuerySize")]
1311    #[inline]
1312    pub fn query_size<Size: ImageSizeQuery<u32, DIM, ARRAYED> + Default>(&self) -> Size
1313    where
1314        Image<
1315            SampledType,
1316            DIM,
1317            DEPTH,
1318            ARRAYED,
1319            { Multisampled::True as u32 },
1320            SAMPLED,
1321            FORMAT,
1322            COMPONENTS,
1323        >: HasQuerySize,
1324    {
1325        let mut result: Size = Default::default();
1326        unsafe {
1327            asm! {
1328                "%sampledImage = OpLoad _ {this}",
1329                "%image = OpImage _ %sampledImage",
1330                "%result = OpImageQuerySize typeof*{result} %image",
1331                "OpStore {result} %result",
1332                this = in(reg) self,
1333                result = in(reg) &mut result,
1334            }
1335        }
1336        result
1337    }
1338}
1339
1340/// Helper trait that defines all `*_with` methods on an `Image` that use the extra image operands,
1341/// such as bias or lod, defined by the `SampleParams` struct.
1342pub trait ImageWithMethods<
1343    SampledType: SampleType<FORMAT, COMPONENTS>,
1344    const DIM: u32,
1345    const DEPTH: u32,
1346    const ARRAYED: u32,
1347    const MULTISAMPLED: u32,
1348    const SAMPLED: u32,
1349    const FORMAT: u32,
1350    const COMPONENTS: u32,
1351    Params,
1352>
1353{
1354    /// Fetch a single texel with a sampler set at compile time
1355    #[doc(alias = "OpImageFetch")]
1356    fn fetch_with<I>(
1357        &self,
1358        coordinate: impl ImageCoordinate<I, DIM, ARRAYED>,
1359        params: Params,
1360    ) -> SampledType::SampleResult
1361    where
1362        I: Integer;
1363
1364    /// Gathers the requested component from four texels.
1365    #[doc(alias = "OpImageGather")]
1366    fn gather_with<F>(
1367        &self,
1368        sampler: Sampler,
1369        coordinate: impl ImageCoordinate<F, DIM, ARRAYED>,
1370        component: u32,
1371        params: Params,
1372    ) -> SampledType::Vec4
1373    where
1374        Self: HasGather,
1375        F: Float;
1376
1377    /// Sample texels at `coord` from the image using `sampler`.
1378    fn sample_with<F>(
1379        &self,
1380        sampler: Sampler,
1381        coord: impl ImageCoordinate<F, DIM, ARRAYED>,
1382        params: Params,
1383    ) -> SampledType::SampleResult
1384    where
1385        F: Float;
1386
1387    /// Sample the image's depth reference
1388    #[doc(alias = "OpImageSampleDrefImplicitLod")]
1389    fn sample_depth_reference_with<F>(
1390        &self,
1391        sampler: Sampler,
1392        coordinate: impl ImageCoordinate<F, DIM, ARRAYED>,
1393        depth_reference: f32,
1394        params: Params,
1395    ) -> SampledType
1396    where
1397        F: Float;
1398
1399    /// Sample the image with a project coordinate
1400    #[doc(alias = "OpImageSampleProjImplicitLod")]
1401    fn sample_with_project_coordinate_with<F>(
1402        &self,
1403        sampler: Sampler,
1404        project_coordinate: impl ImageCoordinate<F, DIM, { Arrayed::True as u32 }>,
1405        params: Params,
1406    ) -> SampledType::SampleResult
1407    where
1408        F: Float;
1409
1410    /// Sample the image's depth reference with the project coordinate
1411    #[doc(alias = "OpImageSampleProjDrefImplicitLod")]
1412    fn sample_depth_reference_with_project_coordinate_with<F>(
1413        &self,
1414        sampler: Sampler,
1415        project_coordinate: impl ImageCoordinate<F, DIM, { Arrayed::True as u32 }>,
1416        depth_reference: f32,
1417        params: Params,
1418    ) -> SampledType
1419    where
1420        F: Float;
1421}
1422
1423#[crate::macros::gen_sample_param_permutations]
1424impl<
1425    SampledType: SampleType<FORMAT, COMPONENTS>,
1426    const DIM: u32,
1427    const DEPTH: u32,
1428    const ARRAYED: u32,
1429    const MULTISAMPLED: u32,
1430    const SAMPLED: u32,
1431    const FORMAT: u32,
1432    const COMPONENTS: u32,
1433>
1434    ImageWithMethods<
1435        SampledType,
1436        DIM,
1437        DEPTH,
1438        ARRAYED,
1439        MULTISAMPLED,
1440        SAMPLED,
1441        FORMAT,
1442        COMPONENTS,
1443        SampleParams,
1444    > for Image<SampledType, DIM, DEPTH, ARRAYED, MULTISAMPLED, SAMPLED, FORMAT, COMPONENTS>
1445{
1446    #[crate::macros::gpu_only]
1447    #[doc(alias = "OpImageFetch")]
1448    #[inline]
1449    fn fetch_with<I>(
1450        &self,
1451        coordinate: impl ImageCoordinate<I, DIM, ARRAYED>,
1452        params: SampleParams,
1453    ) -> SampledType::SampleResult
1454    where
1455        I: Integer,
1456    {
1457        let mut result = SampledType::Vec4::default();
1458        unsafe {
1459            asm! {
1460                "OpDecorate %image NonUniform",
1461                "OpDecorate %result NonUniform",
1462                "%image = OpLoad _ {this}",
1463                "%coordinate = OpLoad _ {coordinate}",
1464                "%result = OpImageFetch typeof*{result} %image %coordinate $PARAMS",
1465                "OpStore {result} %result",
1466                result = in(reg) &mut result,
1467                this = in(reg) self,
1468                coordinate = in(reg) &coordinate,
1469            }
1470        }
1471        result.truncate_into()
1472    }
1473
1474    /// Gathers the requested component from four texels.
1475    #[crate::macros::gpu_only]
1476    #[doc(alias = "OpImageGather")]
1477    #[inline]
1478    fn gather_with<F>(
1479        &self,
1480        sampler: Sampler,
1481        coordinate: impl ImageCoordinate<F, DIM, ARRAYED>,
1482        component: u32,
1483        params: SampleParams,
1484    ) -> SampledType::Vec4
1485    where
1486        Self: HasGather,
1487        F: Float,
1488    {
1489        let mut result = SampledType::Vec4::default();
1490        unsafe {
1491            asm! {
1492                "OpDecorate %image NonUniform",
1493                "OpDecorate %sampler NonUniform",
1494                "OpDecorate %sampledImage NonUniform",
1495                "OpDecorate %result NonUniform",
1496                "%typeSampledImage = OpTypeSampledImage typeof*{this}",
1497                "%image = OpLoad _ {this}",
1498                "%sampler = OpLoad _ {sampler}",
1499                "%coordinate = OpLoad _ {coordinate}",
1500                "%sampledImage = OpSampledImage %typeSampledImage %image %sampler",
1501                "%result = OpImageGather typeof*{result} %sampledImage %coordinate {component} $PARAMS",
1502                "OpStore {result} %result",
1503                result = in(reg) &mut result,
1504                this = in(reg) self,
1505                sampler = in(reg) &sampler,
1506                coordinate = in(reg) &coordinate,
1507                component = in(reg) component,
1508            }
1509        }
1510        result
1511    }
1512
1513    /// Sample texels at `coord` from the image using `sampler`.
1514    #[crate::macros::gpu_only]
1515    #[inline]
1516    fn sample_with<F>(
1517        &self,
1518        sampler: Sampler,
1519        coord: impl ImageCoordinate<F, DIM, ARRAYED>,
1520        params: SampleParams,
1521    ) -> SampledType::SampleResult
1522    where
1523        F: Float,
1524    {
1525        unsafe {
1526            let mut result = SampledType::Vec4::default();
1527            asm!(
1528                "OpDecorate %image NonUniform",
1529                "OpDecorate %sampler NonUniform",
1530                "OpDecorate %sampledImage NonUniform",
1531                "OpDecorate %result NonUniform",
1532                "%typeSampledImage = OpTypeSampledImage typeof*{this}",
1533                "%image = OpLoad _ {this}",
1534                "%sampler = OpLoad _ {sampler}",
1535                "%coord = OpLoad _ {coord}",
1536                "%sampledImage = OpSampledImage %typeSampledImage %image %sampler",
1537                "%result = OpImageSample$LOD typeof*{result} %sampledImage %coord $PARAMS",
1538                "OpStore {result} %result",
1539                result = in(reg) &mut result,
1540                this = in(reg) self,
1541                sampler = in(reg) &sampler,
1542                coord = in(reg) &coord,
1543            );
1544            result.truncate_into()
1545        }
1546    }
1547
1548    /// Sample the image's depth reference
1549    #[crate::macros::gpu_only]
1550    #[doc(alias = "OpImageSampleDrefImplicitLod")]
1551    #[inline]
1552    fn sample_depth_reference_with<F>(
1553        &self,
1554        sampler: Sampler,
1555        coordinate: impl ImageCoordinate<F, DIM, ARRAYED>,
1556        depth_reference: f32,
1557        params: SampleParams,
1558    ) -> SampledType
1559    where
1560        F: Float,
1561    {
1562        let mut result = Default::default();
1563        unsafe {
1564            asm!(
1565                "OpDecorate %image NonUniform",
1566                "OpDecorate %sampler NonUniform",
1567                "OpDecorate %sampledImage NonUniform",
1568                "OpDecorate %result NonUniform",
1569                "%image = OpLoad _ {this}",
1570                "%sampler = OpLoad _ {sampler}",
1571                "%coordinate = OpLoad _ {coordinate}",
1572                "%depth_reference = OpLoad _ {depth_reference}", // not required to do this way, but done for consistency
1573                "%sampledImage = OpSampledImage _ %image %sampler",
1574                "%result = OpImageSampleDref$LOD typeof*{result} %sampledImage %coordinate %depth_reference $PARAMS",
1575                "OpStore {result} %result",
1576                result = in(reg) &mut result,
1577                this = in(reg) self,
1578                sampler = in(reg) &sampler,
1579                coordinate = in(reg) &coordinate,
1580                depth_reference = in(reg) &depth_reference,
1581            );
1582        }
1583        result
1584    }
1585
1586    /// Sample the image with a project coordinate
1587    #[crate::macros::gpu_only]
1588    #[doc(alias = "OpImageSampleProjImplicitLod")]
1589    #[inline]
1590    fn sample_with_project_coordinate_with<F>(
1591        &self,
1592        sampler: Sampler,
1593        project_coordinate: impl ImageCoordinate<F, DIM, { Arrayed::True as u32 }>,
1594        params: SampleParams,
1595    ) -> SampledType::SampleResult
1596    where
1597        F: Float,
1598    {
1599        unsafe {
1600            let mut result = SampledType::Vec4::default();
1601            asm!(
1602                "OpDecorate %image NonUniform",
1603                "OpDecorate %sampler NonUniform",
1604                "OpDecorate %sampledImage NonUniform",
1605                "OpDecorate %result NonUniform",
1606                "%image = OpLoad _ {this}",
1607                "%sampler = OpLoad _ {sampler}",
1608                "%project_coordinate = OpLoad _ {project_coordinate}",
1609                "%sampledImage = OpSampledImage _ %image %sampler",
1610                "%result = OpImageSampleProj$LOD typeof*{result} %sampledImage %project_coordinate $PARAMS",
1611                "OpStore {result} %result",
1612                result = in(reg) &mut result,
1613                this = in(reg) self,
1614                sampler = in(reg) &sampler,
1615                project_coordinate = in(reg) &project_coordinate,
1616            );
1617            result.truncate_into()
1618        }
1619    }
1620
1621    /// Sample the image's depth reference with the project coordinate
1622    #[crate::macros::gpu_only]
1623    #[doc(alias = "OpImageSampleProjDrefImplicitLod")]
1624    #[inline]
1625    fn sample_depth_reference_with_project_coordinate_with<F>(
1626        &self,
1627        sampler: Sampler,
1628        project_coordinate: impl ImageCoordinate<F, DIM, { Arrayed::True as u32 }>,
1629        depth_reference: f32,
1630        params: SampleParams,
1631    ) -> SampledType
1632    where
1633        F: Float,
1634    {
1635        let mut result = Default::default();
1636        unsafe {
1637            asm!(
1638                "OpDecorate %image NonUniform",
1639                "OpDecorate %sampler NonUniform",
1640                "OpDecorate %sampledImage NonUniform",
1641                "OpDecorate %result NonUniform",
1642                "%image = OpLoad _ {this}",
1643                "%sampler = OpLoad _ {sampler}",
1644                "%project_coordinate = OpLoad _ {project_coordinate}",
1645                "%depth_reference = OpLoad _ {depth_reference}", // not required to do this way, but done for consistency
1646                "%sampledImage = OpSampledImage _ %image %sampler",
1647                "%result = OpImageSampleProjDref$LOD typeof*{result} %sampledImage %project_coordinate %depth_reference $PARAMS",
1648                "OpStore {result} %result",
1649                result = in(reg) &mut result,
1650                this = in(reg) self,
1651                sampler = in(reg) &sampler,
1652                project_coordinate = in(reg) &project_coordinate,
1653                depth_reference = in(reg) &depth_reference,
1654            );
1655        }
1656        result
1657    }
1658}
1659
1660/// This is a marker trait to represent the constraints on `OpImageGather` too complex to be
1661/// represented by const generics. Specifically:
1662///
1663/// "Its `OpTypeImage` must have a Dim of 2D, Cube, or Rect. The MS operand of the underlying
1664/// `OpTypeImage` must be 0."
1665pub trait HasGather {}
1666impl<
1667    SampledType: SampleType<FORMAT, COMPONENTS>,
1668    const DEPTH: u32,
1669    const FORMAT: u32,
1670    const ARRAYED: u32,
1671    const SAMPLED: u32,
1672    const COMPONENTS: u32,
1673> HasGather
1674    for Image<
1675        SampledType,
1676        { Dimensionality::TwoD as u32 },
1677        DEPTH,
1678        ARRAYED,
1679        { Multisampled::False as u32 },
1680        SAMPLED,
1681        FORMAT,
1682        COMPONENTS,
1683    >
1684{
1685}
1686impl<
1687    SampledType: SampleType<FORMAT, COMPONENTS>,
1688    const DEPTH: u32,
1689    const FORMAT: u32,
1690    const ARRAYED: u32,
1691    const SAMPLED: u32,
1692    const COMPONENTS: u32,
1693> HasGather
1694    for Image<
1695        SampledType,
1696        { Dimensionality::Rect as u32 },
1697        DEPTH,
1698        ARRAYED,
1699        { Multisampled::False as u32 },
1700        SAMPLED,
1701        FORMAT,
1702        COMPONENTS,
1703    >
1704{
1705}
1706impl<
1707    SampledType: SampleType<FORMAT, COMPONENTS>,
1708    const DEPTH: u32,
1709    const FORMAT: u32,
1710    const ARRAYED: u32,
1711    const SAMPLED: u32,
1712    const COMPONENTS: u32,
1713> HasGather
1714    for Image<
1715        SampledType,
1716        { Dimensionality::Cube as u32 },
1717        DEPTH,
1718        ARRAYED,
1719        { Multisampled::False as u32 },
1720        SAMPLED,
1721        FORMAT,
1722        COMPONENTS,
1723    >
1724{
1725}
1726
1727/// This is a marker trait to represent the constraints on `OpImageQueryLevels` and
1728/// `OpImageQueryLod` too complex to be represented by const generics. Specifically:
1729///
1730/// "Its Dim operand must be one of 1D, 2D, 3D, or Cube."
1731pub trait HasQueryLevels {}
1732impl<
1733    SampledType: SampleType<FORMAT, COMPONENTS>,
1734    const DEPTH: u32,
1735    const FORMAT: u32,
1736    const ARRAYED: u32,
1737    const MULTISAMPLED: u32,
1738    const SAMPLED: u32,
1739    const COMPONENTS: u32,
1740> HasQueryLevels
1741    for Image<
1742        SampledType,
1743        { Dimensionality::OneD as u32 },
1744        DEPTH,
1745        ARRAYED,
1746        MULTISAMPLED,
1747        SAMPLED,
1748        FORMAT,
1749        COMPONENTS,
1750    >
1751{
1752}
1753impl<
1754    SampledType: SampleType<FORMAT, COMPONENTS>,
1755    const DEPTH: u32,
1756    const FORMAT: u32,
1757    const ARRAYED: u32,
1758    const MULTISAMPLED: u32,
1759    const SAMPLED: u32,
1760    const COMPONENTS: u32,
1761> HasQueryLevels
1762    for Image<
1763        SampledType,
1764        { Dimensionality::TwoD as u32 },
1765        DEPTH,
1766        ARRAYED,
1767        MULTISAMPLED,
1768        SAMPLED,
1769        FORMAT,
1770        COMPONENTS,
1771    >
1772{
1773}
1774impl<
1775    SampledType: SampleType<FORMAT, COMPONENTS>,
1776    const DEPTH: u32,
1777    const FORMAT: u32,
1778    const ARRAYED: u32,
1779    const MULTISAMPLED: u32,
1780    const SAMPLED: u32,
1781    const COMPONENTS: u32,
1782> HasQueryLevels
1783    for Image<
1784        SampledType,
1785        { Dimensionality::ThreeD as u32 },
1786        DEPTH,
1787        ARRAYED,
1788        MULTISAMPLED,
1789        SAMPLED,
1790        FORMAT,
1791        COMPONENTS,
1792    >
1793{
1794}
1795impl<
1796    SampledType: SampleType<FORMAT, COMPONENTS>,
1797    const DEPTH: u32,
1798    const FORMAT: u32,
1799    const ARRAYED: u32,
1800    const MULTISAMPLED: u32,
1801    const SAMPLED: u32,
1802    const COMPONENTS: u32,
1803> HasQueryLevels
1804    for Image<
1805        SampledType,
1806        { Dimensionality::Cube as u32 },
1807        DEPTH,
1808        ARRAYED,
1809        MULTISAMPLED,
1810        SAMPLED,
1811        FORMAT,
1812        COMPONENTS,
1813    >
1814{
1815}
1816
1817/// This is a marker trait to represent the constraints on `OpImageQuerySize` too complex to be
1818/// represented by const generics. Specifically:
1819///
1820/// "Its Dim operand must be 1D, 2D, 3D, Cube, Rect, or Buffer. Additionally, if its Dim is 1D, 2D,
1821/// 3D, or Cube, it must also have either an MS of 1 or a Sampled of 0 or 2."
1822pub trait HasQuerySize {}
1823impl<
1824    SampledType: SampleType<FORMAT, COMPONENTS>,
1825    const DEPTH: u32,
1826    const FORMAT: u32,
1827    const ARRAYED: u32,
1828    const SAMPLED: u32,
1829    const COMPONENTS: u32,
1830> HasQuerySize
1831    for Image<
1832        SampledType,
1833        { Dimensionality::OneD as u32 },
1834        DEPTH,
1835        ARRAYED,
1836        { Multisampled::True as u32 },
1837        SAMPLED,
1838        FORMAT,
1839        COMPONENTS,
1840    >
1841{
1842}
1843impl<
1844    SampledType: SampleType<FORMAT, COMPONENTS>,
1845    const DEPTH: u32,
1846    const FORMAT: u32,
1847    const ARRAYED: u32,
1848    const COMPONENTS: u32,
1849> HasQuerySize
1850    for Image<
1851        SampledType,
1852        { Dimensionality::OneD as u32 },
1853        DEPTH,
1854        ARRAYED,
1855        { Multisampled::False as u32 },
1856        { Sampled::Unknown as u32 },
1857        FORMAT,
1858        COMPONENTS,
1859    >
1860{
1861}
1862impl<
1863    SampledType: SampleType<FORMAT, COMPONENTS>,
1864    const DEPTH: u32,
1865    const FORMAT: u32,
1866    const ARRAYED: u32,
1867    const COMPONENTS: u32,
1868> HasQuerySize
1869    for Image<
1870        SampledType,
1871        { Dimensionality::OneD as u32 },
1872        DEPTH,
1873        ARRAYED,
1874        { Multisampled::False as u32 },
1875        { Sampled::No as u32 },
1876        FORMAT,
1877        COMPONENTS,
1878    >
1879{
1880}
1881impl<
1882    SampledType: SampleType<FORMAT, COMPONENTS>,
1883    const DEPTH: u32,
1884    const FORMAT: u32,
1885    const ARRAYED: u32,
1886    const SAMPLED: u32,
1887    const COMPONENTS: u32,
1888> HasQuerySize
1889    for Image<
1890        SampledType,
1891        { Dimensionality::TwoD as u32 },
1892        DEPTH,
1893        ARRAYED,
1894        { Multisampled::True as u32 },
1895        SAMPLED,
1896        FORMAT,
1897        COMPONENTS,
1898    >
1899{
1900}
1901impl<
1902    SampledType: SampleType<FORMAT, COMPONENTS>,
1903    const DEPTH: u32,
1904    const FORMAT: u32,
1905    const ARRAYED: u32,
1906    const COMPONENTS: u32,
1907> HasQuerySize
1908    for Image<
1909        SampledType,
1910        { Dimensionality::TwoD as u32 },
1911        DEPTH,
1912        ARRAYED,
1913        { Multisampled::False as u32 },
1914        { Sampled::Unknown as u32 },
1915        FORMAT,
1916        COMPONENTS,
1917    >
1918{
1919}
1920impl<
1921    SampledType: SampleType<FORMAT, COMPONENTS>,
1922    const DEPTH: u32,
1923    const FORMAT: u32,
1924    const ARRAYED: u32,
1925    const COMPONENTS: u32,
1926> HasQuerySize
1927    for Image<
1928        SampledType,
1929        { Dimensionality::TwoD as u32 },
1930        DEPTH,
1931        ARRAYED,
1932        { Multisampled::False as u32 },
1933        { Sampled::No as u32 },
1934        FORMAT,
1935        COMPONENTS,
1936    >
1937{
1938}
1939impl<
1940    SampledType: SampleType<FORMAT, COMPONENTS>,
1941    const DEPTH: u32,
1942    const FORMAT: u32,
1943    const ARRAYED: u32,
1944    const SAMPLED: u32,
1945    const COMPONENTS: u32,
1946> HasQuerySize
1947    for Image<
1948        SampledType,
1949        { Dimensionality::ThreeD as u32 },
1950        DEPTH,
1951        ARRAYED,
1952        { Multisampled::True as u32 },
1953        SAMPLED,
1954        FORMAT,
1955        COMPONENTS,
1956    >
1957{
1958}
1959impl<
1960    SampledType: SampleType<FORMAT, COMPONENTS>,
1961    const DEPTH: u32,
1962    const FORMAT: u32,
1963    const ARRAYED: u32,
1964    const COMPONENTS: u32,
1965> HasQuerySize
1966    for Image<
1967        SampledType,
1968        { Dimensionality::ThreeD as u32 },
1969        DEPTH,
1970        ARRAYED,
1971        { Multisampled::False as u32 },
1972        { Sampled::Unknown as u32 },
1973        FORMAT,
1974        COMPONENTS,
1975    >
1976{
1977}
1978impl<
1979    SampledType: SampleType<FORMAT, COMPONENTS>,
1980    const DEPTH: u32,
1981    const FORMAT: u32,
1982    const ARRAYED: u32,
1983    const COMPONENTS: u32,
1984> HasQuerySize
1985    for Image<
1986        SampledType,
1987        { Dimensionality::ThreeD as u32 },
1988        DEPTH,
1989        ARRAYED,
1990        { Multisampled::False as u32 },
1991        { Sampled::No as u32 },
1992        FORMAT,
1993        COMPONENTS,
1994    >
1995{
1996}
1997impl<
1998    SampledType: SampleType<FORMAT, COMPONENTS>,
1999    const DEPTH: u32,
2000    const FORMAT: u32,
2001    const ARRAYED: u32,
2002    const SAMPLED: u32,
2003    const COMPONENTS: u32,
2004> HasQuerySize
2005    for Image<
2006        SampledType,
2007        { Dimensionality::Cube as u32 },
2008        DEPTH,
2009        ARRAYED,
2010        { Multisampled::True as u32 },
2011        SAMPLED,
2012        FORMAT,
2013        COMPONENTS,
2014    >
2015{
2016}
2017impl<
2018    SampledType: SampleType<FORMAT, COMPONENTS>,
2019    const DEPTH: u32,
2020    const FORMAT: u32,
2021    const ARRAYED: u32,
2022    const COMPONENTS: u32,
2023> HasQuerySize
2024    for Image<
2025        SampledType,
2026        { Dimensionality::Cube as u32 },
2027        DEPTH,
2028        ARRAYED,
2029        { Multisampled::False as u32 },
2030        { Sampled::Unknown as u32 },
2031        FORMAT,
2032        COMPONENTS,
2033    >
2034{
2035}
2036impl<
2037    SampledType: SampleType<FORMAT, COMPONENTS>,
2038    const DEPTH: u32,
2039    const FORMAT: u32,
2040    const ARRAYED: u32,
2041    const COMPONENTS: u32,
2042> HasQuerySize
2043    for Image<
2044        SampledType,
2045        { Dimensionality::Cube as u32 },
2046        DEPTH,
2047        ARRAYED,
2048        { Multisampled::False as u32 },
2049        { Sampled::No as u32 },
2050        FORMAT,
2051        COMPONENTS,
2052    >
2053{
2054}
2055impl<
2056    SampledType: SampleType<FORMAT, COMPONENTS>,
2057    const DEPTH: u32,
2058    const FORMAT: u32,
2059    const ARRAYED: u32,
2060    const MULTISAMPLED: u32,
2061    const SAMPLED: u32,
2062    const COMPONENTS: u32,
2063> HasQuerySize
2064    for Image<
2065        SampledType,
2066        { Dimensionality::Rect as u32 },
2067        DEPTH,
2068        ARRAYED,
2069        MULTISAMPLED,
2070        SAMPLED,
2071        FORMAT,
2072        COMPONENTS,
2073    >
2074{
2075}
2076impl<
2077    SampledType: SampleType<FORMAT, COMPONENTS>,
2078    const DEPTH: u32,
2079    const FORMAT: u32,
2080    const ARRAYED: u32,
2081    const MULTISAMPLED: u32,
2082    const SAMPLED: u32,
2083    const COMPONENTS: u32,
2084> HasQuerySize
2085    for Image<
2086        SampledType,
2087        { Dimensionality::Buffer as u32 },
2088        DEPTH,
2089        ARRAYED,
2090        MULTISAMPLED,
2091        SAMPLED,
2092        FORMAT,
2093        COMPONENTS,
2094    >
2095{
2096}
2097
2098/// This is a marker trait to represent the constraints on `OpImageQuerySizeLod` too complex to be
2099/// represented by const generics. Specifically:
2100///
2101/// "Its Dim operand must be one of 1D, 2D, 3D, or Cube, and its MS must be 0."
2102pub trait HasQuerySizeLod {}
2103impl<
2104    SampledType: SampleType<FORMAT, COMPONENTS>,
2105    const DEPTH: u32,
2106    const FORMAT: u32,
2107    const ARRAYED: u32,
2108    const SAMPLED: u32,
2109    const COMPONENTS: u32,
2110> HasQuerySizeLod
2111    for Image<
2112        SampledType,
2113        { Dimensionality::OneD as u32 },
2114        DEPTH,
2115        ARRAYED,
2116        { Multisampled::False as u32 },
2117        SAMPLED,
2118        FORMAT,
2119        COMPONENTS,
2120    >
2121{
2122}
2123impl<
2124    SampledType: SampleType<FORMAT, COMPONENTS>,
2125    const DEPTH: u32,
2126    const FORMAT: u32,
2127    const ARRAYED: u32,
2128    const SAMPLED: u32,
2129    const COMPONENTS: u32,
2130> HasQuerySizeLod
2131    for Image<
2132        SampledType,
2133        { Dimensionality::TwoD as u32 },
2134        DEPTH,
2135        ARRAYED,
2136        { Multisampled::False as u32 },
2137        SAMPLED,
2138        FORMAT,
2139        COMPONENTS,
2140    >
2141{
2142}
2143impl<
2144    SampledType: SampleType<FORMAT, COMPONENTS>,
2145    const DEPTH: u32,
2146    const FORMAT: u32,
2147    const ARRAYED: u32,
2148    const SAMPLED: u32,
2149    const COMPONENTS: u32,
2150> HasQuerySizeLod
2151    for Image<
2152        SampledType,
2153        { Dimensionality::ThreeD as u32 },
2154        DEPTH,
2155        ARRAYED,
2156        { Multisampled::False as u32 },
2157        SAMPLED,
2158        FORMAT,
2159        COMPONENTS,
2160    >
2161{
2162}
2163impl<
2164    SampledType: SampleType<FORMAT, COMPONENTS>,
2165    const DEPTH: u32,
2166    const FORMAT: u32,
2167    const ARRAYED: u32,
2168    const SAMPLED: u32,
2169    const COMPONENTS: u32,
2170> HasQuerySizeLod
2171    for Image<
2172        SampledType,
2173        { Dimensionality::Cube as u32 },
2174        DEPTH,
2175        ARRAYED,
2176        { Multisampled::False as u32 },
2177        SAMPLED,
2178        FORMAT,
2179        COMPONENTS,
2180    >
2181{
2182}