wgpu_hal/vulkan/
conv.rs

1use std::vec::Vec;
2
3use ash::vk;
4
5impl super::PrivateCapabilities {
6    pub fn map_texture_format(&self, format: wgt::TextureFormat) -> vk::Format {
7        use ash::vk::Format as F;
8        use wgt::TextureFormat as Tf;
9        use wgt::{AstcBlock, AstcChannel};
10        match format {
11            Tf::R8Unorm => F::R8_UNORM,
12            Tf::R8Snorm => F::R8_SNORM,
13            Tf::R8Uint => F::R8_UINT,
14            Tf::R8Sint => F::R8_SINT,
15            Tf::R16Uint => F::R16_UINT,
16            Tf::R16Sint => F::R16_SINT,
17            Tf::R16Unorm => F::R16_UNORM,
18            Tf::R16Snorm => F::R16_SNORM,
19            Tf::R16Float => F::R16_SFLOAT,
20            Tf::Rg8Unorm => F::R8G8_UNORM,
21            Tf::Rg8Snorm => F::R8G8_SNORM,
22            Tf::Rg8Uint => F::R8G8_UINT,
23            Tf::Rg8Sint => F::R8G8_SINT,
24            Tf::Rg16Unorm => F::R16G16_UNORM,
25            Tf::Rg16Snorm => F::R16G16_SNORM,
26            Tf::R32Uint => F::R32_UINT,
27            Tf::R32Sint => F::R32_SINT,
28            Tf::R32Float => F::R32_SFLOAT,
29            Tf::Rg16Uint => F::R16G16_UINT,
30            Tf::Rg16Sint => F::R16G16_SINT,
31            Tf::Rg16Float => F::R16G16_SFLOAT,
32            Tf::Rgba8Unorm => F::R8G8B8A8_UNORM,
33            Tf::Rgba8UnormSrgb => F::R8G8B8A8_SRGB,
34            Tf::Bgra8UnormSrgb => F::B8G8R8A8_SRGB,
35            Tf::Rgba8Snorm => F::R8G8B8A8_SNORM,
36            Tf::Bgra8Unorm => F::B8G8R8A8_UNORM,
37            Tf::Rgba8Uint => F::R8G8B8A8_UINT,
38            Tf::Rgba8Sint => F::R8G8B8A8_SINT,
39            Tf::Rgb10a2Uint => F::A2B10G10R10_UINT_PACK32,
40            Tf::Rgb10a2Unorm => F::A2B10G10R10_UNORM_PACK32,
41            Tf::Rg11b10Ufloat => F::B10G11R11_UFLOAT_PACK32,
42            Tf::R64Uint => F::R64_UINT,
43            Tf::Rg32Uint => F::R32G32_UINT,
44            Tf::Rg32Sint => F::R32G32_SINT,
45            Tf::Rg32Float => F::R32G32_SFLOAT,
46            Tf::Rgba16Uint => F::R16G16B16A16_UINT,
47            Tf::Rgba16Sint => F::R16G16B16A16_SINT,
48            Tf::Rgba16Unorm => F::R16G16B16A16_UNORM,
49            Tf::Rgba16Snorm => F::R16G16B16A16_SNORM,
50            Tf::Rgba16Float => F::R16G16B16A16_SFLOAT,
51            Tf::Rgba32Uint => F::R32G32B32A32_UINT,
52            Tf::Rgba32Sint => F::R32G32B32A32_SINT,
53            Tf::Rgba32Float => F::R32G32B32A32_SFLOAT,
54            Tf::Depth32Float => F::D32_SFLOAT,
55            Tf::Depth32FloatStencil8 => F::D32_SFLOAT_S8_UINT,
56            Tf::Depth24Plus => {
57                if self.texture_d24 {
58                    F::X8_D24_UNORM_PACK32
59                } else {
60                    F::D32_SFLOAT
61                }
62            }
63            Tf::Depth24PlusStencil8 => {
64                if self.texture_d24_s8 {
65                    F::D24_UNORM_S8_UINT
66                } else {
67                    F::D32_SFLOAT_S8_UINT
68                }
69            }
70            Tf::Stencil8 => {
71                if self.texture_s8 {
72                    F::S8_UINT
73                } else if self.texture_d24_s8 {
74                    F::D24_UNORM_S8_UINT
75                } else {
76                    F::D32_SFLOAT_S8_UINT
77                }
78            }
79            Tf::Depth16Unorm => F::D16_UNORM,
80            Tf::NV12 => F::G8_B8R8_2PLANE_420_UNORM,
81            Tf::Rgb9e5Ufloat => F::E5B9G9R9_UFLOAT_PACK32,
82            Tf::Bc1RgbaUnorm => F::BC1_RGBA_UNORM_BLOCK,
83            Tf::Bc1RgbaUnormSrgb => F::BC1_RGBA_SRGB_BLOCK,
84            Tf::Bc2RgbaUnorm => F::BC2_UNORM_BLOCK,
85            Tf::Bc2RgbaUnormSrgb => F::BC2_SRGB_BLOCK,
86            Tf::Bc3RgbaUnorm => F::BC3_UNORM_BLOCK,
87            Tf::Bc3RgbaUnormSrgb => F::BC3_SRGB_BLOCK,
88            Tf::Bc4RUnorm => F::BC4_UNORM_BLOCK,
89            Tf::Bc4RSnorm => F::BC4_SNORM_BLOCK,
90            Tf::Bc5RgUnorm => F::BC5_UNORM_BLOCK,
91            Tf::Bc5RgSnorm => F::BC5_SNORM_BLOCK,
92            Tf::Bc6hRgbUfloat => F::BC6H_UFLOAT_BLOCK,
93            Tf::Bc6hRgbFloat => F::BC6H_SFLOAT_BLOCK,
94            Tf::Bc7RgbaUnorm => F::BC7_UNORM_BLOCK,
95            Tf::Bc7RgbaUnormSrgb => F::BC7_SRGB_BLOCK,
96            Tf::Etc2Rgb8Unorm => F::ETC2_R8G8B8_UNORM_BLOCK,
97            Tf::Etc2Rgb8UnormSrgb => F::ETC2_R8G8B8_SRGB_BLOCK,
98            Tf::Etc2Rgb8A1Unorm => F::ETC2_R8G8B8A1_UNORM_BLOCK,
99            Tf::Etc2Rgb8A1UnormSrgb => F::ETC2_R8G8B8A1_SRGB_BLOCK,
100            Tf::Etc2Rgba8Unorm => F::ETC2_R8G8B8A8_UNORM_BLOCK,
101            Tf::Etc2Rgba8UnormSrgb => F::ETC2_R8G8B8A8_SRGB_BLOCK,
102            Tf::EacR11Unorm => F::EAC_R11_UNORM_BLOCK,
103            Tf::EacR11Snorm => F::EAC_R11_SNORM_BLOCK,
104            Tf::EacRg11Unorm => F::EAC_R11G11_UNORM_BLOCK,
105            Tf::EacRg11Snorm => F::EAC_R11G11_SNORM_BLOCK,
106            Tf::Astc { block, channel } => match channel {
107                AstcChannel::Unorm => match block {
108                    AstcBlock::B4x4 => F::ASTC_4X4_UNORM_BLOCK,
109                    AstcBlock::B5x4 => F::ASTC_5X4_UNORM_BLOCK,
110                    AstcBlock::B5x5 => F::ASTC_5X5_UNORM_BLOCK,
111                    AstcBlock::B6x5 => F::ASTC_6X5_UNORM_BLOCK,
112                    AstcBlock::B6x6 => F::ASTC_6X6_UNORM_BLOCK,
113                    AstcBlock::B8x5 => F::ASTC_8X5_UNORM_BLOCK,
114                    AstcBlock::B8x6 => F::ASTC_8X6_UNORM_BLOCK,
115                    AstcBlock::B8x8 => F::ASTC_8X8_UNORM_BLOCK,
116                    AstcBlock::B10x5 => F::ASTC_10X5_UNORM_BLOCK,
117                    AstcBlock::B10x6 => F::ASTC_10X6_UNORM_BLOCK,
118                    AstcBlock::B10x8 => F::ASTC_10X8_UNORM_BLOCK,
119                    AstcBlock::B10x10 => F::ASTC_10X10_UNORM_BLOCK,
120                    AstcBlock::B12x10 => F::ASTC_12X10_UNORM_BLOCK,
121                    AstcBlock::B12x12 => F::ASTC_12X12_UNORM_BLOCK,
122                },
123                AstcChannel::UnormSrgb => match block {
124                    AstcBlock::B4x4 => F::ASTC_4X4_SRGB_BLOCK,
125                    AstcBlock::B5x4 => F::ASTC_5X4_SRGB_BLOCK,
126                    AstcBlock::B5x5 => F::ASTC_5X5_SRGB_BLOCK,
127                    AstcBlock::B6x5 => F::ASTC_6X5_SRGB_BLOCK,
128                    AstcBlock::B6x6 => F::ASTC_6X6_SRGB_BLOCK,
129                    AstcBlock::B8x5 => F::ASTC_8X5_SRGB_BLOCK,
130                    AstcBlock::B8x6 => F::ASTC_8X6_SRGB_BLOCK,
131                    AstcBlock::B8x8 => F::ASTC_8X8_SRGB_BLOCK,
132                    AstcBlock::B10x5 => F::ASTC_10X5_SRGB_BLOCK,
133                    AstcBlock::B10x6 => F::ASTC_10X6_SRGB_BLOCK,
134                    AstcBlock::B10x8 => F::ASTC_10X8_SRGB_BLOCK,
135                    AstcBlock::B10x10 => F::ASTC_10X10_SRGB_BLOCK,
136                    AstcBlock::B12x10 => F::ASTC_12X10_SRGB_BLOCK,
137                    AstcBlock::B12x12 => F::ASTC_12X12_SRGB_BLOCK,
138                },
139                AstcChannel::Hdr => match block {
140                    AstcBlock::B4x4 => F::ASTC_4X4_SFLOAT_BLOCK_EXT,
141                    AstcBlock::B5x4 => F::ASTC_5X4_SFLOAT_BLOCK_EXT,
142                    AstcBlock::B5x5 => F::ASTC_5X5_SFLOAT_BLOCK_EXT,
143                    AstcBlock::B6x5 => F::ASTC_6X5_SFLOAT_BLOCK_EXT,
144                    AstcBlock::B6x6 => F::ASTC_6X6_SFLOAT_BLOCK_EXT,
145                    AstcBlock::B8x5 => F::ASTC_8X5_SFLOAT_BLOCK_EXT,
146                    AstcBlock::B8x6 => F::ASTC_8X6_SFLOAT_BLOCK_EXT,
147                    AstcBlock::B8x8 => F::ASTC_8X8_SFLOAT_BLOCK_EXT,
148                    AstcBlock::B10x5 => F::ASTC_10X5_SFLOAT_BLOCK_EXT,
149                    AstcBlock::B10x6 => F::ASTC_10X6_SFLOAT_BLOCK_EXT,
150                    AstcBlock::B10x8 => F::ASTC_10X8_SFLOAT_BLOCK_EXT,
151                    AstcBlock::B10x10 => F::ASTC_10X10_SFLOAT_BLOCK_EXT,
152                    AstcBlock::B12x10 => F::ASTC_12X10_SFLOAT_BLOCK_EXT,
153                    AstcBlock::B12x12 => F::ASTC_12X12_SFLOAT_BLOCK_EXT,
154                },
155            },
156        }
157    }
158}
159
160pub fn map_vk_surface_formats(sf: vk::SurfaceFormatKHR) -> Option<wgt::TextureFormat> {
161    use ash::vk::Format as F;
162    use wgt::TextureFormat as Tf;
163    // List we care about pulled from https://vulkan.gpuinfo.org/listsurfaceformats.php
164    Some(match sf.color_space {
165        vk::ColorSpaceKHR::SRGB_NONLINEAR => match sf.format {
166            F::B8G8R8A8_UNORM => Tf::Bgra8Unorm,
167            F::B8G8R8A8_SRGB => Tf::Bgra8UnormSrgb,
168            F::R8G8B8A8_SNORM => Tf::Rgba8Snorm,
169            F::R8G8B8A8_UNORM => Tf::Rgba8Unorm,
170            F::R8G8B8A8_SRGB => Tf::Rgba8UnormSrgb,
171            _ => return None,
172        },
173        vk::ColorSpaceKHR::EXTENDED_SRGB_LINEAR_EXT => match sf.format {
174            F::R16G16B16A16_SFLOAT => Tf::Rgba16Float,
175            F::R16G16B16A16_SNORM => Tf::Rgba16Snorm,
176            F::R16G16B16A16_UNORM => Tf::Rgba16Unorm,
177            F::A2B10G10R10_UNORM_PACK32 => Tf::Rgb10a2Unorm,
178            _ => return None,
179        },
180        _ => return None,
181    })
182}
183
184impl crate::Attachment<'_, super::TextureView> {
185    pub(super) fn make_attachment_key(
186        &self,
187        ops: crate::AttachmentOps,
188        caps: &super::PrivateCapabilities,
189    ) -> super::AttachmentKey {
190        super::AttachmentKey {
191            format: caps.map_texture_format(self.view.attachment.view_format),
192            layout: derive_image_layout(self.usage, self.view.attachment.view_format),
193            ops,
194        }
195    }
196}
197
198impl crate::ColorAttachment<'_, super::TextureView> {
199    pub(super) unsafe fn make_vk_clear_color(&self) -> vk::ClearColorValue {
200        let cv = &self.clear_value;
201        match self
202            .target
203            .view
204            .attachment
205            .view_format
206            .sample_type(None, None)
207            .unwrap()
208        {
209            wgt::TextureSampleType::Float { .. } => vk::ClearColorValue {
210                float32: [cv.r as f32, cv.g as f32, cv.b as f32, cv.a as f32],
211            },
212            wgt::TextureSampleType::Sint => vk::ClearColorValue {
213                int32: [cv.r as i32, cv.g as i32, cv.b as i32, cv.a as i32],
214            },
215            wgt::TextureSampleType::Uint => vk::ClearColorValue {
216                uint32: [cv.r as u32, cv.g as u32, cv.b as u32, cv.a as u32],
217            },
218            wgt::TextureSampleType::Depth => unreachable!(),
219        }
220    }
221}
222
223pub fn derive_image_layout(usage: wgt::TextureUses, format: wgt::TextureFormat) -> vk::ImageLayout {
224    // Note: depth textures are always sampled with RODS layout
225    let is_color = !format.is_depth_stencil_format();
226    match usage {
227        wgt::TextureUses::UNINITIALIZED => vk::ImageLayout::UNDEFINED,
228        wgt::TextureUses::COPY_SRC => vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
229        wgt::TextureUses::COPY_DST => vk::ImageLayout::TRANSFER_DST_OPTIMAL,
230        wgt::TextureUses::RESOURCE if is_color => vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
231        wgt::TextureUses::COLOR_TARGET => vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
232        wgt::TextureUses::DEPTH_STENCIL_WRITE => vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
233        _ => {
234            if usage == wgt::TextureUses::PRESENT {
235                vk::ImageLayout::PRESENT_SRC_KHR
236            } else if is_color {
237                vk::ImageLayout::GENERAL
238            } else {
239                vk::ImageLayout::DEPTH_STENCIL_READ_ONLY_OPTIMAL
240            }
241        }
242    }
243}
244
245pub fn map_texture_usage(usage: wgt::TextureUses) -> vk::ImageUsageFlags {
246    let mut flags = vk::ImageUsageFlags::empty();
247    if usage.contains(wgt::TextureUses::COPY_SRC) {
248        flags |= vk::ImageUsageFlags::TRANSFER_SRC;
249    }
250    if usage.contains(wgt::TextureUses::COPY_DST) {
251        flags |= vk::ImageUsageFlags::TRANSFER_DST;
252    }
253    if usage.contains(wgt::TextureUses::RESOURCE) {
254        flags |= vk::ImageUsageFlags::SAMPLED;
255    }
256    if usage.contains(wgt::TextureUses::COLOR_TARGET) {
257        flags |= vk::ImageUsageFlags::COLOR_ATTACHMENT;
258    }
259    if usage
260        .intersects(wgt::TextureUses::DEPTH_STENCIL_READ | wgt::TextureUses::DEPTH_STENCIL_WRITE)
261    {
262        flags |= vk::ImageUsageFlags::DEPTH_STENCIL_ATTACHMENT;
263    }
264    if usage.intersects(
265        wgt::TextureUses::STORAGE_READ_ONLY
266            | wgt::TextureUses::STORAGE_WRITE_ONLY
267            | wgt::TextureUses::STORAGE_READ_WRITE
268            | wgt::TextureUses::STORAGE_ATOMIC,
269    ) {
270        flags |= vk::ImageUsageFlags::STORAGE;
271    }
272    flags
273}
274
275pub fn map_texture_usage_to_barrier(
276    usage: wgt::TextureUses,
277) -> (vk::PipelineStageFlags, vk::AccessFlags) {
278    let mut stages = vk::PipelineStageFlags::empty();
279    let mut access = vk::AccessFlags::empty();
280    let shader_stages = vk::PipelineStageFlags::VERTEX_SHADER
281        | vk::PipelineStageFlags::FRAGMENT_SHADER
282        | vk::PipelineStageFlags::COMPUTE_SHADER;
283
284    if usage.contains(wgt::TextureUses::COPY_SRC) {
285        stages |= vk::PipelineStageFlags::TRANSFER;
286        access |= vk::AccessFlags::TRANSFER_READ;
287    }
288    if usage.contains(wgt::TextureUses::COPY_DST) {
289        stages |= vk::PipelineStageFlags::TRANSFER;
290        access |= vk::AccessFlags::TRANSFER_WRITE;
291    }
292    if usage.contains(wgt::TextureUses::RESOURCE) {
293        stages |= shader_stages;
294        access |= vk::AccessFlags::SHADER_READ;
295    }
296    if usage.contains(wgt::TextureUses::COLOR_TARGET) {
297        stages |= vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT;
298        access |= vk::AccessFlags::COLOR_ATTACHMENT_READ | vk::AccessFlags::COLOR_ATTACHMENT_WRITE;
299    }
300    if usage.intersects(wgt::TextureUses::DEPTH_STENCIL_READ) {
301        stages |= vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS
302            | vk::PipelineStageFlags::LATE_FRAGMENT_TESTS;
303        access |= vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ;
304    }
305    if usage.intersects(wgt::TextureUses::DEPTH_STENCIL_WRITE) {
306        stages |= vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS
307            | vk::PipelineStageFlags::LATE_FRAGMENT_TESTS;
308        access |= vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
309            | vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE;
310    }
311    if usage.intersects(
312        wgt::TextureUses::STORAGE_READ_ONLY
313            | wgt::TextureUses::STORAGE_READ_WRITE
314            | wgt::TextureUses::STORAGE_ATOMIC,
315    ) {
316        stages |= shader_stages;
317        access |= vk::AccessFlags::SHADER_READ;
318    }
319    if usage.intersects(
320        wgt::TextureUses::STORAGE_WRITE_ONLY
321            | wgt::TextureUses::STORAGE_READ_WRITE
322            | wgt::TextureUses::STORAGE_ATOMIC,
323    ) {
324        stages |= shader_stages;
325        access |= vk::AccessFlags::SHADER_WRITE;
326    }
327
328    if usage == wgt::TextureUses::UNINITIALIZED || usage == wgt::TextureUses::PRESENT {
329        (
330            vk::PipelineStageFlags::TOP_OF_PIPE,
331            vk::AccessFlags::empty(),
332        )
333    } else {
334        (stages, access)
335    }
336}
337
338pub fn map_vk_image_usage(usage: vk::ImageUsageFlags) -> wgt::TextureUses {
339    let mut bits = wgt::TextureUses::empty();
340    if usage.contains(vk::ImageUsageFlags::TRANSFER_SRC) {
341        bits |= wgt::TextureUses::COPY_SRC;
342    }
343    if usage.contains(vk::ImageUsageFlags::TRANSFER_DST) {
344        bits |= wgt::TextureUses::COPY_DST;
345    }
346    if usage.contains(vk::ImageUsageFlags::SAMPLED) {
347        bits |= wgt::TextureUses::RESOURCE;
348    }
349    if usage.contains(vk::ImageUsageFlags::COLOR_ATTACHMENT) {
350        bits |= wgt::TextureUses::COLOR_TARGET;
351    }
352    if usage.contains(vk::ImageUsageFlags::DEPTH_STENCIL_ATTACHMENT) {
353        bits |= wgt::TextureUses::DEPTH_STENCIL_READ | wgt::TextureUses::DEPTH_STENCIL_WRITE;
354    }
355    if usage.contains(vk::ImageUsageFlags::STORAGE) {
356        bits |= wgt::TextureUses::STORAGE_READ_ONLY
357            | wgt::TextureUses::STORAGE_WRITE_ONLY
358            | wgt::TextureUses::STORAGE_READ_WRITE
359            | wgt::TextureUses::STORAGE_ATOMIC;
360    }
361    bits
362}
363
364pub fn map_texture_dimension(dim: wgt::TextureDimension) -> vk::ImageType {
365    match dim {
366        wgt::TextureDimension::D1 => vk::ImageType::TYPE_1D,
367        wgt::TextureDimension::D2 => vk::ImageType::TYPE_2D,
368        wgt::TextureDimension::D3 => vk::ImageType::TYPE_3D,
369    }
370}
371
372pub fn map_index_format(index_format: wgt::IndexFormat) -> vk::IndexType {
373    match index_format {
374        wgt::IndexFormat::Uint16 => vk::IndexType::UINT16,
375        wgt::IndexFormat::Uint32 => vk::IndexType::UINT32,
376    }
377}
378
379pub fn map_vertex_format(vertex_format: wgt::VertexFormat) -> vk::Format {
380    use wgt::VertexFormat as Vf;
381    match vertex_format {
382        Vf::Uint8 => vk::Format::R8_UINT,
383        Vf::Uint8x2 => vk::Format::R8G8_UINT,
384        Vf::Uint8x4 => vk::Format::R8G8B8A8_UINT,
385        Vf::Sint8 => vk::Format::R8_SINT,
386        Vf::Sint8x2 => vk::Format::R8G8_SINT,
387        Vf::Sint8x4 => vk::Format::R8G8B8A8_SINT,
388        Vf::Unorm8 => vk::Format::R8_UNORM,
389        Vf::Unorm8x2 => vk::Format::R8G8_UNORM,
390        Vf::Unorm8x4 => vk::Format::R8G8B8A8_UNORM,
391        Vf::Snorm8 => vk::Format::R8_SNORM,
392        Vf::Snorm8x2 => vk::Format::R8G8_SNORM,
393        Vf::Snorm8x4 => vk::Format::R8G8B8A8_SNORM,
394        Vf::Uint16 => vk::Format::R16_UINT,
395        Vf::Uint16x2 => vk::Format::R16G16_UINT,
396        Vf::Uint16x4 => vk::Format::R16G16B16A16_UINT,
397        Vf::Sint16 => vk::Format::R16_SINT,
398        Vf::Sint16x2 => vk::Format::R16G16_SINT,
399        Vf::Sint16x4 => vk::Format::R16G16B16A16_SINT,
400        Vf::Unorm16 => vk::Format::R16_UNORM,
401        Vf::Unorm16x2 => vk::Format::R16G16_UNORM,
402        Vf::Unorm16x4 => vk::Format::R16G16B16A16_UNORM,
403        Vf::Snorm16 => vk::Format::R16_SNORM,
404        Vf::Snorm16x2 => vk::Format::R16G16_SNORM,
405        Vf::Snorm16x4 => vk::Format::R16G16B16A16_SNORM,
406        Vf::Float16 => vk::Format::R16_SFLOAT,
407        Vf::Float16x2 => vk::Format::R16G16_SFLOAT,
408        Vf::Float16x4 => vk::Format::R16G16B16A16_SFLOAT,
409        Vf::Float32 => vk::Format::R32_SFLOAT,
410        Vf::Float32x2 => vk::Format::R32G32_SFLOAT,
411        Vf::Float32x3 => vk::Format::R32G32B32_SFLOAT,
412        Vf::Float32x4 => vk::Format::R32G32B32A32_SFLOAT,
413        Vf::Uint32 => vk::Format::R32_UINT,
414        Vf::Uint32x2 => vk::Format::R32G32_UINT,
415        Vf::Uint32x3 => vk::Format::R32G32B32_UINT,
416        Vf::Uint32x4 => vk::Format::R32G32B32A32_UINT,
417        Vf::Sint32 => vk::Format::R32_SINT,
418        Vf::Sint32x2 => vk::Format::R32G32_SINT,
419        Vf::Sint32x3 => vk::Format::R32G32B32_SINT,
420        Vf::Sint32x4 => vk::Format::R32G32B32A32_SINT,
421        Vf::Float64 => vk::Format::R64_SFLOAT,
422        Vf::Float64x2 => vk::Format::R64G64_SFLOAT,
423        Vf::Float64x3 => vk::Format::R64G64B64_SFLOAT,
424        Vf::Float64x4 => vk::Format::R64G64B64A64_SFLOAT,
425        Vf::Unorm10_10_10_2 => vk::Format::A2B10G10R10_UNORM_PACK32,
426        Vf::Unorm8x4Bgra => vk::Format::B8G8R8A8_UNORM,
427    }
428}
429
430pub fn map_aspects(aspects: crate::FormatAspects) -> vk::ImageAspectFlags {
431    let mut flags = vk::ImageAspectFlags::empty();
432    if aspects.contains(crate::FormatAspects::COLOR) {
433        flags |= vk::ImageAspectFlags::COLOR;
434    }
435    if aspects.contains(crate::FormatAspects::DEPTH) {
436        flags |= vk::ImageAspectFlags::DEPTH;
437    }
438    if aspects.contains(crate::FormatAspects::STENCIL) {
439        flags |= vk::ImageAspectFlags::STENCIL;
440    }
441    if aspects.contains(crate::FormatAspects::PLANE_0) {
442        flags |= vk::ImageAspectFlags::PLANE_0;
443    }
444    if aspects.contains(crate::FormatAspects::PLANE_1) {
445        flags |= vk::ImageAspectFlags::PLANE_1;
446    }
447    if aspects.contains(crate::FormatAspects::PLANE_2) {
448        flags |= vk::ImageAspectFlags::PLANE_2;
449    }
450    flags
451}
452
453pub fn map_attachment_ops(
454    op: crate::AttachmentOps,
455) -> (vk::AttachmentLoadOp, vk::AttachmentStoreOp) {
456    let load_op = if op.contains(crate::AttachmentOps::LOAD) {
457        vk::AttachmentLoadOp::LOAD
458    } else {
459        vk::AttachmentLoadOp::CLEAR
460    };
461    let store_op = if op.contains(crate::AttachmentOps::STORE) {
462        vk::AttachmentStoreOp::STORE
463    } else {
464        vk::AttachmentStoreOp::DONT_CARE
465    };
466    (load_op, store_op)
467}
468
469pub fn map_present_mode(mode: wgt::PresentMode) -> vk::PresentModeKHR {
470    match mode {
471        wgt::PresentMode::Immediate => vk::PresentModeKHR::IMMEDIATE,
472        wgt::PresentMode::Mailbox => vk::PresentModeKHR::MAILBOX,
473        wgt::PresentMode::Fifo => vk::PresentModeKHR::FIFO,
474        wgt::PresentMode::FifoRelaxed => vk::PresentModeKHR::FIFO_RELAXED,
475        wgt::PresentMode::AutoNoVsync | wgt::PresentMode::AutoVsync => {
476            unreachable!("Cannot create swapchain with Auto PresentationMode")
477        }
478    }
479}
480
481pub fn map_vk_present_mode(mode: vk::PresentModeKHR) -> Option<wgt::PresentMode> {
482    if mode == vk::PresentModeKHR::IMMEDIATE {
483        Some(wgt::PresentMode::Immediate)
484    } else if mode == vk::PresentModeKHR::MAILBOX {
485        Some(wgt::PresentMode::Mailbox)
486    } else if mode == vk::PresentModeKHR::FIFO {
487        Some(wgt::PresentMode::Fifo)
488    } else if mode == vk::PresentModeKHR::FIFO_RELAXED {
489        Some(wgt::PresentMode::FifoRelaxed)
490    } else {
491        log::warn!("Unrecognized present mode {:?}", mode);
492        None
493    }
494}
495
496pub fn map_composite_alpha_mode(mode: wgt::CompositeAlphaMode) -> vk::CompositeAlphaFlagsKHR {
497    match mode {
498        wgt::CompositeAlphaMode::Opaque => vk::CompositeAlphaFlagsKHR::OPAQUE,
499        wgt::CompositeAlphaMode::PreMultiplied => vk::CompositeAlphaFlagsKHR::PRE_MULTIPLIED,
500        wgt::CompositeAlphaMode::PostMultiplied => vk::CompositeAlphaFlagsKHR::POST_MULTIPLIED,
501        wgt::CompositeAlphaMode::Inherit => vk::CompositeAlphaFlagsKHR::INHERIT,
502        wgt::CompositeAlphaMode::Auto => unreachable!(),
503    }
504}
505
506pub fn map_vk_composite_alpha(flags: vk::CompositeAlphaFlagsKHR) -> Vec<wgt::CompositeAlphaMode> {
507    let mut modes = Vec::new();
508    if flags.contains(vk::CompositeAlphaFlagsKHR::OPAQUE) {
509        modes.push(wgt::CompositeAlphaMode::Opaque);
510    }
511    if flags.contains(vk::CompositeAlphaFlagsKHR::PRE_MULTIPLIED) {
512        modes.push(wgt::CompositeAlphaMode::PreMultiplied);
513    }
514    if flags.contains(vk::CompositeAlphaFlagsKHR::POST_MULTIPLIED) {
515        modes.push(wgt::CompositeAlphaMode::PostMultiplied);
516    }
517    if flags.contains(vk::CompositeAlphaFlagsKHR::INHERIT) {
518        modes.push(wgt::CompositeAlphaMode::Inherit);
519    }
520    modes
521}
522
523pub fn map_buffer_usage(usage: wgt::BufferUses) -> vk::BufferUsageFlags {
524    let mut flags = vk::BufferUsageFlags::empty();
525    if usage.contains(wgt::BufferUses::COPY_SRC) {
526        flags |= vk::BufferUsageFlags::TRANSFER_SRC;
527    }
528    if usage.contains(wgt::BufferUses::COPY_DST) {
529        flags |= vk::BufferUsageFlags::TRANSFER_DST;
530    }
531    if usage.contains(wgt::BufferUses::UNIFORM) {
532        flags |= vk::BufferUsageFlags::UNIFORM_BUFFER;
533    }
534    if usage.intersects(wgt::BufferUses::STORAGE_READ_ONLY | wgt::BufferUses::STORAGE_READ_WRITE) {
535        flags |= vk::BufferUsageFlags::STORAGE_BUFFER;
536    }
537    if usage.contains(wgt::BufferUses::INDEX) {
538        flags |= vk::BufferUsageFlags::INDEX_BUFFER;
539    }
540    if usage.contains(wgt::BufferUses::VERTEX) {
541        flags |= vk::BufferUsageFlags::VERTEX_BUFFER;
542    }
543    if usage.contains(wgt::BufferUses::INDIRECT) {
544        flags |= vk::BufferUsageFlags::INDIRECT_BUFFER;
545    }
546    if usage.contains(wgt::BufferUses::ACCELERATION_STRUCTURE_SCRATCH) {
547        flags |= vk::BufferUsageFlags::STORAGE_BUFFER | vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS;
548    }
549    if usage.intersects(
550        wgt::BufferUses::BOTTOM_LEVEL_ACCELERATION_STRUCTURE_INPUT
551            | wgt::BufferUses::TOP_LEVEL_ACCELERATION_STRUCTURE_INPUT,
552    ) {
553        flags |= vk::BufferUsageFlags::ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_KHR
554            | vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS;
555    }
556    if usage.intersects(wgt::BufferUses::ACCELERATION_STRUCTURE_QUERY) {
557        flags |= vk::BufferUsageFlags::TRANSFER_DST;
558    }
559    flags
560}
561
562pub fn map_buffer_usage_to_barrier(
563    usage: wgt::BufferUses,
564) -> (vk::PipelineStageFlags, vk::AccessFlags) {
565    let mut stages = vk::PipelineStageFlags::empty();
566    let mut access = vk::AccessFlags::empty();
567    let shader_stages = vk::PipelineStageFlags::VERTEX_SHADER
568        | vk::PipelineStageFlags::FRAGMENT_SHADER
569        | vk::PipelineStageFlags::COMPUTE_SHADER;
570
571    if usage.contains(wgt::BufferUses::MAP_READ) {
572        stages |= vk::PipelineStageFlags::HOST;
573        access |= vk::AccessFlags::HOST_READ;
574    }
575    if usage.contains(wgt::BufferUses::MAP_WRITE) {
576        stages |= vk::PipelineStageFlags::HOST;
577        access |= vk::AccessFlags::HOST_WRITE;
578    }
579    if usage.contains(wgt::BufferUses::COPY_SRC) {
580        stages |= vk::PipelineStageFlags::TRANSFER;
581        access |= vk::AccessFlags::TRANSFER_READ;
582    }
583    if usage.contains(wgt::BufferUses::COPY_DST) {
584        stages |= vk::PipelineStageFlags::TRANSFER;
585        access |= vk::AccessFlags::TRANSFER_WRITE;
586    }
587    if usage.contains(wgt::BufferUses::UNIFORM) {
588        stages |= shader_stages;
589        access |= vk::AccessFlags::UNIFORM_READ;
590    }
591    if usage.intersects(wgt::BufferUses::STORAGE_READ_ONLY) {
592        stages |= shader_stages;
593        access |= vk::AccessFlags::SHADER_READ;
594    }
595    if usage.intersects(wgt::BufferUses::STORAGE_READ_WRITE) {
596        stages |= shader_stages;
597        access |= vk::AccessFlags::SHADER_READ | vk::AccessFlags::SHADER_WRITE;
598    }
599    if usage.contains(wgt::BufferUses::INDEX) {
600        stages |= vk::PipelineStageFlags::VERTEX_INPUT;
601        access |= vk::AccessFlags::INDEX_READ;
602    }
603    if usage.contains(wgt::BufferUses::VERTEX) {
604        stages |= vk::PipelineStageFlags::VERTEX_INPUT;
605        access |= vk::AccessFlags::VERTEX_ATTRIBUTE_READ;
606    }
607    if usage.contains(wgt::BufferUses::INDIRECT) {
608        stages |= vk::PipelineStageFlags::DRAW_INDIRECT;
609        access |= vk::AccessFlags::INDIRECT_COMMAND_READ;
610    }
611    if usage.intersects(
612        wgt::BufferUses::BOTTOM_LEVEL_ACCELERATION_STRUCTURE_INPUT
613            | wgt::BufferUses::TOP_LEVEL_ACCELERATION_STRUCTURE_INPUT
614            | wgt::BufferUses::ACCELERATION_STRUCTURE_SCRATCH,
615    ) {
616        stages |= vk::PipelineStageFlags::ACCELERATION_STRUCTURE_BUILD_KHR;
617        access |= vk::AccessFlags::ACCELERATION_STRUCTURE_READ_KHR
618            | vk::AccessFlags::ACCELERATION_STRUCTURE_WRITE_KHR
619            | vk::AccessFlags::SHADER_READ;
620    }
621    if usage.contains(wgt::BufferUses::ACCELERATION_STRUCTURE_QUERY) {
622        stages |= vk::PipelineStageFlags::TRANSFER;
623        access |= vk::AccessFlags::TRANSFER_WRITE;
624    }
625
626    (stages, access)
627}
628
629pub fn map_view_dimension(dim: wgt::TextureViewDimension) -> vk::ImageViewType {
630    match dim {
631        wgt::TextureViewDimension::D1 => vk::ImageViewType::TYPE_1D,
632        wgt::TextureViewDimension::D2 => vk::ImageViewType::TYPE_2D,
633        wgt::TextureViewDimension::D2Array => vk::ImageViewType::TYPE_2D_ARRAY,
634        wgt::TextureViewDimension::Cube => vk::ImageViewType::CUBE,
635        wgt::TextureViewDimension::CubeArray => vk::ImageViewType::CUBE_ARRAY,
636        wgt::TextureViewDimension::D3 => vk::ImageViewType::TYPE_3D,
637    }
638}
639
640pub fn map_copy_extent(extent: &crate::CopyExtent) -> vk::Extent3D {
641    vk::Extent3D {
642        width: extent.width,
643        height: extent.height,
644        depth: extent.depth,
645    }
646}
647
648pub fn map_subresource_range(
649    range: &wgt::ImageSubresourceRange,
650    format: wgt::TextureFormat,
651) -> vk::ImageSubresourceRange {
652    vk::ImageSubresourceRange {
653        aspect_mask: map_aspects(crate::FormatAspects::new(format, range.aspect)),
654        base_mip_level: range.base_mip_level,
655        level_count: range.mip_level_count.unwrap_or(vk::REMAINING_MIP_LEVELS),
656        base_array_layer: range.base_array_layer,
657        layer_count: range
658            .array_layer_count
659            .unwrap_or(vk::REMAINING_ARRAY_LAYERS),
660    }
661}
662
663// Special subresource range mapping for dealing with barriers
664// so that we account for the "hidden" depth aspect in emulated Stencil8.
665pub(super) fn map_subresource_range_combined_aspect(
666    range: &wgt::ImageSubresourceRange,
667    format: wgt::TextureFormat,
668    private_caps: &super::PrivateCapabilities,
669) -> vk::ImageSubresourceRange {
670    let mut range = map_subresource_range(range, format);
671    if !private_caps.texture_s8 && format == wgt::TextureFormat::Stencil8 {
672        range.aspect_mask |= vk::ImageAspectFlags::DEPTH;
673    }
674    range
675}
676
677pub fn map_subresource_layers(
678    base: &crate::TextureCopyBase,
679) -> (vk::ImageSubresourceLayers, vk::Offset3D) {
680    let offset = vk::Offset3D {
681        x: base.origin.x as i32,
682        y: base.origin.y as i32,
683        z: base.origin.z as i32,
684    };
685    let subresource = vk::ImageSubresourceLayers {
686        aspect_mask: map_aspects(base.aspect),
687        mip_level: base.mip_level,
688        base_array_layer: base.array_layer,
689        layer_count: 1,
690    };
691    (subresource, offset)
692}
693
694pub fn map_filter_mode(mode: wgt::FilterMode) -> vk::Filter {
695    match mode {
696        wgt::FilterMode::Nearest => vk::Filter::NEAREST,
697        wgt::FilterMode::Linear => vk::Filter::LINEAR,
698    }
699}
700
701pub fn map_mip_filter_mode(mode: wgt::FilterMode) -> vk::SamplerMipmapMode {
702    match mode {
703        wgt::FilterMode::Nearest => vk::SamplerMipmapMode::NEAREST,
704        wgt::FilterMode::Linear => vk::SamplerMipmapMode::LINEAR,
705    }
706}
707
708pub fn map_address_mode(mode: wgt::AddressMode) -> vk::SamplerAddressMode {
709    match mode {
710        wgt::AddressMode::ClampToEdge => vk::SamplerAddressMode::CLAMP_TO_EDGE,
711        wgt::AddressMode::Repeat => vk::SamplerAddressMode::REPEAT,
712        wgt::AddressMode::MirrorRepeat => vk::SamplerAddressMode::MIRRORED_REPEAT,
713        wgt::AddressMode::ClampToBorder => vk::SamplerAddressMode::CLAMP_TO_BORDER,
714        // wgt::AddressMode::MirrorClamp => vk::SamplerAddressMode::MIRROR_CLAMP_TO_EDGE,
715    }
716}
717
718pub fn map_border_color(border_color: wgt::SamplerBorderColor) -> vk::BorderColor {
719    match border_color {
720        wgt::SamplerBorderColor::TransparentBlack | wgt::SamplerBorderColor::Zero => {
721            vk::BorderColor::FLOAT_TRANSPARENT_BLACK
722        }
723        wgt::SamplerBorderColor::OpaqueBlack => vk::BorderColor::FLOAT_OPAQUE_BLACK,
724        wgt::SamplerBorderColor::OpaqueWhite => vk::BorderColor::FLOAT_OPAQUE_WHITE,
725    }
726}
727
728pub fn map_comparison(fun: wgt::CompareFunction) -> vk::CompareOp {
729    use wgt::CompareFunction as Cf;
730    match fun {
731        Cf::Never => vk::CompareOp::NEVER,
732        Cf::Less => vk::CompareOp::LESS,
733        Cf::LessEqual => vk::CompareOp::LESS_OR_EQUAL,
734        Cf::Equal => vk::CompareOp::EQUAL,
735        Cf::GreaterEqual => vk::CompareOp::GREATER_OR_EQUAL,
736        Cf::Greater => vk::CompareOp::GREATER,
737        Cf::NotEqual => vk::CompareOp::NOT_EQUAL,
738        Cf::Always => vk::CompareOp::ALWAYS,
739    }
740}
741
742pub fn map_shader_stage(stage: wgt::ShaderStages) -> vk::ShaderStageFlags {
743    let mut flags = vk::ShaderStageFlags::empty();
744    if stage.contains(wgt::ShaderStages::VERTEX) {
745        flags |= vk::ShaderStageFlags::VERTEX;
746    }
747    if stage.contains(wgt::ShaderStages::FRAGMENT) {
748        flags |= vk::ShaderStageFlags::FRAGMENT;
749    }
750    if stage.contains(wgt::ShaderStages::COMPUTE) {
751        flags |= vk::ShaderStageFlags::COMPUTE;
752    }
753    flags
754}
755
756pub fn map_binding_type(ty: wgt::BindingType) -> vk::DescriptorType {
757    match ty {
758        wgt::BindingType::Buffer {
759            ty,
760            has_dynamic_offset,
761            ..
762        } => match ty {
763            wgt::BufferBindingType::Storage { .. } => match has_dynamic_offset {
764                true => vk::DescriptorType::STORAGE_BUFFER_DYNAMIC,
765                false => vk::DescriptorType::STORAGE_BUFFER,
766            },
767            wgt::BufferBindingType::Uniform => match has_dynamic_offset {
768                true => vk::DescriptorType::UNIFORM_BUFFER_DYNAMIC,
769                false => vk::DescriptorType::UNIFORM_BUFFER,
770            },
771        },
772        wgt::BindingType::Sampler { .. } => vk::DescriptorType::SAMPLER,
773        wgt::BindingType::Texture { .. } => vk::DescriptorType::SAMPLED_IMAGE,
774        wgt::BindingType::StorageTexture { .. } => vk::DescriptorType::STORAGE_IMAGE,
775        wgt::BindingType::AccelerationStructure { .. } => {
776            vk::DescriptorType::ACCELERATION_STRUCTURE_KHR
777        }
778    }
779}
780
781pub fn map_topology(topology: wgt::PrimitiveTopology) -> vk::PrimitiveTopology {
782    use wgt::PrimitiveTopology as Pt;
783    match topology {
784        Pt::PointList => vk::PrimitiveTopology::POINT_LIST,
785        Pt::LineList => vk::PrimitiveTopology::LINE_LIST,
786        Pt::LineStrip => vk::PrimitiveTopology::LINE_STRIP,
787        Pt::TriangleList => vk::PrimitiveTopology::TRIANGLE_LIST,
788        Pt::TriangleStrip => vk::PrimitiveTopology::TRIANGLE_STRIP,
789    }
790}
791
792pub fn map_polygon_mode(mode: wgt::PolygonMode) -> vk::PolygonMode {
793    match mode {
794        wgt::PolygonMode::Fill => vk::PolygonMode::FILL,
795        wgt::PolygonMode::Line => vk::PolygonMode::LINE,
796        wgt::PolygonMode::Point => vk::PolygonMode::POINT,
797    }
798}
799
800pub fn map_front_face(front_face: wgt::FrontFace) -> vk::FrontFace {
801    match front_face {
802        wgt::FrontFace::Cw => vk::FrontFace::CLOCKWISE,
803        wgt::FrontFace::Ccw => vk::FrontFace::COUNTER_CLOCKWISE,
804    }
805}
806
807pub fn map_cull_face(face: wgt::Face) -> vk::CullModeFlags {
808    match face {
809        wgt::Face::Front => vk::CullModeFlags::FRONT,
810        wgt::Face::Back => vk::CullModeFlags::BACK,
811    }
812}
813
814pub fn map_stencil_op(op: wgt::StencilOperation) -> vk::StencilOp {
815    use wgt::StencilOperation as So;
816    match op {
817        So::Keep => vk::StencilOp::KEEP,
818        So::Zero => vk::StencilOp::ZERO,
819        So::Replace => vk::StencilOp::REPLACE,
820        So::Invert => vk::StencilOp::INVERT,
821        So::IncrementClamp => vk::StencilOp::INCREMENT_AND_CLAMP,
822        So::IncrementWrap => vk::StencilOp::INCREMENT_AND_WRAP,
823        So::DecrementClamp => vk::StencilOp::DECREMENT_AND_CLAMP,
824        So::DecrementWrap => vk::StencilOp::DECREMENT_AND_WRAP,
825    }
826}
827
828pub fn map_stencil_face(
829    face: &wgt::StencilFaceState,
830    compare_mask: u32,
831    write_mask: u32,
832) -> vk::StencilOpState {
833    vk::StencilOpState {
834        fail_op: map_stencil_op(face.fail_op),
835        pass_op: map_stencil_op(face.pass_op),
836        depth_fail_op: map_stencil_op(face.depth_fail_op),
837        compare_op: map_comparison(face.compare),
838        compare_mask,
839        write_mask,
840        reference: 0,
841    }
842}
843
844fn map_blend_factor(factor: wgt::BlendFactor) -> vk::BlendFactor {
845    use wgt::BlendFactor as Bf;
846    match factor {
847        Bf::Zero => vk::BlendFactor::ZERO,
848        Bf::One => vk::BlendFactor::ONE,
849        Bf::Src => vk::BlendFactor::SRC_COLOR,
850        Bf::OneMinusSrc => vk::BlendFactor::ONE_MINUS_SRC_COLOR,
851        Bf::SrcAlpha => vk::BlendFactor::SRC_ALPHA,
852        Bf::OneMinusSrcAlpha => vk::BlendFactor::ONE_MINUS_SRC_ALPHA,
853        Bf::Dst => vk::BlendFactor::DST_COLOR,
854        Bf::OneMinusDst => vk::BlendFactor::ONE_MINUS_DST_COLOR,
855        Bf::DstAlpha => vk::BlendFactor::DST_ALPHA,
856        Bf::OneMinusDstAlpha => vk::BlendFactor::ONE_MINUS_DST_ALPHA,
857        Bf::SrcAlphaSaturated => vk::BlendFactor::SRC_ALPHA_SATURATE,
858        Bf::Constant => vk::BlendFactor::CONSTANT_COLOR,
859        Bf::OneMinusConstant => vk::BlendFactor::ONE_MINUS_CONSTANT_COLOR,
860        Bf::Src1 => vk::BlendFactor::SRC1_COLOR,
861        Bf::OneMinusSrc1 => vk::BlendFactor::ONE_MINUS_SRC1_COLOR,
862        Bf::Src1Alpha => vk::BlendFactor::SRC1_ALPHA,
863        Bf::OneMinusSrc1Alpha => vk::BlendFactor::ONE_MINUS_SRC1_ALPHA,
864    }
865}
866
867fn map_blend_op(operation: wgt::BlendOperation) -> vk::BlendOp {
868    use wgt::BlendOperation as Bo;
869    match operation {
870        Bo::Add => vk::BlendOp::ADD,
871        Bo::Subtract => vk::BlendOp::SUBTRACT,
872        Bo::ReverseSubtract => vk::BlendOp::REVERSE_SUBTRACT,
873        Bo::Min => vk::BlendOp::MIN,
874        Bo::Max => vk::BlendOp::MAX,
875    }
876}
877
878pub fn map_blend_component(
879    component: &wgt::BlendComponent,
880) -> (vk::BlendOp, vk::BlendFactor, vk::BlendFactor) {
881    let op = map_blend_op(component.operation);
882    let src = map_blend_factor(component.src_factor);
883    let dst = map_blend_factor(component.dst_factor);
884    (op, src, dst)
885}
886
887pub fn map_pipeline_statistics(
888    types: wgt::PipelineStatisticsTypes,
889) -> vk::QueryPipelineStatisticFlags {
890    use wgt::PipelineStatisticsTypes as Pst;
891    let mut flags = vk::QueryPipelineStatisticFlags::empty();
892    if types.contains(Pst::VERTEX_SHADER_INVOCATIONS) {
893        flags |= vk::QueryPipelineStatisticFlags::VERTEX_SHADER_INVOCATIONS;
894    }
895    if types.contains(Pst::CLIPPER_INVOCATIONS) {
896        flags |= vk::QueryPipelineStatisticFlags::CLIPPING_INVOCATIONS;
897    }
898    if types.contains(Pst::CLIPPER_PRIMITIVES_OUT) {
899        flags |= vk::QueryPipelineStatisticFlags::CLIPPING_PRIMITIVES;
900    }
901    if types.contains(Pst::FRAGMENT_SHADER_INVOCATIONS) {
902        flags |= vk::QueryPipelineStatisticFlags::FRAGMENT_SHADER_INVOCATIONS;
903    }
904    if types.contains(Pst::COMPUTE_SHADER_INVOCATIONS) {
905        flags |= vk::QueryPipelineStatisticFlags::COMPUTE_SHADER_INVOCATIONS;
906    }
907    flags
908}
909
910pub fn map_acceleration_structure_format(
911    format: crate::AccelerationStructureFormat,
912) -> vk::AccelerationStructureTypeKHR {
913    match format {
914        crate::AccelerationStructureFormat::TopLevel => vk::AccelerationStructureTypeKHR::TOP_LEVEL,
915        crate::AccelerationStructureFormat::BottomLevel => {
916            vk::AccelerationStructureTypeKHR::BOTTOM_LEVEL
917        }
918    }
919}
920
921pub fn map_acceleration_structure_build_mode(
922    format: crate::AccelerationStructureBuildMode,
923) -> vk::BuildAccelerationStructureModeKHR {
924    match format {
925        crate::AccelerationStructureBuildMode::Build => {
926            vk::BuildAccelerationStructureModeKHR::BUILD
927        }
928        crate::AccelerationStructureBuildMode::Update => {
929            vk::BuildAccelerationStructureModeKHR::UPDATE
930        }
931    }
932}
933
934pub fn map_acceleration_structure_flags(
935    flags: crate::AccelerationStructureBuildFlags,
936) -> vk::BuildAccelerationStructureFlagsKHR {
937    let mut vk_flags = vk::BuildAccelerationStructureFlagsKHR::empty();
938
939    if flags.contains(crate::AccelerationStructureBuildFlags::PREFER_FAST_TRACE) {
940        vk_flags |= vk::BuildAccelerationStructureFlagsKHR::PREFER_FAST_TRACE;
941    }
942
943    if flags.contains(crate::AccelerationStructureBuildFlags::PREFER_FAST_BUILD) {
944        vk_flags |= vk::BuildAccelerationStructureFlagsKHR::PREFER_FAST_BUILD;
945    }
946
947    if flags.contains(crate::AccelerationStructureBuildFlags::ALLOW_UPDATE) {
948        vk_flags |= vk::BuildAccelerationStructureFlagsKHR::ALLOW_UPDATE;
949    }
950
951    if flags.contains(crate::AccelerationStructureBuildFlags::LOW_MEMORY) {
952        vk_flags |= vk::BuildAccelerationStructureFlagsKHR::LOW_MEMORY;
953    }
954
955    if flags.contains(crate::AccelerationStructureBuildFlags::ALLOW_COMPACTION) {
956        vk_flags |= vk::BuildAccelerationStructureFlagsKHR::ALLOW_COMPACTION
957    }
958
959    if flags.contains(crate::AccelerationStructureBuildFlags::ALLOW_RAY_HIT_VERTEX_RETURN) {
960        vk_flags |= vk::BuildAccelerationStructureFlagsKHR::ALLOW_DATA_ACCESS
961    }
962
963    vk_flags
964}
965
966pub fn map_acceleration_structure_geometry_flags(
967    flags: crate::AccelerationStructureGeometryFlags,
968) -> vk::GeometryFlagsKHR {
969    let mut vk_flags = vk::GeometryFlagsKHR::empty();
970
971    if flags.contains(crate::AccelerationStructureGeometryFlags::OPAQUE) {
972        vk_flags |= vk::GeometryFlagsKHR::OPAQUE;
973    }
974
975    if flags.contains(crate::AccelerationStructureGeometryFlags::NO_DUPLICATE_ANY_HIT_INVOCATION) {
976        vk_flags |= vk::GeometryFlagsKHR::NO_DUPLICATE_ANY_HIT_INVOCATION;
977    }
978
979    vk_flags
980}
981
982pub fn map_acceleration_structure_usage_to_barrier(
983    usage: crate::AccelerationStructureUses,
984    features: wgt::Features,
985) -> (vk::PipelineStageFlags, vk::AccessFlags) {
986    let mut stages = vk::PipelineStageFlags::empty();
987    let mut access = vk::AccessFlags::empty();
988
989    if usage.contains(crate::AccelerationStructureUses::BUILD_INPUT) {
990        stages |= vk::PipelineStageFlags::ACCELERATION_STRUCTURE_BUILD_KHR;
991        access |= vk::AccessFlags::ACCELERATION_STRUCTURE_READ_KHR;
992    }
993    if usage.contains(crate::AccelerationStructureUses::QUERY_INPUT) {
994        stages |= vk::PipelineStageFlags::ACCELERATION_STRUCTURE_BUILD_KHR;
995        access |= vk::AccessFlags::ACCELERATION_STRUCTURE_READ_KHR;
996    }
997    if usage.contains(crate::AccelerationStructureUses::BUILD_OUTPUT) {
998        stages |= vk::PipelineStageFlags::ACCELERATION_STRUCTURE_BUILD_KHR;
999        access |= vk::AccessFlags::ACCELERATION_STRUCTURE_WRITE_KHR;
1000    }
1001    if usage.contains(crate::AccelerationStructureUses::SHADER_INPUT)
1002        && features.contains(wgt::Features::EXPERIMENTAL_RAY_QUERY)
1003    {
1004        stages |= vk::PipelineStageFlags::VERTEX_SHADER
1005            | vk::PipelineStageFlags::FRAGMENT_SHADER
1006            | vk::PipelineStageFlags::COMPUTE_SHADER;
1007        access |= vk::AccessFlags::ACCELERATION_STRUCTURE_READ_KHR;
1008    }
1009    if usage.contains(crate::AccelerationStructureUses::COPY_SRC) {
1010        stages |= vk::PipelineStageFlags::ACCELERATION_STRUCTURE_BUILD_KHR;
1011        access |= vk::AccessFlags::ACCELERATION_STRUCTURE_READ_KHR;
1012    }
1013    if usage.contains(crate::AccelerationStructureUses::COPY_DST) {
1014        stages |= vk::PipelineStageFlags::ACCELERATION_STRUCTURE_BUILD_KHR;
1015        access |= vk::AccessFlags::ACCELERATION_STRUCTURE_WRITE_KHR;
1016    }
1017
1018    (stages, access)
1019}