mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
[naga] remove span and validate features (#4706)
This commit is contained in:
@@ -57,6 +57,7 @@ Passing an owned value `window` to `Surface` will return a `Surface<'static>`. S
|
|||||||
|
|
||||||
#### Naga
|
#### Naga
|
||||||
|
|
||||||
|
- Remove `span` and `validate` features. Always fully validate shader modules, and always track source positions for use in error messages. By @teoxoy in [#4706](https://github.com/gfx-rs/wgpu/pull/4706)
|
||||||
- Introduce a new `Scalar` struct type for use in Naga's IR, and update all frontend, middle, and backend code appropriately. By @jimblandy in [#4673](https://github.com/gfx-rs/wgpu/pull/4673).
|
- Introduce a new `Scalar` struct type for use in Naga's IR, and update all frontend, middle, and backend code appropriately. By @jimblandy in [#4673](https://github.com/gfx-rs/wgpu/pull/4673).
|
||||||
- Add more metal keywords. By @fornwall in [#4707](https://github.com/gfx-rs/wgpu/pull/4707).
|
- Add more metal keywords. By @fornwall in [#4707](https://github.com/gfx-rs/wgpu/pull/4707).
|
||||||
|
|
||||||
|
|||||||
@@ -19,9 +19,7 @@ argh = "0.1.5"
|
|||||||
version = "0.14"
|
version = "0.14"
|
||||||
path = "../naga"
|
path = "../naga"
|
||||||
features = [
|
features = [
|
||||||
"validate",
|
|
||||||
"compact",
|
"compact",
|
||||||
"span",
|
|
||||||
"wgsl-in",
|
"wgsl-in",
|
||||||
"wgsl-out",
|
"wgsl-out",
|
||||||
"glsl-in",
|
"glsl-in",
|
||||||
|
|||||||
@@ -26,11 +26,9 @@ deserialize = ["serde", "bitflags/serde", "indexmap/serde"]
|
|||||||
arbitrary = ["dep:arbitrary", "bitflags/arbitrary", "indexmap/arbitrary"]
|
arbitrary = ["dep:arbitrary", "bitflags/arbitrary", "indexmap/arbitrary"]
|
||||||
spv-in = ["petgraph", "spirv"]
|
spv-in = ["petgraph", "spirv"]
|
||||||
spv-out = ["spirv"]
|
spv-out = ["spirv"]
|
||||||
wgsl-in = ["codespan-reporting", "hexf-parse", "termcolor", "unicode-xid"]
|
wgsl-in = ["hexf-parse", "unicode-xid"]
|
||||||
wgsl-out = []
|
wgsl-out = []
|
||||||
hlsl-out = []
|
hlsl-out = []
|
||||||
span = ["codespan-reporting", "termcolor"]
|
|
||||||
validate = []
|
|
||||||
compact = []
|
compact = []
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
@@ -41,11 +39,11 @@ harness = false
|
|||||||
arbitrary = { version = "1.3", features = ["derive"], optional = true }
|
arbitrary = { version = "1.3", features = ["derive"], optional = true }
|
||||||
bitflags = "2.2"
|
bitflags = "2.2"
|
||||||
bit-set = "0.5"
|
bit-set = "0.5"
|
||||||
termcolor = { version = "1.4.0", optional = true }
|
termcolor = { version = "1.4.0" }
|
||||||
# remove termcolor dep when updating to the next version of codespan-reporting
|
# remove termcolor dep when updating to the next version of codespan-reporting
|
||||||
# termcolor minimum version was wrong and was fixed in
|
# termcolor minimum version was wrong and was fixed in
|
||||||
# https://github.com/brendanzab/codespan/commit/e99c867339a877731437e7ee6a903a3d03b5439e
|
# https://github.com/brendanzab/codespan/commit/e99c867339a877731437e7ee6a903a3d03b5439e
|
||||||
codespan-reporting = { version = "0.11.0", optional = true }
|
codespan-reporting = { version = "0.11.0" }
|
||||||
rustc-hash = "1.1.0"
|
rustc-hash = "1.1.0"
|
||||||
indexmap = { version = "2", features = ["std"] }
|
indexmap = { version = "2", features = ["std"] }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|||||||
@@ -119,7 +119,6 @@ fn gather_modules() -> Vec<naga::Module> {
|
|||||||
fn validation(c: &mut Criterion) {
|
fn validation(c: &mut Criterion) {
|
||||||
let inputs = gather_modules();
|
let inputs = gather_modules();
|
||||||
let mut group = c.benchmark_group("valid");
|
let mut group = c.benchmark_group("valid");
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
group.bench_function("safe", |b| {
|
group.bench_function("safe", |b| {
|
||||||
let mut validator = naga::valid::Validator::new(
|
let mut validator = naga::valid::Validator::new(
|
||||||
naga::valid::ValidationFlags::all(),
|
naga::valid::ValidationFlags::all(),
|
||||||
@@ -131,7 +130,6 @@ fn validation(c: &mut Criterion) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
group.bench_function("unsafe", |b| {
|
group.bench_function("unsafe", |b| {
|
||||||
let mut validator = naga::valid::Validator::new(
|
let mut validator = naga::valid::Validator::new(
|
||||||
naga::valid::ValidationFlags::empty(),
|
naga::valid::ValidationFlags::empty(),
|
||||||
@@ -146,7 +144,6 @@ fn validation(c: &mut Criterion) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn backends(c: &mut Criterion) {
|
fn backends(c: &mut Criterion) {
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
let inputs = {
|
let inputs = {
|
||||||
let mut validator = naga::valid::Validator::new(
|
let mut validator = naga::valid::Validator::new(
|
||||||
naga::valid::ValidationFlags::empty(),
|
naga::valid::ValidationFlags::empty(),
|
||||||
@@ -158,8 +155,6 @@ fn backends(c: &mut Criterion) {
|
|||||||
.flat_map(|module| validator.validate(&module).ok().map(|info| (module, info)))
|
.flat_map(|module| validator.validate(&module).ok().map(|info| (module, info)))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
};
|
};
|
||||||
#[cfg(not(feature = "validate"))]
|
|
||||||
let inputs = Vec::<(naga::Module, naga::valid::ModuleInfo)>::new();
|
|
||||||
|
|
||||||
let mut group = c.benchmark_group("back");
|
let mut group = c.benchmark_group("back");
|
||||||
#[cfg(feature = "wgsl-out")]
|
#[cfg(feature = "wgsl-out")]
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ libfuzzer-sys = "0.4"
|
|||||||
[target.'cfg(not(any(target_arch = "wasm32", target_os = "ios")))'.dependencies.naga]
|
[target.'cfg(not(any(target_arch = "wasm32", target_os = "ios")))'.dependencies.naga]
|
||||||
path = ".."
|
path = ".."
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
features = ["arbitrary", "spv-in", "wgsl-in", "glsl-in", "validate"]
|
features = ["arbitrary", "spv-in", "wgsl-in", "glsl-in"]
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "spv_parser"
|
name = "spv_parser"
|
||||||
|
|||||||
@@ -247,7 +247,6 @@ impl<T> Range<T> {
|
|||||||
pub struct Arena<T> {
|
pub struct Arena<T> {
|
||||||
/// Values of this arena.
|
/// Values of this arena.
|
||||||
data: Vec<T>,
|
data: Vec<T>,
|
||||||
#[cfg(feature = "span")]
|
|
||||||
#[cfg_attr(feature = "serialize", serde(skip))]
|
#[cfg_attr(feature = "serialize", serde(skip))]
|
||||||
span_info: Vec<Span>,
|
span_info: Vec<Span>,
|
||||||
}
|
}
|
||||||
@@ -269,7 +268,6 @@ impl<T> Arena<T> {
|
|||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Arena {
|
Arena {
|
||||||
data: Vec::new(),
|
data: Vec::new(),
|
||||||
#[cfg(feature = "span")]
|
|
||||||
span_info: Vec::new(),
|
span_info: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -310,11 +308,8 @@ impl<T> Arena<T> {
|
|||||||
|
|
||||||
/// Adds a new value to the arena, returning a typed handle.
|
/// Adds a new value to the arena, returning a typed handle.
|
||||||
pub fn append(&mut self, value: T, span: Span) -> Handle<T> {
|
pub fn append(&mut self, value: T, span: Span) -> Handle<T> {
|
||||||
#[cfg(not(feature = "span"))]
|
|
||||||
let _ = span;
|
|
||||||
let index = self.data.len();
|
let index = self.data.len();
|
||||||
self.data.push(value);
|
self.data.push(value);
|
||||||
#[cfg(feature = "span")]
|
|
||||||
self.span_info.push(span);
|
self.span_info.push(span);
|
||||||
Handle::from_usize(index)
|
Handle::from_usize(index)
|
||||||
}
|
}
|
||||||
@@ -377,18 +372,10 @@ impl<T> Arena<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_span(&self, handle: Handle<T>) -> Span {
|
pub fn get_span(&self, handle: Handle<T>) -> Span {
|
||||||
#[cfg(feature = "span")]
|
*self
|
||||||
{
|
.span_info
|
||||||
*self
|
.get(handle.index())
|
||||||
.span_info
|
.unwrap_or(&Span::default())
|
||||||
.get(handle.index())
|
|
||||||
.unwrap_or(&Span::default())
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "span"))]
|
|
||||||
{
|
|
||||||
let _ = handle;
|
|
||||||
Span::default()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assert that `handle` is valid for this arena.
|
/// Assert that `handle` is valid for this arena.
|
||||||
@@ -438,7 +425,6 @@ impl<T> Arena<T> {
|
|||||||
// Since `predicate` needs mutable access to each element,
|
// Since `predicate` needs mutable access to each element,
|
||||||
// we can't feasibly call it twice, so we have to compact
|
// we can't feasibly call it twice, so we have to compact
|
||||||
// spans by hand in parallel as part of this iteration.
|
// spans by hand in parallel as part of this iteration.
|
||||||
#[cfg(feature = "span")]
|
|
||||||
if keep {
|
if keep {
|
||||||
self.span_info[retained] = self.span_info[index];
|
self.span_info[retained] = self.span_info[index];
|
||||||
retained += 1;
|
retained += 1;
|
||||||
@@ -448,7 +434,6 @@ impl<T> Arena<T> {
|
|||||||
keep
|
keep
|
||||||
});
|
});
|
||||||
|
|
||||||
#[cfg(feature = "span")]
|
|
||||||
self.span_info.truncate(retained);
|
self.span_info.truncate(retained);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -463,16 +448,11 @@ where
|
|||||||
D: serde::Deserializer<'de>,
|
D: serde::Deserializer<'de>,
|
||||||
{
|
{
|
||||||
let data = Vec::deserialize(deserializer)?;
|
let data = Vec::deserialize(deserializer)?;
|
||||||
#[cfg(feature = "span")]
|
|
||||||
let span_info = std::iter::repeat(Span::default())
|
let span_info = std::iter::repeat(Span::default())
|
||||||
.take(data.len())
|
.take(data.len())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self { data, span_info })
|
||||||
data,
|
|
||||||
#[cfg(feature = "span")]
|
|
||||||
span_info,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,7 +541,6 @@ pub struct UniqueArena<T> {
|
|||||||
/// promises that its elements "are indexed in a compact range, without
|
/// promises that its elements "are indexed in a compact range, without
|
||||||
/// holes in the range 0..set.len()", so we can always use the indices
|
/// holes in the range 0..set.len()", so we can always use the indices
|
||||||
/// returned by insertion as indices into this vector.
|
/// returned by insertion as indices into this vector.
|
||||||
#[cfg(feature = "span")]
|
|
||||||
span_info: Vec<Span>,
|
span_info: Vec<Span>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -570,7 +549,6 @@ impl<T> UniqueArena<T> {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
UniqueArena {
|
UniqueArena {
|
||||||
set: FastIndexSet::default(),
|
set: FastIndexSet::default(),
|
||||||
#[cfg(feature = "span")]
|
|
||||||
span_info: Vec::new(),
|
span_info: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -588,7 +566,6 @@ impl<T> UniqueArena<T> {
|
|||||||
/// Clears the arena, keeping all allocations.
|
/// Clears the arena, keeping all allocations.
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
self.set.clear();
|
self.set.clear();
|
||||||
#[cfg(feature = "span")]
|
|
||||||
self.span_info.clear();
|
self.span_info.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -596,29 +573,17 @@ impl<T> UniqueArena<T> {
|
|||||||
///
|
///
|
||||||
/// If a value has been inserted multiple times, the span returned is the
|
/// If a value has been inserted multiple times, the span returned is the
|
||||||
/// one provided with the first insertion.
|
/// one provided with the first insertion.
|
||||||
///
|
|
||||||
/// If the `span` feature is not enabled, always return `Span::default`.
|
|
||||||
/// This can be detected with [`Span::is_defined`].
|
|
||||||
pub fn get_span(&self, handle: Handle<T>) -> Span {
|
pub fn get_span(&self, handle: Handle<T>) -> Span {
|
||||||
#[cfg(feature = "span")]
|
*self
|
||||||
{
|
.span_info
|
||||||
*self
|
.get(handle.index())
|
||||||
.span_info
|
.unwrap_or(&Span::default())
|
||||||
.get(handle.index())
|
|
||||||
.unwrap_or(&Span::default())
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "span"))]
|
|
||||||
{
|
|
||||||
let _ = handle;
|
|
||||||
Span::default()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "compact")]
|
#[cfg(feature = "compact")]
|
||||||
pub(crate) fn drain_all(&mut self) -> UniqueArenaDrain<T> {
|
pub(crate) fn drain_all(&mut self) -> UniqueArenaDrain<T> {
|
||||||
UniqueArenaDrain {
|
UniqueArenaDrain {
|
||||||
inner_elts: self.set.drain(..),
|
inner_elts: self.set.drain(..),
|
||||||
#[cfg(feature = "span")]
|
|
||||||
inner_spans: self.span_info.drain(..),
|
inner_spans: self.span_info.drain(..),
|
||||||
index: Index::new(1).unwrap(),
|
index: Index::new(1).unwrap(),
|
||||||
}
|
}
|
||||||
@@ -628,7 +593,6 @@ impl<T> UniqueArena<T> {
|
|||||||
#[cfg(feature = "compact")]
|
#[cfg(feature = "compact")]
|
||||||
pub(crate) struct UniqueArenaDrain<'a, T> {
|
pub(crate) struct UniqueArenaDrain<'a, T> {
|
||||||
inner_elts: indexmap::set::Drain<'a, T>,
|
inner_elts: indexmap::set::Drain<'a, T>,
|
||||||
#[cfg(feature = "span")]
|
|
||||||
inner_spans: std::vec::Drain<'a, Span>,
|
inner_spans: std::vec::Drain<'a, Span>,
|
||||||
index: Index,
|
index: Index,
|
||||||
}
|
}
|
||||||
@@ -642,10 +606,7 @@ impl<'a, T> Iterator for UniqueArenaDrain<'a, T> {
|
|||||||
Some(elt) => {
|
Some(elt) => {
|
||||||
let handle = Handle::new(self.index);
|
let handle = Handle::new(self.index);
|
||||||
self.index = self.index.checked_add(1).unwrap();
|
self.index = self.index.checked_add(1).unwrap();
|
||||||
#[cfg(feature = "span")]
|
|
||||||
let span = self.inner_spans.next().unwrap();
|
let span = self.inner_spans.next().unwrap();
|
||||||
#[cfg(not(feature = "span"))]
|
|
||||||
let span = Span::default();
|
|
||||||
Some((handle, elt, span))
|
Some((handle, elt, span))
|
||||||
}
|
}
|
||||||
None => None,
|
None => None,
|
||||||
@@ -672,27 +633,21 @@ impl<T: Eq + hash::Hash> UniqueArena<T> {
|
|||||||
/// If this arena already contains an element that is `Eq` to `value`,
|
/// If this arena already contains an element that is `Eq` to `value`,
|
||||||
/// return a `Handle` to the existing element, and drop `value`.
|
/// return a `Handle` to the existing element, and drop `value`.
|
||||||
///
|
///
|
||||||
/// When the `span` feature is enabled, if `value` is inserted into the
|
/// If `value` is inserted into the arena, associate `span` with
|
||||||
/// arena, associate `span` with it. An element's span can be retrieved with
|
/// it. An element's span can be retrieved with the [`get_span`]
|
||||||
/// the [`get_span`] method.
|
/// method.
|
||||||
///
|
///
|
||||||
/// [`Handle<T>`]: Handle
|
/// [`Handle<T>`]: Handle
|
||||||
/// [`get_span`]: UniqueArena::get_span
|
/// [`get_span`]: UniqueArena::get_span
|
||||||
pub fn insert(&mut self, value: T, span: Span) -> Handle<T> {
|
pub fn insert(&mut self, value: T, span: Span) -> Handle<T> {
|
||||||
let (index, added) = self.set.insert_full(value);
|
let (index, added) = self.set.insert_full(value);
|
||||||
|
|
||||||
#[cfg(feature = "span")]
|
if added {
|
||||||
{
|
debug_assert!(index == self.span_info.len());
|
||||||
if added {
|
self.span_info.push(span);
|
||||||
debug_assert!(index == self.span_info.len());
|
|
||||||
self.span_info.push(span);
|
|
||||||
}
|
|
||||||
|
|
||||||
debug_assert!(self.set.len() == self.span_info.len());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "span"))]
|
debug_assert!(self.set.len() == self.span_info.len());
|
||||||
let _ = (span, added);
|
|
||||||
|
|
||||||
Handle::from_usize(index)
|
Handle::from_usize(index)
|
||||||
}
|
}
|
||||||
@@ -779,14 +734,9 @@ where
|
|||||||
D: serde::Deserializer<'de>,
|
D: serde::Deserializer<'de>,
|
||||||
{
|
{
|
||||||
let set = FastIndexSet::deserialize(deserializer)?;
|
let set = FastIndexSet::deserialize(deserializer)?;
|
||||||
#[cfg(feature = "span")]
|
|
||||||
let span_info = std::iter::repeat(Span::default()).take(set.len()).collect();
|
let span_info = std::iter::repeat(Span::default()).take(set.len()).collect();
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self { set, span_info })
|
||||||
set,
|
|
||||||
#[cfg(feature = "span")]
|
|
||||||
span_info,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -800,7 +750,6 @@ where
|
|||||||
let mut arena = Self::default();
|
let mut arena = Self::default();
|
||||||
for elem in u.arbitrary_iter()? {
|
for elem in u.arbitrary_iter()? {
|
||||||
arena.set.insert(elem?);
|
arena.set.insert(elem?);
|
||||||
#[cfg(feature = "span")]
|
|
||||||
arena.span_info.push(Span::UNDEFINED);
|
arena.span_info.push(Span::UNDEFINED);
|
||||||
}
|
}
|
||||||
Ok(arena)
|
Ok(arena)
|
||||||
@@ -810,7 +759,6 @@ where
|
|||||||
let mut arena = Self::default();
|
let mut arena = Self::default();
|
||||||
for elem in u.arbitrary_take_rest_iter()? {
|
for elem in u.arbitrary_take_rest_iter()? {
|
||||||
arena.set.insert(elem?);
|
arena.set.insert(elem?);
|
||||||
#[cfg(feature = "span")]
|
|
||||||
arena.span_info.push(Span::UNDEFINED);
|
arena.span_info.push(Span::UNDEFINED);
|
||||||
}
|
}
|
||||||
Ok(arena)
|
Ok(arena)
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ use std::ops::{Deref, DerefMut, RangeBounds};
|
|||||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||||
pub struct Block {
|
pub struct Block {
|
||||||
body: Vec<Statement>,
|
body: Vec<Statement>,
|
||||||
#[cfg(feature = "span")]
|
|
||||||
#[cfg_attr(feature = "serialize", serde(skip))]
|
#[cfg_attr(feature = "serialize", serde(skip))]
|
||||||
span_info: Vec<Span>,
|
span_info: Vec<Span>,
|
||||||
}
|
}
|
||||||
@@ -17,27 +16,20 @@ impl Block {
|
|||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
body: Vec::new(),
|
body: Vec::new(),
|
||||||
#[cfg(feature = "span")]
|
|
||||||
span_info: Vec::new(),
|
span_info: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_vec(body: Vec<Statement>) -> Self {
|
pub fn from_vec(body: Vec<Statement>) -> Self {
|
||||||
#[cfg(feature = "span")]
|
|
||||||
let span_info = std::iter::repeat(Span::default())
|
let span_info = std::iter::repeat(Span::default())
|
||||||
.take(body.len())
|
.take(body.len())
|
||||||
.collect();
|
.collect();
|
||||||
Self {
|
Self { body, span_info }
|
||||||
body,
|
|
||||||
#[cfg(feature = "span")]
|
|
||||||
span_info,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_capacity(capacity: usize) -> Self {
|
pub fn with_capacity(capacity: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
body: Vec::with_capacity(capacity),
|
body: Vec::with_capacity(capacity),
|
||||||
#[cfg(feature = "span")]
|
|
||||||
span_info: Vec::with_capacity(capacity),
|
span_info: Vec::with_capacity(capacity),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,7 +37,6 @@ impl Block {
|
|||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
pub fn push(&mut self, end: Statement, span: Span) {
|
pub fn push(&mut self, end: Statement, span: Span) {
|
||||||
self.body.push(end);
|
self.body.push(end);
|
||||||
#[cfg(feature = "span")]
|
|
||||||
self.span_info.push(span);
|
self.span_info.push(span);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,43 +47,31 @@ impl Block {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn extend_block(&mut self, other: Self) {
|
pub fn extend_block(&mut self, other: Self) {
|
||||||
#[cfg(feature = "span")]
|
|
||||||
self.span_info.extend(other.span_info);
|
self.span_info.extend(other.span_info);
|
||||||
self.body.extend(other.body);
|
self.body.extend(other.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn append(&mut self, other: &mut Self) {
|
pub fn append(&mut self, other: &mut Self) {
|
||||||
#[cfg(feature = "span")]
|
|
||||||
self.span_info.append(&mut other.span_info);
|
self.span_info.append(&mut other.span_info);
|
||||||
self.body.append(&mut other.body);
|
self.body.append(&mut other.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cull<R: RangeBounds<usize> + Clone>(&mut self, range: R) {
|
pub fn cull<R: RangeBounds<usize> + Clone>(&mut self, range: R) {
|
||||||
#[cfg(feature = "span")]
|
|
||||||
self.span_info.drain(range.clone());
|
self.span_info.drain(range.clone());
|
||||||
self.body.drain(range);
|
self.body.drain(range);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn splice<R: RangeBounds<usize> + Clone>(&mut self, range: R, other: Self) {
|
pub fn splice<R: RangeBounds<usize> + Clone>(&mut self, range: R, other: Self) {
|
||||||
#[cfg(feature = "span")]
|
|
||||||
self.span_info.splice(range.clone(), other.span_info);
|
self.span_info.splice(range.clone(), other.span_info);
|
||||||
self.body.splice(range, other.body);
|
self.body.splice(range, other.body);
|
||||||
}
|
}
|
||||||
pub fn span_iter(&self) -> impl Iterator<Item = (&Statement, &Span)> {
|
pub fn span_iter(&self) -> impl Iterator<Item = (&Statement, &Span)> {
|
||||||
#[cfg(feature = "span")]
|
|
||||||
let span_iter = self.span_info.iter();
|
let span_iter = self.span_info.iter();
|
||||||
#[cfg(not(feature = "span"))]
|
|
||||||
let span_iter = std::iter::repeat_with(|| &Span::UNDEFINED);
|
|
||||||
|
|
||||||
self.body.iter().zip(span_iter)
|
self.body.iter().zip(span_iter)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn span_iter_mut(&mut self) -> impl Iterator<Item = (&mut Statement, Option<&mut Span>)> {
|
pub fn span_iter_mut(&mut self) -> impl Iterator<Item = (&mut Statement, Option<&mut Span>)> {
|
||||||
#[cfg(feature = "span")]
|
|
||||||
let span_iter = self.span_info.iter_mut().map(Some);
|
let span_iter = self.span_info.iter_mut().map(Some);
|
||||||
#[cfg(not(feature = "span"))]
|
|
||||||
let span_iter = std::iter::repeat_with(|| None);
|
|
||||||
|
|
||||||
self.body.iter_mut().zip(span_iter)
|
self.body.iter_mut().zip(span_iter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ impl Emitter {
|
|||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
let mut span = crate::span::Span::default();
|
let mut span = crate::span::Span::default();
|
||||||
let range = arena.range_from(start_len);
|
let range = arena.range_from(start_len);
|
||||||
#[cfg(feature = "span")]
|
|
||||||
for handle in range.clone() {
|
for handle in range.clone() {
|
||||||
span.subsume(arena.get_span(handle))
|
span.subsume(arena.get_span(handle))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,7 +128,6 @@ pub type SpanContext = (Span, String);
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct WithSpan<E> {
|
pub struct WithSpan<E> {
|
||||||
inner: E,
|
inner: E,
|
||||||
#[cfg(feature = "span")]
|
|
||||||
spans: Vec<SpanContext>,
|
spans: Vec<SpanContext>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +164,6 @@ impl<E> WithSpan<E> {
|
|||||||
pub const fn new(inner: E) -> Self {
|
pub const fn new(inner: E) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner,
|
inner,
|
||||||
#[cfg(feature = "span")]
|
|
||||||
spans: Vec::new(),
|
spans: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -182,22 +180,14 @@ impl<E> WithSpan<E> {
|
|||||||
|
|
||||||
/// Iterator over stored [`SpanContext`]s.
|
/// Iterator over stored [`SpanContext`]s.
|
||||||
pub fn spans(&self) -> impl ExactSizeIterator<Item = &SpanContext> {
|
pub fn spans(&self) -> impl ExactSizeIterator<Item = &SpanContext> {
|
||||||
#[cfg(feature = "span")]
|
self.spans.iter()
|
||||||
return self.spans.iter();
|
|
||||||
#[cfg(not(feature = "span"))]
|
|
||||||
return std::iter::empty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a new span with description.
|
/// Add a new span with description.
|
||||||
#[cfg_attr(
|
|
||||||
not(feature = "span"),
|
|
||||||
allow(unused_variables, unused_mut, clippy::missing_const_for_fn)
|
|
||||||
)]
|
|
||||||
pub fn with_span<S>(mut self, span: Span, description: S) -> Self
|
pub fn with_span<S>(mut self, span: Span, description: S) -> Self
|
||||||
where
|
where
|
||||||
S: ToString,
|
S: ToString,
|
||||||
{
|
{
|
||||||
#[cfg(feature = "span")]
|
|
||||||
if span.is_defined() {
|
if span.is_defined() {
|
||||||
self.spans.push((span, description.to_string()));
|
self.spans.push((span, description.to_string()));
|
||||||
}
|
}
|
||||||
@@ -223,7 +213,6 @@ impl<E> WithSpan<E> {
|
|||||||
{
|
{
|
||||||
WithSpan {
|
WithSpan {
|
||||||
inner: self.inner.into(),
|
inner: self.inner.into(),
|
||||||
#[cfg(feature = "span")]
|
|
||||||
spans: self.spans,
|
spans: self.spans,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -234,14 +223,11 @@ impl<E> WithSpan<E> {
|
|||||||
where
|
where
|
||||||
F: FnOnce(E) -> WithSpan<E2>,
|
F: FnOnce(E) -> WithSpan<E2>,
|
||||||
{
|
{
|
||||||
#[cfg_attr(not(feature = "span"), allow(unused_mut))]
|
|
||||||
let mut res = func(self.inner);
|
let mut res = func(self.inner);
|
||||||
#[cfg(feature = "span")]
|
|
||||||
res.spans.extend(self.spans);
|
res.spans.extend(self.spans);
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "span")]
|
|
||||||
/// Return a [`SourceLocation`] for our first span, if we have one.
|
/// Return a [`SourceLocation`] for our first span, if we have one.
|
||||||
pub fn location(&self, source: &str) -> Option<SourceLocation> {
|
pub fn location(&self, source: &str) -> Option<SourceLocation> {
|
||||||
if self.spans.is_empty() {
|
if self.spans.is_empty() {
|
||||||
@@ -251,14 +237,6 @@ impl<E> WithSpan<E> {
|
|||||||
Some(self.spans[0].0.location(source))
|
Some(self.spans[0].0.location(source))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "span"))]
|
|
||||||
#[allow(clippy::missing_const_for_fn)]
|
|
||||||
/// Return a [`SourceLocation`] for our first span, if we have one.
|
|
||||||
pub fn location(&self, _source: &str) -> Option<SourceLocation> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "span")]
|
|
||||||
fn diagnostic(&self) -> codespan_reporting::diagnostic::Diagnostic<()>
|
fn diagnostic(&self) -> codespan_reporting::diagnostic::Diagnostic<()>
|
||||||
where
|
where
|
||||||
E: Error,
|
E: Error,
|
||||||
@@ -286,7 +264,6 @@ impl<E> WithSpan<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Emits a summary of the error to standard error stream.
|
/// Emits a summary of the error to standard error stream.
|
||||||
#[cfg(feature = "span")]
|
|
||||||
pub fn emit_to_stderr(&self, source: &str)
|
pub fn emit_to_stderr(&self, source: &str)
|
||||||
where
|
where
|
||||||
E: Error,
|
E: Error,
|
||||||
@@ -295,7 +272,6 @@ impl<E> WithSpan<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Emits a summary of the error to standard error stream.
|
/// Emits a summary of the error to standard error stream.
|
||||||
#[cfg(feature = "span")]
|
|
||||||
pub fn emit_to_stderr_with_path(&self, source: &str, path: &str)
|
pub fn emit_to_stderr_with_path(&self, source: &str, path: &str)
|
||||||
where
|
where
|
||||||
E: Error,
|
E: Error,
|
||||||
@@ -311,7 +287,6 @@ impl<E> WithSpan<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Emits a summary of the error to a string.
|
/// Emits a summary of the error to a string.
|
||||||
#[cfg(feature = "span")]
|
|
||||||
pub fn emit_to_string(&self, source: &str) -> String
|
pub fn emit_to_string(&self, source: &str) -> String
|
||||||
where
|
where
|
||||||
E: Error,
|
E: Error,
|
||||||
@@ -320,7 +295,6 @@ impl<E> WithSpan<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Emits a summary of the error to a string.
|
/// Emits a summary of the error to a string.
|
||||||
#[cfg(feature = "span")]
|
|
||||||
pub fn emit_to_string_with_path(&self, source: &str, path: &str) -> String
|
pub fn emit_to_string_with_path(&self, source: &str, path: &str) -> String
|
||||||
where
|
where
|
||||||
E: Error,
|
E: Error,
|
||||||
|
|||||||
@@ -778,7 +778,6 @@ impl FunctionInfo {
|
|||||||
let mut requirements = UniformityRequirements::empty();
|
let mut requirements = UniformityRequirements::empty();
|
||||||
for expr in range.clone() {
|
for expr in range.clone() {
|
||||||
let req = self.expressions[expr.index()].uniformity.requirements;
|
let req = self.expressions[expr.index()].uniformity.requirements;
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
if self
|
if self
|
||||||
.flags
|
.flags
|
||||||
.contains(super::ValidationFlags::CONTROL_FLOW_UNIFORMITY)
|
.contains(super::ValidationFlags::CONTROL_FLOW_UNIFORMITY)
|
||||||
@@ -823,7 +822,7 @@ impl FunctionInfo {
|
|||||||
// The uniformity analysis Naga uses now is less accurate than the one in the WGSL standard,
|
// The uniformity analysis Naga uses now is less accurate than the one in the WGSL standard,
|
||||||
// causing Naga to reject correct uses of `workgroupUniformLoad` in some interesting programs.
|
// causing Naga to reject correct uses of `workgroupUniformLoad` in some interesting programs.
|
||||||
|
|
||||||
/* #[cfg(feature = "validate")]
|
/*
|
||||||
if self
|
if self
|
||||||
.flags
|
.flags
|
||||||
.contains(super::ValidationFlags::CONTROL_FLOW_UNIFORMITY)
|
.contains(super::ValidationFlags::CONTROL_FLOW_UNIFORMITY)
|
||||||
@@ -1060,7 +1059,6 @@ impl ModuleInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
fn uniform_control_flow() {
|
fn uniform_control_flow() {
|
||||||
use crate::{Expression as E, Statement as S};
|
use crate::{Expression as E, Statement as S};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#[cfg(feature = "validate")]
|
|
||||||
use crate::proc::TypeResolution;
|
use crate::proc::TypeResolution;
|
||||||
|
|
||||||
use crate::arena::Handle;
|
use crate::arena::Handle;
|
||||||
@@ -14,7 +13,6 @@ pub enum ComposeError {
|
|||||||
ComponentType { index: u32 },
|
ComponentType { index: u32 },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
pub fn validate_compose(
|
pub fn validate_compose(
|
||||||
self_ty_handle: Handle<crate::Type>,
|
self_ty_handle: Handle<crate::Type>,
|
||||||
gctx: crate::proc::GlobalCtx,
|
gctx: crate::proc::GlobalCtx,
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
#[cfg(feature = "validate")]
|
|
||||||
use super::{
|
use super::{
|
||||||
compose::validate_compose, validate_atomic_compare_exchange_struct, FunctionInfo, ModuleInfo,
|
compose::validate_compose, validate_atomic_compare_exchange_struct, FunctionInfo, ModuleInfo,
|
||||||
ShaderStages, TypeFlags,
|
ShaderStages, TypeFlags,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
use crate::arena::UniqueArena;
|
use crate::arena::UniqueArena;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -155,14 +153,12 @@ pub enum LiteralError {
|
|||||||
Width(#[from] super::r#type::WidthError),
|
Width(#[from] super::r#type::WidthError),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
struct ExpressionTypeResolver<'a> {
|
struct ExpressionTypeResolver<'a> {
|
||||||
root: Handle<crate::Expression>,
|
root: Handle<crate::Expression>,
|
||||||
types: &'a UniqueArena<crate::Type>,
|
types: &'a UniqueArena<crate::Type>,
|
||||||
info: &'a FunctionInfo,
|
info: &'a FunctionInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
impl<'a> std::ops::Index<Handle<crate::Expression>> for ExpressionTypeResolver<'a> {
|
impl<'a> std::ops::Index<Handle<crate::Expression>> for ExpressionTypeResolver<'a> {
|
||||||
type Output = crate::TypeInner;
|
type Output = crate::TypeInner;
|
||||||
|
|
||||||
@@ -180,7 +176,6 @@ impl<'a> std::ops::Index<Handle<crate::Expression>> for ExpressionTypeResolver<'
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
impl super::Validator {
|
impl super::Validator {
|
||||||
pub(super) fn validate_const_expression(
|
pub(super) fn validate_const_expression(
|
||||||
&self,
|
&self,
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
use crate::arena::Handle;
|
use crate::arena::Handle;
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
use crate::arena::{Arena, UniqueArena};
|
use crate::arena::{Arena, UniqueArena};
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
use super::validate_atomic_compare_exchange_struct;
|
use super::validate_atomic_compare_exchange_struct;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@@ -10,10 +8,8 @@ use super::{
|
|||||||
ExpressionError, FunctionInfo, ModuleInfo,
|
ExpressionError, FunctionInfo, ModuleInfo,
|
||||||
};
|
};
|
||||||
use crate::span::WithSpan;
|
use crate::span::WithSpan;
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
use crate::span::{AddSpan as _, MapErrWithSpan as _};
|
use crate::span::{AddSpan as _, MapErrWithSpan as _};
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
use bit_set::BitSet;
|
use bit_set::BitSet;
|
||||||
|
|
||||||
#[derive(Clone, Debug, thiserror::Error)]
|
#[derive(Clone, Debug, thiserror::Error)]
|
||||||
@@ -174,13 +170,11 @@ bitflags::bitflags! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
struct BlockInfo {
|
struct BlockInfo {
|
||||||
stages: super::ShaderStages,
|
stages: super::ShaderStages,
|
||||||
finished: bool,
|
finished: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
struct BlockContext<'a> {
|
struct BlockContext<'a> {
|
||||||
abilities: ControlFlowAbility,
|
abilities: ControlFlowAbility,
|
||||||
info: &'a FunctionInfo,
|
info: &'a FunctionInfo,
|
||||||
@@ -194,7 +188,6 @@ struct BlockContext<'a> {
|
|||||||
return_type: Option<Handle<crate::Type>>,
|
return_type: Option<Handle<crate::Type>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
impl<'a> BlockContext<'a> {
|
impl<'a> BlockContext<'a> {
|
||||||
fn new(
|
fn new(
|
||||||
fun: &'a crate::Function,
|
fun: &'a crate::Function,
|
||||||
@@ -263,7 +256,6 @@ impl<'a> BlockContext<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl super::Validator {
|
impl super::Validator {
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
fn validate_call(
|
fn validate_call(
|
||||||
&mut self,
|
&mut self,
|
||||||
function: Handle<crate::Function>,
|
function: Handle<crate::Function>,
|
||||||
@@ -320,7 +312,6 @@ impl super::Validator {
|
|||||||
Ok(callee_info.available_stages)
|
Ok(callee_info.available_stages)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
fn emit_expression(
|
fn emit_expression(
|
||||||
&mut self,
|
&mut self,
|
||||||
handle: Handle<crate::Expression>,
|
handle: Handle<crate::Expression>,
|
||||||
@@ -335,7 +326,6 @@ impl super::Validator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
fn validate_atomic(
|
fn validate_atomic(
|
||||||
&mut self,
|
&mut self,
|
||||||
pointer: Handle<crate::Expression>,
|
pointer: Handle<crate::Expression>,
|
||||||
@@ -410,7 +400,6 @@ impl super::Validator {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
fn validate_block_impl(
|
fn validate_block_impl(
|
||||||
&mut self,
|
&mut self,
|
||||||
statements: &crate::Block,
|
statements: &crate::Block,
|
||||||
@@ -920,7 +909,6 @@ impl super::Validator {
|
|||||||
Ok(BlockInfo { stages, finished })
|
Ok(BlockInfo { stages, finished })
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
fn validate_block(
|
fn validate_block(
|
||||||
&mut self,
|
&mut self,
|
||||||
statements: &crate::Block,
|
statements: &crate::Block,
|
||||||
@@ -934,7 +922,6 @@ impl super::Validator {
|
|||||||
Ok(info)
|
Ok(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
fn validate_local_var(
|
fn validate_local_var(
|
||||||
&self,
|
&self,
|
||||||
var: &crate::LocalVariable,
|
var: &crate::LocalVariable,
|
||||||
@@ -971,16 +958,13 @@ impl super::Validator {
|
|||||||
fun: &crate::Function,
|
fun: &crate::Function,
|
||||||
module: &crate::Module,
|
module: &crate::Module,
|
||||||
mod_info: &ModuleInfo,
|
mod_info: &ModuleInfo,
|
||||||
#[cfg_attr(not(feature = "validate"), allow(unused))] entry_point: bool,
|
entry_point: bool,
|
||||||
) -> Result<FunctionInfo, WithSpan<FunctionError>> {
|
) -> Result<FunctionInfo, WithSpan<FunctionError>> {
|
||||||
#[cfg_attr(not(feature = "validate"), allow(unused_mut))]
|
|
||||||
let mut info = mod_info.process_function(fun, module, self.flags, self.capabilities)?;
|
let mut info = mod_info.process_function(fun, module, self.flags, self.capabilities)?;
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
let expression_constness =
|
let expression_constness =
|
||||||
crate::proc::ExpressionConstnessTracker::from_arena(&fun.expressions);
|
crate::proc::ExpressionConstnessTracker::from_arena(&fun.expressions);
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
for (var_handle, var) in fun.local_variables.iter() {
|
for (var_handle, var) in fun.local_variables.iter() {
|
||||||
self.validate_local_var(var, module.to_ctx(), &info, &expression_constness)
|
self.validate_local_var(var, module.to_ctx(), &info, &expression_constness)
|
||||||
.map_err(|source| {
|
.map_err(|source| {
|
||||||
@@ -994,7 +978,6 @@ impl super::Validator {
|
|||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
for (index, argument) in fun.arguments.iter().enumerate() {
|
for (index, argument) in fun.arguments.iter().enumerate() {
|
||||||
match module.types[argument.ty].inner.pointer_space() {
|
match module.types[argument.ty].inner.pointer_space() {
|
||||||
Some(crate::AddressSpace::Private | crate::AddressSpace::Function) | None => {}
|
Some(crate::AddressSpace::Private | crate::AddressSpace::Function) | None => {}
|
||||||
@@ -1027,7 +1010,6 @@ impl super::Validator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
if let Some(ref result) = fun.result {
|
if let Some(ref result) = fun.result {
|
||||||
if !self.types[result.ty.index()]
|
if !self.types[result.ty.index()]
|
||||||
.flags
|
.flags
|
||||||
@@ -1049,7 +1031,6 @@ impl super::Validator {
|
|||||||
if expr.needs_pre_emit() {
|
if expr.needs_pre_emit() {
|
||||||
self.valid_expression_set.insert(handle.index());
|
self.valid_expression_set.insert(handle.index());
|
||||||
}
|
}
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
if self.flags.contains(super::ValidationFlags::EXPRESSIONS) {
|
if self.flags.contains(super::ValidationFlags::EXPRESSIONS) {
|
||||||
match self.validate_expression(handle, expr, fun, module, &info, mod_info) {
|
match self.validate_expression(handle, expr, fun, module, &info, mod_info) {
|
||||||
Ok(stages) => info.available_stages &= stages,
|
Ok(stages) => info.available_stages &= stages,
|
||||||
@@ -1061,7 +1042,6 @@ impl super::Validator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
if self.flags.contains(super::ValidationFlags::BLOCKS) {
|
if self.flags.contains(super::ValidationFlags::BLOCKS) {
|
||||||
let stages = self
|
let stages = self
|
||||||
.validate_block(
|
.validate_block(
|
||||||
|
|||||||
@@ -5,16 +5,12 @@ use crate::{
|
|||||||
Handle,
|
Handle,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
use crate::{Arena, UniqueArena};
|
use crate::{Arena, UniqueArena};
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
use super::ValidationError;
|
use super::ValidationError;
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
use std::{convert::TryInto, hash::Hash, num::NonZeroU32};
|
use std::{convert::TryInto, hash::Hash, num::NonZeroU32};
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
impl super::Validator {
|
impl super::Validator {
|
||||||
/// Validates that all handles within `module` are:
|
/// Validates that all handles within `module` are:
|
||||||
///
|
///
|
||||||
@@ -547,21 +543,18 @@ impl super::Validator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
impl From<BadHandle> for ValidationError {
|
impl From<BadHandle> for ValidationError {
|
||||||
fn from(source: BadHandle) -> Self {
|
fn from(source: BadHandle) -> Self {
|
||||||
Self::InvalidHandle(source.into())
|
Self::InvalidHandle(source.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
impl From<FwdDepError> for ValidationError {
|
impl From<FwdDepError> for ValidationError {
|
||||||
fn from(source: FwdDepError) -> Self {
|
fn from(source: FwdDepError) -> Self {
|
||||||
Self::InvalidHandle(source.into())
|
Self::InvalidHandle(source.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
impl From<BadRangeError> for ValidationError {
|
impl From<BadRangeError> for ValidationError {
|
||||||
fn from(source: BadRangeError) -> Self {
|
fn from(source: BadRangeError) -> Self {
|
||||||
Self::InvalidHandle(source.into())
|
Self::InvalidHandle(source.into())
|
||||||
@@ -592,7 +585,6 @@ pub struct FwdDepError {
|
|||||||
depends_on_kind: &'static str,
|
depends_on_kind: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
impl<T> Handle<T> {
|
impl<T> Handle<T> {
|
||||||
/// Check that `self` is valid within `arena` using [`Arena::check_contains_handle`].
|
/// Check that `self` is valid within `arena` using [`Arena::check_contains_handle`].
|
||||||
pub(self) fn check_valid_for(self, arena: &Arena<T>) -> Result<(), InvalidHandleError> {
|
pub(self) fn check_valid_for(self, arena: &Arena<T>) -> Result<(), InvalidHandleError> {
|
||||||
@@ -656,7 +648,6 @@ impl<T> Handle<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
impl<T> crate::arena::Range<T> {
|
impl<T> crate::arena::Range<T> {
|
||||||
pub(self) fn check_valid_for(&self, arena: &Arena<T>) -> Result<(), BadRangeError> {
|
pub(self) fn check_valid_for(&self, arena: &Arena<T>) -> Result<(), BadRangeError> {
|
||||||
arena.check_contains_range(self)
|
arena.check_contains_range(self)
|
||||||
@@ -664,7 +655,6 @@ impl<T> crate::arena::Range<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
fn constant_deps() {
|
fn constant_deps() {
|
||||||
use crate::{Constant, Expression, Literal, Span, Type, TypeInner};
|
use crate::{Constant, Expression, Literal, Span, Type, TypeInner};
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ use crate::arena::{Handle, UniqueArena};
|
|||||||
use crate::span::{AddSpan as _, MapErrWithSpan as _, SpanProvider as _, WithSpan};
|
use crate::span::{AddSpan as _, MapErrWithSpan as _, SpanProvider as _, WithSpan};
|
||||||
use bit_set::BitSet;
|
use bit_set::BitSet;
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
const MAX_WORKGROUP_SIZE: u32 = 0x4000;
|
const MAX_WORKGROUP_SIZE: u32 = 0x4000;
|
||||||
|
|
||||||
#[derive(Clone, Debug, thiserror::Error)]
|
#[derive(Clone, Debug, thiserror::Error)]
|
||||||
@@ -110,7 +109,6 @@ pub enum EntryPointError {
|
|||||||
InvalidLocationsWhileDualSourceBlending { location_mask: BitSet },
|
InvalidLocationsWhileDualSourceBlending { location_mask: BitSet },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
fn storage_usage(access: crate::StorageAccess) -> GlobalUse {
|
fn storage_usage(access: crate::StorageAccess) -> GlobalUse {
|
||||||
let mut storage_usage = GlobalUse::QUERY;
|
let mut storage_usage = GlobalUse::QUERY;
|
||||||
if access.contains(crate::StorageAccess::LOAD) {
|
if access.contains(crate::StorageAccess::LOAD) {
|
||||||
@@ -131,8 +129,6 @@ struct VaryingContext<'a> {
|
|||||||
location_mask: &'a mut BitSet,
|
location_mask: &'a mut BitSet,
|
||||||
built_ins: &'a mut crate::FastHashSet<crate::BuiltIn>,
|
built_ins: &'a mut crate::FastHashSet<crate::BuiltIn>,
|
||||||
capabilities: Capabilities,
|
capabilities: Capabilities,
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
flags: super::ValidationFlags,
|
flags: super::ValidationFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,7 +303,6 @@ impl VaryingContext<'_> {
|
|||||||
|
|
||||||
self.second_blend_source = true;
|
self.second_blend_source = true;
|
||||||
} else if !self.location_mask.insert(location as usize) {
|
} else if !self.location_mask.insert(location as usize) {
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
if self.flags.contains(super::ValidationFlags::BINDINGS) {
|
if self.flags.contains(super::ValidationFlags::BINDINGS) {
|
||||||
return Err(VaryingError::BindingCollision { location });
|
return Err(VaryingError::BindingCollision { location });
|
||||||
}
|
}
|
||||||
@@ -369,15 +364,12 @@ impl VaryingContext<'_> {
|
|||||||
let span_context = self.types.get_span_context(ty);
|
let span_context = self.types.get_span_context(ty);
|
||||||
match member.binding {
|
match member.binding {
|
||||||
None => {
|
None => {
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
if self.flags.contains(super::ValidationFlags::BINDINGS) {
|
if self.flags.contains(super::ValidationFlags::BINDINGS) {
|
||||||
return Err(VaryingError::MemberMissingBinding(
|
return Err(VaryingError::MemberMissingBinding(
|
||||||
index as u32,
|
index as u32,
|
||||||
)
|
)
|
||||||
.with_span_context(span_context));
|
.with_span_context(span_context));
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "validate"))]
|
|
||||||
let _ = index;
|
|
||||||
}
|
}
|
||||||
Some(ref binding) => self
|
Some(ref binding) => self
|
||||||
.validate_impl(member.ty, binding)
|
.validate_impl(member.ty, binding)
|
||||||
@@ -385,9 +377,7 @@ impl VaryingContext<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ =>
|
_ => {
|
||||||
{
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
if self.flags.contains(super::ValidationFlags::BINDINGS) {
|
if self.flags.contains(super::ValidationFlags::BINDINGS) {
|
||||||
return Err(VaryingError::MissingBinding.with_span());
|
return Err(VaryingError::MissingBinding.with_span());
|
||||||
}
|
}
|
||||||
@@ -400,7 +390,6 @@ impl VaryingContext<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl super::Validator {
|
impl super::Validator {
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
pub(super) fn validate_global_var(
|
pub(super) fn validate_global_var(
|
||||||
&self,
|
&self,
|
||||||
var: &crate::GlobalVariable,
|
var: &crate::GlobalVariable,
|
||||||
@@ -550,7 +539,6 @@ impl super::Validator {
|
|||||||
module: &crate::Module,
|
module: &crate::Module,
|
||||||
mod_info: &ModuleInfo,
|
mod_info: &ModuleInfo,
|
||||||
) -> Result<FunctionInfo, WithSpan<EntryPointError>> {
|
) -> Result<FunctionInfo, WithSpan<EntryPointError>> {
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
if ep.early_depth_test.is_some() {
|
if ep.early_depth_test.is_some() {
|
||||||
let required = Capabilities::EARLY_DEPTH_TEST;
|
let required = Capabilities::EARLY_DEPTH_TEST;
|
||||||
if !self.capabilities.contains(required) {
|
if !self.capabilities.contains(required) {
|
||||||
@@ -565,7 +553,6 @@ impl super::Validator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
if ep.stage == crate::ShaderStage::Compute {
|
if ep.stage == crate::ShaderStage::Compute {
|
||||||
if ep
|
if ep
|
||||||
.workgroup_size
|
.workgroup_size
|
||||||
@@ -578,12 +565,10 @@ impl super::Validator {
|
|||||||
return Err(EntryPointError::UnexpectedWorkgroupSize.with_span());
|
return Err(EntryPointError::UnexpectedWorkgroupSize.with_span());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(not(feature = "validate"), allow(unused_mut))]
|
|
||||||
let mut info = self
|
let mut info = self
|
||||||
.validate_function(&ep.function, module, mod_info, true)
|
.validate_function(&ep.function, module, mod_info, true)
|
||||||
.map_err(WithSpan::into_other)?;
|
.map_err(WithSpan::into_other)?;
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
{
|
{
|
||||||
use super::ShaderStages;
|
use super::ShaderStages;
|
||||||
|
|
||||||
@@ -611,8 +596,6 @@ impl super::Validator {
|
|||||||
location_mask: &mut self.location_mask,
|
location_mask: &mut self.location_mask,
|
||||||
built_ins: &mut argument_built_ins,
|
built_ins: &mut argument_built_ins,
|
||||||
capabilities: self.capabilities,
|
capabilities: self.capabilities,
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
flags: self.flags,
|
flags: self.flags,
|
||||||
};
|
};
|
||||||
ctx.validate(fa.ty, fa.binding.as_ref())
|
ctx.validate(fa.ty, fa.binding.as_ref())
|
||||||
@@ -631,13 +614,10 @@ impl super::Validator {
|
|||||||
location_mask: &mut self.location_mask,
|
location_mask: &mut self.location_mask,
|
||||||
built_ins: &mut result_built_ins,
|
built_ins: &mut result_built_ins,
|
||||||
capabilities: self.capabilities,
|
capabilities: self.capabilities,
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
flags: self.flags,
|
flags: self.flags,
|
||||||
};
|
};
|
||||||
ctx.validate(fr.ty, fr.binding.as_ref())
|
ctx.validate(fr.ty, fr.binding.as_ref())
|
||||||
.map_err_inner(|e| EntryPointError::Result(e).with_span())?;
|
.map_err_inner(|e| EntryPointError::Result(e).with_span())?;
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
if ctx.second_blend_source {
|
if ctx.second_blend_source {
|
||||||
// Only the first location may be used whhen dual source blending
|
// Only the first location may be used whhen dual source blending
|
||||||
if ctx.location_mask.len() == 1 && ctx.location_mask.contains(0) {
|
if ctx.location_mask.len() == 1 && ctx.location_mask.contains(0) {
|
||||||
@@ -650,18 +630,15 @@ impl super::Validator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
if ep.stage == crate::ShaderStage::Vertex
|
if ep.stage == crate::ShaderStage::Vertex
|
||||||
&& !result_built_ins.contains(&crate::BuiltIn::Position { invariant: false })
|
&& !result_built_ins.contains(&crate::BuiltIn::Position { invariant: false })
|
||||||
{
|
{
|
||||||
return Err(EntryPointError::MissingVertexOutputPosition.with_span());
|
return Err(EntryPointError::MissingVertexOutputPosition.with_span());
|
||||||
}
|
}
|
||||||
} else if ep.stage == crate::ShaderStage::Vertex {
|
} else if ep.stage == crate::ShaderStage::Vertex {
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
return Err(EntryPointError::MissingVertexOutputPosition.with_span());
|
return Err(EntryPointError::MissingVertexOutputPosition.with_span());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
{
|
{
|
||||||
let used_push_constants = module
|
let used_push_constants = module
|
||||||
.global_variables
|
.global_variables
|
||||||
@@ -679,7 +656,6 @@ impl super::Validator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.ep_resource_bindings.clear();
|
self.ep_resource_bindings.clear();
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
for (var_handle, var) in module.global_variables.iter() {
|
for (var_handle, var) in module.global_variables.iter() {
|
||||||
let usage = info[var_handle];
|
let usage = info[var_handle];
|
||||||
if usage.is_empty() {
|
if usage.is_empty() {
|
||||||
|
|||||||
@@ -45,31 +45,22 @@ bitflags::bitflags! {
|
|||||||
/// should never panic.
|
/// should never panic.
|
||||||
///
|
///
|
||||||
/// The default value for `ValidationFlags` is
|
/// The default value for `ValidationFlags` is
|
||||||
/// `ValidationFlags::all()`. If Naga's `"validate"` feature is
|
/// `ValidationFlags::all()`.
|
||||||
/// enabled, this requests full validation; otherwise, this
|
|
||||||
/// requests no validation. (The `"validate"` feature is disabled
|
|
||||||
/// by default.)
|
|
||||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
|
||||||
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
|
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
pub struct ValidationFlags: u8 {
|
pub struct ValidationFlags: u8 {
|
||||||
/// Expressions.
|
/// Expressions.
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
const EXPRESSIONS = 0x1;
|
const EXPRESSIONS = 0x1;
|
||||||
/// Statements and blocks of them.
|
/// Statements and blocks of them.
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
const BLOCKS = 0x2;
|
const BLOCKS = 0x2;
|
||||||
/// Uniformity of control flow for operations that require it.
|
/// Uniformity of control flow for operations that require it.
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
const CONTROL_FLOW_UNIFORMITY = 0x4;
|
const CONTROL_FLOW_UNIFORMITY = 0x4;
|
||||||
/// Host-shareable structure layouts.
|
/// Host-shareable structure layouts.
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
const STRUCT_LAYOUTS = 0x8;
|
const STRUCT_LAYOUTS = 0x8;
|
||||||
/// Constants.
|
/// Constants.
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
const CONSTANTS = 0x10;
|
const CONSTANTS = 0x10;
|
||||||
/// Group, binding, and location attributes.
|
/// Group, binding, and location attributes.
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
const BINDINGS = 0x20;
|
const BINDINGS = 0x20;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,7 +228,6 @@ pub enum ValidationError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl crate::TypeInner {
|
impl crate::TypeInner {
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
const fn is_sized(&self) -> bool {
|
const fn is_sized(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
Self::Scalar { .. }
|
Self::Scalar { .. }
|
||||||
@@ -261,7 +251,6 @@ impl crate::TypeInner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return the `ImageDimension` for which `self` is an appropriate coordinate.
|
/// Return the `ImageDimension` for which `self` is an appropriate coordinate.
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
const fn image_storage_coordinates(&self) -> Option<crate::ImageDimension> {
|
const fn image_storage_coordinates(&self) -> Option<crate::ImageDimension> {
|
||||||
match *self {
|
match *self {
|
||||||
Self::Scalar(crate::Scalar {
|
Self::Scalar(crate::Scalar {
|
||||||
@@ -316,7 +305,6 @@ impl Validator {
|
|||||||
self.valid_expression_set.clear();
|
self.valid_expression_set.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
fn validate_constant(
|
fn validate_constant(
|
||||||
&self,
|
&self,
|
||||||
handle: Handle<crate::Constant>,
|
handle: Handle<crate::Constant>,
|
||||||
@@ -347,7 +335,6 @@ impl Validator {
|
|||||||
self.reset();
|
self.reset();
|
||||||
self.reset_types(module.types.len());
|
self.reset_types(module.types.len());
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
Self::validate_module_handles(module).map_err(|e| e.with_span())?;
|
Self::validate_module_handles(module).map_err(|e| e.with_span())?;
|
||||||
|
|
||||||
self.layouter.update(module.to_ctx()).map_err(|e| {
|
self.layouter.update(module.to_ctx()).map_err(|e| {
|
||||||
@@ -397,7 +384,6 @@ impl Validator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
if self.flags.contains(ValidationFlags::CONSTANTS) {
|
if self.flags.contains(ValidationFlags::CONSTANTS) {
|
||||||
for (handle, _) in module.const_expressions.iter() {
|
for (handle, _) in module.const_expressions.iter() {
|
||||||
self.validate_const_expression(handle, module.to_ctx(), &mod_info)
|
self.validate_const_expression(handle, module.to_ctx(), &mod_info)
|
||||||
@@ -420,7 +406,6 @@ impl Validator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
for (var_handle, var) in module.global_variables.iter() {
|
for (var_handle, var) in module.global_variables.iter() {
|
||||||
self.validate_global_var(var, module.to_ctx(), &mod_info)
|
self.validate_global_var(var, module.to_ctx(), &mod_info)
|
||||||
.map_err(|source| {
|
.map_err(|source| {
|
||||||
@@ -479,7 +464,6 @@ impl Validator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "validate")]
|
|
||||||
fn validate_atomic_compare_exchange_struct(
|
fn validate_atomic_compare_exchange_struct(
|
||||||
types: &crate::UniqueArena<crate::Type>,
|
types: &crate::UniqueArena<crate::Type>,
|
||||||
members: &[crate::StructMember],
|
members: &[crate::StructMember],
|
||||||
|
|||||||
@@ -311,14 +311,10 @@ fn check_targets(
|
|||||||
|
|
||||||
#[cfg(all(feature = "deserialize", feature = "spv-out"))]
|
#[cfg(all(feature = "deserialize", feature = "spv-out"))]
|
||||||
{
|
{
|
||||||
let debug_info = if cfg!(feature = "span") {
|
let debug_info = source_code.map(|code| naga::back::spv::DebugInfo {
|
||||||
source_code.map(|code| naga::back::spv::DebugInfo {
|
source_code: code,
|
||||||
source_code: code,
|
file_name: name.as_ref(),
|
||||||
file_name: name.as_ref(),
|
});
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
if targets.contains(Targets::SPIRV) {
|
if targets.contains(Targets::SPIRV) {
|
||||||
write_output_spv(
|
write_output_spv(
|
||||||
@@ -791,7 +787,6 @@ fn convert_wgsl() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "span")]
|
|
||||||
{
|
{
|
||||||
let inputs = [
|
let inputs = [
|
||||||
("debug-symbol-simple", Targets::SPIRV),
|
("debug-symbol-simple", Targets::SPIRV),
|
||||||
|
|||||||
@@ -1993,7 +1993,6 @@ fn binding_array_non_struct() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "span")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn compaction_preserves_spans() {
|
fn compaction_preserves_spans() {
|
||||||
let source = r#"
|
let source = r#"
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ thiserror = "1"
|
|||||||
[dependencies.naga]
|
[dependencies.naga]
|
||||||
path = "../naga"
|
path = "../naga"
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
features = ["clone", "span", "validate"]
|
features = ["clone"]
|
||||||
|
|
||||||
[dependencies.wgt]
|
[dependencies.wgt]
|
||||||
package = "wgpu-types"
|
package = "wgpu-types"
|
||||||
|
|||||||
Reference in New Issue
Block a user