summaryrefslogtreecommitdiffstats
path: root/gfx/wgpu/wgpu-core/src/conv.rs
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/wgpu/wgpu-core/src/conv.rs')
-rw-r--r--gfx/wgpu/wgpu-core/src/conv.rs833
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,
+ }
+}