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