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