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