1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 use crate::{
6 command::{LoadOp, PassChannel, StoreOp},
7 pipeline::ColorStateError,
8 resource, PrivateFeatures,
9 };
10
11 use std::convert::TryInto;
12
map_adapter_info( info: hal::adapter::AdapterInfo, backend: wgt::Backend, ) -> wgt::AdapterInfo13 pub fn map_adapter_info(
14 info: hal::adapter::AdapterInfo,
15 backend: wgt::Backend,
16 ) -> wgt::AdapterInfo {
17 use hal::adapter::DeviceType as Dt;
18
19 wgt::AdapterInfo {
20 name: info.name,
21 vendor: info.vendor,
22 device: info.device,
23 device_type: match info.device_type {
24 Dt::Other => wgt::DeviceType::Other,
25 Dt::IntegratedGpu => wgt::DeviceType::IntegratedGpu,
26 Dt::DiscreteGpu => wgt::DeviceType::DiscreteGpu,
27 Dt::VirtualGpu => wgt::DeviceType::VirtualGpu,
28 Dt::Cpu => wgt::DeviceType::Cpu,
29 },
30 backend,
31 }
32 }
33
map_buffer_usage(usage: wgt::BufferUsage) -> (hal::buffer::Usage, hal::memory::Properties)34 pub fn map_buffer_usage(usage: wgt::BufferUsage) -> (hal::buffer::Usage, hal::memory::Properties) {
35 use hal::buffer::Usage as U;
36 use hal::memory::Properties as P;
37 use wgt::BufferUsage as W;
38
39 let mut hal_memory = P::empty();
40 if usage.contains(W::MAP_READ) {
41 hal_memory |= P::CPU_VISIBLE | P::CPU_CACHED;
42 }
43 if usage.contains(W::MAP_WRITE) {
44 hal_memory |= P::CPU_VISIBLE;
45 }
46
47 let mut hal_usage = U::empty();
48 if usage.contains(W::COPY_SRC) {
49 hal_usage |= U::TRANSFER_SRC;
50 }
51 if usage.contains(W::COPY_DST) {
52 hal_usage |= U::TRANSFER_DST;
53 }
54 if usage.contains(W::INDEX) {
55 hal_usage |= U::INDEX;
56 }
57 if usage.contains(W::VERTEX) {
58 hal_usage |= U::VERTEX;
59 }
60 if usage.contains(W::UNIFORM) {
61 hal_usage |= U::UNIFORM;
62 }
63 if usage.contains(W::STORAGE) {
64 hal_usage |= U::STORAGE;
65 }
66 if usage.contains(W::INDIRECT) {
67 hal_usage |= U::INDIRECT;
68 }
69
70 (hal_usage, hal_memory)
71 }
72
map_texture_usage( usage: wgt::TextureUsage, aspects: hal::format::Aspects, ) -> hal::image::Usage73 pub fn map_texture_usage(
74 usage: wgt::TextureUsage,
75 aspects: hal::format::Aspects,
76 ) -> hal::image::Usage {
77 use hal::image::Usage as U;
78 use wgt::TextureUsage as W;
79
80 let mut value = U::empty();
81 if usage.contains(W::COPY_SRC) {
82 value |= U::TRANSFER_SRC;
83 }
84 if usage.contains(W::COPY_DST) {
85 value |= U::TRANSFER_DST;
86 }
87 if usage.contains(W::SAMPLED) {
88 value |= U::SAMPLED;
89 }
90 if usage.contains(W::STORAGE) {
91 value |= U::STORAGE;
92 }
93 if usage.contains(W::RENDER_ATTACHMENT) {
94 if aspects.intersects(hal::format::Aspects::DEPTH | hal::format::Aspects::STENCIL) {
95 value |= U::DEPTH_STENCIL_ATTACHMENT;
96 } else {
97 value |= U::COLOR_ATTACHMENT;
98 }
99 }
100 // Note: TextureUsage::Present does not need to be handled explicitly
101 // TODO: HAL Transient Attachment, HAL Input Attachment
102 value
103 }
104
map_binding_type(binding: &wgt::BindGroupLayoutEntry) -> hal::pso::DescriptorType105 pub fn map_binding_type(binding: &wgt::BindGroupLayoutEntry) -> hal::pso::DescriptorType {
106 use hal::pso;
107 use wgt::BindingType as Bt;
108 match binding.ty {
109 Bt::Buffer {
110 ty,
111 has_dynamic_offset,
112 min_binding_size: _,
113 } => pso::DescriptorType::Buffer {
114 ty: match ty {
115 wgt::BufferBindingType::Uniform => pso::BufferDescriptorType::Uniform,
116 wgt::BufferBindingType::Storage { read_only } => {
117 pso::BufferDescriptorType::Storage { read_only }
118 }
119 },
120 format: pso::BufferDescriptorFormat::Structured {
121 dynamic_offset: has_dynamic_offset,
122 },
123 },
124 Bt::Sampler { .. } => pso::DescriptorType::Sampler,
125 Bt::Texture { .. } => pso::DescriptorType::Image {
126 ty: pso::ImageDescriptorType::Sampled {
127 with_sampler: false,
128 },
129 },
130 Bt::StorageTexture { access, .. } => pso::DescriptorType::Image {
131 ty: pso::ImageDescriptorType::Storage {
132 read_only: match access {
133 wgt::StorageTextureAccess::ReadOnly => true,
134 _ => false,
135 },
136 },
137 },
138 }
139 }
140
map_shader_stage_flags(shader_stage_flags: wgt::ShaderStage) -> hal::pso::ShaderStageFlags141 pub fn map_shader_stage_flags(shader_stage_flags: wgt::ShaderStage) -> hal::pso::ShaderStageFlags {
142 use hal::pso::ShaderStageFlags as H;
143 use wgt::ShaderStage as Ss;
144
145 let mut value = H::empty();
146 if shader_stage_flags.contains(Ss::VERTEX) {
147 value |= H::VERTEX;
148 }
149 if shader_stage_flags.contains(Ss::FRAGMENT) {
150 value |= H::FRAGMENT;
151 }
152 if shader_stage_flags.contains(Ss::COMPUTE) {
153 value |= H::COMPUTE;
154 }
155 value
156 }
157
map_hal_flags_to_shader_stage( shader_stage_flags: hal::pso::ShaderStageFlags, ) -> wgt::ShaderStage158 pub fn map_hal_flags_to_shader_stage(
159 shader_stage_flags: hal::pso::ShaderStageFlags,
160 ) -> wgt::ShaderStage {
161 use hal::pso::ShaderStageFlags as H;
162 use wgt::ShaderStage as Ss;
163
164 let mut value = Ss::empty();
165 if shader_stage_flags.contains(H::VERTEX) {
166 value |= Ss::VERTEX;
167 }
168 if shader_stage_flags.contains(H::FRAGMENT) {
169 value |= Ss::FRAGMENT;
170 }
171 if shader_stage_flags.contains(H::COMPUTE) {
172 value |= Ss::COMPUTE;
173 }
174 value
175 }
176
map_extent(extent: &wgt::Extent3d, dim: wgt::TextureDimension) -> hal::image::Extent177 pub fn map_extent(extent: &wgt::Extent3d, dim: wgt::TextureDimension) -> hal::image::Extent {
178 hal::image::Extent {
179 width: extent.width,
180 height: extent.height,
181 depth: match dim {
182 wgt::TextureDimension::D1 | wgt::TextureDimension::D2 => 1,
183 wgt::TextureDimension::D3 => extent.depth_or_array_layers,
184 },
185 }
186 }
187
map_primitive_topology(primitive_topology: wgt::PrimitiveTopology) -> hal::pso::Primitive188 pub fn map_primitive_topology(primitive_topology: wgt::PrimitiveTopology) -> hal::pso::Primitive {
189 use hal::pso::Primitive as H;
190 use wgt::PrimitiveTopology as Pt;
191 match primitive_topology {
192 Pt::PointList => H::PointList,
193 Pt::LineList => H::LineList,
194 Pt::LineStrip => H::LineStrip,
195 Pt::TriangleList => H::TriangleList,
196 Pt::TriangleStrip => H::TriangleStrip,
197 }
198 }
199
map_color_target_state( desc: &wgt::ColorTargetState, ) -> Result<hal::pso::ColorBlendDesc, ColorStateError>200 pub fn map_color_target_state(
201 desc: &wgt::ColorTargetState,
202 ) -> Result<hal::pso::ColorBlendDesc, ColorStateError> {
203 let color_mask = desc.write_mask;
204 let blend = desc
205 .blend
206 .as_ref()
207 .map(|bs| {
208 Ok(hal::pso::BlendState {
209 color: map_blend_component(&bs.color)?,
210 alpha: map_blend_component(&bs.alpha)?,
211 })
212 })
213 .transpose()?;
214 Ok(hal::pso::ColorBlendDesc {
215 mask: map_color_write_flags(color_mask),
216 blend,
217 })
218 }
219
map_color_write_flags(flags: wgt::ColorWrite) -> hal::pso::ColorMask220 fn map_color_write_flags(flags: wgt::ColorWrite) -> hal::pso::ColorMask {
221 use hal::pso::ColorMask as H;
222 use wgt::ColorWrite as Cw;
223
224 let mut value = H::empty();
225 if flags.contains(Cw::RED) {
226 value |= H::RED;
227 }
228 if flags.contains(Cw::GREEN) {
229 value |= H::GREEN;
230 }
231 if flags.contains(Cw::BLUE) {
232 value |= H::BLUE;
233 }
234 if flags.contains(Cw::ALPHA) {
235 value |= H::ALPHA;
236 }
237 value
238 }
239
map_blend_component( component: &wgt::BlendComponent, ) -> Result<hal::pso::BlendOp, ColorStateError>240 fn map_blend_component(
241 component: &wgt::BlendComponent,
242 ) -> Result<hal::pso::BlendOp, ColorStateError> {
243 use hal::pso::BlendOp as H;
244 use wgt::BlendOperation as Bo;
245 Ok(match *component {
246 wgt::BlendComponent {
247 operation: Bo::Add,
248 src_factor,
249 dst_factor,
250 } => H::Add {
251 src: map_blend_factor(src_factor),
252 dst: map_blend_factor(dst_factor),
253 },
254 wgt::BlendComponent {
255 operation: Bo::Subtract,
256 src_factor,
257 dst_factor,
258 } => H::Sub {
259 src: map_blend_factor(src_factor),
260 dst: map_blend_factor(dst_factor),
261 },
262 wgt::BlendComponent {
263 operation: Bo::ReverseSubtract,
264 src_factor,
265 dst_factor,
266 } => H::RevSub {
267 src: map_blend_factor(src_factor),
268 dst: map_blend_factor(dst_factor),
269 },
270 wgt::BlendComponent {
271 operation: Bo::Min,
272 src_factor: wgt::BlendFactor::One,
273 dst_factor: wgt::BlendFactor::One,
274 } => H::Min,
275 wgt::BlendComponent {
276 operation: Bo::Max,
277 src_factor: wgt::BlendFactor::One,
278 dst_factor: wgt::BlendFactor::One,
279 } => H::Max,
280 _ => return Err(ColorStateError::InvalidMinMaxBlendFactors(*component)),
281 })
282 }
283
map_blend_factor(blend_factor: wgt::BlendFactor) -> hal::pso::Factor284 fn map_blend_factor(blend_factor: wgt::BlendFactor) -> hal::pso::Factor {
285 use hal::pso::Factor as H;
286 use wgt::BlendFactor as Bf;
287 match blend_factor {
288 Bf::Zero => H::Zero,
289 Bf::One => H::One,
290 Bf::Src => H::SrcColor,
291 Bf::OneMinusSrc => H::OneMinusSrcColor,
292 Bf::SrcAlpha => H::SrcAlpha,
293 Bf::OneMinusSrcAlpha => H::OneMinusSrcAlpha,
294 Bf::Dst => H::DstColor,
295 Bf::OneMinusDst => H::OneMinusDstColor,
296 Bf::DstAlpha => H::DstAlpha,
297 Bf::OneMinusDstAlpha => H::OneMinusDstAlpha,
298 Bf::SrcAlphaSaturated => H::SrcAlphaSaturate,
299 Bf::Constant => H::ConstColor,
300 Bf::OneMinusConstant => H::OneMinusConstColor,
301 }
302 }
303
map_depth_stencil_state(desc: &wgt::DepthStencilState) -> hal::pso::DepthStencilDesc304 pub fn map_depth_stencil_state(desc: &wgt::DepthStencilState) -> hal::pso::DepthStencilDesc {
305 hal::pso::DepthStencilDesc {
306 depth: if desc.is_depth_enabled() {
307 Some(hal::pso::DepthTest {
308 fun: map_compare_function(desc.depth_compare),
309 write: desc.depth_write_enabled,
310 })
311 } else {
312 None
313 },
314 depth_bounds: false, // TODO
315 stencil: if desc.stencil.is_enabled() {
316 let s = &desc.stencil;
317 Some(hal::pso::StencilTest {
318 faces: hal::pso::Sided {
319 front: map_stencil_face(&s.front),
320 back: map_stencil_face(&s.back),
321 },
322 read_masks: hal::pso::State::Static(hal::pso::Sided::new(s.read_mask)),
323 write_masks: hal::pso::State::Static(hal::pso::Sided::new(s.write_mask)),
324 reference_values: if s.needs_ref_value() {
325 hal::pso::State::Dynamic
326 } else {
327 hal::pso::State::Static(hal::pso::Sided::new(0))
328 },
329 })
330 } else {
331 None
332 },
333 }
334 }
335
map_stencil_face(stencil_state_face_desc: &wgt::StencilFaceState) -> hal::pso::StencilFace336 fn map_stencil_face(stencil_state_face_desc: &wgt::StencilFaceState) -> hal::pso::StencilFace {
337 hal::pso::StencilFace {
338 fun: map_compare_function(stencil_state_face_desc.compare),
339 op_fail: map_stencil_operation(stencil_state_face_desc.fail_op),
340 op_depth_fail: map_stencil_operation(stencil_state_face_desc.depth_fail_op),
341 op_pass: map_stencil_operation(stencil_state_face_desc.pass_op),
342 }
343 }
344
map_compare_function(compare_function: wgt::CompareFunction) -> hal::pso::Comparison345 pub fn map_compare_function(compare_function: wgt::CompareFunction) -> hal::pso::Comparison {
346 use hal::pso::Comparison as H;
347 use wgt::CompareFunction as Cf;
348 match compare_function {
349 Cf::Never => H::Never,
350 Cf::Less => H::Less,
351 Cf::Equal => H::Equal,
352 Cf::LessEqual => H::LessEqual,
353 Cf::Greater => H::Greater,
354 Cf::NotEqual => H::NotEqual,
355 Cf::GreaterEqual => H::GreaterEqual,
356 Cf::Always => H::Always,
357 }
358 }
359
map_stencil_operation(stencil_operation: wgt::StencilOperation) -> hal::pso::StencilOp360 fn map_stencil_operation(stencil_operation: wgt::StencilOperation) -> hal::pso::StencilOp {
361 use hal::pso::StencilOp as H;
362 use wgt::StencilOperation as So;
363 match stencil_operation {
364 So::Keep => H::Keep,
365 So::Zero => H::Zero,
366 So::Replace => H::Replace,
367 So::Invert => H::Invert,
368 So::IncrementClamp => H::IncrementClamp,
369 So::DecrementClamp => H::DecrementClamp,
370 So::IncrementWrap => H::IncrementWrap,
371 So::DecrementWrap => H::DecrementWrap,
372 }
373 }
374
map_texture_format( texture_format: wgt::TextureFormat, private_features: PrivateFeatures, ) -> hal::format::Format375 pub(crate) fn map_texture_format(
376 texture_format: wgt::TextureFormat,
377 private_features: PrivateFeatures,
378 ) -> hal::format::Format {
379 use hal::format::Format as H;
380 use wgt::TextureFormat as Tf;
381 match texture_format {
382 // Normal 8 bit formats
383 Tf::R8Unorm => H::R8Unorm,
384 Tf::R8Snorm => H::R8Snorm,
385 Tf::R8Uint => H::R8Uint,
386 Tf::R8Sint => H::R8Sint,
387
388 // Normal 16 bit formats
389 Tf::R16Uint => H::R16Uint,
390 Tf::R16Sint => H::R16Sint,
391 Tf::R16Float => H::R16Sfloat,
392 Tf::Rg8Unorm => H::Rg8Unorm,
393 Tf::Rg8Snorm => H::Rg8Snorm,
394 Tf::Rg8Uint => H::Rg8Uint,
395 Tf::Rg8Sint => H::Rg8Sint,
396
397 // Normal 32 bit formats
398 Tf::R32Uint => H::R32Uint,
399 Tf::R32Sint => H::R32Sint,
400 Tf::R32Float => H::R32Sfloat,
401 Tf::Rg16Uint => H::Rg16Uint,
402 Tf::Rg16Sint => H::Rg16Sint,
403 Tf::Rg16Float => H::Rg16Sfloat,
404 Tf::Rgba8Unorm => H::Rgba8Unorm,
405 Tf::Rgba8UnormSrgb => H::Rgba8Srgb,
406 Tf::Rgba8Snorm => H::Rgba8Snorm,
407 Tf::Rgba8Uint => H::Rgba8Uint,
408 Tf::Rgba8Sint => H::Rgba8Sint,
409 Tf::Bgra8Unorm => H::Bgra8Unorm,
410 Tf::Bgra8UnormSrgb => H::Bgra8Srgb,
411
412 // Packed 32 bit formats
413 Tf::Rgb10a2Unorm => H::A2r10g10b10Unorm,
414 Tf::Rg11b10Float => H::B10g11r11Ufloat,
415
416 // Normal 64 bit formats
417 Tf::Rg32Uint => H::Rg32Uint,
418 Tf::Rg32Sint => H::Rg32Sint,
419 Tf::Rg32Float => H::Rg32Sfloat,
420 Tf::Rgba16Uint => H::Rgba16Uint,
421 Tf::Rgba16Sint => H::Rgba16Sint,
422 Tf::Rgba16Float => H::Rgba16Sfloat,
423
424 // Normal 128 bit formats
425 Tf::Rgba32Uint => H::Rgba32Uint,
426 Tf::Rgba32Sint => H::Rgba32Sint,
427 Tf::Rgba32Float => H::Rgba32Sfloat,
428
429 // Depth and stencil formats
430 Tf::Depth32Float => H::D32Sfloat,
431 Tf::Depth24Plus => {
432 if private_features.texture_d24 {
433 H::X8D24Unorm
434 } else {
435 H::D32Sfloat
436 }
437 }
438 Tf::Depth24PlusStencil8 => {
439 if private_features.texture_d24_s8 {
440 H::D24UnormS8Uint
441 } else {
442 H::D32SfloatS8Uint
443 }
444 }
445
446 // BCn compressed formats
447 Tf::Bc1RgbaUnorm => H::Bc1RgbaUnorm,
448 Tf::Bc1RgbaUnormSrgb => H::Bc1RgbaSrgb,
449 Tf::Bc2RgbaUnorm => H::Bc2Unorm,
450 Tf::Bc2RgbaUnormSrgb => H::Bc2Srgb,
451 Tf::Bc3RgbaUnorm => H::Bc3Unorm,
452 Tf::Bc3RgbaUnormSrgb => H::Bc3Srgb,
453 Tf::Bc4RUnorm => H::Bc4Unorm,
454 Tf::Bc4RSnorm => H::Bc4Snorm,
455 Tf::Bc5RgUnorm => H::Bc5Unorm,
456 Tf::Bc5RgSnorm => H::Bc5Snorm,
457 Tf::Bc6hRgbSfloat => H::Bc6hSfloat,
458 Tf::Bc6hRgbUfloat => H::Bc6hUfloat,
459 Tf::Bc7RgbaUnorm => H::Bc7Unorm,
460 Tf::Bc7RgbaUnormSrgb => H::Bc7Srgb,
461
462 // ETC compressed formats
463 Tf::Etc2RgbUnorm => H::Etc2R8g8b8Unorm,
464 Tf::Etc2RgbUnormSrgb => H::Etc2R8g8b8Srgb,
465 Tf::Etc2RgbA1Unorm => H::Etc2R8g8b8a1Unorm,
466 Tf::Etc2RgbA1UnormSrgb => H::Etc2R8g8b8a1Srgb,
467 Tf::Etc2RgbA8Unorm => H::Etc2R8g8b8a8Unorm,
468 Tf::Etc2RgbA8UnormSrgb => H::Etc2R8g8b8a8Unorm,
469 Tf::EacRUnorm => H::EacR11Unorm,
470 Tf::EacRSnorm => H::EacR11Snorm,
471 Tf::EtcRgUnorm => H::EacR11g11Unorm,
472 Tf::EtcRgSnorm => H::EacR11g11Snorm,
473
474 // ASTC compressed formats
475 Tf::Astc4x4RgbaUnorm => H::Astc4x4Srgb,
476 Tf::Astc4x4RgbaUnormSrgb => H::Astc4x4Srgb,
477 Tf::Astc5x4RgbaUnorm => H::Astc5x4Unorm,
478 Tf::Astc5x4RgbaUnormSrgb => H::Astc5x4Srgb,
479 Tf::Astc5x5RgbaUnorm => H::Astc5x5Unorm,
480 Tf::Astc5x5RgbaUnormSrgb => H::Astc5x5Srgb,
481 Tf::Astc6x5RgbaUnorm => H::Astc6x5Unorm,
482 Tf::Astc6x5RgbaUnormSrgb => H::Astc6x5Srgb,
483 Tf::Astc6x6RgbaUnorm => H::Astc6x6Unorm,
484 Tf::Astc6x6RgbaUnormSrgb => H::Astc6x6Srgb,
485 Tf::Astc8x5RgbaUnorm => H::Astc8x5Unorm,
486 Tf::Astc8x5RgbaUnormSrgb => H::Astc8x5Srgb,
487 Tf::Astc8x6RgbaUnorm => H::Astc8x6Unorm,
488 Tf::Astc8x6RgbaUnormSrgb => H::Astc8x6Srgb,
489 Tf::Astc10x5RgbaUnorm => H::Astc10x5Unorm,
490 Tf::Astc10x5RgbaUnormSrgb => H::Astc10x5Srgb,
491 Tf::Astc10x6RgbaUnorm => H::Astc10x6Unorm,
492 Tf::Astc10x6RgbaUnormSrgb => H::Astc10x6Srgb,
493 Tf::Astc8x8RgbaUnorm => H::Astc8x8Unorm,
494 Tf::Astc8x8RgbaUnormSrgb => H::Astc8x8Srgb,
495 Tf::Astc10x8RgbaUnorm => H::Astc10x8Unorm,
496 Tf::Astc10x8RgbaUnormSrgb => H::Astc10x8Srgb,
497 Tf::Astc10x10RgbaUnorm => H::Astc10x10Unorm,
498 Tf::Astc10x10RgbaUnormSrgb => H::Astc10x10Srgb,
499 Tf::Astc12x10RgbaUnorm => H::Astc12x10Unorm,
500 Tf::Astc12x10RgbaUnormSrgb => H::Astc12x10Srgb,
501 Tf::Astc12x12RgbaUnorm => H::Astc12x12Unorm,
502 Tf::Astc12x12RgbaUnormSrgb => H::Astc12x12Srgb,
503 }
504 }
505
map_vertex_format(vertex_format: wgt::VertexFormat) -> hal::format::Format506 pub fn map_vertex_format(vertex_format: wgt::VertexFormat) -> hal::format::Format {
507 use hal::format::Format as H;
508 use wgt::VertexFormat as Vf;
509 match vertex_format {
510 Vf::Uint8x2 => H::Rg8Uint,
511 Vf::Uint8x4 => H::Rgba8Uint,
512 Vf::Sint8x2 => H::Rg8Sint,
513 Vf::Sint8x4 => H::Rgba8Sint,
514 Vf::Unorm8x2 => H::Rg8Unorm,
515 Vf::Unorm8x4 => H::Rgba8Unorm,
516 Vf::Snorm8x2 => H::Rg8Snorm,
517 Vf::Snorm8x4 => H::Rgba8Snorm,
518 Vf::Uint16x2 => H::Rg16Uint,
519 Vf::Uint16x4 => H::Rgba16Uint,
520 Vf::Sint16x2 => H::Rg16Sint,
521 Vf::Sint16x4 => H::Rgba16Sint,
522 Vf::Unorm16x2 => H::Rg16Unorm,
523 Vf::Unorm16x4 => H::Rgba16Unorm,
524 Vf::Snorm16x2 => H::Rg16Snorm,
525 Vf::Snorm16x4 => H::Rgba16Snorm,
526 Vf::Float16x2 => H::Rg16Sfloat,
527 Vf::Float16x4 => H::Rgba16Sfloat,
528 Vf::Float32 => H::R32Sfloat,
529 Vf::Float32x2 => H::Rg32Sfloat,
530 Vf::Float32x3 => H::Rgb32Sfloat,
531 Vf::Float32x4 => H::Rgba32Sfloat,
532 Vf::Uint32 => H::R32Uint,
533 Vf::Uint32x2 => H::Rg32Uint,
534 Vf::Uint32x3 => H::Rgb32Uint,
535 Vf::Uint32x4 => H::Rgba32Uint,
536 Vf::Sint32 => H::R32Sint,
537 Vf::Sint32x2 => H::Rg32Sint,
538 Vf::Sint32x3 => H::Rgb32Sint,
539 Vf::Sint32x4 => H::Rgba32Sint,
540 Vf::Float64 => H::R64Sfloat,
541 Vf::Float64x2 => H::Rg64Sfloat,
542 Vf::Float64x3 => H::Rgb64Sfloat,
543 Vf::Float64x4 => H::Rgba64Sfloat,
544 }
545 }
546
is_power_of_two(val: u32) -> bool547 pub fn is_power_of_two(val: u32) -> bool {
548 val != 0 && (val & (val - 1)) == 0
549 }
550
is_valid_copy_src_texture_format(format: wgt::TextureFormat) -> bool551 pub fn is_valid_copy_src_texture_format(format: wgt::TextureFormat) -> bool {
552 use wgt::TextureFormat as Tf;
553 match format {
554 Tf::Depth24Plus | Tf::Depth24PlusStencil8 => false,
555 _ => true,
556 }
557 }
558
is_valid_copy_dst_texture_format(format: wgt::TextureFormat) -> bool559 pub fn is_valid_copy_dst_texture_format(format: wgt::TextureFormat) -> bool {
560 use wgt::TextureFormat as Tf;
561 match format {
562 Tf::Depth32Float | Tf::Depth24Plus | Tf::Depth24PlusStencil8 => false,
563 _ => true,
564 }
565 }
566
567 pub fn map_texture_dimension_size(
568 dimension: wgt::TextureDimension,
569 wgt::Extent3d {
570 width,
571 height,
572 depth_or_array_layers,
573 }: wgt::Extent3d,
574 sample_size: u32,
575 limits: &wgt::Limits,
576 ) -> Result<hal::image::Kind, resource::TextureDimensionError> {
577 use hal::image::Kind as H;
578 use resource::{TextureDimensionError as Tde, TextureErrorDimension as Ted};
579 use wgt::TextureDimension::*;
580
581 let layers = depth_or_array_layers.try_into().unwrap_or(!0);
582 let (kind, extent_limits, sample_limit) = match dimension {
583 D1 => (
584 H::D1(width, layers),
585 [
586 limits.max_texture_dimension_1d,
587 1,
588 limits.max_texture_array_layers,
589 ],
590 1,
591 ),
592 D2 => (
593 H::D2(width, height, layers, sample_size as u8),
594 [
595 limits.max_texture_dimension_2d,
596 limits.max_texture_dimension_2d,
597 limits.max_texture_array_layers,
598 ],
599 32,
600 ),
601 D3 => (
602 H::D3(width, height, depth_or_array_layers),
603 [
604 limits.max_texture_dimension_3d,
605 limits.max_texture_dimension_3d,
606 limits.max_texture_dimension_3d,
607 ],
608 1,
609 ),
610 };
611
612 for (&dim, (&given, &limit)) in [Ted::X, Ted::Y, Ted::Z].iter().zip(
613 [width, height, depth_or_array_layers]
614 .iter()
615 .zip(extent_limits.iter()),
616 ) {
617 if given == 0 {
618 return Err(Tde::Zero(dim));
619 }
620 if given > limit {
621 return Err(Tde::LimitExceeded { dim, given, limit });
622 }
623 }
624 if sample_size == 0 || sample_size > sample_limit || !is_power_of_two(sample_size) {
625 return Err(Tde::InvalidSampleCount(sample_size));
626 }
627
628 Ok(kind)
629 }
630
map_texture_view_dimension(dimension: wgt::TextureViewDimension) -> hal::image::ViewKind631 pub fn map_texture_view_dimension(dimension: wgt::TextureViewDimension) -> hal::image::ViewKind {
632 use hal::image::ViewKind as H;
633 use wgt::TextureViewDimension::*;
634 match dimension {
635 D1 => H::D1,
636 D2 => H::D2,
637 D2Array => H::D2Array,
638 Cube => H::Cube,
639 CubeArray => H::CubeArray,
640 D3 => H::D3,
641 }
642 }
643
map_buffer_state(usage: resource::BufferUse) -> hal::buffer::State644 pub(crate) fn map_buffer_state(usage: resource::BufferUse) -> hal::buffer::State {
645 use crate::resource::BufferUse as W;
646 use hal::buffer::Access as A;
647
648 let mut access = A::empty();
649 if usage.contains(W::MAP_READ) {
650 access |= A::HOST_READ;
651 }
652 if usage.contains(W::MAP_WRITE) {
653 access |= A::HOST_WRITE;
654 }
655 if usage.contains(W::COPY_SRC) {
656 access |= A::TRANSFER_READ;
657 }
658 if usage.contains(W::COPY_DST) {
659 access |= A::TRANSFER_WRITE;
660 }
661 if usage.contains(W::INDEX) {
662 access |= A::INDEX_BUFFER_READ;
663 }
664 if usage.contains(W::VERTEX) {
665 access |= A::VERTEX_BUFFER_READ;
666 }
667 if usage.contains(W::UNIFORM) {
668 access |= A::UNIFORM_READ | A::SHADER_READ;
669 }
670 if usage.contains(W::STORAGE_LOAD) {
671 access |= A::SHADER_READ;
672 }
673 if usage.contains(W::STORAGE_STORE) {
674 access |= A::SHADER_READ | A::SHADER_WRITE;
675 }
676 if usage.contains(W::INDIRECT) {
677 access |= A::INDIRECT_COMMAND_READ;
678 }
679
680 access
681 }
682
map_texture_state( usage: resource::TextureUse, aspects: hal::format::Aspects, ) -> hal::image::State683 pub(crate) fn map_texture_state(
684 usage: resource::TextureUse,
685 aspects: hal::format::Aspects,
686 ) -> hal::image::State {
687 use crate::resource::TextureUse as W;
688 use hal::image::{Access as A, Layout as L};
689
690 let is_color = aspects.contains(hal::format::Aspects::COLOR);
691 let layout = match usage {
692 W::UNINITIALIZED => return (A::empty(), L::Undefined),
693 W::COPY_SRC => L::TransferSrcOptimal,
694 W::COPY_DST => L::TransferDstOptimal,
695 W::SAMPLED if is_color => L::ShaderReadOnlyOptimal,
696 W::ATTACHMENT_READ | W::ATTACHMENT_WRITE if is_color => L::ColorAttachmentOptimal,
697 _ if is_color => L::General,
698 W::ATTACHMENT_WRITE => L::DepthStencilAttachmentOptimal,
699 _ => L::DepthStencilReadOnlyOptimal,
700 };
701
702 let mut access = A::empty();
703 if usage.contains(W::COPY_SRC) {
704 access |= A::TRANSFER_READ;
705 }
706 if usage.contains(W::COPY_DST) {
707 access |= A::TRANSFER_WRITE;
708 }
709 if usage.contains(W::SAMPLED) {
710 access |= A::SHADER_READ;
711 }
712 if usage.contains(W::ATTACHMENT_READ) {
713 access |= if is_color {
714 A::COLOR_ATTACHMENT_READ
715 } else {
716 A::DEPTH_STENCIL_ATTACHMENT_READ
717 };
718 }
719 if usage.contains(W::ATTACHMENT_WRITE) {
720 access |= if is_color {
721 A::COLOR_ATTACHMENT_WRITE
722 } else {
723 A::DEPTH_STENCIL_ATTACHMENT_WRITE
724 };
725 }
726 if usage.contains(W::STORAGE_LOAD) {
727 access |= A::SHADER_READ;
728 }
729 if usage.contains(W::STORAGE_STORE) {
730 access |= A::SHADER_WRITE;
731 }
732
733 (access, layout)
734 }
735
map_query_type(ty: &wgt::QueryType) -> (hal::query::Type, u32)736 pub fn map_query_type(ty: &wgt::QueryType) -> (hal::query::Type, u32) {
737 match *ty {
738 wgt::QueryType::PipelineStatistics(pipeline_statistics) => {
739 let mut ps = hal::query::PipelineStatistic::empty();
740 ps.set(
741 hal::query::PipelineStatistic::VERTEX_SHADER_INVOCATIONS,
742 pipeline_statistics
743 .contains(wgt::PipelineStatisticsTypes::VERTEX_SHADER_INVOCATIONS),
744 );
745 ps.set(
746 hal::query::PipelineStatistic::CLIPPING_INVOCATIONS,
747 pipeline_statistics.contains(wgt::PipelineStatisticsTypes::CLIPPER_INVOCATIONS),
748 );
749 ps.set(
750 hal::query::PipelineStatistic::CLIPPING_PRIMITIVES,
751 pipeline_statistics.contains(wgt::PipelineStatisticsTypes::CLIPPER_PRIMITIVES_OUT),
752 );
753 ps.set(
754 hal::query::PipelineStatistic::FRAGMENT_SHADER_INVOCATIONS,
755 pipeline_statistics
756 .contains(wgt::PipelineStatisticsTypes::FRAGMENT_SHADER_INVOCATIONS),
757 );
758 ps.set(
759 hal::query::PipelineStatistic::COMPUTE_SHADER_INVOCATIONS,
760 pipeline_statistics
761 .contains(wgt::PipelineStatisticsTypes::COMPUTE_SHADER_INVOCATIONS),
762 );
763
764 (
765 hal::query::Type::PipelineStatistics(ps),
766 pipeline_statistics.bits().count_ones(),
767 )
768 }
769 wgt::QueryType::Timestamp => (hal::query::Type::Timestamp, 1),
770 }
771 }
772
map_load_store_ops<V>(channel: &PassChannel<V>) -> hal::pass::AttachmentOps773 pub fn map_load_store_ops<V>(channel: &PassChannel<V>) -> hal::pass::AttachmentOps {
774 hal::pass::AttachmentOps {
775 load: match channel.load_op {
776 LoadOp::Clear => hal::pass::AttachmentLoadOp::Clear,
777 LoadOp::Load => hal::pass::AttachmentLoadOp::Load,
778 },
779 store: match channel.store_op {
780 StoreOp::Clear => hal::pass::AttachmentStoreOp::DontCare, //TODO!
781 StoreOp::Store => hal::pass::AttachmentStoreOp::Store,
782 },
783 }
784 }
785
map_color_f32(color: &wgt::Color) -> hal::pso::ColorValue786 pub fn map_color_f32(color: &wgt::Color) -> hal::pso::ColorValue {
787 [
788 color.r as f32,
789 color.g as f32,
790 color.b as f32,
791 color.a as f32,
792 ]
793 }
map_color_i32(color: &wgt::Color) -> [i32; 4]794 pub fn map_color_i32(color: &wgt::Color) -> [i32; 4] {
795 [
796 color.r as i32,
797 color.g as i32,
798 color.b as i32,
799 color.a as i32,
800 ]
801 }
map_color_u32(color: &wgt::Color) -> [u32; 4]802 pub fn map_color_u32(color: &wgt::Color) -> [u32; 4] {
803 [
804 color.r as u32,
805 color.g as u32,
806 color.b as u32,
807 color.a as u32,
808 ]
809 }
810
map_filter(filter: wgt::FilterMode) -> hal::image::Filter811 pub fn map_filter(filter: wgt::FilterMode) -> hal::image::Filter {
812 match filter {
813 wgt::FilterMode::Nearest => hal::image::Filter::Nearest,
814 wgt::FilterMode::Linear => hal::image::Filter::Linear,
815 }
816 }
817
map_wrap(address: wgt::AddressMode) -> hal::image::WrapMode818 pub fn map_wrap(address: wgt::AddressMode) -> hal::image::WrapMode {
819 use hal::image::WrapMode as W;
820 use wgt::AddressMode as Am;
821 match address {
822 Am::ClampToEdge => W::Clamp,
823 Am::Repeat => W::Tile,
824 Am::MirrorRepeat => W::Mirror,
825 Am::ClampToBorder => W::Border,
826 }
827 }
828
map_primitive_state_to_input_assembler( desc: &wgt::PrimitiveState, ) -> hal::pso::InputAssemblerDesc829 pub fn map_primitive_state_to_input_assembler(
830 desc: &wgt::PrimitiveState,
831 ) -> hal::pso::InputAssemblerDesc {
832 hal::pso::InputAssemblerDesc {
833 primitive: map_primitive_topology(desc.topology),
834 with_adjacency: false,
835 restart_index: desc.strip_index_format.map(map_index_format),
836 }
837 }
838
map_primitive_state_to_rasterizer( desc: &wgt::PrimitiveState, depth_stencil: Option<&wgt::DepthStencilState>, ) -> hal::pso::Rasterizer839 pub fn map_primitive_state_to_rasterizer(
840 desc: &wgt::PrimitiveState,
841 depth_stencil: Option<&wgt::DepthStencilState>,
842 ) -> hal::pso::Rasterizer {
843 use hal::pso;
844 let depth_bias = match depth_stencil {
845 Some(dsd) if dsd.bias.is_enabled() => Some(pso::State::Static(pso::DepthBias {
846 const_factor: dsd.bias.constant as f32,
847 slope_factor: dsd.bias.slope_scale,
848 clamp: dsd.bias.clamp,
849 })),
850 _ => None,
851 };
852 pso::Rasterizer {
853 depth_clamping: desc.clamp_depth,
854 polygon_mode: match desc.polygon_mode {
855 wgt::PolygonMode::Fill => pso::PolygonMode::Fill,
856 wgt::PolygonMode::Line => pso::PolygonMode::Line,
857 wgt::PolygonMode::Point => pso::PolygonMode::Point,
858 },
859 cull_face: match desc.cull_mode {
860 None => pso::Face::empty(),
861 Some(wgt::Face::Front) => pso::Face::FRONT,
862 Some(wgt::Face::Back) => pso::Face::BACK,
863 },
864 front_face: match desc.front_face {
865 wgt::FrontFace::Ccw => pso::FrontFace::CounterClockwise,
866 wgt::FrontFace::Cw => pso::FrontFace::Clockwise,
867 },
868 depth_bias,
869 conservative: desc.conservative,
870 line_width: pso::State::Static(1.0),
871 }
872 }
873
map_multisample_state(desc: &wgt::MultisampleState) -> hal::pso::Multisampling874 pub fn map_multisample_state(desc: &wgt::MultisampleState) -> hal::pso::Multisampling {
875 hal::pso::Multisampling {
876 rasterization_samples: desc.count as _,
877 sample_shading: None,
878 sample_mask: desc.mask,
879 alpha_coverage: desc.alpha_to_coverage_enabled,
880 alpha_to_one: false,
881 }
882 }
883
map_index_format(index_format: wgt::IndexFormat) -> hal::IndexType884 pub fn map_index_format(index_format: wgt::IndexFormat) -> hal::IndexType {
885 match index_format {
886 wgt::IndexFormat::Uint16 => hal::IndexType::U16,
887 wgt::IndexFormat::Uint32 => hal::IndexType::U32,
888 }
889 }
890
891 /// Take `value` and round it up to the nearest alignment `alignment`.
892 ///
893 /// ```text
894 /// (0, 3) -> 0
895 /// (1, 3) -> 3
896 /// (2, 3) -> 3
897 /// (3, 3) -> 3
898 /// (4, 3) -> 6
899 /// ...
align_up(value: u32, alignment: u32) -> u32900 pub fn align_up(value: u32, alignment: u32) -> u32 {
901 ((value + alignment - 1) / alignment) * alignment
902 }
903