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