diff options
Diffstat (limited to 'gfx/wgpu/wgpu-core/src/conv.rs')
-rw-r--r-- | gfx/wgpu/wgpu-core/src/conv.rs | 833 |
1 files changed, 833 insertions, 0 deletions
diff --git a/gfx/wgpu/wgpu-core/src/conv.rs b/gfx/wgpu/wgpu-core/src/conv.rs new file mode 100644 index 0000000000..58093b37e6 --- /dev/null +++ b/gfx/wgpu/wgpu-core/src/conv.rs @@ -0,0 +1,833 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use crate::{ + command::{LoadOp, PassChannel, StoreOp}, + resource, PrivateFeatures, +}; + +use std::convert::TryInto; + +pub fn map_buffer_usage(usage: wgt::BufferUsage) -> (hal::buffer::Usage, hal::memory::Properties) { + use hal::buffer::Usage as U; + use hal::memory::Properties as P; + use wgt::BufferUsage as W; + + let mut hal_memory = P::empty(); + if usage.contains(W::MAP_READ) { + hal_memory |= P::CPU_VISIBLE | P::CPU_CACHED; + } + if usage.contains(W::MAP_WRITE) { + hal_memory |= P::CPU_VISIBLE; + } + + let mut hal_usage = U::empty(); + if usage.contains(W::COPY_SRC) { + hal_usage |= U::TRANSFER_SRC; + } + if usage.contains(W::COPY_DST) { + hal_usage |= U::TRANSFER_DST; + } + if usage.contains(W::INDEX) { + hal_usage |= U::INDEX; + } + if usage.contains(W::VERTEX) { + hal_usage |= U::VERTEX; + } + if usage.contains(W::UNIFORM) { + hal_usage |= U::UNIFORM; + } + if usage.contains(W::STORAGE) { + hal_usage |= U::STORAGE; + } + if usage.contains(W::INDIRECT) { + hal_usage |= U::INDIRECT; + } + + (hal_usage, hal_memory) +} + +pub fn map_texture_usage( + usage: wgt::TextureUsage, + aspects: hal::format::Aspects, +) -> hal::image::Usage { + use hal::image::Usage as U; + use wgt::TextureUsage as W; + + let mut value = U::empty(); + if usage.contains(W::COPY_SRC) { + value |= U::TRANSFER_SRC; + } + if usage.contains(W::COPY_DST) { + value |= U::TRANSFER_DST; + } + if usage.contains(W::SAMPLED) { + value |= U::SAMPLED; + } + if usage.contains(W::STORAGE) { + value |= U::STORAGE; + } + if usage.contains(W::RENDER_ATTACHMENT) { + if aspects.intersects(hal::format::Aspects::DEPTH | hal::format::Aspects::STENCIL) { + value |= U::DEPTH_STENCIL_ATTACHMENT; + } else { + value |= U::COLOR_ATTACHMENT; + } + } + // Note: TextureUsage::Present does not need to be handled explicitly + // TODO: HAL Transient Attachment, HAL Input Attachment + value +} + +pub fn map_binding_type(binding: &wgt::BindGroupLayoutEntry) -> hal::pso::DescriptorType { + use hal::pso; + use wgt::BindingType as Bt; + match binding.ty { + Bt::Buffer { + ty, + has_dynamic_offset, + min_binding_size: _, + } => pso::DescriptorType::Buffer { + ty: match ty { + wgt::BufferBindingType::Uniform => pso::BufferDescriptorType::Uniform, + wgt::BufferBindingType::Storage { read_only } => { + pso::BufferDescriptorType::Storage { read_only } + } + }, + format: pso::BufferDescriptorFormat::Structured { + dynamic_offset: has_dynamic_offset, + }, + }, + Bt::Sampler { .. } => pso::DescriptorType::Sampler, + Bt::Texture { .. } => pso::DescriptorType::Image { + ty: pso::ImageDescriptorType::Sampled { + with_sampler: false, + }, + }, + Bt::StorageTexture { access, .. } => pso::DescriptorType::Image { + ty: pso::ImageDescriptorType::Storage { + read_only: match access { + wgt::StorageTextureAccess::ReadOnly => true, + _ => false, + }, + }, + }, + } +} + +pub fn map_shader_stage_flags(shader_stage_flags: wgt::ShaderStage) -> hal::pso::ShaderStageFlags { + use hal::pso::ShaderStageFlags as H; + use wgt::ShaderStage as Ss; + + let mut value = H::empty(); + if shader_stage_flags.contains(Ss::VERTEX) { + value |= H::VERTEX; + } + if shader_stage_flags.contains(Ss::FRAGMENT) { + value |= H::FRAGMENT; + } + if shader_stage_flags.contains(Ss::COMPUTE) { + value |= H::COMPUTE; + } + value +} + +pub fn map_extent(extent: &wgt::Extent3d, dim: wgt::TextureDimension) -> hal::image::Extent { + hal::image::Extent { + width: extent.width, + height: extent.height, + depth: match dim { + wgt::TextureDimension::D1 | wgt::TextureDimension::D2 => 1, + wgt::TextureDimension::D3 => extent.depth, + }, + } +} + +pub fn map_primitive_topology(primitive_topology: wgt::PrimitiveTopology) -> hal::pso::Primitive { + use hal::pso::Primitive as H; + use wgt::PrimitiveTopology as Pt; + match primitive_topology { + Pt::PointList => H::PointList, + Pt::LineList => H::LineList, + Pt::LineStrip => H::LineStrip, + Pt::TriangleList => H::TriangleList, + Pt::TriangleStrip => H::TriangleStrip, + } +} + +pub fn map_color_state_descriptor(desc: &wgt::ColorStateDescriptor) -> hal::pso::ColorBlendDesc { + let color_mask = desc.write_mask; + let blend_state = if desc.color_blend != wgt::BlendDescriptor::REPLACE + || desc.alpha_blend != wgt::BlendDescriptor::REPLACE + { + Some(hal::pso::BlendState { + color: map_blend_descriptor(&desc.color_blend), + alpha: map_blend_descriptor(&desc.alpha_blend), + }) + } else { + None + }; + hal::pso::ColorBlendDesc { + mask: map_color_write_flags(color_mask), + blend: blend_state, + } +} + +fn map_color_write_flags(flags: wgt::ColorWrite) -> hal::pso::ColorMask { + use hal::pso::ColorMask as H; + use wgt::ColorWrite as Cw; + + let mut value = H::empty(); + if flags.contains(Cw::RED) { + value |= H::RED; + } + if flags.contains(Cw::GREEN) { + value |= H::GREEN; + } + if flags.contains(Cw::BLUE) { + value |= H::BLUE; + } + if flags.contains(Cw::ALPHA) { + value |= H::ALPHA; + } + value +} + +fn map_blend_descriptor(blend_desc: &wgt::BlendDescriptor) -> hal::pso::BlendOp { + use hal::pso::BlendOp as H; + use wgt::BlendOperation as Bo; + match blend_desc.operation { + Bo::Add => H::Add { + src: map_blend_factor(blend_desc.src_factor), + dst: map_blend_factor(blend_desc.dst_factor), + }, + Bo::Subtract => H::Sub { + src: map_blend_factor(blend_desc.src_factor), + dst: map_blend_factor(blend_desc.dst_factor), + }, + Bo::ReverseSubtract => H::RevSub { + src: map_blend_factor(blend_desc.src_factor), + dst: map_blend_factor(blend_desc.dst_factor), + }, + Bo::Min => H::Min, + Bo::Max => H::Max, + } +} + +fn map_blend_factor(blend_factor: wgt::BlendFactor) -> hal::pso::Factor { + use hal::pso::Factor as H; + use wgt::BlendFactor as Bf; + match blend_factor { + Bf::Zero => H::Zero, + Bf::One => H::One, + Bf::SrcColor => H::SrcColor, + Bf::OneMinusSrcColor => H::OneMinusSrcColor, + Bf::SrcAlpha => H::SrcAlpha, + Bf::OneMinusSrcAlpha => H::OneMinusSrcAlpha, + Bf::DstColor => H::DstColor, + Bf::OneMinusDstColor => H::OneMinusDstColor, + Bf::DstAlpha => H::DstAlpha, + Bf::OneMinusDstAlpha => H::OneMinusDstAlpha, + Bf::SrcAlphaSaturated => H::SrcAlphaSaturate, + Bf::BlendColor => H::ConstColor, + Bf::OneMinusBlendColor => H::OneMinusConstColor, + } +} + +pub fn map_depth_stencil_state_descriptor( + desc: &wgt::DepthStencilStateDescriptor, +) -> hal::pso::DepthStencilDesc { + hal::pso::DepthStencilDesc { + depth: if desc.is_depth_enabled() { + Some(hal::pso::DepthTest { + fun: map_compare_function(desc.depth_compare), + write: desc.depth_write_enabled, + }) + } else { + None + }, + depth_bounds: false, // TODO + stencil: if desc.stencil.is_enabled() { + let s = &desc.stencil; + Some(hal::pso::StencilTest { + faces: hal::pso::Sided { + front: map_stencil_face(&s.front), + back: map_stencil_face(&s.back), + }, + read_masks: hal::pso::State::Static(hal::pso::Sided::new(s.read_mask)), + write_masks: hal::pso::State::Static(hal::pso::Sided::new(s.write_mask)), + reference_values: if s.needs_ref_value() { + hal::pso::State::Dynamic + } else { + hal::pso::State::Static(hal::pso::Sided::new(0)) + }, + }) + } else { + None + }, + } +} + +fn map_stencil_face( + stencil_state_face_desc: &wgt::StencilStateFaceDescriptor, +) -> hal::pso::StencilFace { + hal::pso::StencilFace { + fun: map_compare_function(stencil_state_face_desc.compare), + op_fail: map_stencil_operation(stencil_state_face_desc.fail_op), + op_depth_fail: map_stencil_operation(stencil_state_face_desc.depth_fail_op), + op_pass: map_stencil_operation(stencil_state_face_desc.pass_op), + } +} + +pub fn map_compare_function(compare_function: wgt::CompareFunction) -> hal::pso::Comparison { + use hal::pso::Comparison as H; + use wgt::CompareFunction as Cf; + match compare_function { + Cf::Never => H::Never, + Cf::Less => H::Less, + Cf::Equal => H::Equal, + Cf::LessEqual => H::LessEqual, + Cf::Greater => H::Greater, + Cf::NotEqual => H::NotEqual, + Cf::GreaterEqual => H::GreaterEqual, + Cf::Always => H::Always, + } +} + +fn map_stencil_operation(stencil_operation: wgt::StencilOperation) -> hal::pso::StencilOp { + use hal::pso::StencilOp as H; + use wgt::StencilOperation as So; + match stencil_operation { + So::Keep => H::Keep, + So::Zero => H::Zero, + So::Replace => H::Replace, + So::Invert => H::Invert, + So::IncrementClamp => H::IncrementClamp, + So::DecrementClamp => H::DecrementClamp, + So::IncrementWrap => H::IncrementWrap, + So::DecrementWrap => H::DecrementWrap, + } +} + +pub(crate) fn map_texture_format( + texture_format: wgt::TextureFormat, + private_features: PrivateFeatures, +) -> hal::format::Format { + use hal::format::Format as H; + use wgt::TextureFormat as Tf; + match texture_format { + // Normal 8 bit formats + Tf::R8Unorm => H::R8Unorm, + Tf::R8Snorm => H::R8Snorm, + Tf::R8Uint => H::R8Uint, + Tf::R8Sint => H::R8Sint, + + // Normal 16 bit formats + Tf::R16Uint => H::R16Uint, + Tf::R16Sint => H::R16Sint, + Tf::R16Float => H::R16Sfloat, + Tf::Rg8Unorm => H::Rg8Unorm, + Tf::Rg8Snorm => H::Rg8Snorm, + Tf::Rg8Uint => H::Rg8Uint, + Tf::Rg8Sint => H::Rg8Sint, + + // Normal 32 bit formats + Tf::R32Uint => H::R32Uint, + Tf::R32Sint => H::R32Sint, + Tf::R32Float => H::R32Sfloat, + Tf::Rg16Uint => H::Rg16Uint, + Tf::Rg16Sint => H::Rg16Sint, + Tf::Rg16Float => H::Rg16Sfloat, + Tf::Rgba8Unorm => H::Rgba8Unorm, + Tf::Rgba8UnormSrgb => H::Rgba8Srgb, + Tf::Rgba8Snorm => H::Rgba8Snorm, + Tf::Rgba8Uint => H::Rgba8Uint, + Tf::Rgba8Sint => H::Rgba8Sint, + Tf::Bgra8Unorm => H::Bgra8Unorm, + Tf::Bgra8UnormSrgb => H::Bgra8Srgb, + + // Packed 32 bit formats + Tf::Rgb10a2Unorm => H::A2r10g10b10Unorm, + Tf::Rg11b10Float => H::B10g11r11Ufloat, + + // Normal 64 bit formats + Tf::Rg32Uint => H::Rg32Uint, + Tf::Rg32Sint => H::Rg32Sint, + Tf::Rg32Float => H::Rg32Sfloat, + Tf::Rgba16Uint => H::Rgba16Uint, + Tf::Rgba16Sint => H::Rgba16Sint, + Tf::Rgba16Float => H::Rgba16Sfloat, + + // Normal 128 bit formats + Tf::Rgba32Uint => H::Rgba32Uint, + Tf::Rgba32Sint => H::Rgba32Sint, + Tf::Rgba32Float => H::Rgba32Sfloat, + + // Depth and stencil formats + Tf::Depth32Float => H::D32Sfloat, + Tf::Depth24Plus => { + if private_features.texture_d24 { + H::X8D24Unorm + } else { + H::D32Sfloat + } + } + Tf::Depth24PlusStencil8 => { + if private_features.texture_d24_s8 { + H::D24UnormS8Uint + } else { + H::D32SfloatS8Uint + } + } + + // BCn compressed formats + Tf::Bc1RgbaUnorm => H::Bc1RgbaUnorm, + Tf::Bc1RgbaUnormSrgb => H::Bc1RgbaSrgb, + Tf::Bc2RgbaUnorm => H::Bc2Unorm, + Tf::Bc2RgbaUnormSrgb => H::Bc2Srgb, + Tf::Bc3RgbaUnorm => H::Bc3Unorm, + Tf::Bc3RgbaUnormSrgb => H::Bc3Srgb, + Tf::Bc4RUnorm => H::Bc4Unorm, + Tf::Bc4RSnorm => H::Bc4Snorm, + Tf::Bc5RgUnorm => H::Bc5Unorm, + Tf::Bc5RgSnorm => H::Bc5Snorm, + Tf::Bc6hRgbSfloat => H::Bc6hSfloat, + Tf::Bc6hRgbUfloat => H::Bc6hUfloat, + Tf::Bc7RgbaUnorm => H::Bc7Unorm, + Tf::Bc7RgbaUnormSrgb => H::Bc7Srgb, + } +} + +pub fn texture_block_size(format: wgt::TextureFormat) -> (u32, u32) { + use wgt::TextureFormat as Tf; + match format { + Tf::R8Unorm + | Tf::R8Snorm + | Tf::R8Uint + | Tf::R8Sint + | Tf::R16Uint + | Tf::R16Sint + | Tf::R16Float + | Tf::Rg8Unorm + | Tf::Rg8Snorm + | Tf::Rg8Uint + | Tf::Rg8Sint + | Tf::R32Uint + | Tf::R32Sint + | Tf::R32Float + | Tf::Rg16Uint + | Tf::Rg16Sint + | Tf::Rg16Float + | Tf::Rgba8Unorm + | Tf::Rgba8UnormSrgb + | Tf::Rgba8Snorm + | Tf::Rgba8Uint + | Tf::Rgba8Sint + | Tf::Bgra8Unorm + | Tf::Bgra8UnormSrgb + | Tf::Rgb10a2Unorm + | Tf::Rg11b10Float + | Tf::Rg32Uint + | Tf::Rg32Sint + | Tf::Rg32Float + | Tf::Rgba16Uint + | Tf::Rgba16Sint + | Tf::Rgba16Float + | Tf::Rgba32Uint + | Tf::Rgba32Sint + | Tf::Rgba32Float + | Tf::Depth32Float + | Tf::Depth24Plus + | Tf::Depth24PlusStencil8 => (1, 1), + + Tf::Bc1RgbaUnorm + | Tf::Bc1RgbaUnormSrgb + | Tf::Bc2RgbaUnorm + | Tf::Bc2RgbaUnormSrgb + | Tf::Bc3RgbaUnorm + | Tf::Bc3RgbaUnormSrgb + | Tf::Bc4RUnorm + | Tf::Bc4RSnorm + | Tf::Bc5RgUnorm + | Tf::Bc5RgSnorm + | Tf::Bc6hRgbUfloat + | Tf::Bc6hRgbSfloat + | Tf::Bc7RgbaUnorm + | Tf::Bc7RgbaUnormSrgb => (4, 4), + } +} + +pub fn texture_features(format: wgt::TextureFormat) -> wgt::Features { + use wgt::TextureFormat as Tf; + match format { + Tf::R8Unorm + | Tf::R8Snorm + | Tf::R8Uint + | Tf::R8Sint + | Tf::R16Uint + | Tf::R16Sint + | Tf::R16Float + | Tf::Rg8Unorm + | Tf::Rg8Snorm + | Tf::Rg8Uint + | Tf::Rg8Sint + | Tf::R32Uint + | Tf::R32Sint + | Tf::R32Float + | Tf::Rg16Uint + | Tf::Rg16Sint + | Tf::Rg16Float + | Tf::Rgba8Unorm + | Tf::Rgba8UnormSrgb + | Tf::Rgba8Snorm + | Tf::Rgba8Uint + | Tf::Rgba8Sint + | Tf::Bgra8Unorm + | Tf::Bgra8UnormSrgb + | Tf::Rgb10a2Unorm + | Tf::Rg11b10Float + | Tf::Rg32Uint + | Tf::Rg32Sint + | Tf::Rg32Float + | Tf::Rgba16Uint + | Tf::Rgba16Sint + | Tf::Rgba16Float + | Tf::Rgba32Uint + | Tf::Rgba32Sint + | Tf::Rgba32Float + | Tf::Depth32Float + | Tf::Depth24Plus + | Tf::Depth24PlusStencil8 => wgt::Features::empty(), + + Tf::Bc1RgbaUnorm + | Tf::Bc1RgbaUnormSrgb + | Tf::Bc2RgbaUnorm + | Tf::Bc2RgbaUnormSrgb + | Tf::Bc3RgbaUnorm + | Tf::Bc3RgbaUnormSrgb + | Tf::Bc4RUnorm + | Tf::Bc4RSnorm + | Tf::Bc5RgUnorm + | Tf::Bc5RgSnorm + | Tf::Bc6hRgbUfloat + | Tf::Bc6hRgbSfloat + | Tf::Bc7RgbaUnorm + | Tf::Bc7RgbaUnormSrgb => wgt::Features::TEXTURE_COMPRESSION_BC, + } +} + +pub fn map_vertex_format(vertex_format: wgt::VertexFormat) -> hal::format::Format { + use hal::format::Format as H; + use wgt::VertexFormat as Vf; + match vertex_format { + Vf::Uchar2 => H::Rg8Uint, + Vf::Uchar4 => H::Rgba8Uint, + Vf::Char2 => H::Rg8Sint, + Vf::Char4 => H::Rgba8Sint, + Vf::Uchar2Norm => H::Rg8Unorm, + Vf::Uchar4Norm => H::Rgba8Unorm, + Vf::Char2Norm => H::Rg8Snorm, + Vf::Char4Norm => H::Rgba8Snorm, + Vf::Ushort2 => H::Rg16Uint, + Vf::Ushort4 => H::Rgba16Uint, + Vf::Short2 => H::Rg16Sint, + Vf::Short4 => H::Rgba16Sint, + Vf::Ushort2Norm => H::Rg16Unorm, + Vf::Ushort4Norm => H::Rgba16Unorm, + Vf::Short2Norm => H::Rg16Snorm, + Vf::Short4Norm => H::Rgba16Snorm, + Vf::Half2 => H::Rg16Sfloat, + Vf::Half4 => H::Rgba16Sfloat, + Vf::Float => H::R32Sfloat, + Vf::Float2 => H::Rg32Sfloat, + Vf::Float3 => H::Rgb32Sfloat, + Vf::Float4 => H::Rgba32Sfloat, + Vf::Uint => H::R32Uint, + Vf::Uint2 => H::Rg32Uint, + Vf::Uint3 => H::Rgb32Uint, + Vf::Uint4 => H::Rgba32Uint, + Vf::Int => H::R32Sint, + Vf::Int2 => H::Rg32Sint, + Vf::Int3 => H::Rgb32Sint, + Vf::Int4 => H::Rgba32Sint, + } +} + +pub fn is_power_of_two(val: u32) -> bool { + val != 0 && (val & (val - 1)) == 0 +} + +pub fn is_valid_copy_src_texture_format(format: wgt::TextureFormat) -> bool { + use wgt::TextureFormat as Tf; + match format { + Tf::Depth24Plus | Tf::Depth24PlusStencil8 => false, + _ => true, + } +} + +pub fn is_valid_copy_dst_texture_format(format: wgt::TextureFormat) -> bool { + use wgt::TextureFormat as Tf; + match format { + Tf::Depth32Float | Tf::Depth24Plus | Tf::Depth24PlusStencil8 => false, + _ => true, + } +} + +pub fn map_texture_dimension_size( + dimension: wgt::TextureDimension, + wgt::Extent3d { + width, + height, + depth, + }: wgt::Extent3d, + sample_size: u32, +) -> Result<hal::image::Kind, resource::TextureDimensionError> { + use hal::image::Kind as H; + use resource::TextureDimensionError as Tde; + use wgt::TextureDimension::*; + + let zero_dim = if width == 0 { + Some(resource::TextureErrorDimension::X) + } else if height == 0 { + Some(resource::TextureErrorDimension::Y) + } else if depth == 0 { + Some(resource::TextureErrorDimension::Z) + } else { + None + }; + if let Some(dim) = zero_dim { + return Err(resource::TextureDimensionError::Zero(dim)); + } + + Ok(match dimension { + D1 => { + if height != 1 { + return Err(Tde::InvalidHeight); + } + if sample_size != 1 { + return Err(Tde::InvalidSampleCount(sample_size)); + } + let layers = depth.try_into().unwrap_or(!0); + H::D1(width, layers) + } + D2 => { + if sample_size > 32 || !is_power_of_two(sample_size) { + return Err(Tde::InvalidSampleCount(sample_size)); + } + let layers = depth.try_into().unwrap_or(!0); + H::D2(width, height, layers, sample_size as u8) + } + D3 => { + if sample_size != 1 { + return Err(Tde::InvalidSampleCount(sample_size)); + } + H::D3(width, height, depth) + } + }) +} + +pub fn map_texture_view_dimension(dimension: wgt::TextureViewDimension) -> hal::image::ViewKind { + use hal::image::ViewKind as H; + use wgt::TextureViewDimension::*; + match dimension { + D1 => H::D1, + D2 => H::D2, + D2Array => H::D2Array, + Cube => H::Cube, + CubeArray => H::CubeArray, + D3 => H::D3, + } +} + +pub(crate) fn map_buffer_state(usage: resource::BufferUse) -> hal::buffer::State { + use crate::resource::BufferUse as W; + use hal::buffer::Access as A; + + let mut access = A::empty(); + if usage.contains(W::MAP_READ) { + access |= A::HOST_READ; + } + if usage.contains(W::MAP_WRITE) { + access |= A::HOST_WRITE; + } + if usage.contains(W::COPY_SRC) { + access |= A::TRANSFER_READ; + } + if usage.contains(W::COPY_DST) { + access |= A::TRANSFER_WRITE; + } + if usage.contains(W::INDEX) { + access |= A::INDEX_BUFFER_READ; + } + if usage.contains(W::VERTEX) { + access |= A::VERTEX_BUFFER_READ; + } + if usage.contains(W::UNIFORM) { + access |= A::UNIFORM_READ | A::SHADER_READ; + } + if usage.contains(W::STORAGE_LOAD) { + access |= A::SHADER_READ; + } + if usage.contains(W::STORAGE_STORE) { + access |= A::SHADER_WRITE; + } + if usage.contains(W::INDIRECT) { + access |= A::INDIRECT_COMMAND_READ; + } + + access +} + +pub(crate) fn map_texture_state( + usage: resource::TextureUse, + aspects: hal::format::Aspects, +) -> hal::image::State { + use crate::resource::TextureUse as W; + use hal::image::{Access as A, Layout as L}; + + let is_color = aspects.contains(hal::format::Aspects::COLOR); + let layout = match usage { + W::UNINITIALIZED => return (A::empty(), L::Undefined), + W::COPY_SRC => L::TransferSrcOptimal, + W::COPY_DST => L::TransferDstOptimal, + W::SAMPLED if is_color => L::ShaderReadOnlyOptimal, + W::ATTACHMENT_READ | W::ATTACHMENT_WRITE if is_color => L::ColorAttachmentOptimal, + _ if is_color => L::General, + W::ATTACHMENT_WRITE => L::DepthStencilAttachmentOptimal, + _ => L::DepthStencilReadOnlyOptimal, + }; + + let mut access = A::empty(); + if usage.contains(W::COPY_SRC) { + access |= A::TRANSFER_READ; + } + if usage.contains(W::COPY_DST) { + access |= A::TRANSFER_WRITE; + } + if usage.contains(W::SAMPLED) { + access |= A::SHADER_READ; + } + if usage.contains(W::ATTACHMENT_READ) { + access |= if is_color { + A::COLOR_ATTACHMENT_READ + } else { + A::DEPTH_STENCIL_ATTACHMENT_READ + }; + } + if usage.contains(W::ATTACHMENT_WRITE) { + access |= if is_color { + A::COLOR_ATTACHMENT_WRITE + } else { + A::DEPTH_STENCIL_ATTACHMENT_WRITE + }; + } + if usage.contains(W::STORAGE_LOAD) { + access |= A::SHADER_READ; + } + if usage.contains(W::STORAGE_STORE) { + access |= A::SHADER_WRITE; + } + + (access, layout) +} + +pub fn map_load_store_ops<V>(channel: &PassChannel<V>) -> hal::pass::AttachmentOps { + hal::pass::AttachmentOps { + load: match channel.load_op { + LoadOp::Clear => hal::pass::AttachmentLoadOp::Clear, + LoadOp::Load => hal::pass::AttachmentLoadOp::Load, + }, + store: match channel.store_op { + StoreOp::Clear => hal::pass::AttachmentStoreOp::DontCare, //TODO! + StoreOp::Store => hal::pass::AttachmentStoreOp::Store, + }, + } +} + +pub fn map_color_f32(color: &wgt::Color) -> hal::pso::ColorValue { + [ + color.r as f32, + color.g as f32, + color.b as f32, + color.a as f32, + ] +} +pub fn map_color_i32(color: &wgt::Color) -> [i32; 4] { + [ + color.r as i32, + color.g as i32, + color.b as i32, + color.a as i32, + ] +} +pub fn map_color_u32(color: &wgt::Color) -> [u32; 4] { + [ + color.r as u32, + color.g as u32, + color.b as u32, + color.a as u32, + ] +} + +pub fn map_filter(filter: wgt::FilterMode) -> hal::image::Filter { + match filter { + wgt::FilterMode::Nearest => hal::image::Filter::Nearest, + wgt::FilterMode::Linear => hal::image::Filter::Linear, + } +} + +pub fn map_wrap(address: wgt::AddressMode) -> hal::image::WrapMode { + use hal::image::WrapMode as W; + use wgt::AddressMode as Am; + match address { + Am::ClampToEdge => W::Clamp, + Am::Repeat => W::Tile, + Am::MirrorRepeat => W::Mirror, + Am::ClampToBorder => W::Border, + } +} + +pub fn map_rasterization_state_descriptor( + desc: &wgt::RasterizationStateDescriptor, +) -> hal::pso::Rasterizer { + use hal::pso; + pso::Rasterizer { + depth_clamping: desc.clamp_depth, + polygon_mode: match desc.polygon_mode { + wgt::PolygonMode::Fill => pso::PolygonMode::Fill, + wgt::PolygonMode::Line => pso::PolygonMode::Line, + wgt::PolygonMode::Point => pso::PolygonMode::Point, + }, + cull_face: match desc.cull_mode { + wgt::CullMode::None => pso::Face::empty(), + wgt::CullMode::Front => pso::Face::FRONT, + wgt::CullMode::Back => pso::Face::BACK, + }, + front_face: match desc.front_face { + wgt::FrontFace::Ccw => pso::FrontFace::CounterClockwise, + wgt::FrontFace::Cw => pso::FrontFace::Clockwise, + }, + depth_bias: if desc.depth_bias != 0 + || desc.depth_bias_slope_scale != 0.0 + || desc.depth_bias_clamp != 0.0 + { + Some(pso::State::Static(pso::DepthBias { + const_factor: desc.depth_bias as f32, + slope_factor: desc.depth_bias_slope_scale, + clamp: desc.depth_bias_clamp, + })) + } else { + None + }, + conservative: false, + line_width: pso::State::Static(1.0), + } +} + +pub fn map_index_format(index_format: wgt::IndexFormat) -> hal::IndexType { + match index_format { + wgt::IndexFormat::Uint16 => hal::IndexType::U16, + wgt::IndexFormat::Uint32 => hal::IndexType::U32, + } +} |