1use alloc::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::P010 => F::G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
82 Tf::Rgb9e5Ufloat => F::E5B9G9R9_UFLOAT_PACK32,
83 Tf::Bc1RgbaUnorm => F::BC1_RGBA_UNORM_BLOCK,
84 Tf::Bc1RgbaUnormSrgb => F::BC1_RGBA_SRGB_BLOCK,
85 Tf::Bc2RgbaUnorm => F::BC2_UNORM_BLOCK,
86 Tf::Bc2RgbaUnormSrgb => F::BC2_SRGB_BLOCK,
87 Tf::Bc3RgbaUnorm => F::BC3_UNORM_BLOCK,
88 Tf::Bc3RgbaUnormSrgb => F::BC3_SRGB_BLOCK,
89 Tf::Bc4RUnorm => F::BC4_UNORM_BLOCK,
90 Tf::Bc4RSnorm => F::BC4_SNORM_BLOCK,
91 Tf::Bc5RgUnorm => F::BC5_UNORM_BLOCK,
92 Tf::Bc5RgSnorm => F::BC5_SNORM_BLOCK,
93 Tf::Bc6hRgbUfloat => F::BC6H_UFLOAT_BLOCK,
94 Tf::Bc6hRgbFloat => F::BC6H_SFLOAT_BLOCK,
95 Tf::Bc7RgbaUnorm => F::BC7_UNORM_BLOCK,
96 Tf::Bc7RgbaUnormSrgb => F::BC7_SRGB_BLOCK,
97 Tf::Etc2Rgb8Unorm => F::ETC2_R8G8B8_UNORM_BLOCK,
98 Tf::Etc2Rgb8UnormSrgb => F::ETC2_R8G8B8_SRGB_BLOCK,
99 Tf::Etc2Rgb8A1Unorm => F::ETC2_R8G8B8A1_UNORM_BLOCK,
100 Tf::Etc2Rgb8A1UnormSrgb => F::ETC2_R8G8B8A1_SRGB_BLOCK,
101 Tf::Etc2Rgba8Unorm => F::ETC2_R8G8B8A8_UNORM_BLOCK,
102 Tf::Etc2Rgba8UnormSrgb => F::ETC2_R8G8B8A8_SRGB_BLOCK,
103 Tf::EacR11Unorm => F::EAC_R11_UNORM_BLOCK,
104 Tf::EacR11Snorm => F::EAC_R11_SNORM_BLOCK,
105 Tf::EacRg11Unorm => F::EAC_R11G11_UNORM_BLOCK,
106 Tf::EacRg11Snorm => F::EAC_R11G11_SNORM_BLOCK,
107 Tf::Astc { block, channel } => match channel {
108 AstcChannel::Unorm => match block {
109 AstcBlock::B4x4 => F::ASTC_4X4_UNORM_BLOCK,
110 AstcBlock::B5x4 => F::ASTC_5X4_UNORM_BLOCK,
111 AstcBlock::B5x5 => F::ASTC_5X5_UNORM_BLOCK,
112 AstcBlock::B6x5 => F::ASTC_6X5_UNORM_BLOCK,
113 AstcBlock::B6x6 => F::ASTC_6X6_UNORM_BLOCK,
114 AstcBlock::B8x5 => F::ASTC_8X5_UNORM_BLOCK,
115 AstcBlock::B8x6 => F::ASTC_8X6_UNORM_BLOCK,
116 AstcBlock::B8x8 => F::ASTC_8X8_UNORM_BLOCK,
117 AstcBlock::B10x5 => F::ASTC_10X5_UNORM_BLOCK,
118 AstcBlock::B10x6 => F::ASTC_10X6_UNORM_BLOCK,
119 AstcBlock::B10x8 => F::ASTC_10X8_UNORM_BLOCK,
120 AstcBlock::B10x10 => F::ASTC_10X10_UNORM_BLOCK,
121 AstcBlock::B12x10 => F::ASTC_12X10_UNORM_BLOCK,
122 AstcBlock::B12x12 => F::ASTC_12X12_UNORM_BLOCK,
123 },
124 AstcChannel::UnormSrgb => match block {
125 AstcBlock::B4x4 => F::ASTC_4X4_SRGB_BLOCK,
126 AstcBlock::B5x4 => F::ASTC_5X4_SRGB_BLOCK,
127 AstcBlock::B5x5 => F::ASTC_5X5_SRGB_BLOCK,
128 AstcBlock::B6x5 => F::ASTC_6X5_SRGB_BLOCK,
129 AstcBlock::B6x6 => F::ASTC_6X6_SRGB_BLOCK,
130 AstcBlock::B8x5 => F::ASTC_8X5_SRGB_BLOCK,
131 AstcBlock::B8x6 => F::ASTC_8X6_SRGB_BLOCK,
132 AstcBlock::B8x8 => F::ASTC_8X8_SRGB_BLOCK,
133 AstcBlock::B10x5 => F::ASTC_10X5_SRGB_BLOCK,
134 AstcBlock::B10x6 => F::ASTC_10X6_SRGB_BLOCK,
135 AstcBlock::B10x8 => F::ASTC_10X8_SRGB_BLOCK,
136 AstcBlock::B10x10 => F::ASTC_10X10_SRGB_BLOCK,
137 AstcBlock::B12x10 => F::ASTC_12X10_SRGB_BLOCK,
138 AstcBlock::B12x12 => F::ASTC_12X12_SRGB_BLOCK,
139 },
140 AstcChannel::Hdr => match block {
141 AstcBlock::B4x4 => F::ASTC_4X4_SFLOAT_BLOCK_EXT,
142 AstcBlock::B5x4 => F::ASTC_5X4_SFLOAT_BLOCK_EXT,
143 AstcBlock::B5x5 => F::ASTC_5X5_SFLOAT_BLOCK_EXT,
144 AstcBlock::B6x5 => F::ASTC_6X5_SFLOAT_BLOCK_EXT,
145 AstcBlock::B6x6 => F::ASTC_6X6_SFLOAT_BLOCK_EXT,
146 AstcBlock::B8x5 => F::ASTC_8X5_SFLOAT_BLOCK_EXT,
147 AstcBlock::B8x6 => F::ASTC_8X6_SFLOAT_BLOCK_EXT,
148 AstcBlock::B8x8 => F::ASTC_8X8_SFLOAT_BLOCK_EXT,
149 AstcBlock::B10x5 => F::ASTC_10X5_SFLOAT_BLOCK_EXT,
150 AstcBlock::B10x6 => F::ASTC_10X6_SFLOAT_BLOCK_EXT,
151 AstcBlock::B10x8 => F::ASTC_10X8_SFLOAT_BLOCK_EXT,
152 AstcBlock::B10x10 => F::ASTC_10X10_SFLOAT_BLOCK_EXT,
153 AstcBlock::B12x10 => F::ASTC_12X10_SFLOAT_BLOCK_EXT,
154 AstcBlock::B12x12 => F::ASTC_12X12_SFLOAT_BLOCK_EXT,
155 },
156 },
157 }
158 }
159}
160
161pub fn map_vk_surface_formats(
162 sf: vk::SurfaceFormatKHR,
163) -> Option<(wgt::TextureFormat, wgt::SurfaceColorSpace)> {
164 use ash::vk::Format as F;
165 use wgt::TextureFormat as Tf;
166 let format = match sf.format {
168 F::B8G8R8A8_UNORM => Tf::Bgra8Unorm,
169 F::B8G8R8A8_SRGB => Tf::Bgra8UnormSrgb,
170 F::R8G8B8A8_SNORM => Tf::Rgba8Snorm,
171 F::R8G8B8A8_UNORM => Tf::Rgba8Unorm,
172 F::R8G8B8A8_SRGB => Tf::Rgba8UnormSrgb,
173 F::R16G16B16A16_SNORM => Tf::Rgba16Snorm,
174 F::R16G16B16A16_UNORM => Tf::Rgba16Unorm,
175 F::R16G16B16A16_SFLOAT => Tf::Rgba16Float,
176 F::A2B10G10R10_UNORM_PACK32 => Tf::Rgb10a2Unorm,
177 _ => return None,
178 };
179 let color_space = map_vk_color_space(sf.color_space)?;
180 Some((format, color_space))
181}
182
183pub fn map_vk_color_space(color_space: vk::ColorSpaceKHR) -> Option<wgt::SurfaceColorSpace> {
184 use wgt::SurfaceColorSpace as Scs;
185 Some(match color_space {
186 vk::ColorSpaceKHR::SRGB_NONLINEAR => Scs::Srgb,
187 vk::ColorSpaceKHR::EXTENDED_SRGB_LINEAR_EXT => Scs::ExtendedSrgbLinear,
188 vk::ColorSpaceKHR::EXTENDED_SRGB_NONLINEAR_EXT => Scs::ExtendedSrgb,
189 vk::ColorSpaceKHR::DISPLAY_P3_NONLINEAR_EXT => Scs::DisplayP3,
190 vk::ColorSpaceKHR::HDR10_ST2084_EXT => Scs::Bt2100Pq,
191 vk::ColorSpaceKHR::HDR10_HLG_EXT => Scs::Bt2100Hlg,
192 _ => return None,
193 })
194}
195
196pub fn map_surface_color_space(color_space: wgt::SurfaceColorSpace) -> vk::ColorSpaceKHR {
197 use wgt::SurfaceColorSpace as Scs;
198 match color_space {
199 Scs::Auto => unreachable!("wgpu-core resolves `Auto` before configuring the surface"),
200 Scs::Srgb => vk::ColorSpaceKHR::SRGB_NONLINEAR,
201 Scs::ExtendedSrgbLinear => vk::ColorSpaceKHR::EXTENDED_SRGB_LINEAR_EXT,
202 Scs::ExtendedSrgb => vk::ColorSpaceKHR::EXTENDED_SRGB_NONLINEAR_EXT,
203 Scs::DisplayP3 => vk::ColorSpaceKHR::DISPLAY_P3_NONLINEAR_EXT,
204 Scs::Bt2100Pq => vk::ColorSpaceKHR::HDR10_ST2084_EXT,
205 Scs::Bt2100Hlg => vk::ColorSpaceKHR::HDR10_HLG_EXT,
206 Scs::ExtendedDisplayP3 => {
207 unreachable!("`ExtendedDisplayP3` is never reported in the Vulkan surface capabilities")
208 }
209 }
210}
211
212impl crate::Attachment<'_, super::TextureView> {
213 pub(super) fn make_attachment_key(&self, ops: crate::AttachmentOps) -> super::AttachmentKey {
214 super::AttachmentKey {
215 format: self.view.raw_format,
216 layout: derive_image_layout(self.usage, self.view.format),
217 ops,
218 }
219 }
220}
221
222impl crate::ColorAttachment<'_, super::TextureView> {
223 pub(super) unsafe fn make_vk_clear_color(&self) -> vk::ClearColorValue {
224 let cv = &self.clear_value;
225 match self.target.view.format.sample_type(None, None).unwrap() {
226 wgt::TextureSampleType::Float { .. } => vk::ClearColorValue {
227 float32: [cv.r as f32, cv.g as f32, cv.b as f32, cv.a as f32],
228 },
229 wgt::TextureSampleType::Sint => vk::ClearColorValue {
230 int32: [cv.r as i32, cv.g as i32, cv.b as i32, cv.a as i32],
231 },
232 wgt::TextureSampleType::Uint => vk::ClearColorValue {
233 uint32: [cv.r as u32, cv.g as u32, cv.b as u32, cv.a as u32],
234 },
235 wgt::TextureSampleType::Depth => unreachable!(),
236 }
237 }
238}
239
240pub fn derive_image_layout(usage: wgt::TextureUses, format: wgt::TextureFormat) -> vk::ImageLayout {
241 let is_color = !format.is_depth_stencil_format();
243 match usage {
244 wgt::TextureUses::UNINITIALIZED => vk::ImageLayout::UNDEFINED,
245 wgt::TextureUses::COPY_SRC => vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
246 wgt::TextureUses::COPY_DST => vk::ImageLayout::TRANSFER_DST_OPTIMAL,
247 wgt::TextureUses::RESOURCE if is_color => vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
248 wgt::TextureUses::COLOR_TARGET => vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
249 wgt::TextureUses::DEPTH_STENCIL_WRITE => vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
250 _ => {
251 if usage == wgt::TextureUses::PRESENT {
252 vk::ImageLayout::PRESENT_SRC_KHR
253 } else if is_color {
254 vk::ImageLayout::GENERAL
255 } else {
256 vk::ImageLayout::DEPTH_STENCIL_READ_ONLY_OPTIMAL
257 }
258 }
259 }
260}
261
262pub fn map_texture_usage(usage: wgt::TextureUses) -> vk::ImageUsageFlags {
263 let mut flags = vk::ImageUsageFlags::empty();
264 if usage.contains(wgt::TextureUses::COPY_SRC) {
265 flags |= vk::ImageUsageFlags::TRANSFER_SRC;
266 }
267 if usage.contains(wgt::TextureUses::COPY_DST) {
268 flags |= vk::ImageUsageFlags::TRANSFER_DST;
269 }
270 if usage.contains(wgt::TextureUses::RESOURCE) {
271 flags |= vk::ImageUsageFlags::SAMPLED;
272 }
273 if usage.contains(wgt::TextureUses::COLOR_TARGET) {
274 flags |= vk::ImageUsageFlags::COLOR_ATTACHMENT;
275 }
276 if usage
277 .intersects(wgt::TextureUses::DEPTH_STENCIL_READ | wgt::TextureUses::DEPTH_STENCIL_WRITE)
278 {
279 flags |= vk::ImageUsageFlags::DEPTH_STENCIL_ATTACHMENT;
280 }
281 if usage.intersects(
282 wgt::TextureUses::STORAGE_READ_ONLY
283 | wgt::TextureUses::STORAGE_WRITE_ONLY
284 | wgt::TextureUses::STORAGE_READ_WRITE
285 | wgt::TextureUses::STORAGE_ATOMIC,
286 ) {
287 flags |= vk::ImageUsageFlags::STORAGE;
288 }
289 if usage.contains(wgt::TextureUses::TRANSIENT) {
290 flags |= vk::ImageUsageFlags::TRANSIENT_ATTACHMENT;
291 }
292 flags
293}
294
295pub fn map_texture_usage_to_barrier(
296 usage: wgt::TextureUses,
297 queue_flags: vk::QueueFlags,
298) -> (vk::PipelineStageFlags, vk::AccessFlags) {
299 let mut stages = vk::PipelineStageFlags::empty();
300 let mut access = vk::AccessFlags::empty();
301 let shader_stages = shader_stages(queue_flags);
302
303 if usage.contains(wgt::TextureUses::COPY_SRC) {
304 stages |= vk::PipelineStageFlags::TRANSFER;
305 access |= vk::AccessFlags::TRANSFER_READ;
306 }
307 if usage.contains(wgt::TextureUses::COPY_DST) {
308 stages |= vk::PipelineStageFlags::TRANSFER;
309 access |= vk::AccessFlags::TRANSFER_WRITE;
310 }
311 if usage.contains(wgt::TextureUses::RESOURCE) {
312 stages |= shader_stages;
313 access |= vk::AccessFlags::SHADER_READ;
314 }
315 if usage.contains(wgt::TextureUses::COLOR_TARGET) {
316 stages |= vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT;
317 access |= vk::AccessFlags::COLOR_ATTACHMENT_READ | vk::AccessFlags::COLOR_ATTACHMENT_WRITE;
318 }
319 if usage.intersects(wgt::TextureUses::DEPTH_STENCIL_READ) {
320 stages |= vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS
321 | vk::PipelineStageFlags::LATE_FRAGMENT_TESTS;
322 access |= vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ;
323 }
324 if usage.intersects(wgt::TextureUses::DEPTH_STENCIL_WRITE) {
325 stages |= vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS
326 | vk::PipelineStageFlags::LATE_FRAGMENT_TESTS;
327 access |= vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
328 | vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE;
329 }
330 if usage.intersects(
331 wgt::TextureUses::STORAGE_READ_ONLY
332 | wgt::TextureUses::STORAGE_READ_WRITE
333 | wgt::TextureUses::STORAGE_ATOMIC,
334 ) {
335 stages |= shader_stages;
336 access |= vk::AccessFlags::SHADER_READ;
337 }
338 if usage.intersects(
339 wgt::TextureUses::STORAGE_WRITE_ONLY
340 | wgt::TextureUses::STORAGE_READ_WRITE
341 | wgt::TextureUses::STORAGE_ATOMIC,
342 ) {
343 stages |= shader_stages;
344 access |= vk::AccessFlags::SHADER_WRITE;
345 }
346
347 if usage == wgt::TextureUses::UNINITIALIZED || usage == wgt::TextureUses::PRESENT {
348 (
349 vk::PipelineStageFlags::TOP_OF_PIPE,
350 vk::AccessFlags::empty(),
351 )
352 } else {
353 (stages, access)
354 }
355}
356
357pub fn map_vk_image_usage(usage: vk::ImageUsageFlags) -> wgt::TextureUses {
358 let mut bits = wgt::TextureUses::empty();
359 if usage.contains(vk::ImageUsageFlags::TRANSFER_SRC) {
360 bits |= wgt::TextureUses::COPY_SRC;
361 }
362 if usage.contains(vk::ImageUsageFlags::TRANSFER_DST) {
363 bits |= wgt::TextureUses::COPY_DST;
364 }
365 if usage.contains(vk::ImageUsageFlags::SAMPLED) {
366 bits |= wgt::TextureUses::RESOURCE;
367 }
368 if usage.contains(vk::ImageUsageFlags::COLOR_ATTACHMENT) {
369 bits |= wgt::TextureUses::COLOR_TARGET;
370 }
371 if usage.contains(vk::ImageUsageFlags::DEPTH_STENCIL_ATTACHMENT) {
372 bits |= wgt::TextureUses::DEPTH_STENCIL_READ | wgt::TextureUses::DEPTH_STENCIL_WRITE;
373 }
374 if usage.contains(vk::ImageUsageFlags::STORAGE) {
375 bits |= wgt::TextureUses::STORAGE_READ_ONLY
376 | wgt::TextureUses::STORAGE_WRITE_ONLY
377 | wgt::TextureUses::STORAGE_READ_WRITE
378 | wgt::TextureUses::STORAGE_ATOMIC;
379 }
380 if usage.contains(vk::ImageUsageFlags::TRANSIENT_ATTACHMENT) {
381 bits |= wgt::TextureUses::TRANSIENT;
382 }
383 bits
384}
385
386pub fn map_texture_dimension(dim: wgt::TextureDimension) -> vk::ImageType {
387 match dim {
388 wgt::TextureDimension::D1 => vk::ImageType::TYPE_1D,
389 wgt::TextureDimension::D2 => vk::ImageType::TYPE_2D,
390 wgt::TextureDimension::D3 => vk::ImageType::TYPE_3D,
391 }
392}
393
394pub fn map_index_format(index_format: wgt::IndexFormat) -> vk::IndexType {
395 match index_format {
396 wgt::IndexFormat::Uint16 => vk::IndexType::UINT16,
397 wgt::IndexFormat::Uint32 => vk::IndexType::UINT32,
398 }
399}
400
401pub fn map_vertex_format(vertex_format: wgt::VertexFormat) -> vk::Format {
402 use wgt::VertexFormat as Vf;
403 match vertex_format {
404 Vf::Uint8 => vk::Format::R8_UINT,
405 Vf::Uint8x2 => vk::Format::R8G8_UINT,
406 Vf::Uint8x4 => vk::Format::R8G8B8A8_UINT,
407 Vf::Sint8 => vk::Format::R8_SINT,
408 Vf::Sint8x2 => vk::Format::R8G8_SINT,
409 Vf::Sint8x4 => vk::Format::R8G8B8A8_SINT,
410 Vf::Unorm8 => vk::Format::R8_UNORM,
411 Vf::Unorm8x2 => vk::Format::R8G8_UNORM,
412 Vf::Unorm8x4 => vk::Format::R8G8B8A8_UNORM,
413 Vf::Snorm8 => vk::Format::R8_SNORM,
414 Vf::Snorm8x2 => vk::Format::R8G8_SNORM,
415 Vf::Snorm8x4 => vk::Format::R8G8B8A8_SNORM,
416 Vf::Uint16 => vk::Format::R16_UINT,
417 Vf::Uint16x2 => vk::Format::R16G16_UINT,
418 Vf::Uint16x4 => vk::Format::R16G16B16A16_UINT,
419 Vf::Sint16 => vk::Format::R16_SINT,
420 Vf::Sint16x2 => vk::Format::R16G16_SINT,
421 Vf::Sint16x4 => vk::Format::R16G16B16A16_SINT,
422 Vf::Unorm16 => vk::Format::R16_UNORM,
423 Vf::Unorm16x2 => vk::Format::R16G16_UNORM,
424 Vf::Unorm16x4 => vk::Format::R16G16B16A16_UNORM,
425 Vf::Snorm16 => vk::Format::R16_SNORM,
426 Vf::Snorm16x2 => vk::Format::R16G16_SNORM,
427 Vf::Snorm16x4 => vk::Format::R16G16B16A16_SNORM,
428 Vf::Float16 => vk::Format::R16_SFLOAT,
429 Vf::Float16x2 => vk::Format::R16G16_SFLOAT,
430 Vf::Float16x4 => vk::Format::R16G16B16A16_SFLOAT,
431 Vf::Float32 => vk::Format::R32_SFLOAT,
432 Vf::Float32x2 => vk::Format::R32G32_SFLOAT,
433 Vf::Float32x3 => vk::Format::R32G32B32_SFLOAT,
434 Vf::Float32x4 => vk::Format::R32G32B32A32_SFLOAT,
435 Vf::Uint32 => vk::Format::R32_UINT,
436 Vf::Uint32x2 => vk::Format::R32G32_UINT,
437 Vf::Uint32x3 => vk::Format::R32G32B32_UINT,
438 Vf::Uint32x4 => vk::Format::R32G32B32A32_UINT,
439 Vf::Sint32 => vk::Format::R32_SINT,
440 Vf::Sint32x2 => vk::Format::R32G32_SINT,
441 Vf::Sint32x3 => vk::Format::R32G32B32_SINT,
442 Vf::Sint32x4 => vk::Format::R32G32B32A32_SINT,
443 Vf::Float64 => vk::Format::R64_SFLOAT,
444 Vf::Float64x2 => vk::Format::R64G64_SFLOAT,
445 Vf::Float64x3 => vk::Format::R64G64B64_SFLOAT,
446 Vf::Float64x4 => vk::Format::R64G64B64A64_SFLOAT,
447 Vf::Unorm10_10_10_2 => vk::Format::A2B10G10R10_UNORM_PACK32,
448 Vf::Unorm8x4Bgra => vk::Format::B8G8R8A8_UNORM,
449 }
450}
451
452pub fn map_aspects(aspects: crate::FormatAspects) -> vk::ImageAspectFlags {
453 let mut flags = vk::ImageAspectFlags::empty();
454 if aspects.contains(crate::FormatAspects::COLOR) {
455 flags |= vk::ImageAspectFlags::COLOR;
456 }
457 if aspects.contains(crate::FormatAspects::DEPTH) {
458 flags |= vk::ImageAspectFlags::DEPTH;
459 }
460 if aspects.contains(crate::FormatAspects::STENCIL) {
461 flags |= vk::ImageAspectFlags::STENCIL;
462 }
463 if aspects.contains(crate::FormatAspects::PLANE_0) {
464 flags |= vk::ImageAspectFlags::PLANE_0;
465 }
466 if aspects.contains(crate::FormatAspects::PLANE_1) {
467 flags |= vk::ImageAspectFlags::PLANE_1;
468 }
469 if aspects.contains(crate::FormatAspects::PLANE_2) {
470 flags |= vk::ImageAspectFlags::PLANE_2;
471 }
472 flags
473}
474
475pub fn map_attachment_ops(
476 op: crate::AttachmentOps,
477) -> (vk::AttachmentLoadOp, vk::AttachmentStoreOp) {
478 let load_op = if op.contains(crate::AttachmentOps::LOAD) {
479 vk::AttachmentLoadOp::LOAD
480 } else if op.contains(crate::AttachmentOps::LOAD_DONT_CARE) {
481 vk::AttachmentLoadOp::DONT_CARE
482 } else if op.contains(crate::AttachmentOps::LOAD_CLEAR) {
483 vk::AttachmentLoadOp::CLEAR
484 } else {
485 unreachable!()
486 };
487 let store_op = if op.contains(crate::AttachmentOps::STORE) {
488 vk::AttachmentStoreOp::STORE
489 } else if op.contains(crate::AttachmentOps::STORE_DISCARD) {
490 vk::AttachmentStoreOp::DONT_CARE
491 } else {
492 unreachable!()
493 };
494 (load_op, store_op)
495}
496
497pub fn map_present_mode(mode: wgt::PresentMode) -> vk::PresentModeKHR {
498 match mode {
499 wgt::PresentMode::Immediate => vk::PresentModeKHR::IMMEDIATE,
500 wgt::PresentMode::Mailbox => vk::PresentModeKHR::MAILBOX,
501 wgt::PresentMode::Fifo => vk::PresentModeKHR::FIFO,
502 wgt::PresentMode::FifoRelaxed => vk::PresentModeKHR::FIFO_RELAXED,
503 wgt::PresentMode::AutoNoVsync | wgt::PresentMode::AutoVsync => {
504 unreachable!("Cannot create swapchain with Auto PresentationMode")
505 }
506 }
507}
508
509pub fn map_vk_present_mode(mode: vk::PresentModeKHR) -> Option<wgt::PresentMode> {
510 const FIFO_LATEST_READY: vk::PresentModeKHR = vk::PresentModeKHR::from_raw(1_000_361_000);
512
513 match mode {
515 vk::PresentModeKHR::IMMEDIATE => Some(wgt::PresentMode::Immediate),
516 vk::PresentModeKHR::MAILBOX => Some(wgt::PresentMode::Mailbox),
517 vk::PresentModeKHR::FIFO => Some(wgt::PresentMode::Fifo),
518 vk::PresentModeKHR::FIFO_RELAXED => Some(wgt::PresentMode::FifoRelaxed),
519
520 vk::PresentModeKHR::SHARED_DEMAND_REFRESH => None,
522 vk::PresentModeKHR::SHARED_CONTINUOUS_REFRESH => None,
523 FIFO_LATEST_READY => None,
524
525 _ => {
526 log::debug!("Unrecognized present mode {mode:?}");
527 None
528 }
529 }
530}
531
532pub fn map_composite_alpha_mode(mode: wgt::CompositeAlphaMode) -> vk::CompositeAlphaFlagsKHR {
533 match mode {
534 wgt::CompositeAlphaMode::Opaque => vk::CompositeAlphaFlagsKHR::OPAQUE,
535 wgt::CompositeAlphaMode::PreMultiplied => vk::CompositeAlphaFlagsKHR::PRE_MULTIPLIED,
536 wgt::CompositeAlphaMode::PostMultiplied => vk::CompositeAlphaFlagsKHR::POST_MULTIPLIED,
537 wgt::CompositeAlphaMode::Inherit => vk::CompositeAlphaFlagsKHR::INHERIT,
538 wgt::CompositeAlphaMode::Auto => unreachable!(),
539 }
540}
541
542pub fn map_vk_composite_alpha(flags: vk::CompositeAlphaFlagsKHR) -> Vec<wgt::CompositeAlphaMode> {
543 let mut modes = Vec::new();
544 if flags.contains(vk::CompositeAlphaFlagsKHR::OPAQUE) {
545 modes.push(wgt::CompositeAlphaMode::Opaque);
546 }
547 if flags.contains(vk::CompositeAlphaFlagsKHR::PRE_MULTIPLIED) {
548 modes.push(wgt::CompositeAlphaMode::PreMultiplied);
549 }
550 if flags.contains(vk::CompositeAlphaFlagsKHR::POST_MULTIPLIED) {
551 modes.push(wgt::CompositeAlphaMode::PostMultiplied);
552 }
553 if flags.contains(vk::CompositeAlphaFlagsKHR::INHERIT) {
554 modes.push(wgt::CompositeAlphaMode::Inherit);
555 }
556 modes
557}
558
559pub fn map_buffer_usage(usage: wgt::BufferUses) -> vk::BufferUsageFlags {
560 let mut flags = vk::BufferUsageFlags::empty();
561 if usage.contains(wgt::BufferUses::COPY_SRC) {
562 flags |= vk::BufferUsageFlags::TRANSFER_SRC;
563 }
564 if usage.contains(wgt::BufferUses::COPY_DST) {
565 flags |= vk::BufferUsageFlags::TRANSFER_DST;
566 }
567 if usage.contains(wgt::BufferUses::UNIFORM) {
568 flags |= vk::BufferUsageFlags::UNIFORM_BUFFER;
569 }
570 if usage.intersects(wgt::BufferUses::STORAGE_READ_ONLY | wgt::BufferUses::STORAGE_READ_WRITE) {
571 flags |= vk::BufferUsageFlags::STORAGE_BUFFER;
572 }
573 if usage.contains(wgt::BufferUses::INDEX) {
574 flags |= vk::BufferUsageFlags::INDEX_BUFFER;
575 }
576 if usage.contains(wgt::BufferUses::VERTEX) {
577 flags |= vk::BufferUsageFlags::VERTEX_BUFFER;
578 }
579 if usage.contains(wgt::BufferUses::INDIRECT) {
580 flags |= vk::BufferUsageFlags::INDIRECT_BUFFER;
581 }
582 if usage.contains(wgt::BufferUses::ACCELERATION_STRUCTURE_SCRATCH) {
583 flags |= vk::BufferUsageFlags::STORAGE_BUFFER | vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS;
584 }
585 if usage.intersects(
586 wgt::BufferUses::BOTTOM_LEVEL_ACCELERATION_STRUCTURE_INPUT
587 | wgt::BufferUses::TOP_LEVEL_ACCELERATION_STRUCTURE_INPUT,
588 ) {
589 flags |= vk::BufferUsageFlags::ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_KHR
590 | vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS;
591 }
592 if usage.intersects(wgt::BufferUses::ACCELERATION_STRUCTURE_QUERY) {
593 flags |= vk::BufferUsageFlags::TRANSFER_DST;
594 }
595 if usage.intersects(wgt::BufferUses::RAY_TRACING_PIPELINE_SHADER_DATA) {
596 flags |= vk::BufferUsageFlags::SHADER_BINDING_TABLE_KHR
597 | vk::BufferUsageFlags::SHADER_DEVICE_ADDRESS;
598 }
599 flags
600}
601
602pub fn map_buffer_usage_to_barrier(
603 usage: wgt::BufferUses,
604 queue_flags: vk::QueueFlags,
605) -> (vk::PipelineStageFlags, vk::AccessFlags) {
606 let mut stages = vk::PipelineStageFlags::empty();
607 let mut access = vk::AccessFlags::empty();
608 let shader_stages = shader_stages(queue_flags);
609
610 if usage.contains(wgt::BufferUses::MAP_READ) {
611 stages |= vk::PipelineStageFlags::HOST;
612 access |= vk::AccessFlags::HOST_READ;
613 }
614 if usage.contains(wgt::BufferUses::MAP_WRITE) {
615 stages |= vk::PipelineStageFlags::HOST;
616 access |= vk::AccessFlags::HOST_WRITE;
617 }
618 if usage.contains(wgt::BufferUses::COPY_SRC) {
619 stages |= vk::PipelineStageFlags::TRANSFER;
620 access |= vk::AccessFlags::TRANSFER_READ;
621 }
622 if usage.contains(wgt::BufferUses::COPY_DST) {
623 stages |= vk::PipelineStageFlags::TRANSFER;
624 access |= vk::AccessFlags::TRANSFER_WRITE;
625 }
626 if usage.contains(wgt::BufferUses::UNIFORM) {
627 stages |= shader_stages;
628 access |= vk::AccessFlags::UNIFORM_READ;
629 }
630 if usage.intersects(wgt::BufferUses::STORAGE_READ_ONLY) {
631 stages |= shader_stages;
632 access |= vk::AccessFlags::SHADER_READ;
633 }
634 if usage.intersects(wgt::BufferUses::STORAGE_READ_WRITE) {
635 stages |= shader_stages;
636 access |= vk::AccessFlags::SHADER_READ | vk::AccessFlags::SHADER_WRITE;
637 }
638 if usage.contains(wgt::BufferUses::INDEX) {
639 stages |= vk::PipelineStageFlags::VERTEX_INPUT;
640 access |= vk::AccessFlags::INDEX_READ;
641 }
642 if usage.contains(wgt::BufferUses::VERTEX) {
643 stages |= vk::PipelineStageFlags::VERTEX_INPUT;
644 access |= vk::AccessFlags::VERTEX_ATTRIBUTE_READ;
645 }
646 if usage.contains(wgt::BufferUses::INDIRECT) {
647 stages |= vk::PipelineStageFlags::DRAW_INDIRECT;
648 access |= vk::AccessFlags::INDIRECT_COMMAND_READ;
649 }
650 if usage.intersects(
651 wgt::BufferUses::BOTTOM_LEVEL_ACCELERATION_STRUCTURE_INPUT
652 | wgt::BufferUses::TOP_LEVEL_ACCELERATION_STRUCTURE_INPUT
653 | wgt::BufferUses::ACCELERATION_STRUCTURE_SCRATCH,
654 ) {
655 stages |= vk::PipelineStageFlags::ACCELERATION_STRUCTURE_BUILD_KHR;
656 access |= vk::AccessFlags::ACCELERATION_STRUCTURE_READ_KHR
657 | vk::AccessFlags::ACCELERATION_STRUCTURE_WRITE_KHR
658 | vk::AccessFlags::SHADER_READ;
659 }
660 if usage.contains(wgt::BufferUses::ACCELERATION_STRUCTURE_QUERY) {
661 stages |= vk::PipelineStageFlags::TRANSFER;
662 access |= vk::AccessFlags::TRANSFER_WRITE;
663 }
664
665 (stages, access)
666}
667
668fn shader_stages(queue_flags: vk::QueueFlags) -> vk::PipelineStageFlags {
669 let mut stages = vk::PipelineStageFlags::empty();
670
671 if queue_flags.contains(vk::QueueFlags::GRAPHICS) {
672 stages |= vk::PipelineStageFlags::VERTEX_SHADER | vk::PipelineStageFlags::FRAGMENT_SHADER;
673 }
674 if queue_flags.contains(vk::QueueFlags::COMPUTE) {
675 stages |= vk::PipelineStageFlags::COMPUTE_SHADER;
676 }
677
678 stages
679}
680
681pub fn map_view_dimension(dim: wgt::TextureViewDimension) -> vk::ImageViewType {
682 match dim {
683 wgt::TextureViewDimension::D1 => vk::ImageViewType::TYPE_1D,
684 wgt::TextureViewDimension::D2 => vk::ImageViewType::TYPE_2D,
685 wgt::TextureViewDimension::D2Array => vk::ImageViewType::TYPE_2D_ARRAY,
686 wgt::TextureViewDimension::Cube => vk::ImageViewType::CUBE,
687 wgt::TextureViewDimension::CubeArray => vk::ImageViewType::CUBE_ARRAY,
688 wgt::TextureViewDimension::D3 => vk::ImageViewType::TYPE_3D,
689 }
690}
691
692pub fn map_copy_extent(extent: &crate::CopyExtent) -> vk::Extent3D {
693 vk::Extent3D {
694 width: extent.width,
695 height: extent.height,
696 depth: extent.depth,
697 }
698}
699
700pub fn map_subresource_range(
701 range: &wgt::ImageSubresourceRange,
702 format: wgt::TextureFormat,
703) -> vk::ImageSubresourceRange {
704 vk::ImageSubresourceRange {
705 aspect_mask: map_aspects(crate::FormatAspects::new(format, range.aspect)),
706 base_mip_level: range.base_mip_level,
707 level_count: range.mip_level_count.unwrap_or(vk::REMAINING_MIP_LEVELS),
708 base_array_layer: range.base_array_layer,
709 layer_count: range
710 .array_layer_count
711 .unwrap_or(vk::REMAINING_ARRAY_LAYERS),
712 }
713}
714
715pub(super) fn map_subresource_range_combined_aspect(
718 range: &wgt::ImageSubresourceRange,
719 format: wgt::TextureFormat,
720 private_caps: &super::PrivateCapabilities,
721) -> vk::ImageSubresourceRange {
722 let mut range = map_subresource_range(range, format);
723 if !private_caps.texture_s8 && format == wgt::TextureFormat::Stencil8 {
724 range.aspect_mask |= vk::ImageAspectFlags::DEPTH;
725 }
726 range
727}
728
729pub fn map_subresource_layers(
730 base: &crate::TextureCopyBase,
731) -> (vk::ImageSubresourceLayers, vk::Offset3D) {
732 let offset = vk::Offset3D {
733 x: base.origin.x as i32,
734 y: base.origin.y as i32,
735 z: base.origin.z as i32,
736 };
737 let subresource = vk::ImageSubresourceLayers {
738 aspect_mask: map_aspects(base.aspect),
739 mip_level: base.mip_level,
740 base_array_layer: base.array_layer,
741 layer_count: 1,
742 };
743 (subresource, offset)
744}
745
746pub fn map_filter_mode(mode: wgt::FilterMode) -> vk::Filter {
747 match mode {
748 wgt::FilterMode::Nearest => vk::Filter::NEAREST,
749 wgt::FilterMode::Linear => vk::Filter::LINEAR,
750 }
751}
752
753pub fn map_mip_filter_mode(mode: wgt::MipmapFilterMode) -> vk::SamplerMipmapMode {
754 match mode {
755 wgt::MipmapFilterMode::Nearest => vk::SamplerMipmapMode::NEAREST,
756 wgt::MipmapFilterMode::Linear => vk::SamplerMipmapMode::LINEAR,
757 }
758}
759
760pub fn map_address_mode(mode: wgt::AddressMode) -> vk::SamplerAddressMode {
761 match mode {
762 wgt::AddressMode::ClampToEdge => vk::SamplerAddressMode::CLAMP_TO_EDGE,
763 wgt::AddressMode::Repeat => vk::SamplerAddressMode::REPEAT,
764 wgt::AddressMode::MirrorRepeat => vk::SamplerAddressMode::MIRRORED_REPEAT,
765 wgt::AddressMode::ClampToBorder => vk::SamplerAddressMode::CLAMP_TO_BORDER,
766 }
768}
769
770pub fn map_border_color(border_color: wgt::SamplerBorderColor) -> vk::BorderColor {
771 match border_color {
772 wgt::SamplerBorderColor::TransparentBlack | wgt::SamplerBorderColor::Zero => {
773 vk::BorderColor::FLOAT_TRANSPARENT_BLACK
774 }
775 wgt::SamplerBorderColor::OpaqueBlack => vk::BorderColor::FLOAT_OPAQUE_BLACK,
776 wgt::SamplerBorderColor::OpaqueWhite => vk::BorderColor::FLOAT_OPAQUE_WHITE,
777 }
778}
779
780pub fn map_comparison(fun: wgt::CompareFunction) -> vk::CompareOp {
781 use wgt::CompareFunction as Cf;
782 match fun {
783 Cf::Never => vk::CompareOp::NEVER,
784 Cf::Less => vk::CompareOp::LESS,
785 Cf::LessEqual => vk::CompareOp::LESS_OR_EQUAL,
786 Cf::Equal => vk::CompareOp::EQUAL,
787 Cf::GreaterEqual => vk::CompareOp::GREATER_OR_EQUAL,
788 Cf::Greater => vk::CompareOp::GREATER,
789 Cf::NotEqual => vk::CompareOp::NOT_EQUAL,
790 Cf::Always => vk::CompareOp::ALWAYS,
791 }
792}
793
794pub fn map_shader_stage(stage: wgt::ShaderStages) -> vk::ShaderStageFlags {
795 let mut flags = vk::ShaderStageFlags::empty();
796 if stage.contains(wgt::ShaderStages::VERTEX) {
797 flags |= vk::ShaderStageFlags::VERTEX;
798 }
799 if stage.contains(wgt::ShaderStages::FRAGMENT) {
800 flags |= vk::ShaderStageFlags::FRAGMENT;
801 }
802 if stage.contains(wgt::ShaderStages::COMPUTE) {
803 flags |= vk::ShaderStageFlags::COMPUTE;
804 }
805 if stage.contains(wgt::ShaderStages::TASK) {
806 flags |= vk::ShaderStageFlags::TASK_EXT;
807 }
808 if stage.contains(wgt::ShaderStages::MESH) {
809 flags |= vk::ShaderStageFlags::MESH_EXT;
810 }
811 if stage.contains(wgt::ShaderStages::RAY_GENERATION) {
812 flags |= vk::ShaderStageFlags::RAYGEN_KHR;
813 }
814 if stage.contains(wgt::ShaderStages::MISS) {
815 flags |= vk::ShaderStageFlags::MISS_KHR;
816 }
817 if stage.contains(wgt::ShaderStages::ANY_HIT) {
818 flags |= vk::ShaderStageFlags::ANY_HIT_KHR;
819 }
820 if stage.contains(wgt::ShaderStages::CLOSEST_HIT) {
821 flags |= vk::ShaderStageFlags::CLOSEST_HIT_KHR;
822 }
823 flags
824}
825
826pub fn map_binding_type(ty: wgt::BindingType) -> vk::DescriptorType {
827 match ty {
828 wgt::BindingType::Buffer {
829 ty,
830 has_dynamic_offset,
831 ..
832 } => match ty {
833 wgt::BufferBindingType::Storage { .. } => match has_dynamic_offset {
834 true => vk::DescriptorType::STORAGE_BUFFER_DYNAMIC,
835 false => vk::DescriptorType::STORAGE_BUFFER,
836 },
837 wgt::BufferBindingType::Uniform => match has_dynamic_offset {
838 true => vk::DescriptorType::UNIFORM_BUFFER_DYNAMIC,
839 false => vk::DescriptorType::UNIFORM_BUFFER,
840 },
841 },
842 wgt::BindingType::Sampler { .. } => vk::DescriptorType::SAMPLER,
843 wgt::BindingType::Texture { .. } => vk::DescriptorType::SAMPLED_IMAGE,
844 wgt::BindingType::StorageTexture { .. } => vk::DescriptorType::STORAGE_IMAGE,
845 wgt::BindingType::AccelerationStructure { .. } => {
846 vk::DescriptorType::ACCELERATION_STRUCTURE_KHR
847 }
848 wgt::BindingType::ExternalTexture => unimplemented!(),
849 }
850}
851
852pub fn map_topology(topology: wgt::PrimitiveTopology) -> vk::PrimitiveTopology {
853 use wgt::PrimitiveTopology as Pt;
854 match topology {
855 Pt::PointList => vk::PrimitiveTopology::POINT_LIST,
856 Pt::LineList => vk::PrimitiveTopology::LINE_LIST,
857 Pt::LineStrip => vk::PrimitiveTopology::LINE_STRIP,
858 Pt::TriangleList => vk::PrimitiveTopology::TRIANGLE_LIST,
859 Pt::TriangleStrip => vk::PrimitiveTopology::TRIANGLE_STRIP,
860 }
861}
862
863pub fn map_polygon_mode(mode: wgt::PolygonMode) -> vk::PolygonMode {
864 match mode {
865 wgt::PolygonMode::Fill => vk::PolygonMode::FILL,
866 wgt::PolygonMode::Line => vk::PolygonMode::LINE,
867 wgt::PolygonMode::Point => vk::PolygonMode::POINT,
868 }
869}
870
871pub fn map_front_face(front_face: wgt::FrontFace) -> vk::FrontFace {
872 match front_face {
873 wgt::FrontFace::Cw => vk::FrontFace::CLOCKWISE,
874 wgt::FrontFace::Ccw => vk::FrontFace::COUNTER_CLOCKWISE,
875 }
876}
877
878pub fn map_cull_face(face: wgt::Face) -> vk::CullModeFlags {
879 match face {
880 wgt::Face::Front => vk::CullModeFlags::FRONT,
881 wgt::Face::Back => vk::CullModeFlags::BACK,
882 }
883}
884
885pub fn map_stencil_op(op: wgt::StencilOperation) -> vk::StencilOp {
886 use wgt::StencilOperation as So;
887 match op {
888 So::Keep => vk::StencilOp::KEEP,
889 So::Zero => vk::StencilOp::ZERO,
890 So::Replace => vk::StencilOp::REPLACE,
891 So::Invert => vk::StencilOp::INVERT,
892 So::IncrementClamp => vk::StencilOp::INCREMENT_AND_CLAMP,
893 So::IncrementWrap => vk::StencilOp::INCREMENT_AND_WRAP,
894 So::DecrementClamp => vk::StencilOp::DECREMENT_AND_CLAMP,
895 So::DecrementWrap => vk::StencilOp::DECREMENT_AND_WRAP,
896 }
897}
898
899pub fn map_stencil_face(
900 face: &wgt::StencilFaceState,
901 compare_mask: u32,
902 write_mask: u32,
903) -> vk::StencilOpState {
904 vk::StencilOpState {
905 fail_op: map_stencil_op(face.fail_op),
906 pass_op: map_stencil_op(face.pass_op),
907 depth_fail_op: map_stencil_op(face.depth_fail_op),
908 compare_op: map_comparison(face.compare),
909 compare_mask,
910 write_mask,
911 reference: 0,
912 }
913}
914
915fn map_blend_factor(factor: wgt::BlendFactor) -> vk::BlendFactor {
916 use wgt::BlendFactor as Bf;
917 match factor {
918 Bf::Zero => vk::BlendFactor::ZERO,
919 Bf::One => vk::BlendFactor::ONE,
920 Bf::Src => vk::BlendFactor::SRC_COLOR,
921 Bf::OneMinusSrc => vk::BlendFactor::ONE_MINUS_SRC_COLOR,
922 Bf::SrcAlpha => vk::BlendFactor::SRC_ALPHA,
923 Bf::OneMinusSrcAlpha => vk::BlendFactor::ONE_MINUS_SRC_ALPHA,
924 Bf::Dst => vk::BlendFactor::DST_COLOR,
925 Bf::OneMinusDst => vk::BlendFactor::ONE_MINUS_DST_COLOR,
926 Bf::DstAlpha => vk::BlendFactor::DST_ALPHA,
927 Bf::OneMinusDstAlpha => vk::BlendFactor::ONE_MINUS_DST_ALPHA,
928 Bf::SrcAlphaSaturated => vk::BlendFactor::SRC_ALPHA_SATURATE,
929 Bf::Constant => vk::BlendFactor::CONSTANT_COLOR,
930 Bf::OneMinusConstant => vk::BlendFactor::ONE_MINUS_CONSTANT_COLOR,
931 Bf::Src1 => vk::BlendFactor::SRC1_COLOR,
932 Bf::OneMinusSrc1 => vk::BlendFactor::ONE_MINUS_SRC1_COLOR,
933 Bf::Src1Alpha => vk::BlendFactor::SRC1_ALPHA,
934 Bf::OneMinusSrc1Alpha => vk::BlendFactor::ONE_MINUS_SRC1_ALPHA,
935 }
936}
937
938fn map_blend_op(operation: wgt::BlendOperation) -> vk::BlendOp {
939 use wgt::BlendOperation as Bo;
940 match operation {
941 Bo::Add => vk::BlendOp::ADD,
942 Bo::Subtract => vk::BlendOp::SUBTRACT,
943 Bo::ReverseSubtract => vk::BlendOp::REVERSE_SUBTRACT,
944 Bo::Min => vk::BlendOp::MIN,
945 Bo::Max => vk::BlendOp::MAX,
946 }
947}
948
949pub fn map_blend_component(
950 component: &wgt::BlendComponent,
951) -> (vk::BlendOp, vk::BlendFactor, vk::BlendFactor) {
952 let op = map_blend_op(component.operation);
953 let src = map_blend_factor(component.src_factor);
954 let dst = map_blend_factor(component.dst_factor);
955 (op, src, dst)
956}
957
958pub fn map_pipeline_statistics(
959 types: wgt::PipelineStatisticsTypes,
960) -> vk::QueryPipelineStatisticFlags {
961 use wgt::PipelineStatisticsTypes as Pst;
962 let mut flags = vk::QueryPipelineStatisticFlags::empty();
963 if types.contains(Pst::VERTEX_SHADER_INVOCATIONS) {
964 flags |= vk::QueryPipelineStatisticFlags::VERTEX_SHADER_INVOCATIONS;
965 }
966 if types.contains(Pst::CLIPPER_INVOCATIONS) {
967 flags |= vk::QueryPipelineStatisticFlags::CLIPPING_INVOCATIONS;
968 }
969 if types.contains(Pst::CLIPPER_PRIMITIVES_OUT) {
970 flags |= vk::QueryPipelineStatisticFlags::CLIPPING_PRIMITIVES;
971 }
972 if types.contains(Pst::FRAGMENT_SHADER_INVOCATIONS) {
973 flags |= vk::QueryPipelineStatisticFlags::FRAGMENT_SHADER_INVOCATIONS;
974 }
975 if types.contains(Pst::COMPUTE_SHADER_INVOCATIONS) {
976 flags |= vk::QueryPipelineStatisticFlags::COMPUTE_SHADER_INVOCATIONS;
977 }
978 flags
979}
980
981pub fn map_acceleration_structure_format(
982 format: crate::AccelerationStructureFormat,
983) -> vk::AccelerationStructureTypeKHR {
984 match format {
985 crate::AccelerationStructureFormat::TopLevel => vk::AccelerationStructureTypeKHR::TOP_LEVEL,
986 crate::AccelerationStructureFormat::BottomLevel => {
987 vk::AccelerationStructureTypeKHR::BOTTOM_LEVEL
988 }
989 }
990}
991
992pub fn map_acceleration_structure_build_mode(
993 format: crate::AccelerationStructureBuildMode,
994) -> vk::BuildAccelerationStructureModeKHR {
995 match format {
996 crate::AccelerationStructureBuildMode::Build => {
997 vk::BuildAccelerationStructureModeKHR::BUILD
998 }
999 crate::AccelerationStructureBuildMode::Update => {
1000 vk::BuildAccelerationStructureModeKHR::UPDATE
1001 }
1002 }
1003}
1004
1005pub fn map_acceleration_structure_flags(
1006 flags: crate::AccelerationStructureBuildFlags,
1007) -> vk::BuildAccelerationStructureFlagsKHR {
1008 let mut vk_flags = vk::BuildAccelerationStructureFlagsKHR::empty();
1009
1010 if flags.contains(crate::AccelerationStructureBuildFlags::PREFER_FAST_TRACE) {
1011 vk_flags |= vk::BuildAccelerationStructureFlagsKHR::PREFER_FAST_TRACE;
1012 }
1013
1014 if flags.contains(crate::AccelerationStructureBuildFlags::PREFER_FAST_BUILD) {
1015 vk_flags |= vk::BuildAccelerationStructureFlagsKHR::PREFER_FAST_BUILD;
1016 }
1017
1018 if flags.contains(crate::AccelerationStructureBuildFlags::ALLOW_UPDATE) {
1019 vk_flags |= vk::BuildAccelerationStructureFlagsKHR::ALLOW_UPDATE;
1020 }
1021
1022 if flags.contains(crate::AccelerationStructureBuildFlags::LOW_MEMORY) {
1023 vk_flags |= vk::BuildAccelerationStructureFlagsKHR::LOW_MEMORY;
1024 }
1025
1026 if flags.contains(crate::AccelerationStructureBuildFlags::ALLOW_COMPACTION) {
1027 vk_flags |= vk::BuildAccelerationStructureFlagsKHR::ALLOW_COMPACTION
1028 }
1029
1030 if flags.contains(crate::AccelerationStructureBuildFlags::ALLOW_RAY_HIT_VERTEX_RETURN) {
1031 vk_flags |= vk::BuildAccelerationStructureFlagsKHR::ALLOW_DATA_ACCESS
1032 }
1033
1034 vk_flags
1035}
1036
1037pub fn map_acceleration_structure_geometry_flags(
1038 flags: crate::AccelerationStructureGeometryFlags,
1039) -> vk::GeometryFlagsKHR {
1040 let mut vk_flags = vk::GeometryFlagsKHR::empty();
1041
1042 if flags.contains(crate::AccelerationStructureGeometryFlags::OPAQUE) {
1043 vk_flags |= vk::GeometryFlagsKHR::OPAQUE;
1044 }
1045
1046 if flags.contains(crate::AccelerationStructureGeometryFlags::NO_DUPLICATE_ANY_HIT_INVOCATION) {
1047 vk_flags |= vk::GeometryFlagsKHR::NO_DUPLICATE_ANY_HIT_INVOCATION;
1048 }
1049
1050 vk_flags
1051}
1052
1053pub fn map_acceleration_structure_usage_to_barrier(
1054 usage: crate::AccelerationStructureUses,
1055 features: wgt::Features,
1056 queue_flags: vk::QueueFlags,
1057) -> (vk::PipelineStageFlags, vk::AccessFlags) {
1058 let mut stages = vk::PipelineStageFlags::empty();
1059 let mut access = vk::AccessFlags::empty();
1060
1061 if usage.contains(crate::AccelerationStructureUses::BUILD_INPUT) {
1062 stages |= vk::PipelineStageFlags::ACCELERATION_STRUCTURE_BUILD_KHR;
1063 access |= vk::AccessFlags::ACCELERATION_STRUCTURE_READ_KHR;
1064 }
1065 if usage.contains(crate::AccelerationStructureUses::QUERY_INPUT) {
1066 stages |= vk::PipelineStageFlags::ACCELERATION_STRUCTURE_BUILD_KHR;
1067 access |= vk::AccessFlags::ACCELERATION_STRUCTURE_READ_KHR;
1068 }
1069 if usage.contains(crate::AccelerationStructureUses::BUILD_OUTPUT) {
1070 stages |= vk::PipelineStageFlags::ACCELERATION_STRUCTURE_BUILD_KHR;
1071 access |= vk::AccessFlags::ACCELERATION_STRUCTURE_WRITE_KHR;
1072 }
1073 if usage.contains(crate::AccelerationStructureUses::SHADER_INPUT)
1074 && features.contains(wgt::Features::EXPERIMENTAL_RAY_QUERY)
1075 {
1076 stages |= shader_stages(queue_flags);
1077 access |= vk::AccessFlags::ACCELERATION_STRUCTURE_READ_KHR;
1078 }
1079 if usage.contains(crate::AccelerationStructureUses::SHADER_INPUT)
1080 && features.contains(wgt::Features::EXPERIMENTAL_RAY_TRACING_PIPELINES)
1081 {
1082 stages |= vk::PipelineStageFlags::RAY_TRACING_SHADER_KHR;
1083 access |= vk::AccessFlags::ACCELERATION_STRUCTURE_READ_KHR;
1084 }
1085 if usage.contains(crate::AccelerationStructureUses::COPY_SRC) {
1086 stages |= vk::PipelineStageFlags::ACCELERATION_STRUCTURE_BUILD_KHR;
1087 access |= vk::AccessFlags::ACCELERATION_STRUCTURE_READ_KHR;
1088 }
1089 if usage.contains(crate::AccelerationStructureUses::COPY_DST) {
1090 stages |= vk::PipelineStageFlags::ACCELERATION_STRUCTURE_BUILD_KHR;
1091 access |= vk::AccessFlags::ACCELERATION_STRUCTURE_WRITE_KHR;
1092 }
1093
1094 (stages, access)
1095}
1096
1097#[cfg(test)]
1098mod tests {
1099 use super::*;
1100
1101 #[test]
1105 fn color_space_round_trip() {
1106 for vk_color_space in [
1107 vk::ColorSpaceKHR::SRGB_NONLINEAR,
1108 vk::ColorSpaceKHR::EXTENDED_SRGB_LINEAR_EXT,
1109 vk::ColorSpaceKHR::EXTENDED_SRGB_NONLINEAR_EXT,
1110 vk::ColorSpaceKHR::DISPLAY_P3_NONLINEAR_EXT,
1111 vk::ColorSpaceKHR::HDR10_ST2084_EXT,
1112 vk::ColorSpaceKHR::HDR10_HLG_EXT,
1113 ] {
1114 let mapped = map_vk_color_space(vk_color_space).unwrap();
1115 assert_eq!(map_surface_color_space(mapped), vk_color_space);
1116 }
1117 }
1118
1119 #[test]
1120 fn unknown_color_spaces_are_dropped() {
1121 for vk_color_space in [
1122 vk::ColorSpaceKHR::BT2020_LINEAR_EXT,
1123 vk::ColorSpaceKHR::DOLBYVISION_EXT,
1124 vk::ColorSpaceKHR::PASS_THROUGH_EXT,
1125 vk::ColorSpaceKHR::ADOBERGB_NONLINEAR_EXT,
1126 ] {
1127 assert!(map_vk_color_space(vk_color_space).is_none());
1128 assert!(map_vk_surface_formats(vk::SurfaceFormatKHR {
1129 format: vk::Format::B8G8R8A8_UNORM,
1130 color_space: vk_color_space,
1131 })
1132 .is_none());
1133 }
1134 }
1135
1136 #[test]
1137 fn hdr10_surface_format_maps() {
1138 let (format, color_space) = map_vk_surface_formats(vk::SurfaceFormatKHR {
1139 format: vk::Format::A2B10G10R10_UNORM_PACK32,
1140 color_space: vk::ColorSpaceKHR::HDR10_ST2084_EXT,
1141 })
1142 .unwrap();
1143 assert_eq!(format, wgt::TextureFormat::Rgb10a2Unorm);
1144 assert_eq!(color_space, wgt::SurfaceColorSpace::Bt2100Pq);
1145 }
1146
1147 #[test]
1148 fn buffer_shader_stages_follow_queue_flags() {
1149 let usage = wgt::BufferUses::UNIFORM;
1150
1151 let (stages, access) = map_buffer_usage_to_barrier(usage, vk::QueueFlags::GRAPHICS);
1152 assert_eq!(
1153 stages,
1154 vk::PipelineStageFlags::VERTEX_SHADER | vk::PipelineStageFlags::FRAGMENT_SHADER
1155 );
1156 assert_eq!(access, vk::AccessFlags::UNIFORM_READ);
1157
1158 let (stages, access) = map_buffer_usage_to_barrier(usage, vk::QueueFlags::COMPUTE);
1159 assert_eq!(stages, vk::PipelineStageFlags::COMPUTE_SHADER);
1160 assert_eq!(access, vk::AccessFlags::UNIFORM_READ);
1161
1162 let (stages, access) =
1163 map_buffer_usage_to_barrier(usage, vk::QueueFlags::GRAPHICS | vk::QueueFlags::COMPUTE);
1164 assert_eq!(
1165 stages,
1166 vk::PipelineStageFlags::VERTEX_SHADER
1167 | vk::PipelineStageFlags::FRAGMENT_SHADER
1168 | vk::PipelineStageFlags::COMPUTE_SHADER
1169 );
1170 assert_eq!(access, vk::AccessFlags::UNIFORM_READ);
1171 }
1172
1173 #[test]
1174 fn non_shader_buffer_usage_is_unchanged() {
1175 let (stages, access) = map_buffer_usage_to_barrier(
1176 wgt::BufferUses::COPY_SRC | wgt::BufferUses::VERTEX,
1177 vk::QueueFlags::empty(),
1178 );
1179
1180 assert_eq!(
1181 stages,
1182 vk::PipelineStageFlags::TRANSFER | vk::PipelineStageFlags::VERTEX_INPUT
1183 );
1184 assert_eq!(
1185 access,
1186 vk::AccessFlags::TRANSFER_READ | vk::AccessFlags::VERTEX_ATTRIBUTE_READ
1187 );
1188 }
1189
1190 #[test]
1191 fn texture_shader_stages_follow_queue_flags() {
1192 let usage = wgt::TextureUses::RESOURCE;
1193
1194 let (stages, access) = map_texture_usage_to_barrier(usage, vk::QueueFlags::GRAPHICS);
1195 assert_eq!(
1196 stages,
1197 vk::PipelineStageFlags::VERTEX_SHADER | vk::PipelineStageFlags::FRAGMENT_SHADER
1198 );
1199 assert_eq!(access, vk::AccessFlags::SHADER_READ);
1200
1201 let (stages, access) = map_texture_usage_to_barrier(usage, vk::QueueFlags::COMPUTE);
1202 assert_eq!(stages, vk::PipelineStageFlags::COMPUTE_SHADER);
1203 assert_eq!(access, vk::AccessFlags::SHADER_READ);
1204
1205 let (stages, access) =
1206 map_texture_usage_to_barrier(usage, vk::QueueFlags::GRAPHICS | vk::QueueFlags::COMPUTE);
1207 assert_eq!(
1208 stages,
1209 vk::PipelineStageFlags::VERTEX_SHADER
1210 | vk::PipelineStageFlags::FRAGMENT_SHADER
1211 | vk::PipelineStageFlags::COMPUTE_SHADER
1212 );
1213 assert_eq!(access, vk::AccessFlags::SHADER_READ);
1214 }
1215
1216 #[test]
1217 fn non_shader_texture_usage_is_unchanged() {
1218 let (stages, access) = map_texture_usage_to_barrier(
1219 wgt::TextureUses::COPY_SRC | wgt::TextureUses::COLOR_TARGET,
1220 vk::QueueFlags::empty(),
1221 );
1222
1223 assert_eq!(
1224 stages,
1225 vk::PipelineStageFlags::TRANSFER | vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT
1226 );
1227 assert_eq!(
1228 access,
1229 vk::AccessFlags::TRANSFER_READ
1230 | vk::AccessFlags::COLOR_ATTACHMENT_READ
1231 | vk::AccessFlags::COLOR_ATTACHMENT_WRITE
1232 );
1233 }
1234
1235 #[test]
1236 fn acceleration_structure_shader_stages_follow_queue_flags() {
1237 let usage = crate::AccelerationStructureUses::SHADER_INPUT;
1238 let features = wgt::Features::EXPERIMENTAL_RAY_QUERY;
1239
1240 let (stages, access) =
1241 map_acceleration_structure_usage_to_barrier(usage, features, vk::QueueFlags::GRAPHICS);
1242 assert_eq!(
1243 stages,
1244 vk::PipelineStageFlags::VERTEX_SHADER | vk::PipelineStageFlags::FRAGMENT_SHADER
1245 );
1246 assert_eq!(access, vk::AccessFlags::ACCELERATION_STRUCTURE_READ_KHR);
1247
1248 let (stages, access) =
1249 map_acceleration_structure_usage_to_barrier(usage, features, vk::QueueFlags::COMPUTE);
1250 assert_eq!(stages, vk::PipelineStageFlags::COMPUTE_SHADER);
1251 assert_eq!(access, vk::AccessFlags::ACCELERATION_STRUCTURE_READ_KHR);
1252
1253 let (stages, access) = map_acceleration_structure_usage_to_barrier(
1254 usage,
1255 features,
1256 vk::QueueFlags::GRAPHICS | vk::QueueFlags::COMPUTE,
1257 );
1258 assert_eq!(
1259 stages,
1260 vk::PipelineStageFlags::VERTEX_SHADER
1261 | vk::PipelineStageFlags::FRAGMENT_SHADER
1262 | vk::PipelineStageFlags::COMPUTE_SHADER
1263 );
1264 assert_eq!(access, vk::AccessFlags::ACCELERATION_STRUCTURE_READ_KHR);
1265 }
1266
1267 #[test]
1268 fn non_shader_acceleration_structure_usage_is_unchanged() {
1269 let (stages, access) = map_acceleration_structure_usage_to_barrier(
1270 crate::AccelerationStructureUses::BUILD_INPUT
1271 | crate::AccelerationStructureUses::BUILD_OUTPUT,
1272 wgt::Features::empty(),
1273 vk::QueueFlags::empty(),
1274 );
1275
1276 assert_eq!(
1277 stages,
1278 vk::PipelineStageFlags::ACCELERATION_STRUCTURE_BUILD_KHR
1279 );
1280 assert_eq!(
1281 access,
1282 vk::AccessFlags::ACCELERATION_STRUCTURE_READ_KHR
1283 | vk::AccessFlags::ACCELERATION_STRUCTURE_WRITE_KHR
1284 );
1285 }
1286}