spirv_std/
image.rs

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