898: Update naga with improved SPIR-V parsing and reflection r=cwfitzgerald a=kvark

**Connections**
Fixes #892
Fixes #899
Includes https://github.com/gfx-rs/naga/pull/153 and the awesome https://github.com/gfx-rs/naga/pull/122
Also includes https://github.com/gfx-rs/naga/pull/157 now.

**Description**
This PR updates naga and our validation code.
~~We can successfully validate only `hello-triangle` and `cube` examples, still.~~
We mostly pass the validation of the examples now!
Meta-issue filed in https://github.com/gfx-rs/naga/issues/155 to unlock the rest.

**Testing**
Tested on examples in https://github.com/gfx-rs/wgpu-rs/pull/537

Co-authored-by: Dzmitry Malyshau <kvarkus@gmail.com>
This commit is contained in:
bors[bot] 2020-08-27 21:06:27 +00:00 committed by GitHub
commit 4de1d24bc6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 217 additions and 132 deletions

39
Cargo.lock generated
View File

@ -338,6 +338,12 @@ dependencies = [
"termcolor", "termcolor",
] ]
[[package]]
name = "fixedbitset"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
[[package]] [[package]]
name = "float-cmp" name = "float-cmp"
version = "0.7.0" version = "0.7.0"
@ -542,6 +548,15 @@ dependencies = [
"slab", "slab",
] ]
[[package]]
name = "hashbrown"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.1.13" version = "0.1.13"
@ -569,6 +584,16 @@ dependencies = [
"quick-error", "quick-error",
] ]
[[package]]
name = "indexmap"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b45e59b16c76b11bf9738fd5d38879d3bd28ad292d7b313608becb17ae2df9"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]] [[package]]
name = "inplace_it" name = "inplace_it"
version = "0.3.2" version = "0.3.2"
@ -805,13 +830,13 @@ dependencies = [
[[package]] [[package]]
name = "naga" name = "naga"
version = "0.2.0" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "git+https://github.com/gfx-rs/naga?rev=bd9efe5915e548b9a2ec1f3d3e9296c90b31e69a#bd9efe5915e548b9a2ec1f3d3e9296c90b31e69a"
checksum = "0873deb76cf44b7454fba7b2ba6a89d3de70c08aceffd2c489379b3d9d08e661"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"fxhash", "fxhash",
"log", "log",
"num-traits", "num-traits",
"petgraph",
"spirv_headers", "spirv_headers",
"thiserror", "thiserror",
] ]
@ -1002,6 +1027,16 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "petgraph"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7"
dependencies = [
"fixedbitset",
"indexmap",
]
[[package]] [[package]]
name = "pkg-config" name = "pkg-config"
version = "0.3.17" version = "0.3.17"

View File

@ -39,9 +39,9 @@ gfx-memory = "0.2"
[dependencies.naga] [dependencies.naga]
version = "0.2" version = "0.2"
#git = "https://github.com/gfx-rs/naga" git = "https://github.com/gfx-rs/naga"
#rev = "1eb637038dd15fc1dad770eca8e6943424dbc122" rev = "bd9efe5915e548b9a2ec1f3d3e9296c90b31e69a"
features = ["spirv"] features = ["spirv-in", "spirv-out"]
[dependencies.wgt] [dependencies.wgt]
path = "../wgpu-types" path = "../wgpu-types"

View File

@ -65,16 +65,22 @@ pub enum BindingError {
dim: naga::ImageDimension, dim: naga::ImageDimension,
is_array: bool, is_array: bool,
}, },
#[error("component type {0:?} of a sampled texture doesn't match the shader")] #[error("component type {binding:?} of a sampled texture doesn't match the shader {shader:?}")]
WrongTextureComponentType(Option<naga::ScalarKind>), WrongTextureComponentType {
#[error("texture sampling capability doesn't match the shader")] binding: naga::ScalarKind,
WrongTextureSampled, shader: naga::ScalarKind,
#[error("multisampled flag doesn't match the shader")] },
WrongTextureMultisampled, #[error("texture class {binding:?} doesn't match the shader {shader:?}")]
WrongTextureClass {
binding: naga::ImageClass,
shader: naga::ImageClass,
},
#[error("comparison flag doesn't match the shader")] #[error("comparison flag doesn't match the shader")]
WrongSamplerComparison, WrongSamplerComparison,
#[error("derived bind group layout type is not consistent between stages")] #[error("derived bind group layout type is not consistent between stages")]
InconsistentlyDerivedType, InconsistentlyDerivedType,
#[error("texture format {0:?} isn't recognized")]
UnknownStorageFormat(wgt::TextureFormat),
} }
#[derive(Clone, Debug, Error)] #[derive(Clone, Debug, Error)]
@ -151,6 +157,7 @@ fn get_aligned_type_size(
}, },
Ti::Struct { ref members } => members.last().map_or(0, |member| { Ti::Struct { ref members } => members.last().map_or(0, |member| {
let offset = match member.origin { let offset = match member.origin {
naga::MemberOrigin::Empty => 0,
naga::MemberOrigin::BuiltIn(_) => { naga::MemberOrigin::BuiltIn(_) => {
tracing::error!("Missing offset on a struct member"); tracing::error!("Missing offset on a struct member");
0 // TODO: make it a proper error 0 // TODO: make it a proper error
@ -204,22 +211,19 @@ fn check_binding_use(
naga::TypeInner::Sampler { comparison } => match entry.ty { naga::TypeInner::Sampler { comparison } => match entry.ty {
BindingType::Sampler { comparison: cmp } => { BindingType::Sampler { comparison: cmp } => {
if cmp == comparison { if cmp == comparison {
Ok(naga::GlobalUse::empty()) Ok(naga::GlobalUse::LOAD)
} else { } else {
Err(BindingError::WrongSamplerComparison) Err(BindingError::WrongSamplerComparison)
} }
} }
_ => Err(BindingError::WrongType), _ => Err(BindingError::WrongType),
}, },
naga::TypeInner::Image { base, dim, flags } => { naga::TypeInner::Image {
if flags.contains(naga::ImageFlags::MULTISAMPLED) { kind,
match entry.ty { dim,
BindingType::SampledTexture { arrayed,
multisampled: true, .. class,
} => {} } => {
_ => return Err(BindingError::WrongTextureMultisampled),
}
}
let view_dimension = match entry.ty { let view_dimension = match entry.ty {
BindingType::SampledTexture { dimension, .. } BindingType::SampledTexture { dimension, .. }
| BindingType::StorageTexture { dimension, .. } => dimension, | BindingType::StorageTexture { dimension, .. } => dimension,
@ -230,7 +234,7 @@ fn check_binding_use(
}) })
} }
}; };
if flags.contains(naga::ImageFlags::ARRAYED) { if arrayed {
match (dim, view_dimension) { match (dim, view_dimension) {
(naga::ImageDimension::D2, wgt::TextureViewDimension::D2Array) => (), (naga::ImageDimension::D2, wgt::TextureViewDimension::D2Array) => (),
(naga::ImageDimension::Cube, wgt::TextureViewDimension::CubeArray) => (), (naga::ImageDimension::Cube, wgt::TextureViewDimension::CubeArray) => (),
@ -255,39 +259,66 @@ fn check_binding_use(
} }
} }
} }
let (allowed_usage, is_sampled) = match entry.ty { let expected_class = match entry.ty {
BindingType::SampledTexture { component_type, .. } => { BindingType::SampledTexture {
let expected_scalar_kind = match component_type { dimension: _,
wgt::TextureComponentType::Float => naga::ScalarKind::Float, component_type,
wgt::TextureComponentType::Sint => naga::ScalarKind::Sint, multisampled,
wgt::TextureComponentType::Uint => naga::ScalarKind::Uint, } => {
}; let (expected_scalar_kind, comparison) = match component_type {
match module.types[base].inner { wgt::TextureComponentType::Float => (naga::ScalarKind::Float, false),
naga::TypeInner::Scalar { kind, .. } wgt::TextureComponentType::Sint => (naga::ScalarKind::Sint, false),
| naga::TypeInner::Vector { kind, .. } wgt::TextureComponentType::Uint => (naga::ScalarKind::Uint, false),
if kind == expected_scalar_kind => {} wgt::TextureComponentType::DepthComparison => {
naga::TypeInner::Scalar { kind, .. } (naga::ScalarKind::Float, true)
| naga::TypeInner::Vector { kind, .. } => {
return Err(BindingError::WrongTextureComponentType(Some(kind)))
} }
_ => return Err(BindingError::WrongTextureComponentType(None)),
}; };
(naga::GlobalUse::LOAD, true) if kind != expected_scalar_kind {
} return Err(BindingError::WrongTextureComponentType {
BindingType::StorageTexture { readonly, .. } => { binding: expected_scalar_kind,
if readonly { shader: kind,
//TODO: check entry.storage_texture_format });
(naga::GlobalUse::LOAD, false)
} else {
(naga::GlobalUse::STORE, false)
} }
if multisampled {
naga::ImageClass::Multisampled
} else if comparison {
naga::ImageClass::Depth
} else {
naga::ImageClass::Sampled
}
}
BindingType::StorageTexture {
readonly,
format,
dimension: _,
} => {
let naga_format = match format {
wgt::TextureFormat::Rgba32Float => naga::StorageFormat::Rgba32f,
_ => return Err(BindingError::UnknownStorageFormat(format)),
};
let access = if readonly {
naga::StorageAccess::LOAD
} else {
naga::StorageAccess::STORE
};
naga::ImageClass::Storage(naga_format, access)
} }
_ => return Err(BindingError::WrongType), _ => return Err(BindingError::WrongType),
}; };
if is_sampled != flags.contains(naga::ImageFlags::SAMPLED) { if class != expected_class {
return Err(BindingError::WrongTextureSampled); return Err(BindingError::WrongTextureClass {
binding: expected_class,
shader: class,
});
} }
Ok(allowed_usage) Ok(match class {
naga::ImageClass::Storage(_, access)
if access.contains(naga::StorageAccess::STORE) =>
{
naga::GlobalUse::STORE
}
_ => naga::GlobalUse::LOAD,
})
} }
_ => Err(BindingError::WrongType), _ => Err(BindingError::WrongType),
} }
@ -367,133 +398,137 @@ impl<'a, T> std::ops::Deref for MaybeOwned<'a, T> {
pub fn map_vertex_format(format: wgt::VertexFormat) -> naga::TypeInner { pub fn map_vertex_format(format: wgt::VertexFormat) -> naga::TypeInner {
use naga::TypeInner as Ti; use naga::TypeInner as Ti;
use wgt::VertexFormat as Vf; use wgt::VertexFormat as Vf;
//Note: Shader always sees data as int, uint, or float.
// It doesn't know if the original is normalized in a tighter form.
let width = 4;
match format { match format {
Vf::Uchar2 => Ti::Vector { Vf::Uchar2 => Ti::Vector {
size: naga::VectorSize::Bi, size: naga::VectorSize::Bi,
kind: naga::ScalarKind::Uint, kind: naga::ScalarKind::Uint,
width: 1, width,
}, },
Vf::Uchar4 => Ti::Vector { Vf::Uchar4 => Ti::Vector {
size: naga::VectorSize::Quad, size: naga::VectorSize::Quad,
kind: naga::ScalarKind::Uint, kind: naga::ScalarKind::Uint,
width: 1, width,
}, },
Vf::Char2 => Ti::Vector { Vf::Char2 => Ti::Vector {
size: naga::VectorSize::Bi, size: naga::VectorSize::Bi,
kind: naga::ScalarKind::Sint, kind: naga::ScalarKind::Sint,
width: 1, width,
}, },
Vf::Char4 => Ti::Vector { Vf::Char4 => Ti::Vector {
size: naga::VectorSize::Quad, size: naga::VectorSize::Quad,
kind: naga::ScalarKind::Sint, kind: naga::ScalarKind::Sint,
width: 1, width,
}, },
Vf::Uchar2Norm => Ti::Vector { Vf::Uchar2Norm => Ti::Vector {
size: naga::VectorSize::Bi, size: naga::VectorSize::Bi,
kind: naga::ScalarKind::Float, kind: naga::ScalarKind::Float,
width: 1, width,
}, },
Vf::Uchar4Norm => Ti::Vector { Vf::Uchar4Norm => Ti::Vector {
size: naga::VectorSize::Quad, size: naga::VectorSize::Quad,
kind: naga::ScalarKind::Float, kind: naga::ScalarKind::Float,
width: 1, width,
}, },
Vf::Char2Norm => Ti::Vector { Vf::Char2Norm => Ti::Vector {
size: naga::VectorSize::Bi, size: naga::VectorSize::Bi,
kind: naga::ScalarKind::Float, kind: naga::ScalarKind::Float,
width: 1, width,
}, },
Vf::Char4Norm => Ti::Vector { Vf::Char4Norm => Ti::Vector {
size: naga::VectorSize::Quad, size: naga::VectorSize::Quad,
kind: naga::ScalarKind::Float, kind: naga::ScalarKind::Float,
width: 1, width,
}, },
Vf::Ushort2 => Ti::Vector { Vf::Ushort2 => Ti::Vector {
size: naga::VectorSize::Bi, size: naga::VectorSize::Bi,
kind: naga::ScalarKind::Uint, kind: naga::ScalarKind::Uint,
width: 2, width,
}, },
Vf::Ushort4 => Ti::Vector { Vf::Ushort4 => Ti::Vector {
size: naga::VectorSize::Quad, size: naga::VectorSize::Quad,
kind: naga::ScalarKind::Uint, kind: naga::ScalarKind::Uint,
width: 2, width,
}, },
Vf::Short2 => Ti::Vector { Vf::Short2 => Ti::Vector {
size: naga::VectorSize::Bi, size: naga::VectorSize::Bi,
kind: naga::ScalarKind::Sint, kind: naga::ScalarKind::Sint,
width: 2, width,
}, },
Vf::Short4 => Ti::Vector { Vf::Short4 => Ti::Vector {
size: naga::VectorSize::Quad, size: naga::VectorSize::Quad,
kind: naga::ScalarKind::Sint, kind: naga::ScalarKind::Sint,
width: 2, width,
}, },
Vf::Ushort2Norm | Vf::Short2Norm | Vf::Half2 => Ti::Vector { Vf::Ushort2Norm | Vf::Short2Norm | Vf::Half2 => Ti::Vector {
size: naga::VectorSize::Bi, size: naga::VectorSize::Bi,
kind: naga::ScalarKind::Float, kind: naga::ScalarKind::Float,
width: 2, width,
}, },
Vf::Ushort4Norm | Vf::Short4Norm | Vf::Half4 => Ti::Vector { Vf::Ushort4Norm | Vf::Short4Norm | Vf::Half4 => Ti::Vector {
size: naga::VectorSize::Quad, size: naga::VectorSize::Quad,
kind: naga::ScalarKind::Float, kind: naga::ScalarKind::Float,
width: 2, width,
}, },
Vf::Float => Ti::Scalar { Vf::Float => Ti::Scalar {
kind: naga::ScalarKind::Float, kind: naga::ScalarKind::Float,
width: 4, width,
}, },
Vf::Float2 => Ti::Vector { Vf::Float2 => Ti::Vector {
size: naga::VectorSize::Bi, size: naga::VectorSize::Bi,
kind: naga::ScalarKind::Float, kind: naga::ScalarKind::Float,
width: 4, width,
}, },
Vf::Float3 => Ti::Vector { Vf::Float3 => Ti::Vector {
size: naga::VectorSize::Tri, size: naga::VectorSize::Tri,
kind: naga::ScalarKind::Float, kind: naga::ScalarKind::Float,
width: 4, width,
}, },
Vf::Float4 => Ti::Vector { Vf::Float4 => Ti::Vector {
size: naga::VectorSize::Quad, size: naga::VectorSize::Quad,
kind: naga::ScalarKind::Float, kind: naga::ScalarKind::Float,
width: 4, width,
}, },
Vf::Uint => Ti::Scalar { Vf::Uint => Ti::Scalar {
kind: naga::ScalarKind::Uint, kind: naga::ScalarKind::Uint,
width: 4, width,
}, },
Vf::Uint2 => Ti::Vector { Vf::Uint2 => Ti::Vector {
size: naga::VectorSize::Bi, size: naga::VectorSize::Bi,
kind: naga::ScalarKind::Uint, kind: naga::ScalarKind::Uint,
width: 4, width,
}, },
Vf::Uint3 => Ti::Vector { Vf::Uint3 => Ti::Vector {
size: naga::VectorSize::Tri, size: naga::VectorSize::Tri,
kind: naga::ScalarKind::Uint, kind: naga::ScalarKind::Uint,
width: 4, width,
}, },
Vf::Uint4 => Ti::Vector { Vf::Uint4 => Ti::Vector {
size: naga::VectorSize::Quad, size: naga::VectorSize::Quad,
kind: naga::ScalarKind::Uint, kind: naga::ScalarKind::Uint,
width: 4, width,
}, },
Vf::Int => Ti::Scalar { Vf::Int => Ti::Scalar {
kind: naga::ScalarKind::Sint, kind: naga::ScalarKind::Sint,
width: 4, width,
}, },
Vf::Int2 => Ti::Vector { Vf::Int2 => Ti::Vector {
size: naga::VectorSize::Bi, size: naga::VectorSize::Bi,
kind: naga::ScalarKind::Sint, kind: naga::ScalarKind::Sint,
width: 4, width,
}, },
Vf::Int3 => Ti::Vector { Vf::Int3 => Ti::Vector {
size: naga::VectorSize::Tri, size: naga::VectorSize::Tri,
kind: naga::ScalarKind::Sint, kind: naga::ScalarKind::Sint,
width: 4, width,
}, },
Vf::Int4 => Ti::Vector { Vf::Int4 => Ti::Vector {
size: naga::VectorSize::Quad, size: naga::VectorSize::Quad,
kind: naga::ScalarKind::Sint, kind: naga::ScalarKind::Sint,
width: 4, width,
}, },
} }
} }
@ -502,72 +537,75 @@ fn map_texture_format(format: wgt::TextureFormat) -> naga::TypeInner {
use naga::{ScalarKind as Sk, TypeInner as Ti, VectorSize as Vs}; use naga::{ScalarKind as Sk, TypeInner as Ti, VectorSize as Vs};
use wgt::TextureFormat as Tf; use wgt::TextureFormat as Tf;
//Note: Shader always sees data as int, uint, or float.
// It doesn't know if the original is normalized in a tighter form.
let width = 4;
match format { match format {
Tf::R8Unorm | Tf::R8Snorm => Ti::Scalar { Tf::R8Unorm | Tf::R8Snorm => Ti::Scalar {
kind: Sk::Float, kind: Sk::Float,
width: 1, width,
}, },
Tf::R8Uint => Ti::Scalar { Tf::R8Uint => Ti::Scalar {
kind: Sk::Uint, kind: Sk::Uint,
width: 1, width,
}, },
Tf::R8Sint => Ti::Scalar { Tf::R8Sint => Ti::Scalar {
kind: Sk::Sint, kind: Sk::Sint,
width: 1, width,
}, },
Tf::R16Uint => Ti::Scalar { Tf::R16Uint => Ti::Scalar {
kind: Sk::Uint, kind: Sk::Uint,
width: 2, width,
}, },
Tf::R16Sint => Ti::Scalar { Tf::R16Sint => Ti::Scalar {
kind: Sk::Sint, kind: Sk::Sint,
width: 2, width,
}, },
Tf::R16Float => Ti::Scalar { Tf::R16Float => Ti::Scalar {
kind: Sk::Float, kind: Sk::Float,
width: 2, width,
}, },
Tf::Rg8Unorm | Tf::Rg8Snorm => Ti::Vector { Tf::Rg8Unorm | Tf::Rg8Snorm => Ti::Vector {
size: Vs::Bi, size: Vs::Bi,
kind: Sk::Float, kind: Sk::Float,
width: 1, width,
}, },
Tf::Rg8Uint => Ti::Vector { Tf::Rg8Uint => Ti::Vector {
size: Vs::Bi, size: Vs::Bi,
kind: Sk::Uint, kind: Sk::Uint,
width: 1, width,
}, },
Tf::Rg8Sint => Ti::Vector { Tf::Rg8Sint => Ti::Vector {
size: Vs::Bi, size: Vs::Bi,
kind: Sk::Sint, kind: Sk::Sint,
width: 1, width,
}, },
Tf::R32Uint => Ti::Scalar { Tf::R32Uint => Ti::Scalar {
kind: Sk::Uint, kind: Sk::Uint,
width: 4, width,
}, },
Tf::R32Sint => Ti::Scalar { Tf::R32Sint => Ti::Scalar {
kind: Sk::Sint, kind: Sk::Sint,
width: 4, width,
}, },
Tf::R32Float => Ti::Scalar { Tf::R32Float => Ti::Scalar {
kind: Sk::Float, kind: Sk::Float,
width: 4, width,
}, },
Tf::Rg16Uint => Ti::Vector { Tf::Rg16Uint => Ti::Vector {
size: Vs::Bi, size: Vs::Bi,
kind: Sk::Uint, kind: Sk::Uint,
width: 2, width,
}, },
Tf::Rg16Sint => Ti::Vector { Tf::Rg16Sint => Ti::Vector {
size: Vs::Bi, size: Vs::Bi,
kind: Sk::Sint, kind: Sk::Sint,
width: 2, width,
}, },
Tf::Rg16Float => Ti::Vector { Tf::Rg16Float => Ti::Vector {
size: Vs::Bi, size: Vs::Bi,
kind: Sk::Float, kind: Sk::Float,
width: 2, width,
}, },
Tf::Rgba8Unorm Tf::Rgba8Unorm
| Tf::Rgba8UnormSrgb | Tf::Rgba8UnormSrgb
@ -576,72 +614,72 @@ fn map_texture_format(format: wgt::TextureFormat) -> naga::TypeInner {
| Tf::Bgra8UnormSrgb => Ti::Vector { | Tf::Bgra8UnormSrgb => Ti::Vector {
size: Vs::Quad, size: Vs::Quad,
kind: Sk::Float, kind: Sk::Float,
width: 1, width,
}, },
Tf::Rgba8Uint => Ti::Vector { Tf::Rgba8Uint => Ti::Vector {
size: Vs::Quad, size: Vs::Quad,
kind: Sk::Uint, kind: Sk::Uint,
width: 1, width,
}, },
Tf::Rgba8Sint => Ti::Vector { Tf::Rgba8Sint => Ti::Vector {
size: Vs::Quad, size: Vs::Quad,
kind: Sk::Sint, kind: Sk::Sint,
width: 1, width,
}, },
Tf::Rgb10a2Unorm => Ti::Vector { Tf::Rgb10a2Unorm => Ti::Vector {
size: Vs::Quad, size: Vs::Quad,
kind: Sk::Float, kind: Sk::Float,
width: 1, width,
}, },
Tf::Rg11b10Float => Ti::Vector { Tf::Rg11b10Float => Ti::Vector {
size: Vs::Tri, size: Vs::Tri,
kind: Sk::Float, kind: Sk::Float,
width: 1, width,
}, },
Tf::Rg32Uint => Ti::Vector { Tf::Rg32Uint => Ti::Vector {
size: Vs::Bi, size: Vs::Bi,
kind: Sk::Uint, kind: Sk::Uint,
width: 4, width,
}, },
Tf::Rg32Sint => Ti::Vector { Tf::Rg32Sint => Ti::Vector {
size: Vs::Bi, size: Vs::Bi,
kind: Sk::Sint, kind: Sk::Sint,
width: 4, width,
}, },
Tf::Rg32Float => Ti::Vector { Tf::Rg32Float => Ti::Vector {
size: Vs::Bi, size: Vs::Bi,
kind: Sk::Float, kind: Sk::Float,
width: 4, width,
}, },
Tf::Rgba16Uint => Ti::Vector { Tf::Rgba16Uint => Ti::Vector {
size: Vs::Quad, size: Vs::Quad,
kind: Sk::Uint, kind: Sk::Uint,
width: 2, width,
}, },
Tf::Rgba16Sint => Ti::Vector { Tf::Rgba16Sint => Ti::Vector {
size: Vs::Quad, size: Vs::Quad,
kind: Sk::Sint, kind: Sk::Sint,
width: 2, width,
}, },
Tf::Rgba16Float => Ti::Vector { Tf::Rgba16Float => Ti::Vector {
size: Vs::Quad, size: Vs::Quad,
kind: Sk::Float, kind: Sk::Float,
width: 2, width,
}, },
Tf::Rgba32Uint => Ti::Vector { Tf::Rgba32Uint => Ti::Vector {
size: Vs::Quad, size: Vs::Quad,
kind: Sk::Uint, kind: Sk::Uint,
width: 4, width,
}, },
Tf::Rgba32Sint => Ti::Vector { Tf::Rgba32Sint => Ti::Vector {
size: Vs::Quad, size: Vs::Quad,
kind: Sk::Sint, kind: Sk::Sint,
width: 4, width,
}, },
Tf::Rgba32Float => Ti::Vector { Tf::Rgba32Float => Ti::Vector {
size: Vs::Quad, size: Vs::Quad,
kind: Sk::Float, kind: Sk::Float,
width: 4, width,
}, },
Tf::Depth32Float | Tf::Depth24Plus | Tf::Depth24PlusStencil8 => { Tf::Depth32Float | Tf::Depth24Plus | Tf::Depth24PlusStencil8 => {
panic!("Unexpected depth format") panic!("Unexpected depth format")
@ -656,21 +694,21 @@ fn map_texture_format(format: wgt::TextureFormat) -> naga::TypeInner {
| Tf::Bc7RgbaUnormSrgb => Ti::Vector { | Tf::Bc7RgbaUnormSrgb => Ti::Vector {
size: Vs::Quad, size: Vs::Quad,
kind: Sk::Float, kind: Sk::Float,
width: 1, width,
}, },
Tf::Bc4RUnorm | Tf::Bc4RSnorm => Ti::Scalar { Tf::Bc4RUnorm | Tf::Bc4RSnorm => Ti::Scalar {
kind: Sk::Float, kind: Sk::Float,
width: 1, width,
}, },
Tf::Bc5RgUnorm | Tf::Bc5RgSnorm => Ti::Vector { Tf::Bc5RgUnorm | Tf::Bc5RgSnorm => Ti::Vector {
size: Vs::Bi, size: Vs::Bi,
kind: Sk::Float, kind: Sk::Float,
width: 1, width,
}, },
Tf::Bc6hRgbUfloat | Tf::Bc6hRgbSfloat => Ti::Vector { Tf::Bc6hRgbUfloat | Tf::Bc6hRgbSfloat => Ti::Vector {
size: Vs::Tri, size: Vs::Tri,
kind: Sk::Float, kind: Sk::Float,
width: 1, width,
}, },
} }
} }
@ -715,39 +753,49 @@ fn derive_binding_type(
} }
} }
naga::TypeInner::Sampler { comparison } => BindingType::Sampler { comparison }, naga::TypeInner::Sampler { comparison } => BindingType::Sampler { comparison },
naga::TypeInner::Image { base, dim, flags } => { naga::TypeInner::Image {
let array = flags.contains(naga::ImageFlags::ARRAYED); kind,
dim,
arrayed,
class,
} => {
let dimension = match dim { let dimension = match dim {
naga::ImageDimension::D1 => wgt::TextureViewDimension::D1, naga::ImageDimension::D1 => wgt::TextureViewDimension::D1,
naga::ImageDimension::D2 if array => wgt::TextureViewDimension::D2Array, naga::ImageDimension::D2 if arrayed => wgt::TextureViewDimension::D2Array,
naga::ImageDimension::D2 => wgt::TextureViewDimension::D2, naga::ImageDimension::D2 => wgt::TextureViewDimension::D2,
naga::ImageDimension::D3 => wgt::TextureViewDimension::D3, naga::ImageDimension::D3 => wgt::TextureViewDimension::D3,
naga::ImageDimension::Cube if array => wgt::TextureViewDimension::CubeArray, naga::ImageDimension::Cube if arrayed => wgt::TextureViewDimension::CubeArray,
naga::ImageDimension::Cube => wgt::TextureViewDimension::Cube, naga::ImageDimension::Cube => wgt::TextureViewDimension::Cube,
}; };
if flags.contains(naga::ImageFlags::SAMPLED) { let component_type = match kind {
BindingType::SampledTexture { naga::ScalarKind::Float => wgt::TextureComponentType::Float,
naga::ScalarKind::Sint => wgt::TextureComponentType::Sint,
naga::ScalarKind::Uint => wgt::TextureComponentType::Uint,
naga::ScalarKind::Bool => unreachable!(),
};
match class {
naga::ImageClass::Sampled => BindingType::SampledTexture {
dimension, dimension,
component_type: match module.types[base].inner { component_type,
naga::TypeInner::Scalar { kind, .. } multisampled: false,
| naga::TypeInner::Vector { kind, .. } => match kind { },
naga::ScalarKind::Float => wgt::TextureComponentType::Float, naga::ImageClass::Multisampled => BindingType::SampledTexture {
naga::ScalarKind::Sint => wgt::TextureComponentType::Sint, dimension,
naga::ScalarKind::Uint => wgt::TextureComponentType::Uint, component_type,
other => { multisampled: true,
return Err(BindingError::WrongTextureComponentType(Some(other))) },
} naga::ImageClass::Depth => BindingType::SampledTexture {
}, dimension,
_ => return Err(BindingError::WrongTextureComponentType(None)), component_type: wgt::TextureComponentType::DepthComparison,
multisampled: false,
},
naga::ImageClass::Storage(format, access) => BindingType::StorageTexture {
dimension,
format: match format {
naga::StorageFormat::Rgba32f => wgt::TextureFormat::Rgba32Float,
}, },
multisampled: flags.contains(naga::ImageFlags::MULTISAMPLED), readonly: !access.contains(naga::StorageAccess::STORE),
} },
} else {
BindingType::StorageTexture {
dimension,
format: wgt::TextureFormat::Rgba8Unorm, //TODO
readonly: !flags.contains(naga::ImageFlags::CAN_STORE),
}
} }
} }
_ => return Err(BindingError::WrongType), _ => return Err(BindingError::WrongType),

View File

@ -1591,6 +1591,8 @@ pub enum TextureComponentType {
Sint, Sint,
/// They see it as a unsigned integer `utexture1D`, `utexture2D` etc /// They see it as a unsigned integer `utexture1D`, `utexture2D` etc
Uint, Uint,
/// They see it as a floating point 0-1 result of comparison, i.e. `shadowTexture2D`
DepthComparison,
} }
impl From<TextureFormat> for TextureComponentType { impl From<TextureFormat> for TextureComponentType {