From d135870658473d0dbaa00c3033d1cab344a8af58 Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Wed, 20 Sep 2023 07:32:45 +0000 Subject: [PATCH] Bug 1853105 - Update `wgpu` to revision 7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e. r=webgpu-reviewers,supply-chain-reviewers,ErichDonGubler Differential Revision: https://phabricator.services.mozilla.com/D188214 --- .cargo/config.in | 8 +- Cargo.lock | 8 +- gfx/wgpu_bindings/Cargo.toml | 12 +- gfx/wgpu_bindings/moz.yaml | 4 +- supply-chain/audits.toml | 20 + third_party/rust/naga/.cargo-checksum.json | 2 +- .../rust/naga/src/back/glsl/features.rs | 11 + .../rust/naga/src/back/glsl/keywords.rs | 3 + third_party/rust/naga/src/back/glsl/mod.rs | 72 +- third_party/rust/naga/src/back/hlsl/help.rs | 53 ++ .../rust/naga/src/back/hlsl/keywords.rs | 3 + third_party/rust/naga/src/back/hlsl/writer.rs | 21 +- .../rust/naga/src/back/msl/keywords.rs | 2 + third_party/rust/naga/src/back/msl/mod.rs | 29 +- third_party/rust/naga/src/back/msl/writer.rs | 108 ++- third_party/rust/naga/src/back/spv/block.rs | 4 +- third_party/rust/naga/src/back/spv/writer.rs | 4 + third_party/rust/naga/src/back/wgsl/writer.rs | 35 +- .../rust/naga/src/front/glsl/builtins.rs | 196 ++--- .../rust/naga/src/front/glsl/context.rs | 626 +++++++--------- .../rust/naga/src/front/glsl/functions.rs | 682 +++++++++--------- third_party/rust/naga/src/front/glsl/mod.rs | 26 +- .../rust/naga/src/front/glsl/parser.rs | 60 +- .../src/front/glsl/parser/declarations.rs | 77 +- .../naga/src/front/glsl/parser/expressions.rs | 63 +- .../naga/src/front/glsl/parser/functions.rs | 440 ++++++----- .../rust/naga/src/front/glsl/parser/types.rs | 54 +- third_party/rust/naga/src/front/glsl/types.rs | 49 +- .../rust/naga/src/front/glsl/variables.rs | 77 +- .../rust/naga/src/front/interpolator.rs | 1 + third_party/rust/naga/src/front/spv/mod.rs | 1 + third_party/rust/naga/src/front/type_gen.rs | 248 +++++-- third_party/rust/naga/src/front/wgsl/error.rs | 11 +- .../rust/naga/src/front/wgsl/lower/mod.rs | 77 +- .../rust/naga/src/front/wgsl/parse/ast.rs | 2 +- .../rust/naga/src/front/wgsl/parse/mod.rs | 35 +- third_party/rust/naga/src/front/wgsl/tests.rs | 87 ++- third_party/rust/naga/src/lib.rs | 33 + third_party/rust/naga/src/proc/mod.rs | 4 +- third_party/rust/naga/src/proc/typifier.rs | 27 +- third_party/rust/naga/src/valid/analyzer.rs | 5 + third_party/rust/naga/src/valid/expression.rs | 80 +- third_party/rust/naga/src/valid/interface.rs | 66 +- third_party/rust/naga/src/valid/mod.rs | 2 + .../rust/wgpu-core/.cargo-checksum.json | 2 +- third_party/rust/wgpu-core/Cargo.toml | 2 +- .../rust/wgpu-core/src/device/global.rs | 26 +- third_party/rust/wgpu-core/src/device/mod.rs | 3 +- third_party/rust/wgpu-core/src/instance.rs | 16 +- third_party/rust/wgpu-core/src/present.rs | 14 +- third_party/rust/wgpu-core/src/validation.rs | 1 + .../rust/wgpu-hal/.cargo-checksum.json | 2 +- third_party/rust/wgpu-hal/Cargo.toml | 4 +- third_party/rust/wgpu-hal/src/dx12/device.rs | 5 +- third_party/rust/wgpu-hal/src/dx12/mod.rs | 33 +- third_party/rust/wgpu-hal/src/lib.rs | 16 + .../rust/wgpu-hal/src/vulkan/device.rs | 2 +- .../rust/wgpu-hal/src/vulkan/instance.rs | 51 +- .../rust/wgpu-types/.cargo-checksum.json | 2 +- third_party/rust/wgpu-types/Cargo.toml | 2 +- 60 files changed, 2153 insertions(+), 1456 deletions(-) diff --git a/.cargo/config.in b/.cargo/config.in index be59da0e406f..d13616e3df24 100644 --- a/.cargo/config.in +++ b/.cargo/config.in @@ -25,14 +25,14 @@ git = "https://github.com/franziskuskiefer/cose-rust" rev = "43c22248d136c8b38fe42ea709d08da6355cf04b" replace-with = "vendored-sources" -[source."git+https://github.com/gfx-rs/naga?rev=7a19f3af909202c7eafd36633b5584bfbb353ecb"] +[source."git+https://github.com/gfx-rs/naga?rev=cc87b8f9eb30bb55d0735b89d3df3e099e1a6e7c"] git = "https://github.com/gfx-rs/naga" -rev = "7a19f3af909202c7eafd36633b5584bfbb353ecb" +rev = "cc87b8f9eb30bb55d0735b89d3df3e099e1a6e7c" replace-with = "vendored-sources" -[source."git+https://github.com/gfx-rs/wgpu?rev=332cd0325da52675432830870584ec9766679c34"] +[source."git+https://github.com/gfx-rs/wgpu?rev=7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e"] git = "https://github.com/gfx-rs/wgpu" -rev = "332cd0325da52675432830870584ec9766679c34" +rev = "7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e" replace-with = "vendored-sources" [source."git+https://github.com/glandium/prost?rev=95964e9d33df3c2a9c3f14285e262867cab6f96b"] diff --git a/Cargo.lock b/Cargo.lock index 282151e190e1..f882e8234864 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3724,7 +3724,7 @@ checksum = "a2983372caf4480544083767bf2d27defafe32af49ab4df3a0b7fc90793a3664" [[package]] name = "naga" version = "0.13.0" -source = "git+https://github.com/gfx-rs/naga?rev=7a19f3af909202c7eafd36633b5584bfbb353ecb#7a19f3af909202c7eafd36633b5584bfbb353ecb" +source = "git+https://github.com/gfx-rs/naga?rev=cc87b8f9eb30bb55d0735b89d3df3e099e1a6e7c#cc87b8f9eb30bb55d0735b89d3df3e099e1a6e7c" dependencies = [ "bit-set", "bitflags 2.999.999", @@ -6301,7 +6301,7 @@ dependencies = [ [[package]] name = "wgpu-core" version = "0.17.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=332cd0325da52675432830870584ec9766679c34#332cd0325da52675432830870584ec9766679c34" +source = "git+https://github.com/gfx-rs/wgpu?rev=7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e#7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e" dependencies = [ "arrayvec", "bit-vec", @@ -6324,7 +6324,7 @@ dependencies = [ [[package]] name = "wgpu-hal" version = "0.17.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=332cd0325da52675432830870584ec9766679c34#332cd0325da52675432830870584ec9766679c34" +source = "git+https://github.com/gfx-rs/wgpu?rev=7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e#7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e" dependencies = [ "android_system_properties", "arrayvec", @@ -6360,7 +6360,7 @@ dependencies = [ [[package]] name = "wgpu-types" version = "0.17.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=332cd0325da52675432830870584ec9766679c34#332cd0325da52675432830870584ec9766679c34" +source = "git+https://github.com/gfx-rs/wgpu?rev=7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e#7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e" dependencies = [ "bitflags 2.999.999", "js-sys", diff --git a/gfx/wgpu_bindings/Cargo.toml b/gfx/wgpu_bindings/Cargo.toml index a60a997d4560..38ef45574572 100644 --- a/gfx/wgpu_bindings/Cargo.toml +++ b/gfx/wgpu_bindings/Cargo.toml @@ -17,7 +17,7 @@ default = [] [dependencies.wgc] package = "wgpu-core" git = "https://github.com/gfx-rs/wgpu" -rev = "332cd0325da52675432830870584ec9766679c34" +rev = "7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e" #Note: "replay" shouldn't ideally be needed, # but it allows us to serialize everything across IPC. features = ["replay", "trace", "serial-pass", "strict_asserts", "wgsl"] @@ -27,32 +27,32 @@ features = ["replay", "trace", "serial-pass", "strict_asserts", "wgsl"] [target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies.wgc] package = "wgpu-core" git = "https://github.com/gfx-rs/wgpu" -rev = "332cd0325da52675432830870584ec9766679c34" +rev = "7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e" features = ["metal"] # We want the wgpu-core Direct3D backends on Windows. [target.'cfg(windows)'.dependencies.wgc] package = "wgpu-core" git = "https://github.com/gfx-rs/wgpu" -rev = "332cd0325da52675432830870584ec9766679c34" +rev = "7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e" features = ["dx11", "dx12"] # We want the wgpu-core Vulkan backend on Linux and Windows. [target.'cfg(any(windows, all(unix, not(any(target_os = "macos", target_os = "ios")))))'.dependencies.wgc] package = "wgpu-core" git = "https://github.com/gfx-rs/wgpu" -rev = "332cd0325da52675432830870584ec9766679c34" +rev = "7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e" features = ["vulkan"] [dependencies.wgt] package = "wgpu-types" git = "https://github.com/gfx-rs/wgpu" -rev = "332cd0325da52675432830870584ec9766679c34" +rev = "7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e" [dependencies.wgh] package = "wgpu-hal" git = "https://github.com/gfx-rs/wgpu" -rev = "332cd0325da52675432830870584ec9766679c34" +rev = "7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e" [target.'cfg(windows)'.dependencies] d3d12 = "0.7.0" diff --git a/gfx/wgpu_bindings/moz.yaml b/gfx/wgpu_bindings/moz.yaml index eeb92dd6f96f..c216659eb6f2 100644 --- a/gfx/wgpu_bindings/moz.yaml +++ b/gfx/wgpu_bindings/moz.yaml @@ -20,11 +20,11 @@ origin: # Human-readable identifier for this version/release # Generally "version NNN", "tag SSS", "bookmark SSS" - release: commit 332cd0325da52675432830870584ec9766679c34 + release: commit 7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e # Revision to pull in # Must be a long or short commit SHA (long preferred) - revision: 332cd0325da52675432830870584ec9766679c34 + revision: 7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e license: ['MIT', 'Apache-2.0'] diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml index a697d5a70579..251440de2c95 100644 --- a/supply-chain/audits.toml +++ b/supply-chain/audits.toml @@ -2283,6 +2283,11 @@ who = "Teodor Tanasoaia " criteria = "safe-to-deploy" delta = "0.12.0@git:b99d58ea435090e561377949f428bce2c18451bb -> 0.12.0@git:76003dc0035d53a474d366dcdf49d2e4d12e921f" +[[audits.naga]] +who = "Nicolas Silva " +criteria = "safe-to-deploy" +delta = "0.13.0@git:7a19f3af909202c7eafd36633b5584bfbb353ecb -> 0.13.0@git:cc87b8f9eb30bb55d0735b89d3df3e099e1a6e7c" + [[audits.naga]] who = "Erich Gubler check_feature!(MULTI_VIEW, 140, 300), _ => check_feature!(MULTI_VIEW, 140, 310), @@ -233,6 +236,10 @@ impl FeaturesManager { // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_query_levels.txt writeln!(out, "#extension GL_ARB_texture_query_levels : require")?; } + if self.0.contains(Features::DUAL_SOURCE_BLENDING) && version.is_es() { + // https://registry.khronos.org/OpenGL/extensions/EXT/EXT_blend_func_extended.txt + writeln!(out, "#extension GL_EXT_blend_func_extended : require")?; + } Ok(()) } @@ -497,6 +504,7 @@ impl<'a, W> Writer<'a, W> { location: _, interpolation, sampling, + second_blend_source, } => { if interpolation == Some(Interpolation::Linear) { self.features.request(Features::NOPERSPECTIVE_QUALIFIER); @@ -504,6 +512,9 @@ impl<'a, W> Writer<'a, W> { if sampling == Some(Sampling::Sample) { self.features.request(Features::SAMPLE_QUALIFIER); } + if second_blend_source { + self.features.request(Features::DUAL_SOURCE_BLENDING); + } } } } diff --git a/third_party/rust/naga/src/back/glsl/keywords.rs b/third_party/rust/naga/src/back/glsl/keywords.rs index 9679020a0a2b..afadd6e7f1a8 100644 --- a/third_party/rust/naga/src/back/glsl/keywords.rs +++ b/third_party/rust/naga/src/back/glsl/keywords.rs @@ -477,4 +477,7 @@ pub const RESERVED_KEYWORDS: &[&str] = &[ // entry point name (should not be shadowed) // "main", + // Naga utilities: + super::MODF_FUNCTION, + super::FREXP_FUNCTION, ]; diff --git a/third_party/rust/naga/src/back/glsl/mod.rs b/third_party/rust/naga/src/back/glsl/mod.rs index ef5dd0143f47..54d5f341a243 100644 --- a/third_party/rust/naga/src/back/glsl/mod.rs +++ b/third_party/rust/naga/src/back/glsl/mod.rs @@ -72,6 +72,9 @@ pub const SUPPORTED_ES_VERSIONS: &[u16] = &[300, 310, 320]; /// of detail for bounds checking in `ImageLoad` const CLAMPED_LOD_SUFFIX: &str = "_clamped_lod"; +pub(crate) const MODF_FUNCTION: &str = "naga_modf"; +pub(crate) const FREXP_FUNCTION: &str = "naga_frexp"; + /// Mapping between resources and bindings. pub type BindingMap = std::collections::BTreeMap; @@ -333,6 +336,12 @@ struct VaryingName<'a> { impl fmt::Display for VaryingName<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self.binding { + crate::Binding::Location { + second_blend_source: true, + .. + } => { + write!(f, "_fs2p_location1",) + } crate::Binding::Location { location, .. } => { let prefix = match (self.stage, self.output) { (ShaderStage::Compute, _) => unreachable!(), @@ -625,6 +634,53 @@ impl<'a, W: Write> Writer<'a, W> { } } + // Write functions to create special types. + for (type_key, struct_ty) in self.module.special_types.predeclared_types.iter() { + match type_key { + &crate::PredeclaredType::ModfResult { size, width } + | &crate::PredeclaredType::FrexpResult { size, width } => { + let arg_type_name_owner; + let arg_type_name = if let Some(size) = size { + arg_type_name_owner = + format!("{}vec{}", if width == 8 { "d" } else { "" }, size as u8); + &arg_type_name_owner + } else if width == 8 { + "double" + } else { + "float" + }; + + let other_type_name_owner; + let (defined_func_name, called_func_name, other_type_name) = + if matches!(type_key, &crate::PredeclaredType::ModfResult { .. }) { + (MODF_FUNCTION, "modf", arg_type_name) + } else { + let other_type_name = if let Some(size) = size { + other_type_name_owner = format!("ivec{}", size as u8); + &other_type_name_owner + } else { + "int" + }; + (FREXP_FUNCTION, "frexp", other_type_name) + }; + + let struct_name = &self.names[&NameKey::Type(*struct_ty)]; + + writeln!(self.out)?; + writeln!( + self.out, + "{} {defined_func_name}({arg_type_name} arg) {{ + {other_type_name} other; + {arg_type_name} fract = {called_func_name}(arg, other); + return {}(fract, other); +}}", + struct_name, struct_name + )?; + } + &crate::PredeclaredType::AtomicCompareExchangeWeakResult { .. } => {} + } + } + // Write all named constants let mut constants = self .module @@ -1235,12 +1291,13 @@ impl<'a, W: Write> Writer<'a, W> { Some(binding) => binding, }; - let (location, interpolation, sampling) = match *binding { + let (location, interpolation, sampling, second_blend_source) = match *binding { crate::Binding::Location { location, interpolation, sampling, - } => (location, interpolation, sampling), + second_blend_source, + } => (location, interpolation, sampling, second_blend_source), crate::Binding::BuiltIn(built_in) => { if let crate::BuiltIn::Position { invariant: true } = built_in { match (self.options.version, self.entry_point.stage) { @@ -1281,7 +1338,11 @@ impl<'a, W: Write> Writer<'a, W> { // Write the I/O locations, if allowed if self.options.version.supports_explicit_locations() || !emit_interpolation_and_auxiliary { - write!(self.out, "layout(location = {location}) ")?; + if second_blend_source { + write!(self.out, "layout(location = {location}, index = 1) ")?; + } else { + write!(self.out, "layout(location = {location}) ")?; + } } // Write the interpolation qualifier. @@ -1318,6 +1379,7 @@ impl<'a, W: Write> Writer<'a, W> { location, interpolation: None, sampling: None, + second_blend_source, }, stage: self.entry_point.stage, output, @@ -2985,8 +3047,8 @@ impl<'a, W: Write> Writer<'a, W> { Mf::Round => "roundEven", Mf::Fract => "fract", Mf::Trunc => "trunc", - Mf::Modf => "modf", - Mf::Frexp => "frexp", + Mf::Modf => MODF_FUNCTION, + Mf::Frexp => FREXP_FUNCTION, Mf::Ldexp => "ldexp", // exponent Mf::Exp => "exp", diff --git a/third_party/rust/naga/src/back/hlsl/help.rs b/third_party/rust/naga/src/back/hlsl/help.rs index 7ad46313157f..2d725514b276 100644 --- a/third_party/rust/naga/src/back/hlsl/help.rs +++ b/third_party/rust/naga/src/back/hlsl/help.rs @@ -781,6 +781,59 @@ impl<'a, W: Write> super::Writer<'a, W> { Ok(()) } + /// Write functions to create special types. + pub(super) fn write_special_functions(&mut self, module: &crate::Module) -> BackendResult { + for (type_key, struct_ty) in module.special_types.predeclared_types.iter() { + match type_key { + &crate::PredeclaredType::ModfResult { size, width } + | &crate::PredeclaredType::FrexpResult { size, width } => { + let arg_type_name_owner; + let arg_type_name = if let Some(size) = size { + arg_type_name_owner = format!( + "{}{}", + if width == 8 { "double" } else { "float" }, + size as u8 + ); + &arg_type_name_owner + } else if width == 8 { + "double" + } else { + "float" + }; + + let (defined_func_name, called_func_name, second_field_name, sign_multiplier) = + if matches!(type_key, &crate::PredeclaredType::ModfResult { .. }) { + (super::writer::MODF_FUNCTION, "modf", "whole", "") + } else { + ( + super::writer::FREXP_FUNCTION, + "frexp", + "exp_", + "sign(arg) * ", + ) + }; + + let struct_name = &self.names[&NameKey::Type(*struct_ty)]; + + writeln!( + self.out, + "{struct_name} {defined_func_name}({arg_type_name} arg) {{ + {arg_type_name} other; + {struct_name} result; + result.fract = {sign_multiplier}{called_func_name}(arg, other); + result.{second_field_name} = other; + return result; +}}" + )?; + writeln!(self.out)?; + } + &crate::PredeclaredType::AtomicCompareExchangeWeakResult { .. } => {} + } + } + + Ok(()) + } + /// Helper function that writes compose wrapped functions pub(super) fn write_wrapped_compose_functions( &mut self, diff --git a/third_party/rust/naga/src/back/hlsl/keywords.rs b/third_party/rust/naga/src/back/hlsl/keywords.rs index 81b797bbf5ad..059e533ff706 100644 --- a/third_party/rust/naga/src/back/hlsl/keywords.rs +++ b/third_party/rust/naga/src/back/hlsl/keywords.rs @@ -814,6 +814,9 @@ pub const RESERVED: &[&str] = &[ "TextureBuffer", "ConstantBuffer", "RayQuery", + // Naga utilities + super::writer::MODF_FUNCTION, + super::writer::FREXP_FUNCTION, ]; // DXC scalar types, from https://github.com/microsoft/DirectXShaderCompiler/blob/18c9e114f9c314f93e68fbc72ce207d4ed2e65ae/tools/clang/lib/AST/ASTContextHLSL.cpp#L48-L254 diff --git a/third_party/rust/naga/src/back/hlsl/writer.rs b/third_party/rust/naga/src/back/hlsl/writer.rs index 4f191263881a..6da98502f147 100644 --- a/third_party/rust/naga/src/back/hlsl/writer.rs +++ b/third_party/rust/naga/src/back/hlsl/writer.rs @@ -17,6 +17,9 @@ const SPECIAL_BASE_VERTEX: &str = "base_vertex"; const SPECIAL_BASE_INSTANCE: &str = "base_instance"; const SPECIAL_OTHER: &str = "other"; +pub(crate) const MODF_FUNCTION: &str = "naga_modf"; +pub(crate) const FREXP_FUNCTION: &str = "naga_frexp"; + struct EpStructMember { name: String, ty: Handle, @@ -244,6 +247,8 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { } } + self.write_special_functions(module)?; + self.write_wrapped_compose_functions(module, &module.const_expressions)?; // Write all named constants @@ -416,7 +421,17 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { let builtin_str = builtin.to_hlsl_str()?; write!(self.out, " : {builtin_str}")?; } - crate::Binding::Location { location, .. } => { + crate::Binding::Location { + second_blend_source: true, + .. + } => { + write!(self.out, " : SV_Target1")?; + } + crate::Binding::Location { + location, + second_blend_source: false, + .. + } => { if stage == Some((crate::ShaderStage::Fragment, Io::Output)) { write!(self.out, " : SV_Target{location}")?; } else { @@ -2665,8 +2680,8 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { Mf::Round => Function::Regular("round"), Mf::Fract => Function::Regular("frac"), Mf::Trunc => Function::Regular("trunc"), - Mf::Modf => Function::Regular("modf"), - Mf::Frexp => Function::Regular("frexp"), + Mf::Modf => Function::Regular(MODF_FUNCTION), + Mf::Frexp => Function::Regular(FREXP_FUNCTION), Mf::Ldexp => Function::Regular("ldexp"), // exponent Mf::Exp => Function::Regular("exp"), diff --git a/third_party/rust/naga/src/back/msl/keywords.rs b/third_party/rust/naga/src/back/msl/keywords.rs index a3a9c52dcc65..f34b618db8ef 100644 --- a/third_party/rust/naga/src/back/msl/keywords.rs +++ b/third_party/rust/naga/src/back/msl/keywords.rs @@ -214,4 +214,6 @@ pub const RESERVED: &[&str] = &[ // Naga utilities "DefaultConstructible", "clamped_lod_e", + super::writer::FREXP_FUNCTION, + super::writer::MODF_FUNCTION, ]; diff --git a/third_party/rust/naga/src/back/msl/mod.rs b/third_party/rust/naga/src/back/msl/mod.rs index 78bcc2123bc5..819d48a8fdc7 100644 --- a/third_party/rust/naga/src/back/msl/mod.rs +++ b/third_party/rust/naga/src/back/msl/mod.rs @@ -82,7 +82,10 @@ pub type EntryPointResourceMap = std::collections::BTreeMap match mode { LocationMode::VertexInput => Ok(ResolvedBinding::Attribute(location)), - LocationMode::FragmentOutput => Ok(ResolvedBinding::Color(location)), + LocationMode::FragmentOutput => { + if second_blend_source && self.lang_version < (1, 2) { + return Err(Error::UnsupportedAttribute( + "second_blend_source".to_string(), + )); + } + Ok(ResolvedBinding::Color { + location, + second_blend_source, + }) + } LocationMode::VertexOutput | LocationMode::FragmentInput => { Ok(ResolvedBinding::User { prefix: if self.spirv_cross_compatibility { @@ -404,7 +418,16 @@ impl ResolvedBinding { write!(out, "{name}")?; } Self::Attribute(index) => write!(out, "attribute({index})")?, - Self::Color(index) => write!(out, "color({index})")?, + Self::Color { + location, + second_blend_source, + } => { + if second_blend_source { + write!(out, "color({location}) index(1)")? + } else { + write!(out, "color({location})")? + } + } Self::User { prefix, index, diff --git a/third_party/rust/naga/src/back/msl/writer.rs b/third_party/rust/naga/src/back/msl/writer.rs index a8a103e6d020..67ab88728570 100644 --- a/third_party/rust/naga/src/back/msl/writer.rs +++ b/third_party/rust/naga/src/back/msl/writer.rs @@ -32,6 +32,9 @@ const RAY_QUERY_FIELD_INTERSECTION: &str = "intersection"; const RAY_QUERY_FIELD_READY: &str = "ready"; const RAY_QUERY_FUN_MAP_INTERSECTION: &str = "_map_intersection_type"; +pub(crate) const MODF_FUNCTION: &str = "naga_modf"; +pub(crate) const FREXP_FUNCTION: &str = "naga_frexp"; + /// Write the Metal name for a Naga numeric type: scalar, vector, or matrix. /// /// The `sizes` slice determines whether this function writes a @@ -1181,6 +1184,31 @@ impl Writer { Ok(()) } + /// Emit code for the sign(i32) expression. + /// + fn put_isign( + &mut self, + arg: Handle, + context: &ExpressionContext, + ) -> BackendResult { + write!(self.out, "{NAMESPACE}::select({NAMESPACE}::select(")?; + match context.resolve_type(arg) { + &crate::TypeInner::Vector { size, .. } => { + let size = back::vector_size_str(size); + write!(self.out, "int{size}(-1), int{size}(1)")?; + } + _ => { + write!(self.out, "-1, 1")?; + } + } + write!(self.out, ", (")?; + self.put_expression(arg, context, true)?; + write!(self.out, " > 0)), 0, (")?; + self.put_expression(arg, context, true)?; + write!(self.out, " == 0))")?; + Ok(()) + } + fn put_const_expression( &mut self, expr_handle: Handle, @@ -1644,8 +1672,9 @@ impl Writer { } => { use crate::MathFunction as Mf; - let scalar_argument = match *context.resolve_type(arg) { - crate::TypeInner::Scalar { .. } => true, + let arg_type = context.resolve_type(arg); + let scalar_argument = match arg_type { + &crate::TypeInner::Scalar { .. } => true, _ => false, }; @@ -1678,8 +1707,8 @@ impl Writer { Mf::Round => "rint", Mf::Fract => "fract", Mf::Trunc => "trunc", - Mf::Modf => "modf", - Mf::Frexp => "frexp", + Mf::Modf => MODF_FUNCTION, + Mf::Frexp => FREXP_FUNCTION, Mf::Ldexp => "ldexp", // exponent Mf::Exp => "exp", @@ -1710,7 +1739,12 @@ impl Writer { Mf::Reflect => "reflect", Mf::Refract => "refract", // computational - Mf::Sign => "sign", + Mf::Sign => match arg_type.scalar_kind() { + Some(crate::ScalarKind::Sint) => { + return self.put_isign(arg, context); + } + _ => "sign", + }, Mf::Fma => "fma", Mf::Mix => "mix", Mf::Step => "step", @@ -1813,6 +1847,9 @@ impl Writer { write!(self.out, "((")?; self.put_expression(arg, context, false)?; write!(self.out, ") * 57.295779513082322865)")?; + } else if fun == Mf::Modf || fun == Mf::Frexp { + write!(self.out, "{fun_name}")?; + self.put_call_parameters(iter::once(arg), context)?; } else { write!(self.out, "{NAMESPACE}::{fun_name}")?; self.put_call_parameters( @@ -2417,6 +2454,16 @@ impl Writer { crate::MathFunction::FindMsb => { self.need_bake_expressions.insert(arg); } + crate::MathFunction::Sign => { + // WGSL's `sign` function works also on signed ints, but Metal's only + // works on floating points, so we emit inline code for integer `sign` + // calls. But that code uses each argument 2 times (see `put_isign`), + // so to avoid duplicated evaluation, we must bake the argument. + let inner = context.resolve_type(expr_handle); + if inner.scalar_kind() == Some(crate::ScalarKind::Sint) { + self.need_bake_expressions.insert(arg); + } + } _ => {} } } @@ -3236,6 +3283,57 @@ impl Writer { } } } + + // Write functions to create special types. + for (type_key, struct_ty) in module.special_types.predeclared_types.iter() { + match type_key { + &crate::PredeclaredType::ModfResult { size, width } + | &crate::PredeclaredType::FrexpResult { size, width } => { + let arg_type_name_owner; + let arg_type_name = if let Some(size) = size { + arg_type_name_owner = format!( + "{NAMESPACE}::{}{}", + if width == 8 { "double" } else { "float" }, + size as u8 + ); + &arg_type_name_owner + } else if width == 8 { + "double" + } else { + "float" + }; + + let other_type_name_owner; + let (defined_func_name, called_func_name, other_type_name) = + if matches!(type_key, &crate::PredeclaredType::ModfResult { .. }) { + (MODF_FUNCTION, "modf", arg_type_name) + } else { + let other_type_name = if let Some(size) = size { + other_type_name_owner = format!("int{}", size as u8); + &other_type_name_owner + } else { + "int" + }; + (FREXP_FUNCTION, "frexp", other_type_name) + }; + + let struct_name = &self.names[&NameKey::Type(*struct_ty)]; + + writeln!(self.out)?; + writeln!( + self.out, + "{} {defined_func_name}({arg_type_name} arg) {{ + {other_type_name} other; + {arg_type_name} fract = {NAMESPACE}::{called_func_name}(arg, other); + return {}{{ fract, other }}; +}}", + struct_name, struct_name + )?; + } + &crate::PredeclaredType::AtomicCompareExchangeWeakResult { .. } => {} + } + } + Ok(()) } diff --git a/third_party/rust/naga/src/back/spv/block.rs b/third_party/rust/naga/src/back/spv/block.rs index 11841bc5228b..c5246ad190c3 100644 --- a/third_party/rust/naga/src/back/spv/block.rs +++ b/third_party/rust/naga/src/back/spv/block.rs @@ -787,8 +787,8 @@ impl<'w> BlockContext<'w> { Mf::Floor => MathOp::Ext(spirv::GLOp::Floor), Mf::Fract => MathOp::Ext(spirv::GLOp::Fract), Mf::Trunc => MathOp::Ext(spirv::GLOp::Trunc), - Mf::Modf => MathOp::Ext(spirv::GLOp::Modf), - Mf::Frexp => MathOp::Ext(spirv::GLOp::Frexp), + Mf::Modf => MathOp::Ext(spirv::GLOp::ModfStruct), + Mf::Frexp => MathOp::Ext(spirv::GLOp::FrexpStruct), Mf::Ldexp => MathOp::Ext(spirv::GLOp::Ldexp), // geometry Mf::Dot => match *self.fun_info[arg].ty.inner_with(&self.ir_module.types) { diff --git a/third_party/rust/naga/src/back/spv/writer.rs b/third_party/rust/naga/src/back/spv/writer.rs index e6db93602a42..41a13cbc19d3 100644 --- a/third_party/rust/naga/src/back/spv/writer.rs +++ b/third_party/rust/naga/src/back/spv/writer.rs @@ -1434,6 +1434,7 @@ impl Writer { location, interpolation, sampling, + second_blend_source, } => { self.decorate(id, Decoration::Location, &[location]); @@ -1473,6 +1474,9 @@ impl Writer { } } } + if second_blend_source { + self.decorate(id, Decoration::Index, &[1]); + } } crate::Binding::BuiltIn(built_in) => { use crate::BuiltIn as Bi; diff --git a/third_party/rust/naga/src/back/wgsl/writer.rs b/third_party/rust/naga/src/back/wgsl/writer.rs index 44dd2a97c005..da39cd94f27b 100644 --- a/third_party/rust/naga/src/back/wgsl/writer.rs +++ b/third_party/rust/naga/src/back/wgsl/writer.rs @@ -17,6 +17,7 @@ enum Attribute { Invariant, Interpolate(Option, Option), Location(u32), + SecondBlendSource, Stage(ShaderStage), WorkGroupSize([u32; 3]), } @@ -96,6 +97,14 @@ impl Writer { self.ep_results.clear(); } + fn is_builtin_wgsl_struct(&self, module: &Module, handle: Handle) -> bool { + module + .special_types + .predeclared_types + .values() + .any(|t| *t == handle) + } + pub fn write(&mut self, module: &Module, info: &valid::ModuleInfo) -> BackendResult { self.reset(module); @@ -108,13 +117,13 @@ impl Writer { // Write all structs for (handle, ty) in module.types.iter() { - if let TypeInner::Struct { - ref members, - span: _, - } = ty.inner - { - self.write_struct(module, handle, members)?; - writeln!(self.out)?; + if let TypeInner::Struct { ref members, .. } = ty.inner { + { + if !self.is_builtin_wgsl_struct(module, handle) { + self.write_struct(module, handle, members)?; + writeln!(self.out)?; + } + } } } @@ -319,6 +328,7 @@ impl Writer { for attribute in attributes { match *attribute { Attribute::Location(id) => write!(self.out, "@location({id}) ")?, + Attribute::SecondBlendSource => write!(self.out, "@second_blend_source ")?, Attribute::BuiltIn(builtin_attrib) => { let builtin = builtin_str(builtin_attrib)?; write!(self.out, "@builtin({builtin}) ")?; @@ -1917,9 +1927,20 @@ fn map_binding_to_attribute(binding: &crate::Binding) -> Vec { location, interpolation, sampling, + second_blend_source: false, } => vec![ Attribute::Location(location), Attribute::Interpolate(interpolation, sampling), ], + crate::Binding::Location { + location, + interpolation, + sampling, + second_blend_source: true, + } => vec![ + Attribute::Location(location), + Attribute::SecondBlendSource, + Attribute::Interpolate(interpolation, sampling), + ], } } diff --git a/third_party/rust/naga/src/front/glsl/builtins.rs b/third_party/rust/naga/src/front/glsl/builtins.rs index 5a5acf4321ad..811be65ccea6 100644 --- a/third_party/rust/naga/src/front/glsl/builtins.rs +++ b/third_party/rust/naga/src/front/glsl/builtins.rs @@ -7,7 +7,7 @@ use super::{ Error, ErrorKind, Frontend, Result, }; use crate::{ - BinaryOperator, Block, DerivativeAxis as Axis, DerivativeControl as Ctrl, Expression, Handle, + BinaryOperator, DerivativeAxis as Axis, DerivativeControl as Ctrl, Expression, Handle, ImageClass, ImageDimension as Dim, ImageQuery, MathFunction, Module, RelationalFunction, SampleLevel, ScalarKind as Sk, Span, Type, TypeInner, UnaryOperator, VectorSize, }; @@ -1280,14 +1280,14 @@ fn inject_common_builtin( 0b10 => Some(VectorSize::Tri), _ => Some(VectorSize::Quad), }; - let ty = || match size { + let ty = |kind| match size { Some(size) => TypeInner::Vector { size, - kind: Sk::Float, + kind, width: float_width, }, None => TypeInner::Scalar { - kind: Sk::Float, + kind, width: float_width, }, }; @@ -1300,9 +1300,15 @@ fn inject_common_builtin( _ => unreachable!(), }; + let second_kind = if fun == MacroCall::MathFunction(MathFunction::Ldexp) { + Sk::Sint + } else { + Sk::Float + }; + declaration .overloads - .push(module.add_builtin(vec![ty(), ty()], fun)) + .push(module.add_builtin(vec![ty(Sk::Float), ty(second_kind)], fun)) } } "transpose" => { @@ -1678,7 +1684,6 @@ impl MacroCall { &self, frontend: &mut Frontend, ctx: &mut Context, - body: &mut Block, args: &mut [Handle], meta: Span, ) -> Result>> { @@ -1688,14 +1693,8 @@ impl MacroCall { args[0] } MacroCall::SamplerShadow => { - sampled_to_depth( - &mut frontend.module, - ctx, - args[0], - meta, - &mut frontend.errors, - ); - frontend.invalidate_expression(ctx, args[0], meta)?; + sampled_to_depth(ctx, args[0], meta, &mut frontend.errors); + ctx.invalidate_expression(args[0], meta)?; ctx.samplers.insert(args[0], args[1]); args[0] } @@ -1708,7 +1707,7 @@ impl MacroCall { let mut coords = args[1]; if proj { - let size = match *frontend.resolve_type(ctx, coords, meta)? { + let size = match *ctx.resolve_type(coords, meta)? { TypeInner::Vector { size, .. } => size, _ => unreachable!(), }; @@ -1718,8 +1717,7 @@ impl MacroCall { index: size as u32 - 1, }, Span::default(), - body, - ); + )?; let left = if let VectorSize::Bi = size { ctx.add_expression( Expression::AccessIndex { @@ -1727,8 +1725,7 @@ impl MacroCall { index: 0, }, Span::default(), - body, - ) + )? } else { let size = match size { VectorSize::Tri => VectorSize::Bi, @@ -1737,9 +1734,8 @@ impl MacroCall { right = ctx.add_expression( Expression::Splat { size, value: right }, Span::default(), - body, - ); - ctx.vector_resize(size, coords, Span::default(), body) + )?; + ctx.vector_resize(size, coords, Span::default())? }; coords = ctx.add_expression( Expression::Binary { @@ -1748,13 +1744,11 @@ impl MacroCall { right, }, Span::default(), - body, - ); + )?; } let extra = args.get(2).copied(); - let comps = - frontend.coordinate_components(ctx, args[0], coords, extra, meta, body)?; + let comps = frontend.coordinate_components(ctx, args[0], coords, extra, meta)?; let mut num_args = 2; @@ -1801,7 +1795,7 @@ impl MacroCall { true => { let offset_arg = args[num_args]; num_args += 1; - match frontend.solve_constant(ctx, offset_arg, meta) { + match ctx.solve_constant(offset_arg, meta) { Ok(v) => Some(v), Err(e) => { frontend.errors.push(e); @@ -1820,7 +1814,7 @@ impl MacroCall { .map_or(SampleLevel::Auto, SampleLevel::Bias); } - texture_call(ctx, args[0], level, comps, texture_offset, body, meta)? + texture_call(ctx, args[0], level, comps, texture_offset, meta)? } MacroCall::TextureSize { arrayed } => { @@ -1832,20 +1826,18 @@ impl MacroCall { }, }, Span::default(), - body, - ); + )?; if arrayed { let mut components = Vec::with_capacity(4); - let size = match *frontend.resolve_type(ctx, expr, meta)? { + let size = match *ctx.resolve_type(expr, meta)? { TypeInner::Vector { size: ori_size, .. } => { for index in 0..(ori_size as u32) { components.push(ctx.add_expression( Expression::AccessIndex { base: expr, index }, Span::default(), - body, - )) + )?) } match ori_size { @@ -1865,10 +1857,9 @@ impl MacroCall { query: ImageQuery::NumLayers, }, Span::default(), - body, - )); + )?); - let ty = frontend.module.types.insert( + let ty = ctx.module.types.insert( Type { name: None, inner: TypeInner::Vector { @@ -1880,7 +1871,7 @@ impl MacroCall { Span::default(), ); - expr = ctx.add_expression(Expression::Compose { components, ty }, meta, body) + expr = ctx.add_expression(Expression::Compose { components, ty }, meta)? } ctx.add_expression( @@ -1890,12 +1881,10 @@ impl MacroCall { convert: Some(4), }, Span::default(), - body, - ) + )? } MacroCall::ImageLoad { multi } => { - let comps = - frontend.coordinate_components(ctx, args[0], args[1], None, meta, body)?; + let comps = frontend.coordinate_components(ctx, args[0], args[1], None, meta)?; let (sample, level) = match (multi, args.get(2)) { (_, None) => (None, None), (true, Some(&arg)) => (Some(arg), None), @@ -1910,14 +1899,12 @@ impl MacroCall { level, }, Span::default(), - body, - ) + )? } MacroCall::ImageStore => { - let comps = - frontend.coordinate_components(ctx, args[0], args[1], None, meta, body)?; - ctx.emit_restart(body); - body.push( + let comps = frontend.coordinate_components(ctx, args[0], args[1], None, meta)?; + ctx.emit_restart(); + ctx.body.push( crate::Statement::ImageStore { image: args[0], coordinate: comps.coordinate, @@ -1937,8 +1924,7 @@ impl MacroCall { arg3: args.get(3).copied(), }, Span::default(), - body, - ), + )?, mc @ (MacroCall::FindLsbUint | MacroCall::FindMsbUint) => { let fun = match mc { MacroCall::FindLsbUint => MathFunction::FindLsb, @@ -1954,8 +1940,7 @@ impl MacroCall { arg3: None, }, Span::default(), - body, - ); + )?; ctx.add_expression( Expression::As { expr: res, @@ -1963,8 +1948,7 @@ impl MacroCall { convert: Some(4), }, Span::default(), - body, - ) + )? } MacroCall::BitfieldInsert => { let conv_arg_2 = ctx.add_expression( @@ -1974,8 +1958,7 @@ impl MacroCall { convert: Some(4), }, Span::default(), - body, - ); + )?; let conv_arg_3 = ctx.add_expression( Expression::As { expr: args[3], @@ -1983,8 +1966,7 @@ impl MacroCall { convert: Some(4), }, Span::default(), - body, - ); + )?; ctx.add_expression( Expression::Math { fun: MathFunction::InsertBits, @@ -1994,8 +1976,7 @@ impl MacroCall { arg3: Some(conv_arg_3), }, Span::default(), - body, - ) + )? } MacroCall::BitfieldExtract => { let conv_arg_1 = ctx.add_expression( @@ -2005,8 +1986,7 @@ impl MacroCall { convert: Some(4), }, Span::default(), - body, - ); + )?; let conv_arg_2 = ctx.add_expression( Expression::As { expr: args[2], @@ -2014,8 +1994,7 @@ impl MacroCall { convert: Some(4), }, Span::default(), - body, - ); + )?; ctx.add_expression( Expression::Math { fun: MathFunction::ExtractBits, @@ -2025,8 +2004,7 @@ impl MacroCall { arg3: None, }, Span::default(), - body, - ) + )? } MacroCall::Relational(fun) => ctx.add_expression( Expression::Relational { @@ -2034,13 +2012,10 @@ impl MacroCall { argument: args[0], }, Span::default(), - body, - ), - MacroCall::Unary(op) => ctx.add_expression( - Expression::Unary { op, expr: args[0] }, - Span::default(), - body, - ), + )?, + MacroCall::Unary(op) => { + ctx.add_expression(Expression::Unary { op, expr: args[0] }, Span::default())? + } MacroCall::Binary(op) => ctx.add_expression( Expression::Binary { op, @@ -2048,10 +2023,9 @@ impl MacroCall { right: args[1], }, Span::default(), - body, - ), + )?, MacroCall::Mod(size) => { - ctx.implicit_splat(frontend, &mut args[1], meta, size)?; + ctx.implicit_splat(&mut args[1], meta, size)?; // x - y * floor(x / y) @@ -2062,8 +2036,7 @@ impl MacroCall { right: args[1], }, Span::default(), - body, - ); + )?; let floor = ctx.add_expression( Expression::Math { fun: MathFunction::Floor, @@ -2073,8 +2046,7 @@ impl MacroCall { arg3: None, }, Span::default(), - body, - ); + )?; let mult = ctx.add_expression( Expression::Binary { op: BinaryOperator::Multiply, @@ -2082,8 +2054,7 @@ impl MacroCall { right: args[1], }, Span::default(), - body, - ); + )?; ctx.add_expression( Expression::Binary { op: BinaryOperator::Subtract, @@ -2091,11 +2062,10 @@ impl MacroCall { right: mult, }, Span::default(), - body, - ) + )? } MacroCall::Splatted(fun, size, i) => { - ctx.implicit_splat(frontend, &mut args[i], meta, size)?; + ctx.implicit_splat(&mut args[i], meta, size)?; ctx.add_expression( Expression::Math { @@ -2106,8 +2076,7 @@ impl MacroCall { arg3: args.get(3).copied(), }, Span::default(), - body, - ) + )? } MacroCall::MixBoolean => ctx.add_expression( Expression::Select { @@ -2116,11 +2085,10 @@ impl MacroCall { reject: args[0], }, Span::default(), - body, - ), + )?, MacroCall::Clamp(size) => { - ctx.implicit_splat(frontend, &mut args[1], meta, size)?; - ctx.implicit_splat(frontend, &mut args[2], meta, size)?; + ctx.implicit_splat(&mut args[1], meta, size)?; + ctx.implicit_splat(&mut args[2], meta, size)?; ctx.add_expression( Expression::Math { @@ -2131,8 +2099,7 @@ impl MacroCall { arg3: args.get(3).copied(), }, Span::default(), - body, - ) + )? } MacroCall::BitCast(kind) => ctx.add_expression( Expression::As { @@ -2141,8 +2108,7 @@ impl MacroCall { convert: None, }, Span::default(), - body, - ), + )?, MacroCall::Derivate(axis, ctrl) => ctx.add_expression( Expression::Derivative { axis, @@ -2150,16 +2116,16 @@ impl MacroCall { expr: args[0], }, Span::default(), - body, - ), + )?, MacroCall::Barrier => { - ctx.emit_restart(body); - body.push(crate::Statement::Barrier(crate::Barrier::all()), meta); + ctx.emit_restart(); + ctx.body + .push(crate::Statement::Barrier(crate::Barrier::all()), meta); return Ok(None); } MacroCall::SmoothStep { splatted } => { - ctx.implicit_splat(frontend, &mut args[0], meta, splatted)?; - ctx.implicit_splat(frontend, &mut args[1], meta, splatted)?; + ctx.implicit_splat(&mut args[0], meta, splatted)?; + ctx.implicit_splat(&mut args[1], meta, splatted)?; ctx.add_expression( Expression::Math { @@ -2170,8 +2136,7 @@ impl MacroCall { arg3: None, }, Span::default(), - body, - ) + )? } })) } @@ -2183,7 +2148,6 @@ fn texture_call( level: SampleLevel, comps: CoordComponents, offset: Option>, - body: &mut Block, meta: Span, ) -> Result> { if let Some(sampler) = ctx.samplers.get(&image).copied() { @@ -2205,8 +2169,7 @@ fn texture_call( depth_ref: comps.depth_ref, }, meta, - body, - )) + )?) } else { Err(Error { kind: ErrorKind::SemanticError("Bad call".into()), @@ -2235,13 +2198,12 @@ impl Frontend { coord: Handle, extra: Option>, meta: Span, - body: &mut Block, ) -> Result { if let TypeInner::Image { dim, arrayed, class, - } = *self.resolve_type(ctx, image, meta)? + } = *ctx.resolve_type(image, meta)? { let image_size = match dim { Dim::D1 => None, @@ -2249,7 +2211,7 @@ impl Frontend { Dim::D3 => Some(VectorSize::Tri), Dim::Cube => Some(VectorSize::Tri), }; - let coord_size = match *self.resolve_type(ctx, coord, meta)? { + let coord_size = match *ctx.resolve_type(coord, meta)? { TypeInner::Vector { size, .. } => Some(size), _ => None, }; @@ -2261,7 +2223,7 @@ impl Frontend { let coordinate = match (image_size, coord_size) { (Some(size), Some(coord_s)) if size != coord_s => { - ctx.vector_resize(size, coord, Span::default(), body) + ctx.vector_resize(size, coord, Span::default())? } (None, Some(_)) => ctx.add_expression( Expression::AccessIndex { @@ -2269,8 +2231,7 @@ impl Frontend { index: 0, }, Span::default(), - body, - ), + )?, _ => coord, }; @@ -2283,8 +2244,7 @@ impl Frontend { Some(ctx.add_expression( Expression::AccessIndex { base: coord, index }, Span::default(), - body, - )) + )?) } else { None }; @@ -2300,8 +2260,7 @@ impl Frontend { Some(ctx.add_expression( Expression::AccessIndex { base: coord, index }, Span::default(), - body, - )) + )?) } } false => None, @@ -2332,7 +2291,6 @@ impl Frontend { /// Helper function to cast a expression holding a sampled image to a /// depth image. pub fn sampled_to_depth( - module: &mut Module, ctx: &mut Context, image: Handle, meta: Span, @@ -2340,7 +2298,7 @@ pub fn sampled_to_depth( ) { // Get the a mutable type handle of the underlying image storage let ty = match ctx[image] { - Expression::GlobalVariable(handle) => &mut module.global_variables.get_mut(handle).ty, + Expression::GlobalVariable(handle) => &mut ctx.module.global_variables.get_mut(handle).ty, Expression::FunctionArgument(i) => { // Mark the function argument as carrying a depth texture ctx.parameters_info[i as usize].depth = true; @@ -2356,7 +2314,7 @@ pub fn sampled_to_depth( } }; - match module.types[*ty].inner { + match ctx.module.types[*ty].inner { // Update the image class to depth in case it already isn't TypeInner::Image { class, @@ -2364,7 +2322,7 @@ pub fn sampled_to_depth( arrayed, } => match class { ImageClass::Sampled { multi, .. } => { - *ty = module.types.insert( + *ty = ctx.module.types.insert( Type { name: None, inner: TypeInner::Image { diff --git a/third_party/rust/naga/src/front/glsl/context.rs b/third_party/rust/naga/src/front/glsl/context.rs index e16dc125e7f7..407619c3d2a7 100644 --- a/third_party/rust/naga/src/front/glsl/context.rs +++ b/third_party/rust/naga/src/front/glsl/context.rs @@ -44,7 +44,7 @@ impl ExprPos { } #[derive(Debug)] -pub struct Context { +pub struct Context<'a> { pub expressions: Arena, pub locals: Arena, @@ -74,10 +74,12 @@ pub struct Context { pub typifier: Typifier, emitter: Emitter, stmt_ctx: Option, + pub body: Block, + pub module: &'a mut crate::Module, } -impl Context { - pub fn new(frontend: &Frontend, body: &mut Block) -> Self { +impl<'a> Context<'a> { + pub fn new(frontend: &Frontend, module: &'a mut crate::Module) -> Result { let mut this = Context { expressions: Arena::new(), locals: Arena::new(), @@ -92,62 +94,84 @@ impl Context { typifier: Typifier::new(), emitter: Emitter::default(), stmt_ctx: Some(StmtContext::new()), + body: Block::new(), + module, }; this.emit_start(); for &(ref name, lookup) in frontend.global_variables.iter() { - this.add_global(frontend, name, lookup, body) + this.add_global(name, lookup)? } - this + Ok(this) + } + + pub fn new_body(&mut self, cb: F) -> Result + where + F: FnOnce(&mut Self) -> Result<()>, + { + self.new_body_with_ret(cb).map(|(b, _)| b) + } + + pub fn new_body_with_ret(&mut self, cb: F) -> Result<(Block, R)> + where + F: FnOnce(&mut Self) -> Result, + { + self.emit_restart(); + let old_body = std::mem::replace(&mut self.body, Block::new()); + let res = cb(self); + self.emit_restart(); + let new_body = std::mem::replace(&mut self.body, old_body); + res.map(|r| (new_body, r)) + } + + pub fn with_body(&mut self, body: Block, cb: F) -> Result + where + F: FnOnce(&mut Self) -> Result<()>, + { + self.emit_restart(); + let old_body = std::mem::replace(&mut self.body, body); + let res = cb(self); + self.emit_restart(); + let body = std::mem::replace(&mut self.body, old_body); + res.map(|_| body) } pub fn add_global( &mut self, - frontend: &Frontend, name: &str, GlobalLookup { kind, entry_arg, mutable, }: GlobalLookup, - body: &mut Block, - ) { - self.emit_end(body); + ) -> Result<()> { let (expr, load, constant) = match kind { GlobalLookupKind::Variable(v) => { - let span = frontend.module.global_variables.get_span(v); - let res = ( - self.expressions.append(Expression::GlobalVariable(v), span), - frontend.module.global_variables[v].space != AddressSpace::Handle, + let span = self.module.global_variables.get_span(v); + ( + self.add_expression(Expression::GlobalVariable(v), span)?, + self.module.global_variables[v].space != AddressSpace::Handle, None, - ); - self.emit_start(); - - res + ) } GlobalLookupKind::BlockSelect(handle, index) => { - let span = frontend.module.global_variables.get_span(handle); - let base = self - .expressions - .append(Expression::GlobalVariable(handle), span); - self.emit_start(); - let expr = self - .expressions - .append(Expression::AccessIndex { base, index }, span); + let span = self.module.global_variables.get_span(handle); + let base = self.add_expression(Expression::GlobalVariable(handle), span)?; + let expr = self.add_expression(Expression::AccessIndex { base, index }, span)?; ( expr, { - let ty = frontend.module.global_variables[handle].ty; + let ty = self.module.global_variables[handle].ty; - match frontend.module.types[ty].inner { + match self.module.types[ty].inner { TypeInner::Struct { ref members, .. } => { if let TypeInner::Array { size: crate::ArraySize::Dynamic, .. - } = frontend.module.types[members[index as usize].ty].inner + } = self.module.types[members[index as usize].ty].inner { false } else { @@ -161,14 +185,12 @@ impl Context { ) } GlobalLookupKind::Constant(v, ty) => { - let span = frontend.module.constants.get_span(v); - let res = ( - self.expressions.append(Expression::Constant(v), span), + let span = self.module.constants.get_span(v); + ( + self.add_expression(Expression::Constant(v), span)?, false, Some((v, ty)), - ); - self.emit_start(); - res + ) } }; @@ -181,6 +203,8 @@ impl Context { }; self.symbol_table.add(name.into(), var); + + Ok(()) } /// Starts the expression emitter @@ -193,7 +217,7 @@ impl Context { self.emitter.start(&self.expressions) } - /// Emits all the expressions captured by the emitter to the passed `body` + /// Emits all the expressions captured by the emitter to the current body /// /// # Panics /// @@ -201,36 +225,31 @@ impl Context { /// - If called twice in a row without calling [`emit_start`]. /// /// [`emit_start`]: Self::emit_start - pub fn emit_end(&mut self, body: &mut Block) { - body.extend(self.emitter.finish(&self.expressions)) + pub fn emit_end(&mut self) { + self.body.extend(self.emitter.finish(&self.expressions)) } - /// Emits all the expressions captured by the emitter to the passed `body` + /// Emits all the expressions captured by the emitter to the current body /// and starts the emitter again /// /// # Panics /// /// - If called before calling [`emit_start`][Self::emit_start]. - pub fn emit_restart(&mut self, body: &mut Block) { - self.emit_end(body); + pub fn emit_restart(&mut self) { + self.emit_end(); self.emit_start() } - pub fn add_expression( - &mut self, - expr: Expression, - meta: Span, - body: &mut Block, - ) -> Handle { + pub fn add_expression(&mut self, expr: Expression, meta: Span) -> Result> { let needs_pre_emit = expr.needs_pre_emit(); if needs_pre_emit { - self.emit_end(body); + self.emit_end(); } let handle = self.expressions.append(expr, meta); if needs_pre_emit { self.emit_start(); } - handle + Ok(handle) } /// Add variable to current scope @@ -257,12 +276,10 @@ impl Context { /// Add function argument to current scope pub fn add_function_arg( &mut self, - frontend: &mut Frontend, - body: &mut Block, name_meta: Option<(String, Span)>, ty: Handle, qualifier: ParameterQualifier, - ) { + ) -> Result<()> { let index = self.arguments.len(); let mut arg = FunctionArgument { name: name_meta.as_ref().map(|&(ref name, _)| name.clone()), @@ -271,14 +288,14 @@ impl Context { }; self.parameters.push(ty); - let opaque = match frontend.module.types[ty].inner { + let opaque = match self.module.types[ty].inner { TypeInner::Image { .. } | TypeInner::Sampler { .. } => true, _ => false, }; if qualifier.is_lhs() { - let span = frontend.module.types.get_span(arg.ty); - arg.ty = frontend.module.types.insert( + let span = self.module.types.get_span(arg.ty); + arg.ty = self.module.types.insert( Type { name: None, inner: TypeInner::Pointer { @@ -298,7 +315,7 @@ impl Context { }); if let Some((name, meta)) = name_meta { - let expr = self.add_expression(Expression::FunctionArgument(index as u32), meta, body); + let expr = self.add_expression(Expression::FunctionArgument(index as u32), meta)?; let mutable = qualifier != ParameterQualifier::Const && !opaque; let load = qualifier.is_lhs(); @@ -311,11 +328,11 @@ impl Context { }, meta, ); - let local_expr = self.add_expression(Expression::LocalVariable(handle), meta, body); + let local_expr = self.add_expression(Expression::LocalVariable(handle), meta)?; - self.emit_restart(body); + self.emit_restart(); - body.push( + self.body.push( Statement::Store { pointer: local_expr, value: expr, @@ -342,6 +359,8 @@ impl Context { self.symbol_table.add(name, var); } + + Ok(()) } /// Returns a [`StmtContext`](StmtContext) to be used in parsing and lowering @@ -364,9 +383,8 @@ impl Context { frontend: &mut Frontend, expr: Handle, pos: ExprPos, - body: &mut Block, ) -> Result<(Option>, Span)> { - let res = self.lower_inner(&stmt, frontend, expr, pos, body); + let res = self.lower_inner(&stmt, frontend, expr, pos); stmt.hir_exprs.clear(); self.stmt_ctx = Some(stmt); @@ -385,9 +403,8 @@ impl Context { frontend: &mut Frontend, expr: Handle, pos: ExprPos, - body: &mut Block, ) -> Result<(Handle, Span)> { - let res = self.lower_expect_inner(&stmt, frontend, expr, pos, body); + let res = self.lower_expect_inner(&stmt, frontend, expr, pos); stmt.hir_exprs.clear(); self.stmt_ctx = Some(stmt); @@ -406,9 +423,8 @@ impl Context { frontend: &mut Frontend, expr: Handle, pos: ExprPos, - body: &mut Block, ) -> Result<(Handle, Span)> { - let (maybe_expr, meta) = self.lower_inner(stmt, frontend, expr, pos, body)?; + let (maybe_expr, meta) = self.lower_inner(stmt, frontend, expr, pos)?; let expr = match maybe_expr { Some(e) => e, @@ -428,8 +444,7 @@ impl Context { pointer: Handle, value: Handle, meta: Span, - body: &mut Block, - ) { + ) -> Result<()> { if let Expression::Swizzle { size, mut vector, @@ -456,20 +471,18 @@ impl Context { index: pattern[index].index(), }, meta, - body, - ); + )?; let src = self.add_expression( Expression::AccessIndex { base: value, index: index as u32, }, meta, - body, - ); + )?; - self.emit_restart(body); + self.emit_restart(); - body.push( + self.body.push( Statement::Store { pointer: dst, value: src, @@ -478,10 +491,12 @@ impl Context { ); } } else { - self.emit_restart(body); + self.emit_restart(); - body.push(Statement::Store { pointer, value }, meta); + self.body.push(Statement::Store { pointer, value }, meta); } + + Ok(()) } /// Internal implementation of [`lower`](Self::lower) @@ -491,7 +506,6 @@ impl Context { frontend: &mut Frontend, expr: Handle, pos: ExprPos, - body: &mut Block, ) -> Result<(Option>, Span)> { let HirExpr { ref kind, meta } = stmt.hir_exprs[expr]; @@ -500,12 +514,12 @@ impl Context { let handle = match *kind { HirExprKind::Access { base, index } => { let (index, index_meta) = - self.lower_expect_inner(stmt, frontend, index, ExprPos::Rhs, body)?; + self.lower_expect_inner(stmt, frontend, index, ExprPos::Rhs)?; let maybe_constant_index = match pos { // Don't try to generate `AccessIndex` if in a LHS position, since it // wouldn't produce a pointer. ExprPos::Lhs => None, - _ => frontend.solve_constant(self, index, index_meta).ok(), + _ => self.solve_constant(index, index_meta).ok(), }; let base = self @@ -514,7 +528,6 @@ impl Context { frontend, base, pos.maybe_access_base(maybe_constant_index.is_some()), - body, )? .0; @@ -523,22 +536,20 @@ impl Context { Some(self.add_expression( Expression::AccessIndex { base, - index: - frontend.module.to_ctx().eval_expr_to_u32(const_expr).ok()?, + index: self.module.to_ctx().eval_expr_to_u32(const_expr).ok()?, }, meta, - body, )) }) .unwrap_or_else(|| { - self.add_expression(Expression::Access { base, index }, meta, body) - }); + self.add_expression(Expression::Access { base, index }, meta) + })?; if ExprPos::Rhs == pos { - let resolved = frontend.resolve_type(self, pointer, meta)?; + let resolved = self.resolve_type(pointer, meta)?; if resolved.pointer_space().is_some() { return Ok(( - Some(self.add_expression(Expression::Load { pointer }, meta, body)), + Some(self.add_expression(Expression::Load { pointer }, meta)?), meta, )); } @@ -547,38 +558,32 @@ impl Context { pointer } HirExprKind::Select { base, ref field } => { - let base = self.lower_expect_inner(stmt, frontend, base, pos, body)?.0; + let base = self.lower_expect_inner(stmt, frontend, base, pos)?.0; - frontend.field_selection(self, pos, body, base, field, meta)? + frontend.field_selection(self, pos, base, field, meta)? } HirExprKind::Literal(literal) if pos != ExprPos::Lhs => { - self.add_expression(Expression::Literal(literal), meta, body) + self.add_expression(Expression::Literal(literal), meta)? } HirExprKind::Binary { left, op, right } if pos != ExprPos::Lhs => { let (mut left, left_meta) = - self.lower_expect_inner(stmt, frontend, left, ExprPos::Rhs, body)?; + self.lower_expect_inner(stmt, frontend, left, ExprPos::Rhs)?; let (mut right, right_meta) = - self.lower_expect_inner(stmt, frontend, right, ExprPos::Rhs, body)?; + self.lower_expect_inner(stmt, frontend, right, ExprPos::Rhs)?; match op { - BinaryOperator::ShiftLeft | BinaryOperator::ShiftRight => self - .implicit_conversion( - frontend, - &mut right, - right_meta, - ScalarKind::Uint, - 4, - )?, - _ => self.binary_implicit_conversion( - frontend, &mut left, left_meta, &mut right, right_meta, - )?, + BinaryOperator::ShiftLeft | BinaryOperator::ShiftRight => { + self.implicit_conversion(&mut right, right_meta, ScalarKind::Uint, 4)? + } + _ => self + .binary_implicit_conversion(&mut left, left_meta, &mut right, right_meta)?, } - frontend.typifier_grow(self, left, left_meta)?; - frontend.typifier_grow(self, right, right_meta)?; + self.typifier_grow(left, left_meta)?; + self.typifier_grow(right, right_meta)?; - let left_inner = self.typifier.get(left, &frontend.module.types); - let right_inner = self.typifier.get(right, &frontend.module.types); + let left_inner = self.typifier.get(left, &self.module.types); + let right_inner = self.typifier.get(right, &self.module.types); match (left_inner, right_inner) { ( @@ -623,45 +628,39 @@ impl Context { let left_vector = self.add_expression( Expression::AccessIndex { base: left, index }, meta, - body, - ); + )?; let right_vector = self.add_expression( Expression::AccessIndex { base: right, index }, meta, - body, - ); + )?; // Divide the vectors - let column = self.expressions.append( + let column = self.add_expression( Expression::Binary { op, left: left_vector, right: right_vector, }, meta, - ); + )?; components.push(column) } - // Rebuild the matrix from the divided vectors - self.expressions.append( - Expression::Compose { - ty: frontend.module.types.insert( - Type { - name: None, - inner: TypeInner::Matrix { - columns: left_columns, - rows: left_rows, - width: left_width, - }, - }, - Span::default(), - ), - components, + let ty = self.module.types.insert( + Type { + name: None, + inner: TypeInner::Matrix { + columns: left_columns, + rows: left_rows, + width: left_width, + }, }, - meta, - ) + Span::default(), + ); + + // Rebuild the matrix from the divided vectors + self.add_expression(Expression::Compose { ty, components }, meta)? } BinaryOperator::Equal | BinaryOperator::NotEqual => { // Naga IR doesn't support matrix comparisons so we need to @@ -691,22 +690,20 @@ impl Context { let left_vector = self.add_expression( Expression::AccessIndex { base: left, index }, meta, - body, - ); + )?; let right_vector = self.add_expression( Expression::AccessIndex { base: right, index }, meta, - body, - ); + )?; - let argument = self.expressions.append( + let argument = self.add_expression( Expression::Binary { op, left: left_vector, right: right_vector, }, meta, - ); + )?; // The result of comparing two vectors is a boolean vector // so use a relational function like all to get a single @@ -714,8 +711,7 @@ impl Context { let compare = self.add_expression( Expression::Relational { fun, argument }, meta, - body, - ); + )?; // Fold the result root = Some(match root { @@ -726,19 +722,16 @@ impl Context { right, }, meta, - body, - ), + )?, None => compare, }); } root.unwrap() } - _ => self.add_expression( - Expression::Binary { left, op, right }, - meta, - body, - ), + _ => { + self.add_expression(Expression::Binary { left, op, right }, meta)? + } } } (&TypeInner::Vector { .. }, &TypeInner::Vector { .. }) => match op { @@ -750,19 +743,12 @@ impl Context { false => (BinaryOperator::NotEqual, RelationalFunction::Any), }; - let argument = self - .expressions - .append(Expression::Binary { op, left, right }, meta); + let argument = + self.add_expression(Expression::Binary { op, left, right }, meta)?; - self.add_expression( - Expression::Relational { fun, argument }, - meta, - body, - ) - } - _ => { - self.add_expression(Expression::Binary { left, op, right }, meta, body) + self.add_expression(Expression::Relational { fun, argument }, meta)? } + _ => self.add_expression(Expression::Binary { left, op, right }, meta)?, }, (&TypeInner::Vector { size, .. }, &TypeInner::Scalar { .. }) => match op { BinaryOperator::Add @@ -773,11 +759,8 @@ impl Context { | BinaryOperator::InclusiveOr | BinaryOperator::ShiftLeft | BinaryOperator::ShiftRight => { - let scalar_vector = self.add_expression( - Expression::Splat { size, value: right }, - meta, - body, - ); + let scalar_vector = self + .add_expression(Expression::Splat { size, value: right }, meta)?; self.add_expression( Expression::Binary { @@ -786,12 +769,9 @@ impl Context { right: scalar_vector, }, meta, - body, - ) - } - _ => { - self.add_expression(Expression::Binary { left, op, right }, meta, body) + )? } + _ => self.add_expression(Expression::Binary { left, op, right }, meta)?, }, (&TypeInner::Scalar { .. }, &TypeInner::Vector { size, .. }) => match op { BinaryOperator::Add @@ -800,11 +780,8 @@ impl Context { | BinaryOperator::And | BinaryOperator::ExclusiveOr | BinaryOperator::InclusiveOr => { - let scalar_vector = self.add_expression( - Expression::Splat { size, value: left }, - meta, - body, - ); + let scalar_vector = + self.add_expression(Expression::Splat { size, value: left }, meta)?; self.add_expression( Expression::Binary { @@ -813,12 +790,9 @@ impl Context { right, }, meta, - body, - ) - } - _ => { - self.add_expression(Expression::Binary { left, op, right }, meta, body) + )? } + _ => self.add_expression(Expression::Binary { left, op, right }, meta)?, }, ( &TypeInner::Scalar { @@ -857,8 +831,7 @@ impl Context { value: left, }, meta, - body, - ); + )?; let mut components = Vec::with_capacity(columns as usize); @@ -867,47 +840,40 @@ impl Context { let matrix_column = self.add_expression( Expression::AccessIndex { base: right, index }, meta, - body, - ); + )?; // Apply the operation to the splatted vector and // the column vector - let column = self.expressions.append( + let column = self.add_expression( Expression::Binary { op, left: scalar_vector, right: matrix_column, }, meta, - ); + )?; components.push(column) } - // Rebuild the matrix from the operation result vectors - self.expressions.append( - Expression::Compose { - ty: frontend.module.types.insert( - Type { - name: None, - inner: TypeInner::Matrix { - columns, - rows, - width: left_width, - }, - }, - Span::default(), - ), - components, + let ty = self.module.types.insert( + Type { + name: None, + inner: TypeInner::Matrix { + columns, + rows, + width: left_width, + }, }, - meta, - ) + Span::default(), + ); + + // Rebuild the matrix from the operation result vectors + self.add_expression(Expression::Compose { ty, components }, meta)? + } + _ => { + self.add_expression(Expression::Binary { left, op, right }, meta)? } - _ => self.add_expression( - Expression::Binary { left, op, right }, - meta, - body, - ), } } ( @@ -948,8 +914,7 @@ impl Context { value: right, }, meta, - body, - ); + )?; let mut components = Vec::with_capacity(columns as usize); @@ -958,58 +923,51 @@ impl Context { let matrix_column = self.add_expression( Expression::AccessIndex { base: left, index }, meta, - body, - ); + )?; // Apply the operation to the splatted vector and // the column vector - let column = self.expressions.append( + let column = self.add_expression( Expression::Binary { op, left: matrix_column, right: scalar_vector, }, meta, - ); + )?; components.push(column) } - // Rebuild the matrix from the operation result vectors - self.expressions.append( - Expression::Compose { - ty: frontend.module.types.insert( - Type { - name: None, - inner: TypeInner::Matrix { - columns, - rows, - width: left_width, - }, - }, - Span::default(), - ), - components, + let ty = self.module.types.insert( + Type { + name: None, + inner: TypeInner::Matrix { + columns, + rows, + width: left_width, + }, }, - meta, - ) + Span::default(), + ); + + // Rebuild the matrix from the operation result vectors + self.add_expression(Expression::Compose { ty, components }, meta)? + } + _ => { + self.add_expression(Expression::Binary { left, op, right }, meta)? } - _ => self.add_expression( - Expression::Binary { left, op, right }, - meta, - body, - ), } } - _ => self.add_expression(Expression::Binary { left, op, right }, meta, body), + _ => self.add_expression(Expression::Binary { left, op, right }, meta)?, } } HirExprKind::Unary { op, expr } if pos != ExprPos::Lhs => { let expr = self - .lower_expect_inner(stmt, frontend, expr, ExprPos::Rhs, body)? + .lower_expect_inner(stmt, frontend, expr, ExprPos::Rhs)? .0; - self.add_expression(Expression::Unary { op, expr }, meta, body) + self.add_expression(Expression::Unary { op, expr }, meta)? } HirExprKind::Variable(ref var) => match pos { ExprPos::Lhs => { @@ -1035,7 +993,7 @@ impl Context { LocalVariable { name: None, ty, - init: Some(frontend.module.const_expressions.append( + init: Some(self.module.const_expressions.append( Expression::Constant(constant), Span::default(), )), @@ -1043,11 +1001,7 @@ impl Context { Span::default(), ); - self.add_expression( - Expression::LocalVariable(local), - Span::default(), - body, - ) + self.add_expression(Expression::LocalVariable(local), Span::default())? } else { var.expr } @@ -1056,7 +1010,7 @@ impl Context { } } _ if var.load => { - self.add_expression(Expression::Load { pointer: var.expr }, meta, body) + self.add_expression(Expression::Load { pointer: var.expr }, meta)? } ExprPos::Rhs => var.expr, }, @@ -1064,7 +1018,6 @@ impl Context { let maybe_expr = frontend.function_or_constructor_call( self, stmt, - body, call.kind.clone(), &call.args, meta, @@ -1097,31 +1050,20 @@ impl Context { // Lower the condition first to the current bodyy let condition = self - .lower_expect_inner(stmt, frontend, condition, ExprPos::Rhs, body)? + .lower_expect_inner(stmt, frontend, condition, ExprPos::Rhs)? .0; - // Emit all expressions since we will be adding statements to - // other bodies next - self.emit_restart(body); + let (mut accept_body, (mut accept, accept_meta)) = + self.new_body_with_ret(|ctx| { + // Lower the `true` branch + ctx.lower_expect_inner(stmt, frontend, accept, pos) + })?; - // Create the bodies for the two cases - let mut accept_body = Block::new(); - let mut reject_body = Block::new(); - - // Lower the `true` branch - let (mut accept, accept_meta) = - self.lower_expect_inner(stmt, frontend, accept, pos, &mut accept_body)?; - - // Flush the body of the `true` branch, to start emitting on the - // `false` branch - self.emit_restart(&mut accept_body); - - // Lower the `false` branch - let (mut reject, reject_meta) = - self.lower_expect_inner(stmt, frontend, reject, pos, &mut reject_body)?; - - // Flush the body of the `false` branch - self.emit_restart(&mut reject_body); + let (mut reject_body, (mut reject, reject_meta)) = + self.new_body_with_ret(|ctx| { + // Lower the `false` branch + ctx.lower_expect_inner(stmt, frontend, reject, pos) + })?; // We need to do some custom implicit conversions since the two target expressions // are in different bodies @@ -1130,40 +1072,42 @@ impl Context { Some((reject_power, reject_width, reject_kind)), ) = ( // Get the components of both branches and calculate the type power - self.expr_scalar_components(frontend, accept, accept_meta)? + self.expr_scalar_components(accept, accept_meta)? .and_then(|(kind, width)| Some((type_power(kind, width)?, width, kind))), - self.expr_scalar_components(frontend, reject, reject_meta)? + self.expr_scalar_components(reject, reject_meta)? .and_then(|(kind, width)| Some((type_power(kind, width)?, width, kind))), ) { match accept_power.cmp(&reject_power) { std::cmp::Ordering::Less => { - self.conversion(&mut accept, accept_meta, reject_kind, reject_width)?; - // The expression belongs to the `true` branch so we need to flush to - // the respective body - self.emit_end(&mut accept_body); + accept_body = self.with_body(accept_body, |ctx| { + ctx.conversion( + &mut accept, + accept_meta, + reject_kind, + reject_width, + )?; + Ok(()) + })?; } - // Technically there's nothing to flush but later we will need to - // add some expressions that must not be emitted so instead - // of flushing, starting and flushing again, just make sure - // everything is flushed. - std::cmp::Ordering::Equal => self.emit_end(body), + std::cmp::Ordering::Equal => {} std::cmp::Ordering::Greater => { - self.conversion(&mut reject, reject_meta, accept_kind, accept_width)?; - // The expression belongs to the `false` branch so we need to flush to - // the respective body - self.emit_end(&mut reject_body); + reject_body = self.with_body(reject_body, |ctx| { + ctx.conversion( + &mut reject, + reject_meta, + accept_kind, + accept_width, + )?; + Ok(()) + })?; } } - } else { - // Technically there's nothing to flush but later we will need to - // add some expressions that must not be emitted. - self.emit_end(body) } // We need to get the type of the resulting expression to create the local, // this must be done after implicit conversions to ensure both branches have // the same type. - let ty = frontend.resolve_type_handle(self, accept, accept_meta)?; + let ty = self.resolve_type_handle(accept, accept_meta)?; // Add the local that will hold the result of our conditional let local = self.locals.append( @@ -1175,13 +1119,9 @@ impl Context { meta, ); - // Note: `Expression::LocalVariable` must not be emited so it's important - // that at this point the emitter is flushed but not started. - let local_expr = self - .expressions - .append(Expression::LocalVariable(local), meta); + let local_expr = self.add_expression(Expression::LocalVariable(local), meta)?; - // Add to each body the store to the result variable + // Add to each the store to the result variable accept_body.push( Statement::Store { pointer: local_expr, @@ -1199,7 +1139,7 @@ impl Context { // Finally add the `If` to the main body with the `condition` we lowered // earlier and the branches we prepared. - body.push( + self.body.push( Statement::If { condition, accept: accept_body, @@ -1208,47 +1148,43 @@ impl Context { meta, ); - // Restart the emitter - self.emit_start(); - // Note: `Expression::Load` must be emited before it's used so make // sure the emitter is active here. - self.expressions.append( + self.add_expression( Expression::Load { pointer: local_expr, }, meta, - ) + )? } HirExprKind::Assign { tgt, value } if ExprPos::Lhs != pos => { let (pointer, ptr_meta) = - self.lower_expect_inner(stmt, frontend, tgt, ExprPos::Lhs, body)?; + self.lower_expect_inner(stmt, frontend, tgt, ExprPos::Lhs)?; let (mut value, value_meta) = - self.lower_expect_inner(stmt, frontend, value, ExprPos::Rhs, body)?; + self.lower_expect_inner(stmt, frontend, value, ExprPos::Rhs)?; - let ty = match *frontend.resolve_type(self, pointer, ptr_meta)? { - TypeInner::Pointer { base, .. } => &frontend.module.types[base].inner, + let ty = match *self.resolve_type(pointer, ptr_meta)? { + TypeInner::Pointer { base, .. } => &self.module.types[base].inner, ref ty => ty, }; if let Some((kind, width)) = scalar_components(ty) { - self.implicit_conversion(frontend, &mut value, value_meta, kind, width)?; + self.implicit_conversion(&mut value, value_meta, kind, width)?; } - self.lower_store(pointer, value, meta, body); + self.lower_store(pointer, value, meta)?; value } HirExprKind::PrePostfix { op, postfix, expr } if ExprPos::Lhs != pos => { - let (pointer, _) = - self.lower_expect_inner(stmt, frontend, expr, ExprPos::Lhs, body)?; + let (pointer, _) = self.lower_expect_inner(stmt, frontend, expr, ExprPos::Lhs)?; let left = if let Expression::Swizzle { .. } = self.expressions[pointer] { pointer } else { - self.add_expression(Expression::Load { pointer }, meta, body) + self.add_expression(Expression::Load { pointer }, meta)? }; - let res = match *frontend.resolve_type(self, left, meta)? { + let res = match *self.resolve_type(left, meta)? { TypeInner::Scalar { kind, width } => { let ty = TypeInner::Scalar { kind, width }; Literal::one(kind, width).map(|i| (ty, i, None, None)) @@ -1285,18 +1221,17 @@ impl Context { } }; - let mut right = self.add_expression(Expression::Literal(literal), meta, body); + let mut right = self.add_expression(Expression::Literal(literal), meta)?; // Glsl allows pre/postfixes operations on vectors and matrices, so if the // target is either of them change the right side of the addition to be splatted // to the same size as the target, furthermore if the target is a matrix // use a composed matrix using the splatted value. if let Some(size) = rows { - right = - self.add_expression(Expression::Splat { size, value: right }, meta, body); + right = self.add_expression(Expression::Splat { size, value: right }, meta)?; if let Some(cols) = columns { - let ty = frontend.module.types.insert( + let ty = self.module.types.insert( Type { name: None, inner: ty_inner, @@ -1310,14 +1245,13 @@ impl Context { components: std::iter::repeat(right).take(cols as usize).collect(), }, meta, - body, - ); + )?; } } - let value = self.add_expression(Expression::Binary { op, left, right }, meta, body); + let value = self.add_expression(Expression::Binary { op, left, right }, meta)?; - self.lower_store(pointer, value, meta, body); + self.lower_store(pointer, value, meta)?; if postfix { left @@ -1332,7 +1266,7 @@ impl Context { } if ExprPos::Lhs != pos => { let args = args .iter() - .map(|e| self.lower_expect_inner(stmt, frontend, *e, ExprPos::Rhs, body)) + .map(|e| self.lower_expect_inner(stmt, frontend, *e, ExprPos::Rhs)) .collect::>>()?; match name.as_ref() { "length" => { @@ -1344,10 +1278,8 @@ impl Context { meta, }); } - let lowered_array = self - .lower_expect_inner(stmt, frontend, object, pos, body)? - .0; - let array_type = frontend.resolve_type(self, lowered_array, meta)?; + let lowered_array = self.lower_expect_inner(stmt, frontend, object, pos)?.0; + let array_type = self.resolve_type(lowered_array, meta)?; match *array_type { TypeInner::Array { @@ -1357,10 +1289,8 @@ impl Context { let mut array_length = self.add_expression( Expression::Literal(Literal::U32(size.get())), meta, - body, - ); + )?; self.forced_conversion( - frontend, &mut array_length, meta, ScalarKind::Sint, @@ -1370,11 +1300,8 @@ impl Context { } // let the error be handled in type checking if it's not a dynamic array _ => { - let mut array_length = self.add_expression( - Expression::ArrayLength(lowered_array), - meta, - body, - ); + let mut array_length = self + .add_expression(Expression::ArrayLength(lowered_array), meta)?; self.conversion(&mut array_length, meta, ScalarKind::Sint, 4)?; array_length } @@ -1414,22 +1341,16 @@ impl Context { pub fn expr_scalar_components( &mut self, - frontend: &Frontend, expr: Handle, meta: Span, ) -> Result> { - let ty = frontend.resolve_type(self, expr, meta)?; + let ty = self.resolve_type(expr, meta)?; Ok(scalar_components(ty)) } - pub fn expr_power( - &mut self, - frontend: &Frontend, - expr: Handle, - meta: Span, - ) -> Result> { + pub fn expr_power(&mut self, expr: Handle, meta: Span) -> Result> { Ok(self - .expr_scalar_components(frontend, expr, meta)? + .expr_scalar_components(expr, meta)? .and_then(|(kind, width)| type_power(kind, width))) } @@ -1440,30 +1361,28 @@ impl Context { kind: ScalarKind, width: crate::Bytes, ) -> Result<()> { - *expr = self.expressions.append( + *expr = self.add_expression( Expression::As { expr: *expr, kind, convert: Some(width), }, meta, - ); + )?; Ok(()) } pub fn implicit_conversion( &mut self, - frontend: &Frontend, expr: &mut Handle, meta: Span, kind: ScalarKind, width: crate::Bytes, ) -> Result<()> { - if let (Some(tgt_power), Some(expr_power)) = ( - type_power(kind, width), - self.expr_power(frontend, *expr, meta)?, - ) { + if let (Some(tgt_power), Some(expr_power)) = + (type_power(kind, width), self.expr_power(*expr, meta)?) + { if tgt_power > expr_power { self.conversion(expr, meta, kind, width)?; } @@ -1474,15 +1393,12 @@ impl Context { pub fn forced_conversion( &mut self, - frontend: &Frontend, expr: &mut Handle, meta: Span, kind: ScalarKind, width: crate::Bytes, ) -> Result<()> { - if let Some((expr_scalar_kind, expr_width)) = - self.expr_scalar_components(frontend, *expr, meta)? - { + if let Some((expr_scalar_kind, expr_width)) = self.expr_scalar_components(*expr, meta)? { if expr_scalar_kind != kind || expr_width != width { self.conversion(expr, meta, kind, width)?; } @@ -1493,14 +1409,13 @@ impl Context { pub fn binary_implicit_conversion( &mut self, - frontend: &Frontend, left: &mut Handle, left_meta: Span, right: &mut Handle, right_meta: Span, ) -> Result<()> { - let left_components = self.expr_scalar_components(frontend, *left, left_meta)?; - let right_components = self.expr_scalar_components(frontend, *right, right_meta)?; + let left_components = self.expr_scalar_components(*left, left_meta)?; + let right_components = self.expr_scalar_components(*right, right_meta)?; if let ( Some((left_power, left_width, left_kind)), @@ -1526,17 +1441,14 @@ impl Context { pub fn implicit_splat( &mut self, - frontend: &Frontend, expr: &mut Handle, meta: Span, vector_size: Option, ) -> Result<()> { - let expr_type = frontend.resolve_type(self, *expr, meta)?; + let expr_type = self.resolve_type(*expr, meta)?; if let (&TypeInner::Scalar { .. }, Some(size)) = (expr_type, vector_size) { - *expr = self - .expressions - .append(Expression::Splat { size, value: *expr }, meta) + *expr = self.add_expression(Expression::Splat { size, value: *expr }, meta)? } Ok(()) @@ -1547,8 +1459,7 @@ impl Context { size: VectorSize, vector: Handle, meta: Span, - body: &mut Block, - ) -> Handle { + ) -> Result> { self.add_expression( Expression::Swizzle { size, @@ -1556,12 +1467,11 @@ impl Context { pattern: crate::SwizzleComponent::XYZW, }, meta, - body, ) } } -impl Index> for Context { +impl Index> for Context<'_> { type Output = Expression; fn index(&self, index: Handle) -> &Self::Output { diff --git a/third_party/rust/naga/src/front/glsl/functions.rs b/third_party/rust/naga/src/front/glsl/functions.rs index f448272583e3..fe96d2c4eb14 100644 --- a/third_party/rust/naga/src/front/glsl/functions.rs +++ b/third_party/rust/naga/src/front/glsl/functions.rs @@ -7,9 +7,9 @@ use super::{ Frontend, Result, }; use crate::{ - front::glsl::types::type_power, proc::ensure_block_returns, AddressSpace, Arena, Block, - EntryPoint, Expression, Function, FunctionArgument, FunctionResult, Handle, Literal, - LocalVariable, ScalarKind, Span, Statement, StructMember, Type, TypeInner, + front::glsl::types::type_power, proc::ensure_block_returns, AddressSpace, Block, EntryPoint, + Expression, Function, FunctionArgument, FunctionResult, Handle, Literal, LocalVariable, + ScalarKind, Span, Statement, StructMember, Type, TypeInner, }; use std::iter; @@ -28,27 +28,25 @@ impl Frontend { &mut self, ctx: &mut Context, stmt: &StmtContext, - body: &mut Block, fc: FunctionCallKind, raw_args: &[Handle], meta: Span, ) -> Result>> { let args: Vec<_> = raw_args .iter() - .map(|e| ctx.lower_expect_inner(stmt, self, *e, ExprPos::Rhs, body)) + .map(|e| ctx.lower_expect_inner(stmt, self, *e, ExprPos::Rhs)) .collect::>()?; match fc { FunctionCallKind::TypeConstructor(ty) => { if args.len() == 1 { - self.constructor_single(ctx, body, ty, args[0], meta) - .map(Some) + self.constructor_single(ctx, ty, args[0], meta).map(Some) } else { - self.constructor_many(ctx, body, ty, args, meta).map(Some) + self.constructor_many(ctx, ty, args, meta).map(Some) } } FunctionCallKind::Function(name) => { - self.function_call(ctx, stmt, body, name, args, raw_args, meta) + self.function_call(ctx, stmt, name, args, raw_args, meta) } } } @@ -56,31 +54,29 @@ impl Frontend { fn constructor_single( &mut self, ctx: &mut Context, - body: &mut Block, ty: Handle, (mut value, expr_meta): (Handle, Span), meta: Span, ) -> Result> { - let expr_type = self.resolve_type(ctx, value, expr_meta)?; + let expr_type = ctx.resolve_type(value, expr_meta)?; let vector_size = match *expr_type { TypeInner::Vector { size, .. } => Some(size), _ => None, }; + let expr_is_bool = expr_type.scalar_kind() == Some(ScalarKind::Bool); + // Special case: if casting from a bool, we need to use Select and not As. - match self.module.types[ty].inner.scalar_kind() { - Some(result_scalar_kind) - if expr_type.scalar_kind() == Some(ScalarKind::Bool) - && result_scalar_kind != ScalarKind::Bool => - { + match ctx.module.types[ty].inner.scalar_kind() { + Some(result_scalar_kind) if expr_is_bool && result_scalar_kind != ScalarKind::Bool => { let l0 = Literal::zero(result_scalar_kind, 4).unwrap(); let l1 = Literal::one(result_scalar_kind, 4).unwrap(); - let mut reject = ctx.add_expression(Expression::Literal(l0), expr_meta, body); - let mut accept = ctx.add_expression(Expression::Literal(l1), expr_meta, body); + let mut reject = ctx.add_expression(Expression::Literal(l0), expr_meta)?; + let mut accept = ctx.add_expression(Expression::Literal(l1), expr_meta)?; - ctx.implicit_splat(self, &mut reject, meta, vector_size)?; - ctx.implicit_splat(self, &mut accept, meta, vector_size)?; + ctx.implicit_splat(&mut reject, meta, vector_size)?; + ctx.implicit_splat(&mut accept, meta, vector_size)?; let h = ctx.add_expression( Expression::Select { @@ -89,24 +85,22 @@ impl Frontend { condition: value, }, expr_meta, - body, - ); + )?; return Ok(h); } _ => {} } - Ok(match self.module.types[ty].inner { + Ok(match ctx.module.types[ty].inner { TypeInner::Vector { size, kind, width } if vector_size.is_none() => { - ctx.forced_conversion(self, &mut value, expr_meta, kind, width)?; + ctx.forced_conversion(&mut value, expr_meta, kind, width)?; - if let TypeInner::Scalar { .. } = *self.resolve_type(ctx, value, expr_meta)? { - ctx.add_expression(Expression::Splat { size, value }, meta, body) + if let TypeInner::Scalar { .. } = *ctx.resolve_type(value, expr_meta)? { + ctx.add_expression(Expression::Splat { size, value }, meta)? } else { self.vector_constructor( ctx, - body, ty, size, kind, @@ -119,7 +113,7 @@ impl Frontend { TypeInner::Scalar { kind, width } => { let mut expr = value; if let TypeInner::Vector { .. } | TypeInner::Matrix { .. } = - *self.resolve_type(ctx, value, expr_meta)? + *ctx.resolve_type(value, expr_meta)? { expr = ctx.add_expression( Expression::AccessIndex { @@ -127,19 +121,17 @@ impl Frontend { index: 0, }, meta, - body, - ); + )?; } - if let TypeInner::Matrix { .. } = *self.resolve_type(ctx, value, expr_meta)? { + if let TypeInner::Matrix { .. } = *ctx.resolve_type(value, expr_meta)? { expr = ctx.add_expression( Expression::AccessIndex { base: expr, index: 0, }, meta, - body, - ); + )?; } ctx.add_expression( @@ -149,12 +141,11 @@ impl Frontend { convert: Some(width), }, meta, - body, - ) + )? } TypeInner::Vector { size, kind, width } => { if vector_size.map_or(true, |s| s != size) { - value = ctx.vector_resize(size, value, expr_meta, body); + value = ctx.vector_resize(size, value, expr_meta)?; } ctx.add_expression( @@ -164,29 +155,19 @@ impl Frontend { convert: Some(width), }, meta, - body, - ) + )? } TypeInner::Matrix { columns, rows, width, - } => self.matrix_one_arg( - ctx, - body, - ty, - columns, - rows, - width, - (value, expr_meta), - meta, - )?, + } => self.matrix_one_arg(ctx, ty, columns, rows, width, (value, expr_meta), meta)?, TypeInner::Struct { ref members, .. } => { let scalar_components = members .get(0) - .and_then(|member| scalar_components(&self.module.types[member.ty].inner)); + .and_then(|member| scalar_components(&ctx.module.types[member.ty].inner)); if let Some((kind, width)) = scalar_components { - ctx.implicit_conversion(self, &mut value, expr_meta, kind, width)?; + ctx.implicit_conversion(&mut value, expr_meta, kind, width)?; } ctx.add_expression( @@ -195,14 +176,13 @@ impl Frontend { components: vec![value], }, meta, - body, - ) + )? } TypeInner::Array { base, .. } => { - let scalar_components = scalar_components(&self.module.types[base].inner); + let scalar_components = scalar_components(&ctx.module.types[base].inner); if let Some((kind, width)) = scalar_components { - ctx.implicit_conversion(self, &mut value, expr_meta, kind, width)?; + ctx.implicit_conversion(&mut value, expr_meta, kind, width)?; } ctx.add_expression( @@ -211,8 +191,7 @@ impl Frontend { components: vec![value], }, meta, - body, - ) + )? } _ => { self.errors.push(Error { @@ -229,7 +208,6 @@ impl Frontend { fn matrix_one_arg( &mut self, ctx: &mut Context, - body: &mut Block, ty: Handle, columns: crate::VectorSize, rows: crate::VectorSize, @@ -242,13 +220,13 @@ impl Frontend { // `Expression::As` doesn't support matrix width // casts so we need to do some extra work for casts - ctx.forced_conversion(self, &mut value, expr_meta, ScalarKind::Float, width)?; - match *self.resolve_type(ctx, value, expr_meta)? { + ctx.forced_conversion(&mut value, expr_meta, ScalarKind::Float, width)?; + match *ctx.resolve_type(value, expr_meta)? { TypeInner::Scalar { .. } => { // If a matrix is constructed with a single scalar value, then that // value is used to initialize all the values along the diagonal of // the matrix; the rest are given zeros. - let vector_ty = self.module.types.insert( + let vector_ty = ctx.module.types.insert( Type { name: None, inner: TypeInner::Vector { @@ -261,7 +239,7 @@ impl Frontend { ); let zero_literal = Literal::zero(ScalarKind::Float, width).unwrap(); - let zero = ctx.add_expression(Expression::Literal(zero_literal), meta, body); + let zero = ctx.add_expression(Expression::Literal(zero_literal), meta)?; for i in 0..columns as u32 { components.push( @@ -276,8 +254,7 @@ impl Frontend { .collect(), }, meta, - body, - ), + )?, ) } } @@ -294,10 +271,10 @@ impl Frontend { let zero_literal = Literal::zero(ScalarKind::Float, width).unwrap(); let one_literal = Literal::one(ScalarKind::Float, width).unwrap(); - let zero = ctx.add_expression(Expression::Literal(zero_literal), meta, body); - let one = ctx.add_expression(Expression::Literal(one_literal), meta, body); + let zero = ctx.add_expression(Expression::Literal(zero_literal), meta)?; + let one = ctx.add_expression(Expression::Literal(one_literal), meta)?; - let vector_ty = self.module.types.insert( + let vector_ty = ctx.module.types.insert( Type { name: None, inner: TypeInner::Vector { @@ -319,8 +296,7 @@ impl Frontend { index: i, }, meta, - body, - ); + )?; components.push(match ori_rows.cmp(&rows) { Ordering::Less => { @@ -333,15 +309,14 @@ impl Frontend { index: r, }, meta, - body, ) } else if r == i { - one + Ok(one) } else { - zero + Ok(zero) } }) - .collect(); + .collect::>()?; ctx.add_expression( Expression::Compose { @@ -349,11 +324,10 @@ impl Frontend { components, }, meta, - body, - ) + )? } Ordering::Equal => vector, - Ordering::Greater => ctx.vector_resize(rows, vector, meta, body), + Ordering::Greater => ctx.vector_resize(rows, vector, meta)?, }) } else { let compose_expr = Expression::Compose { @@ -366,7 +340,7 @@ impl Frontend { .collect(), }; - let vec = ctx.add_expression(compose_expr, meta, body); + let vec = ctx.add_expression(compose_expr, meta)?; components.push(vec) } @@ -377,14 +351,13 @@ impl Frontend { } } - Ok(ctx.add_expression(Expression::Compose { ty, components }, meta, body)) + ctx.add_expression(Expression::Compose { ty, components }, meta) } #[allow(clippy::too_many_arguments)] fn vector_constructor( &mut self, ctx: &mut Context, - body: &mut Block, ty: Handle, size: crate::VectorSize, kind: ScalarKind, @@ -395,13 +368,13 @@ impl Frontend { let mut components = Vec::with_capacity(size as usize); for (mut arg, expr_meta) in args.iter().copied() { - ctx.forced_conversion(self, &mut arg, expr_meta, kind, width)?; + ctx.forced_conversion(&mut arg, expr_meta, kind, width)?; if components.len() >= size as usize { break; } - match *self.resolve_type(ctx, arg, expr_meta)? { + match *ctx.resolve_type(arg, expr_meta)? { TypeInner::Scalar { .. } => components.push(arg), TypeInner::Matrix { rows, columns, .. } => { components.reserve(rows as usize * columns as usize); @@ -412,14 +385,12 @@ impl Frontend { index: c, }, expr_meta, - body, - ); + )?; for r in 0..(rows as u32) { components.push(ctx.add_expression( Expression::AccessIndex { base, index: r }, expr_meta, - body, - )) + )?) } } } @@ -429,8 +400,7 @@ impl Frontend { components.push(ctx.add_expression( Expression::AccessIndex { base: arg, index }, expr_meta, - body, - )) + )?) } } _ => components.push(arg), @@ -439,20 +409,19 @@ impl Frontend { components.truncate(size as usize); - Ok(ctx.add_expression(Expression::Compose { ty, components }, meta, body)) + ctx.add_expression(Expression::Compose { ty, components }, meta) } fn constructor_many( &mut self, ctx: &mut Context, - body: &mut Block, ty: Handle, args: Vec<(Handle, Span)>, meta: Span, ) -> Result> { let mut components = Vec::with_capacity(args.len()); - match self.module.types[ty].inner { + let struct_member_data = match ctx.module.types[ty].inner { TypeInner::Matrix { columns, rows, @@ -461,9 +430,9 @@ impl Frontend { let mut flattened = Vec::with_capacity(columns as usize * rows as usize); for (mut arg, meta) in args.iter().copied() { - ctx.forced_conversion(self, &mut arg, meta, ScalarKind::Float, width)?; + ctx.forced_conversion(&mut arg, meta, ScalarKind::Float, width)?; - match *self.resolve_type(ctx, arg, meta)? { + match *ctx.resolve_type(arg, meta)? { TypeInner::Vector { size, .. } => { for i in 0..(size as u32) { flattened.push(ctx.add_expression( @@ -472,15 +441,14 @@ impl Frontend { index: i, }, meta, - body, - )) + )?) } } _ => flattened.push(arg), } } - let ty = self.module.types.insert( + let ty = ctx.module.types.insert( Type { name: None, inner: TypeInner::Vector { @@ -499,42 +467,51 @@ impl Frontend { components: Vec::from(chunk), }, meta, - body, - )) + )?) } + None } TypeInner::Vector { size, kind, width } => { - return self.vector_constructor(ctx, body, ty, size, kind, width, &args, meta) + return self.vector_constructor(ctx, ty, size, kind, width, &args, meta) } TypeInner::Array { base, .. } => { for (mut arg, meta) in args.iter().copied() { - let scalar_components = scalar_components(&self.module.types[base].inner); + let scalar_components = scalar_components(&ctx.module.types[base].inner); if let Some((kind, width)) = scalar_components { - ctx.implicit_conversion(self, &mut arg, meta, kind, width)?; - } - - components.push(arg) - } - } - TypeInner::Struct { ref members, .. } => { - for ((mut arg, meta), member) in args.iter().copied().zip(members.iter()) { - let scalar_components = scalar_components(&self.module.types[member.ty].inner); - if let Some((kind, width)) = scalar_components { - ctx.implicit_conversion(self, &mut arg, meta, kind, width)?; + ctx.implicit_conversion(&mut arg, meta, kind, width)?; } components.push(arg) } + None } + TypeInner::Struct { ref members, .. } => Some( + members + .iter() + .map(|member| scalar_components(&ctx.module.types[member.ty].inner)) + .collect::>(), + ), _ => { return Err(Error { kind: ErrorKind::SemanticError("Constructor: Too many arguments".into()), meta, }) } + }; + + if let Some(struct_member_data) = struct_member_data { + for ((mut arg, meta), scalar_components) in + args.iter().copied().zip(struct_member_data.iter().copied()) + { + if let Some((kind, width)) = scalar_components { + ctx.implicit_conversion(&mut arg, meta, kind, width)?; + } + + components.push(arg) + } } - Ok(ctx.add_expression(Expression::Compose { ty, components }, meta, body)) + ctx.add_expression(Expression::Compose { ty, components }, meta) } #[allow(clippy::too_many_arguments)] @@ -542,7 +519,6 @@ impl Frontend { &mut self, ctx: &mut Context, stmt: &StmtContext, - body: &mut Block, name: String, args: Vec<(Handle, Span)>, raw_args: &[Handle], @@ -551,13 +527,13 @@ impl Frontend { // Grow the typifier to be able to index it later without needing // to hold the context mutably for &(expr, span) in args.iter() { - self.typifier_grow(ctx, expr, span)?; + ctx.typifier_grow(expr, span)?; } // Check if the passed arguments require any special variations let mut variations = builtin_required_variations( args.iter() - .map(|&(expr, _)| ctx.typifier.get(expr, &self.module.types)), + .map(|&(expr, _)| ctx.typifier.get(expr, &ctx.module.types)), ); // Initiate the declaration if it wasn't previously initialized and inject builtins @@ -565,7 +541,7 @@ impl Frontend { variations |= BuiltinVariations::STANDARD; Default::default() }); - inject_builtin(declaration, &mut self.module, &name, variations); + inject_builtin(declaration, ctx.module, &name, variations); // Borrow again but without mutability, at this point a declaration is guaranteed let declaration = self.lookup_function.get(&name).unwrap(); @@ -609,18 +585,14 @@ impl Frontend { // If the image is used in the overload as a depth texture convert it // before comparing, otherwise exact matches wouldn't be reported if parameter_info.depth { - sampled_to_depth( - &mut self.module, - ctx, - call_argument.0, - call_argument.1, - &mut self.errors, - ); - self.invalidate_expression(ctx, call_argument.0, call_argument.1)? + sampled_to_depth(ctx, call_argument.0, call_argument.1, &mut self.errors); + ctx.invalidate_expression(call_argument.0, call_argument.1)? } - let overload_param_ty = &self.module.types[*overload_parameter].inner; - let call_arg_ty = self.resolve_type(ctx, call_argument.0, call_argument.1)?; + ctx.typifier_grow(call_argument.0, call_argument.1)?; + + let overload_param_ty = &ctx.module.types[*overload_parameter].inner; + let call_arg_ty = ctx.typifier.get(call_argument.0, &ctx.module.types); log::trace!( "Testing parameter {}\n\tOverload = {:?}\n\tCall = {:?}", @@ -823,12 +795,11 @@ impl Frontend { .zip(¶meters) { let (mut handle, meta) = - ctx.lower_expect_inner(stmt, self, *expr, parameter_info.qualifier.as_pos(), body)?; + ctx.lower_expect_inner(stmt, self, *expr, parameter_info.qualifier.as_pos())?; if parameter_info.qualifier.is_lhs() { self.process_lhs_argument( ctx, - body, meta, *parameter, parameter_info, @@ -841,11 +812,11 @@ impl Frontend { continue; } - let scalar_comps = scalar_components(&self.module.types[*parameter].inner); + let scalar_comps = scalar_components(&ctx.module.types[*parameter].inner); // Apply implicit conversions as needed if let Some((kind, width)) = scalar_comps { - ctx.implicit_conversion(self, &mut handle, meta, kind, width)?; + ctx.implicit_conversion(&mut handle, meta, kind, width)?; } arguments.push(handle) @@ -853,15 +824,15 @@ impl Frontend { match kind { FunctionKind::Call(function) => { - ctx.emit_end(body); + ctx.emit_end(); let result = if !is_void { - Some(ctx.add_expression(Expression::CallResult(function), meta, body)) + Some(ctx.add_expression(Expression::CallResult(function), meta)?) } else { None }; - body.push( + ctx.body.push( crate::Statement::Call { function, arguments, @@ -879,16 +850,15 @@ impl Frontend { pointer: proxy_write.value, }, meta, - body, - ); + )?; if let Some((kind, width)) = proxy_write.convert { ctx.conversion(&mut value, meta, kind, width)?; } - ctx.emit_restart(body); + ctx.emit_restart(); - body.push( + ctx.body.push( Statement::Store { pointer: proxy_write.target, value, @@ -899,9 +869,7 @@ impl Frontend { Ok(result) } - FunctionKind::Macro(builtin) => { - builtin.call(self, ctx, body, arguments.as_mut_slice(), meta) - } + FunctionKind::Macro(builtin) => builtin.call(self, ctx, arguments.as_mut_slice(), meta), } } @@ -911,7 +879,6 @@ impl Frontend { fn process_lhs_argument( &mut self, ctx: &mut Context, - body: &mut Block, meta: Span, parameter_ty: Handle, parameter_info: &ParameterInfo, @@ -920,7 +887,7 @@ impl Frontend { proxy_writes: &mut Vec, arguments: &mut Vec>, ) -> Result<()> { - let original_ty = self.resolve_type(ctx, original, meta)?; + let original_ty = ctx.resolve_type(original, meta)?; let original_pointer_space = original_ty.pointer_space(); // The type of a possible spill variable needed for a proxy write @@ -928,7 +895,7 @@ impl Frontend { // If the argument is to be passed as a pointer but the type of the // expression returns a vector it must mean that it was for example // swizzled and it must be spilled into a local before calling - TypeInner::Vector { size, kind, width } => Some(self.module.types.insert( + TypeInner::Vector { size, kind, width } => Some(ctx.module.types.insert( Type { name: None, inner: TypeInner::Vector { size, kind, width }, @@ -951,7 +918,7 @@ impl Frontend { }; Some( - self.module + ctx.module .types .insert(Type { name: None, inner }, Span::default()), ) @@ -962,17 +929,15 @@ impl Frontend { // Since the original expression might be a pointer and we want a value // for the proxy writes, we might need to load the pointer. let value = if original_pointer_space.is_some() { - ctx.add_expression( - Expression::Load { pointer: original }, - Span::default(), - body, - ) + ctx.add_expression(Expression::Load { pointer: original }, Span::default())? } else { original }; - let call_arg_ty = self.resolve_type(ctx, call_argument.0, call_argument.1)?; - let overload_param_ty = &self.module.types[parameter_ty].inner; + ctx.typifier_grow(call_argument.0, call_argument.1)?; + + let overload_param_ty = &ctx.module.types[parameter_ty].inner; + let call_arg_ty = ctx.typifier.get(call_argument.0, &ctx.module.types); let needs_conversion = call_arg_ty != overload_param_ty; let arg_scalar_comps = scalar_components(call_arg_ty); @@ -995,12 +960,12 @@ impl Frontend { Span::default(), ); let spill_expr = - ctx.add_expression(Expression::LocalVariable(spill_var), Span::default(), body); + ctx.add_expression(Expression::LocalVariable(spill_var), Span::default())?; // If the argument is also copied in we must store the value of the // original variable to the spill variable. if let ParameterQualifier::InOut = parameter_info.qualifier { - body.push( + ctx.body.push( Statement::Store { pointer: spill_expr, value, @@ -1037,8 +1002,7 @@ impl Frontend { index: *component as u32, }, Span::default(), - body, - ); + )?; let spill_component = ctx.add_expression( Expression::AccessIndex { @@ -1046,8 +1010,7 @@ impl Frontend { index: i as u32, }, Span::default(), - body, - ); + )?; proxy_writes.push(ProxyWrite { target: original, @@ -1071,32 +1034,28 @@ impl Frontend { pub(crate) fn add_function( &mut self, - ctx: Context, + mut ctx: Context, name: String, result: Option, - mut body: Block, meta: Span, ) { - ensure_block_returns(&mut body); + ensure_block_returns(&mut ctx.body); let void = result.is_none(); - let &mut Frontend { - ref mut lookup_function, - ref mut module, - .. - } = self; - // Check if the passed arguments require any special variations - let mut variations = - builtin_required_variations(ctx.parameters.iter().map(|&arg| &module.types[arg].inner)); + let mut variations = builtin_required_variations( + ctx.parameters + .iter() + .map(|&arg| &ctx.module.types[arg].inner), + ); // Initiate the declaration if it wasn't previously initialized and inject builtins - let declaration = lookup_function.entry(name.clone()).or_insert_with(|| { + let declaration = self.lookup_function.entry(name.clone()).or_insert_with(|| { variations |= BuiltinVariations::STANDARD; Default::default() }); - inject_builtin(declaration, module, &name, variations); + inject_builtin(declaration, ctx.module, &name, variations); let Context { expressions, @@ -1104,6 +1063,8 @@ impl Frontend { arguments, parameters, parameters_info, + body, + module, .. } = ctx; @@ -1141,7 +1102,7 @@ impl Frontend { decl.defined = true; decl.parameters_info = parameters_info; match decl.kind { - FunctionKind::Call(handle) => *self.module.functions.get_mut(handle) = function, + FunctionKind::Call(handle) => *module.functions.get_mut(handle) = function, FunctionKind::Macro(_) => { let handle = module.functions.append(function, meta); decl.kind = FunctionKind::Call(handle) @@ -1170,27 +1131,25 @@ impl Frontend { ) { let void = result.is_none(); - let &mut Frontend { - ref mut lookup_function, - ref mut module, - .. - } = self; - // Check if the passed arguments require any special variations - let mut variations = - builtin_required_variations(ctx.parameters.iter().map(|&arg| &module.types[arg].inner)); + let mut variations = builtin_required_variations( + ctx.parameters + .iter() + .map(|&arg| &ctx.module.types[arg].inner), + ); // Initiate the declaration if it wasn't previously initialized and inject builtins - let declaration = lookup_function.entry(name.clone()).or_insert_with(|| { + let declaration = self.lookup_function.entry(name.clone()).or_insert_with(|| { variations |= BuiltinVariations::STANDARD; Default::default() }); - inject_builtin(declaration, module, &name, variations); + inject_builtin(declaration, ctx.module, &name, variations); let Context { arguments, parameters, parameters_info, + module, .. } = ctx; @@ -1232,161 +1191,71 @@ impl Frontend { }); } - /// Helper function for building the input/output interface of the entry point + /// Create a Naga [`EntryPoint`] that calls the GLSL `main` function. /// - /// Calls `f` with the data of the entry point argument, flattening composite types - /// recursively + /// We compile the GLSL `main` function as an ordinary Naga [`Function`]. + /// This function synthesizes a Naga [`EntryPoint`] to call that. /// - /// The passed arguments to the callback are: - /// - The name - /// - The pointer expression to the global storage - /// - The handle to the type of the entry point argument - /// - The binding of the entry point argument - /// - The expression arena - fn arg_type_walker( - &self, - name: Option, - binding: crate::Binding, - pointer: Handle, - ty: Handle, - expressions: &mut Arena, - f: &mut impl FnMut( - Option, - Handle, - Handle, - crate::Binding, - &mut Arena, - ), - ) { - match self.module.types[ty].inner { - // TODO: Better error reporting - // right now we just don't walk the array if the size isn't known at - // compile time and let validation catch it - TypeInner::Array { - base, - size: crate::ArraySize::Constant(size), - .. - } => { - let mut location = match binding { - crate::Binding::Location { location, .. } => location, - crate::Binding::BuiltIn(_) => return, - }; - - let interpolation = - self.module.types[base] - .inner - .scalar_kind() - .map(|kind| match kind { - ScalarKind::Float => crate::Interpolation::Perspective, - _ => crate::Interpolation::Flat, - }); - - for index in 0..size.get() { - let member_pointer = expressions.append( - Expression::AccessIndex { - base: pointer, - index, - }, - crate::Span::default(), - ); - - let binding = crate::Binding::Location { - location, - interpolation, - sampling: None, - }; - location += 1; - - self.arg_type_walker( - name.clone(), - binding, - member_pointer, - base, - expressions, - f, - ) - } - } - TypeInner::Struct { ref members, .. } => { - let mut location = match binding { - crate::Binding::Location { location, .. } => location, - crate::Binding::BuiltIn(_) => return, - }; - - for (i, member) in members.iter().enumerate() { - let member_pointer = expressions.append( - Expression::AccessIndex { - base: pointer, - index: i as u32, - }, - crate::Span::default(), - ); - - let binding = match member.binding.clone() { - Some(binding) => binding, - None => { - let interpolation = self.module.types[member.ty] - .inner - .scalar_kind() - .map(|kind| match kind { - ScalarKind::Float => crate::Interpolation::Perspective, - _ => crate::Interpolation::Flat, - }); - let binding = crate::Binding::Location { - location, - interpolation, - sampling: None, - }; - location += 1; - binding - } - }; - - self.arg_type_walker( - member.name.clone(), - binding, - member_pointer, - member.ty, - expressions, - f, - ) - } - } - _ => f(name, pointer, ty, binding, expressions), - } - } - + /// Each GLSL input and output variable (including builtins) becomes a Naga + /// [`GlobalVariable`]s in the [`Private`] address space, which `main` can + /// access in the usual way. + /// + /// The `EntryPoint` we synthesize here has an argument for each GLSL input + /// variable, and returns a struct with a member for each GLSL output + /// variable. The entry point contains code to: + /// + /// - copy its arguments into the Naga globals representing the GLSL input + /// variables, + /// + /// - call the Naga `Function` representing the GLSL `main` function, and then + /// + /// - build its return value from whatever values the GLSL `main` left in + /// the Naga globals representing GLSL `output` variables. + /// + /// Upon entry, [`ctx.body`] should contain code, accumulated by prior calls + /// to [`ParsingContext::parse_external_declaration`][pxd], to initialize + /// private global variables as needed. This code gets spliced into the + /// entry point before the call to `main`. + /// + /// [`GlobalVariable`]: crate::GlobalVariable + /// [`Private`]: crate::AddressSpace::Private + /// [`ctx.body`]: Context::body + /// [pxd]: super::ParsingContext::parse_external_declaration pub(crate) fn add_entry_point( &mut self, function: Handle, - global_init_body: Block, - mut expressions: Arena, - ) { + mut ctx: Context, + ) -> Result<()> { let mut arguments = Vec::new(); - let mut body = Block::with_capacity( + + let body = Block::with_capacity( // global init body - global_init_body.len() + - // prologue and epilogue - self.entry_args.len() * 2 - // Call, Emit for composing struct and return - + 3, + ctx.body.len() + + // prologue and epilogue + self.entry_args.len() * 2 + // Call, Emit for composing struct and return + + 3, ); + let global_init_body = std::mem::replace(&mut ctx.body, body); + for arg in self.entry_args.iter() { if arg.storage != StorageQualifier::Input { continue; } - let pointer = - expressions.append(Expression::GlobalVariable(arg.handle), Default::default()); + let pointer = ctx + .expressions + .append(Expression::GlobalVariable(arg.handle), Default::default()); - self.arg_type_walker( + let ty = ctx.module.global_variables[arg.handle].ty; + + ctx.arg_type_walker( arg.name.clone(), arg.binding.clone(), pointer, - self.module.global_variables[arg.handle].ty, - &mut expressions, - &mut |name, pointer, ty, binding, expressions| { + ty, + &mut |ctx, name, pointer, ty, binding| { let idx = arguments.len() as u32; arguments.push(FunctionArgument { @@ -1395,16 +1264,18 @@ impl Frontend { binding: Some(binding), }); - let value = - expressions.append(Expression::FunctionArgument(idx), Default::default()); - body.push(Statement::Store { pointer, value }, Default::default()); + let value = ctx + .expressions + .append(Expression::FunctionArgument(idx), Default::default()); + ctx.body + .push(Statement::Store { pointer, value }, Default::default()); }, - ) + )? } - body.extend_block(global_init_body); + ctx.body.extend_block(global_init_body); - body.push( + ctx.body.push( Statement::Call { function, arguments: Vec::new(), @@ -1422,16 +1293,18 @@ impl Frontend { continue; } - let pointer = - expressions.append(Expression::GlobalVariable(arg.handle), Default::default()); + let pointer = ctx + .expressions + .append(Expression::GlobalVariable(arg.handle), Default::default()); - self.arg_type_walker( + let ty = ctx.module.global_variables[arg.handle].ty; + + ctx.arg_type_walker( arg.name.clone(), arg.binding.clone(), pointer, - self.module.global_variables[arg.handle].ty, - &mut expressions, - &mut |name, pointer, ty, binding, expressions| { + ty, + &mut |ctx, name, pointer, ty, binding| { members.push(StructMember { name, ty, @@ -1439,21 +1312,23 @@ impl Frontend { offset: span, }); - span += self.module.types[ty].inner.size(self.module.to_ctx()); + span += ctx.module.types[ty].inner.size(ctx.module.to_ctx()); - let len = expressions.len(); - let load = expressions.append(Expression::Load { pointer }, Default::default()); - body.push( - Statement::Emit(expressions.range_from(len)), + let len = ctx.expressions.len(); + let load = ctx + .expressions + .append(Expression::Load { pointer }, Default::default()); + ctx.body.push( + Statement::Emit(ctx.expressions.range_from(len)), Default::default(), ); components.push(load) }, - ) + )? } let (ty, value) = if !components.is_empty() { - let ty = self.module.types.insert( + let ty = ctx.module.types.insert( Type { name: None, inner: TypeInner::Struct { members, span }, @@ -1461,11 +1336,12 @@ impl Frontend { Default::default(), ); - let len = expressions.len(); - let res = - expressions.append(Expression::Compose { ty, components }, Default::default()); - body.push( - Statement::Emit(expressions.range_from(len)), + let len = ctx.expressions.len(); + let res = ctx + .expressions + .append(Expression::Compose { ty, components }, Default::default()); + ctx.body.push( + Statement::Emit(ctx.expressions.range_from(len)), Default::default(), ); @@ -1474,9 +1350,14 @@ impl Frontend { (None, None) }; - body.push(Statement::Return { value }, Default::default()); + ctx.body + .push(Statement::Return { value }, Default::default()); - self.module.entry_points.push(EntryPoint { + let Context { + body, expressions, .. + } = ctx; + + ctx.module.entry_points.push(EntryPoint { name: "main".to_string(), stage: self.meta.stage, early_depth_test: Some(crate::EarlyDepthTest { conservative: None }) @@ -1490,6 +1371,123 @@ impl Frontend { ..Default::default() }, }); + + Ok(()) + } +} + +impl Context<'_> { + /// Helper function for building the input/output interface of the entry point + /// + /// Calls `f` with the data of the entry point argument, flattening composite types + /// recursively + /// + /// The passed arguments to the callback are: + /// - The ctx + /// - The name + /// - The pointer expression to the global storage + /// - The handle to the type of the entry point argument + /// - The binding of the entry point argument + fn arg_type_walker( + &mut self, + name: Option, + binding: crate::Binding, + pointer: Handle, + ty: Handle, + f: &mut impl FnMut( + &mut Context, + Option, + Handle, + Handle, + crate::Binding, + ), + ) -> Result<()> { + match self.module.types[ty].inner { + // TODO: Better error reporting + // right now we just don't walk the array if the size isn't known at + // compile time and let validation catch it + TypeInner::Array { + base, + size: crate::ArraySize::Constant(size), + .. + } => { + let mut location = match binding { + crate::Binding::Location { location, .. } => location, + crate::Binding::BuiltIn(_) => return Ok(()), + }; + + let interpolation = + self.module.types[base] + .inner + .scalar_kind() + .map(|kind| match kind { + ScalarKind::Float => crate::Interpolation::Perspective, + _ => crate::Interpolation::Flat, + }); + + for index in 0..size.get() { + let member_pointer = self.add_expression( + Expression::AccessIndex { + base: pointer, + index, + }, + crate::Span::default(), + )?; + + let binding = crate::Binding::Location { + location, + interpolation, + sampling: None, + second_blend_source: false, + }; + location += 1; + + self.arg_type_walker(name.clone(), binding, member_pointer, base, f)? + } + } + TypeInner::Struct { ref members, .. } => { + let mut location = match binding { + crate::Binding::Location { location, .. } => location, + crate::Binding::BuiltIn(_) => return Ok(()), + }; + + for (i, member) in members.clone().into_iter().enumerate() { + let member_pointer = self.add_expression( + Expression::AccessIndex { + base: pointer, + index: i as u32, + }, + crate::Span::default(), + )?; + + let binding = match member.binding { + Some(binding) => binding, + None => { + let interpolation = self.module.types[member.ty] + .inner + .scalar_kind() + .map(|kind| match kind { + ScalarKind::Float => crate::Interpolation::Perspective, + _ => crate::Interpolation::Flat, + }); + let binding = crate::Binding::Location { + location, + interpolation, + sampling: None, + second_blend_source: false, + }; + location += 1; + binding + } + }; + + self.arg_type_walker(member.name, binding, member_pointer, member.ty, f)? + } + } + _ => f(self, name, pointer, ty, binding), + } + + Ok(()) } } diff --git a/third_party/rust/naga/src/front/glsl/mod.rs b/third_party/rust/naga/src/front/glsl/mod.rs index a1aa4622d3e0..f8f554bf2dc1 100644 --- a/third_party/rust/naga/src/front/glsl/mod.rs +++ b/third_party/rust/naga/src/front/glsl/mod.rs @@ -175,8 +175,6 @@ pub struct Frontend { layouter: Layouter, errors: Vec, - - module: Module, } impl Frontend { @@ -188,10 +186,6 @@ impl Frontend { self.global_variables.clear(); self.entry_args.clear(); self.layouter.clear(); - - // This is necessary because if the last parsing errored out, the module - // wouldn't have been taken - self.module = Module::default(); } /// Parses a shader either outputting a shader [`Module`](Module) or a list @@ -208,14 +202,18 @@ impl Frontend { let lexer = lex::Lexer::new(source, &options.defines); let mut ctx = ParsingContext::new(lexer); - if let Err(e) = ctx.parse(self) { - self.errors.push(e); - } - - if self.errors.is_empty() { - Ok(std::mem::take(&mut self.module)) - } else { - Err(std::mem::take(&mut self.errors)) + match ctx.parse(self) { + Ok(module) => { + if self.errors.is_empty() { + Ok(module) + } else { + Err(std::mem::take(&mut self.errors)) + } + } + Err(e) => { + self.errors.push(e); + Err(std::mem::take(&mut self.errors)) + } } } diff --git a/third_party/rust/naga/src/front/glsl/parser.rs b/third_party/rust/naga/src/front/glsl/parser.rs index 7db30ea80f39..1a3b5a908639 100644 --- a/third_party/rust/naga/src/front/glsl/parser.rs +++ b/third_party/rust/naga/src/front/glsl/parser.rs @@ -9,7 +9,7 @@ use super::{ variables::{GlobalOrConstant, VarDeclaration}, Frontend, Result, }; -use crate::{arena::Handle, proc::U32EvalError, Block, Expression, Span, Type}; +use crate::{arena::Handle, proc::U32EvalError, Expression, Module, Span, Type}; use pp_rs::token::{PreprocessorError, Token as PPToken, TokenValue as PPTokenValue}; use std::iter::Peekable; @@ -162,13 +162,14 @@ impl<'source> ParsingContext<'source> { }) } - pub fn parse(&mut self, frontend: &mut Frontend) -> Result<()> { + pub fn parse(&mut self, frontend: &mut Frontend) -> Result { + let mut module = Module::default(); + // Body and expression arena for global initialization - let mut body = Block::new(); - let mut ctx = Context::new(frontend, &mut body); + let mut ctx = Context::new(frontend, &mut module)?; while self.peek(frontend).is_some() { - self.parse_external_declaration(frontend, &mut ctx, &mut body)?; + self.parse_external_declaration(frontend, &mut ctx)?; } // Add an `EntryPoint` to `parser.module` for `main`, if a @@ -177,8 +178,8 @@ impl<'source> ParsingContext<'source> { for decl in declaration.overloads.iter() { if let FunctionKind::Call(handle) = decl.kind { if decl.defined && decl.parameters.is_empty() { - frontend.add_entry_point(handle, body, ctx.expressions); - return Ok(()); + frontend.add_entry_point(handle, ctx)?; + return Ok(module); } } } @@ -190,10 +191,14 @@ impl<'source> ParsingContext<'source> { }) } - fn parse_uint_constant(&mut self, frontend: &mut Frontend) -> Result<(u32, Span)> { - let (const_expr, meta) = self.parse_constant_expression(frontend)?; + fn parse_uint_constant( + &mut self, + frontend: &mut Frontend, + ctx: &mut Context, + ) -> Result<(u32, Span)> { + let (const_expr, meta) = self.parse_constant_expression(frontend, ctx.module)?; - let res = frontend.module.to_ctx().eval_expr_to_u32(const_expr); + let res = ctx.module.to_ctx().eval_expr_to_u32(const_expr); let int = match res { Ok(value) => Ok(value), @@ -213,16 +218,15 @@ impl<'source> ParsingContext<'source> { fn parse_constant_expression( &mut self, frontend: &mut Frontend, + module: &mut Module, ) -> Result<(Handle, Span)> { - let mut block = Block::new(); - - let mut ctx = Context::new(frontend, &mut block); + let mut ctx = Context::new(frontend, module)?; let mut stmt_ctx = ctx.stmt_ctx(); - let expr = self.parse_conditional(frontend, &mut ctx, &mut stmt_ctx, &mut block, None)?; - let (root, meta) = ctx.lower_expect(stmt_ctx, frontend, expr, ExprPos::Rhs, &mut block)?; + let expr = self.parse_conditional(frontend, &mut ctx, &mut stmt_ctx, None)?; + let (root, meta) = ctx.lower_expect(stmt_ctx, frontend, expr, ExprPos::Rhs)?; - Ok((frontend.solve_constant(&ctx, root, meta)?, meta)) + Ok((ctx.solve_constant(root, meta)?, meta)) } } @@ -387,16 +391,14 @@ impl Frontend { } } -pub struct DeclarationContext<'ctx, 'qualifiers> { +pub struct DeclarationContext<'ctx, 'qualifiers, 'a> { qualifiers: TypeQualifiers<'qualifiers>, /// Indicates a global declaration external: bool, - - ctx: &'ctx mut Context, - body: &'ctx mut Block, + ctx: &'ctx mut Context<'a>, } -impl<'ctx, 'qualifiers> DeclarationContext<'ctx, 'qualifiers> { +impl<'ctx, 'qualifiers, 'a> DeclarationContext<'ctx, 'qualifiers, 'a> { fn add_var( &mut self, frontend: &mut Frontend, @@ -415,24 +417,14 @@ impl<'ctx, 'qualifiers> DeclarationContext<'ctx, 'qualifiers> { match self.external { true => { - let global = frontend.add_global_var(self.ctx, self.body, decl)?; + let global = frontend.add_global_var(self.ctx, decl)?; let expr = match global { GlobalOrConstant::Global(handle) => Expression::GlobalVariable(handle), GlobalOrConstant::Constant(handle) => Expression::Constant(handle), }; - Ok(self.ctx.add_expression(expr, meta, self.body)) + Ok(self.ctx.add_expression(expr, meta)?) } - false => frontend.add_local_var(self.ctx, self.body, decl), + false => frontend.add_local_var(self.ctx, decl), } } - - /// Emits all the expressions captured by the emitter and starts the emitter again - /// - /// Alias to [`emit_restart`] with the declaration body - /// - /// [`emit_restart`]: Context::emit_restart - #[inline] - fn flush_expressions(&mut self) { - self.ctx.emit_restart(self.body); - } } diff --git a/third_party/rust/naga/src/front/glsl/parser/declarations.rs b/third_party/rust/naga/src/front/glsl/parser/declarations.rs index e99dda54f210..2abd67672b08 100644 --- a/third_party/rust/naga/src/front/glsl/parser/declarations.rs +++ b/third_party/rust/naga/src/front/glsl/parser/declarations.rs @@ -13,8 +13,8 @@ use crate::{ Error, ErrorKind, Frontend, Span, }, proc::Alignment, - AddressSpace, Block, Expression, FunctionResult, Handle, ScalarKind, Statement, StructMember, - Type, TypeInner, + AddressSpace, Expression, FunctionResult, Handle, ScalarKind, Statement, StructMember, Type, + TypeInner, }; use super::{DeclarationContext, ParsingContext, Result}; @@ -73,10 +73,9 @@ impl<'source> ParsingContext<'source> { &mut self, frontend: &mut Frontend, global_ctx: &mut Context, - global_body: &mut Block, ) -> Result<()> { if self - .parse_declaration(frontend, global_ctx, global_body, true)? + .parse_declaration(frontend, global_ctx, true)? .is_none() { let token = self.bump(frontend)?; @@ -103,7 +102,6 @@ impl<'source> ParsingContext<'source> { frontend: &mut Frontend, ty: Handle, ctx: &mut Context, - body: &mut Block, ) -> Result<(Handle, Span)> { // initializer: // assignment_expression @@ -118,10 +116,9 @@ impl<'source> ParsingContext<'source> { let mut components = Vec::new(); loop { // The type expected to be parsed inside the initializer list - let new_ty = - element_or_member_type(ty, components.len(), &mut frontend.module.types); + let new_ty = element_or_member_type(ty, components.len(), &mut ctx.module.types); - components.push(self.parse_initializer(frontend, new_ty, ctx, body)?.0); + components.push(self.parse_initializer(frontend, new_ty, ctx)?.0); let token = self.bump(frontend)?; match token.value { @@ -150,18 +147,17 @@ impl<'source> ParsingContext<'source> { } Ok(( - ctx.add_expression(Expression::Compose { ty, components }, meta, body), + ctx.add_expression(Expression::Compose { ty, components }, meta)?, meta, )) } else { let mut stmt = ctx.stmt_ctx(); - let expr = self.parse_assignment(frontend, ctx, &mut stmt, body)?; - let (mut init, init_meta) = - ctx.lower_expect(stmt, frontend, expr, ExprPos::Rhs, body)?; + let expr = self.parse_assignment(frontend, ctx, &mut stmt)?; + let (mut init, init_meta) = ctx.lower_expect(stmt, frontend, expr, ExprPos::Rhs)?; - let scalar_components = scalar_components(&frontend.module.types[ty].inner); + let scalar_components = scalar_components(&ctx.module.types[ty].inner); if let Some((kind, width)) = scalar_components { - ctx.implicit_conversion(frontend, &mut init, init_meta, kind, width)?; + ctx.implicit_conversion(&mut init, init_meta, kind, width)?; } Ok((init, init_meta)) @@ -223,18 +219,17 @@ impl<'source> ParsingContext<'source> { // parse an array specifier if it exists // NOTE: unlike other parse methods this one doesn't expect an array specifier and // returns Ok(None) rather than an error if there is not one - self.parse_array_specifier(frontend, &mut meta, &mut ty)?; + self.parse_array_specifier(frontend, ctx.ctx, &mut meta, &mut ty)?; let init = self .bump_if(frontend, TokenValue::Assign) .map::, _>(|_| { - let (mut expr, init_meta) = - self.parse_initializer(frontend, ty, ctx.ctx, ctx.body)?; + let (mut expr, init_meta) = self.parse_initializer(frontend, ty, ctx.ctx)?; - let scalar_components = scalar_components(&frontend.module.types[ty].inner); + let scalar_components = scalar_components(&ctx.ctx.module.types[ty].inner); if let Some((kind, width)) = scalar_components { ctx.ctx - .implicit_conversion(frontend, &mut expr, init_meta, kind, width)?; + .implicit_conversion(&mut expr, init_meta, kind, width)?; } meta.subsume(init_meta); @@ -246,7 +241,7 @@ impl<'source> ParsingContext<'source> { let is_const = ctx.qualifiers.storage.0 == StorageQualifier::Const; let maybe_const_expr = if ctx.external { if let Some((root, meta)) = init { - match frontend.solve_constant(ctx.ctx, root, meta) { + match ctx.ctx.solve_constant(root, meta) { Ok(res) => Some(res), // If the declaration is external (global scope) and is constant qualified // then the initializer must be a constant expression @@ -263,8 +258,8 @@ impl<'source> ParsingContext<'source> { let pointer = ctx.add_var(frontend, ty, name, maybe_const_expr, meta)?; if let Some((value, _)) = init.filter(|_| maybe_const_expr.is_none()) { - ctx.flush_expressions(); - ctx.body.push(Statement::Store { pointer, value }, meta); + ctx.ctx.emit_restart(); + ctx.ctx.body.push(Statement::Store { pointer, value }, meta); } let token = self.bump(frontend)?; @@ -291,7 +286,6 @@ impl<'source> ParsingContext<'source> { &mut self, frontend: &mut Frontend, ctx: &mut Context, - body: &mut Block, external: bool, ) -> Result> { //declaration: @@ -307,12 +301,12 @@ impl<'source> ParsingContext<'source> { // type_qualifier IDENTIFIER identifier_list SEMICOLON if self.peek_type_qualifier(frontend) || self.peek_type_name(frontend) { - let mut qualifiers = self.parse_type_qualifiers(frontend)?; + let mut qualifiers = self.parse_type_qualifiers(frontend, ctx)?; if self.peek_type_name(frontend) { // This branch handles variables and function prototypes and if // external is true also function definitions - let (ty, mut meta) = self.parse_type(frontend)?; + let (ty, mut meta) = self.parse_type(frontend, ctx)?; let token = self.bump(frontend)?; let token_fallthrough = match token.value { @@ -322,11 +316,10 @@ impl<'source> ParsingContext<'source> { self.bump(frontend)?; let result = ty.map(|ty| FunctionResult { ty, binding: None }); - let mut body = Block::new(); - let mut context = Context::new(frontend, &mut body); + let mut context = Context::new(frontend, ctx.module)?; - self.parse_function_args(frontend, &mut context, &mut body)?; + self.parse_function_args(frontend, &mut context)?; let end_meta = self.expect(frontend, TokenValue::RightParen)?.meta; meta.subsume(end_meta); @@ -349,11 +342,10 @@ impl<'source> ParsingContext<'source> { token.meta, frontend, &mut context, - &mut body, &mut None, )?; - frontend.add_function(context, name, result, body, meta); + frontend.add_function(context, name, result, meta); Ok(Some(meta)) } @@ -394,7 +386,6 @@ impl<'source> ParsingContext<'source> { qualifiers, external, ctx, - body, }; self.backtrack(token_fallthrough)?; @@ -419,7 +410,6 @@ impl<'source> ParsingContext<'source> { self.parse_block_declaration( frontend, ctx, - body, &mut qualifiers, ty_name, token.meta, @@ -427,7 +417,7 @@ impl<'source> ParsingContext<'source> { .map(Some) } else { if qualifiers.invariant.take().is_some() { - frontend.make_variable_invariant(ctx, body, &ty_name, token.meta); + frontend.make_variable_invariant(ctx, &ty_name, token.meta)?; qualifiers.unused_errors(&mut frontend.errors); self.expect(frontend, TokenValue::Semicolon)?; @@ -500,9 +490,9 @@ impl<'source> ParsingContext<'source> { } }; - let (ty, meta) = self.parse_type_non_void(frontend)?; + let (ty, meta) = self.parse_type_non_void(frontend, ctx)?; - match frontend.module.types[ty].inner { + match ctx.module.types[ty].inner { TypeInner::Scalar { kind: ScalarKind::Float | ScalarKind::Sint, .. @@ -528,7 +518,6 @@ impl<'source> ParsingContext<'source> { &mut self, frontend: &mut Frontend, ctx: &mut Context, - body: &mut Block, qualifiers: &mut TypeQualifiers, ty_name: String, mut meta: Span, @@ -548,10 +537,10 @@ impl<'source> ParsingContext<'source> { }; let mut members = Vec::new(); - let span = self.parse_struct_declaration_list(frontend, &mut members, layout)?; + let span = self.parse_struct_declaration_list(frontend, ctx, &mut members, layout)?; self.expect(frontend, TokenValue::RightBrace)?; - let mut ty = frontend.module.types.insert( + let mut ty = ctx.module.types.insert( Type { name: Some(ty_name), inner: TypeInner::Struct { @@ -566,7 +555,7 @@ impl<'source> ParsingContext<'source> { let name = match token.value { TokenValue::Semicolon => None, TokenValue::Identifier(name) => { - self.parse_array_specifier(frontend, &mut meta, &mut ty)?; + self.parse_array_specifier(frontend, ctx, &mut meta, &mut ty)?; self.expect(frontend, TokenValue::Semicolon)?; @@ -585,7 +574,6 @@ impl<'source> ParsingContext<'source> { let global = frontend.add_global_var( ctx, - body, VarDeclaration { qualifiers, ty, @@ -607,7 +595,7 @@ impl<'source> ParsingContext<'source> { entry_arg: None, mutable: true, }; - ctx.add_global(frontend, &k, lookup, body); + ctx.add_global(&k, lookup)?; frontend.global_variables.push((k, lookup)); } @@ -619,6 +607,7 @@ impl<'source> ParsingContext<'source> { pub fn parse_struct_declaration_list( &mut self, frontend: &mut Frontend, + ctx: &mut Context, members: &mut Vec, layout: StructLayout, ) -> Result { @@ -628,12 +617,12 @@ impl<'source> ParsingContext<'source> { loop { // TODO: type_qualifier - let (base_ty, mut meta) = self.parse_type_non_void(frontend)?; + let (base_ty, mut meta) = self.parse_type_non_void(frontend, ctx)?; loop { let (name, name_meta) = self.expect_ident(frontend)?; let mut ty = base_ty; - self.parse_array_specifier(frontend, &mut meta, &mut ty)?; + self.parse_array_specifier(frontend, ctx, &mut meta, &mut ty)?; meta.subsume(name_meta); @@ -641,7 +630,7 @@ impl<'source> ParsingContext<'source> { ty, meta, layout, - &mut frontend.module.types, + &mut ctx.module.types, &mut frontend.errors, ); diff --git a/third_party/rust/naga/src/front/glsl/parser/expressions.rs b/third_party/rust/naga/src/front/glsl/parser/expressions.rs index 7e47b2eea710..32e0959c26f9 100644 --- a/third_party/rust/naga/src/front/glsl/parser/expressions.rs +++ b/third_party/rust/naga/src/front/glsl/parser/expressions.rs @@ -9,7 +9,7 @@ use crate::{ token::{Token, TokenValue}, Error, Frontend, Result, Span, }, - ArraySize, BinaryOperator, Block, Handle, Literal, Type, TypeInner, UnaryOperator, + ArraySize, BinaryOperator, Handle, Literal, Type, TypeInner, UnaryOperator, }; impl<'source> ParsingContext<'source> { @@ -18,7 +18,6 @@ impl<'source> ParsingContext<'source> { frontend: &mut Frontend, ctx: &mut Context, stmt: &mut StmtContext, - body: &mut Block, ) -> Result> { let mut token = self.bump(frontend)?; @@ -47,7 +46,7 @@ impl<'source> ParsingContext<'source> { } TokenValue::BoolConstant(value) => Literal::Bool(value), TokenValue::LeftParen => { - let expr = self.parse_expression(frontend, ctx, stmt, body)?; + let expr = self.parse_expression(frontend, ctx, stmt)?; let meta = self.expect(frontend, TokenValue::RightParen)?.meta; token.meta.subsume(meta); @@ -84,7 +83,6 @@ impl<'source> ParsingContext<'source> { frontend: &mut Frontend, ctx: &mut Context, stmt: &mut StmtContext, - body: &mut Block, meta: &mut Span, ) -> Result>> { let mut args = Vec::new(); @@ -92,7 +90,7 @@ impl<'source> ParsingContext<'source> { meta.subsume(token.meta); } else { loop { - args.push(self.parse_assignment(frontend, ctx, stmt, body)?); + args.push(self.parse_assignment(frontend, ctx, stmt)?); let token = self.bump(frontend)?; match token.value { @@ -122,21 +120,20 @@ impl<'source> ParsingContext<'source> { frontend: &mut Frontend, ctx: &mut Context, stmt: &mut StmtContext, - body: &mut Block, ) -> Result> { let mut base = if self.peek_type_name(frontend) { - let (mut handle, mut meta) = self.parse_type_non_void(frontend)?; + let (mut handle, mut meta) = self.parse_type_non_void(frontend, ctx)?; self.expect(frontend, TokenValue::LeftParen)?; - let args = self.parse_function_call_args(frontend, ctx, stmt, body, &mut meta)?; + let args = self.parse_function_call_args(frontend, ctx, stmt, &mut meta)?; if let TypeInner::Array { size: ArraySize::Dynamic, stride, base, - } = frontend.module.types[handle].inner + } = ctx.module.types[handle].inner { - let span = frontend.module.types.get_span(handle); + let span = ctx.module.types.get_span(handle); let size = u32::try_from(args.len()) .ok() @@ -148,7 +145,7 @@ impl<'source> ParsingContext<'source> { meta, })?; - handle = frontend.module.types.insert( + handle = ctx.module.types.insert( Type { name: None, inner: TypeInner::Array { @@ -175,7 +172,7 @@ impl<'source> ParsingContext<'source> { let (name, mut meta) = self.expect_ident(frontend)?; let expr = if self.bump_if(frontend, TokenValue::LeftParen).is_some() { - let args = self.parse_function_call_args(frontend, ctx, stmt, body, &mut meta)?; + let args = self.parse_function_call_args(frontend, ctx, stmt, &mut meta)?; let kind = match frontend.lookup_type.get(&name) { Some(ty) => FunctionCallKind::TypeConstructor(*ty), @@ -187,7 +184,7 @@ impl<'source> ParsingContext<'source> { meta, } } else { - let var = match frontend.lookup_variable(ctx, body, &name, meta) { + let var = match frontend.lookup_variable(ctx, &name, meta)? { Some(var) => var, None => { return Err(Error { @@ -205,7 +202,7 @@ impl<'source> ParsingContext<'source> { stmt.hir_exprs.append(expr, Default::default()) } else { - self.parse_primary(frontend, ctx, stmt, body)? + self.parse_primary(frontend, ctx, stmt)? }; while let TokenValue::LeftBracket @@ -217,7 +214,7 @@ impl<'source> ParsingContext<'source> { match value { TokenValue::LeftBracket => { - let index = self.parse_expression(frontend, ctx, stmt, body)?; + let index = self.parse_expression(frontend, ctx, stmt)?; let end_meta = self.expect(frontend, TokenValue::RightBracket)?.meta; meta.subsume(end_meta); @@ -233,8 +230,7 @@ impl<'source> ParsingContext<'source> { let (field, end_meta) = self.expect_ident(frontend)?; if self.bump_if(frontend, TokenValue::LeftParen).is_some() { - let args = - self.parse_function_call_args(frontend, ctx, stmt, body, &mut meta)?; + let args = self.parse_function_call_args(frontend, ctx, stmt, &mut meta)?; base = stmt.hir_exprs.append( HirExpr { @@ -287,13 +283,12 @@ impl<'source> ParsingContext<'source> { frontend: &mut Frontend, ctx: &mut Context, stmt: &mut StmtContext, - body: &mut Block, ) -> Result> { Ok(match self.expect_peek(frontend)?.value { TokenValue::Plus | TokenValue::Dash | TokenValue::Bang | TokenValue::Tilde => { let Token { value, mut meta } = self.bump(frontend)?; - let expr = self.parse_unary(frontend, ctx, stmt, body)?; + let expr = self.parse_unary(frontend, ctx, stmt)?; let end_meta = stmt.hir_exprs[expr].meta; let kind = match value { @@ -315,7 +310,7 @@ impl<'source> ParsingContext<'source> { TokenValue::Increment | TokenValue::Decrement => { let Token { value, meta } = self.bump(frontend)?; - let expr = self.parse_unary(frontend, ctx, stmt, body)?; + let expr = self.parse_unary(frontend, ctx, stmt)?; stmt.hir_exprs.append( HirExpr { @@ -332,7 +327,7 @@ impl<'source> ParsingContext<'source> { Default::default(), ) } - _ => self.parse_postfix(frontend, ctx, stmt, body)?, + _ => self.parse_postfix(frontend, ctx, stmt)?, }) } @@ -341,13 +336,12 @@ impl<'source> ParsingContext<'source> { frontend: &mut Frontend, ctx: &mut Context, stmt: &mut StmtContext, - body: &mut Block, passthrough: Option>, min_bp: u8, ) -> Result> { let mut left = passthrough .ok_or(ErrorKind::EndOfFile /* Dummy error */) - .or_else(|_| self.parse_unary(frontend, ctx, stmt, body))?; + .or_else(|_| self.parse_unary(frontend, ctx, stmt))?; let mut meta = stmt.hir_exprs[left].meta; while let Some((l_bp, r_bp)) = binding_power(&self.expect_peek(frontend)?.value) { @@ -357,7 +351,7 @@ impl<'source> ParsingContext<'source> { let Token { value, .. } = self.bump(frontend)?; - let right = self.parse_binary(frontend, ctx, stmt, body, None, r_bp)?; + let right = self.parse_binary(frontend, ctx, stmt, None, r_bp)?; let end_meta = stmt.hir_exprs[right].meta; meta.subsume(end_meta); @@ -403,16 +397,15 @@ impl<'source> ParsingContext<'source> { frontend: &mut Frontend, ctx: &mut Context, stmt: &mut StmtContext, - body: &mut Block, passthrough: Option>, ) -> Result> { - let mut condition = self.parse_binary(frontend, ctx, stmt, body, passthrough, 0)?; + let mut condition = self.parse_binary(frontend, ctx, stmt, passthrough, 0)?; let mut meta = stmt.hir_exprs[condition].meta; if self.bump_if(frontend, TokenValue::Question).is_some() { - let accept = self.parse_expression(frontend, ctx, stmt, body)?; + let accept = self.parse_expression(frontend, ctx, stmt)?; self.expect(frontend, TokenValue::Colon)?; - let reject = self.parse_assignment(frontend, ctx, stmt, body)?; + let reject = self.parse_assignment(frontend, ctx, stmt)?; let end_meta = stmt.hir_exprs[reject].meta; meta.subsume(end_meta); @@ -437,15 +430,14 @@ impl<'source> ParsingContext<'source> { frontend: &mut Frontend, ctx: &mut Context, stmt: &mut StmtContext, - body: &mut Block, ) -> Result> { - let tgt = self.parse_unary(frontend, ctx, stmt, body)?; + let tgt = self.parse_unary(frontend, ctx, stmt)?; let mut meta = stmt.hir_exprs[tgt].meta; Ok(match self.expect_peek(frontend)?.value { TokenValue::Assign => { self.bump(frontend)?; - let value = self.parse_assignment(frontend, ctx, stmt, body)?; + let value = self.parse_assignment(frontend, ctx, stmt)?; let end_meta = stmt.hir_exprs[value].meta; meta.subsume(end_meta); @@ -468,7 +460,7 @@ impl<'source> ParsingContext<'source> { | TokenValue::RightShiftAssign | TokenValue::XorAssign => { let token = self.bump(frontend)?; - let right = self.parse_assignment(frontend, ctx, stmt, body)?; + let right = self.parse_assignment(frontend, ctx, stmt)?; let end_meta = stmt.hir_exprs[right].meta; meta.subsume(end_meta); @@ -504,7 +496,7 @@ impl<'source> ParsingContext<'source> { Default::default(), ) } - _ => self.parse_conditional(frontend, ctx, stmt, body, Some(tgt))?, + _ => self.parse_conditional(frontend, ctx, stmt, Some(tgt))?, }) } @@ -513,13 +505,12 @@ impl<'source> ParsingContext<'source> { frontend: &mut Frontend, ctx: &mut Context, stmt: &mut StmtContext, - body: &mut Block, ) -> Result> { - let mut expr = self.parse_assignment(frontend, ctx, stmt, body)?; + let mut expr = self.parse_assignment(frontend, ctx, stmt)?; while let TokenValue::Comma = self.expect_peek(frontend)?.value { self.bump(frontend)?; - expr = self.parse_assignment(frontend, ctx, stmt, body)?; + expr = self.parse_assignment(frontend, ctx, stmt)?; } Ok(expr) diff --git a/third_party/rust/naga/src/front/glsl/parser/functions.rs b/third_party/rust/naga/src/front/glsl/parser/functions.rs index c05d060ea14b..200afc78fd13 100644 --- a/third_party/rust/naga/src/front/glsl/parser/functions.rs +++ b/third_party/rust/naga/src/front/glsl/parser/functions.rs @@ -40,12 +40,11 @@ impl<'source> ParsingContext<'source> { &mut self, frontend: &mut Frontend, ctx: &mut Context, - body: &mut Block, terminator: &mut Option, ) -> Result> { // Type qualifiers always identify a declaration statement if self.peek_type_qualifier(frontend) { - return self.parse_declaration(frontend, ctx, body, false); + return self.parse_declaration(frontend, ctx, false); } // Type names can identify either declaration statements or type constructors @@ -61,7 +60,7 @@ impl<'source> ParsingContext<'source> { self.backtrack(token)?; if declaration { - return self.parse_declaration(frontend, ctx, body, false); + return self.parse_declaration(frontend, ctx, false); } } @@ -79,14 +78,14 @@ impl<'source> ParsingContext<'source> { let meta_rest = match *value { TokenValue::Continue => { let meta = self.bump(frontend)?.meta; - body.push(Statement::Continue, meta); - terminator.get_or_insert(body.len()); + ctx.body.push(Statement::Continue, meta); + terminator.get_or_insert(ctx.body.len()); self.expect(frontend, TokenValue::Semicolon)?.meta } TokenValue::Break => { let meta = self.bump(frontend)?.meta; - body.push(Statement::Break, meta); - terminator.get_or_insert(body.len()); + ctx.body.push(Statement::Break, meta); + terminator.get_or_insert(ctx.body.len()); self.expect(frontend, TokenValue::Semicolon)?.meta } TokenValue::Return => { @@ -96,25 +95,25 @@ impl<'source> ParsingContext<'source> { _ => { // TODO: Implicit conversions let mut stmt = ctx.stmt_ctx(); - let expr = self.parse_expression(frontend, ctx, &mut stmt, body)?; + let expr = self.parse_expression(frontend, ctx, &mut stmt)?; self.expect(frontend, TokenValue::Semicolon)?; let (handle, meta) = - ctx.lower_expect(stmt, frontend, expr, ExprPos::Rhs, body)?; + ctx.lower_expect(stmt, frontend, expr, ExprPos::Rhs)?; (Some(handle), meta) } }; - ctx.emit_restart(body); + ctx.emit_restart(); - body.push(Statement::Return { value }, meta); - terminator.get_or_insert(body.len()); + ctx.body.push(Statement::Return { value }, meta); + terminator.get_or_insert(ctx.body.len()); meta } TokenValue::Discard => { let meta = self.bump(frontend)?.meta; - body.push(Statement::Kill, meta); - terminator.get_or_insert(body.len()); + ctx.body.push(Statement::Kill, meta); + terminator.get_or_insert(ctx.body.len()); self.expect(frontend, TokenValue::Semicolon)?.meta } @@ -124,33 +123,31 @@ impl<'source> ParsingContext<'source> { self.expect(frontend, TokenValue::LeftParen)?; let condition = { let mut stmt = ctx.stmt_ctx(); - let expr = self.parse_expression(frontend, ctx, &mut stmt, body)?; + let expr = self.parse_expression(frontend, ctx, &mut stmt)?; let (handle, more_meta) = - ctx.lower_expect(stmt, frontend, expr, ExprPos::Rhs, body)?; + ctx.lower_expect(stmt, frontend, expr, ExprPos::Rhs)?; meta.subsume(more_meta); handle }; self.expect(frontend, TokenValue::RightParen)?; - ctx.emit_restart(body); - - let mut accept = Block::new(); - if let Some(more_meta) = - self.parse_statement(frontend, ctx, &mut accept, &mut None)? - { - meta.subsume(more_meta) - } - - let mut reject = Block::new(); - if self.bump_if(frontend, TokenValue::Else).is_some() { - if let Some(more_meta) = - self.parse_statement(frontend, ctx, &mut reject, &mut None)? - { + let accept = ctx.new_body(|ctx| { + if let Some(more_meta) = self.parse_statement(frontend, ctx, &mut None)? { meta.subsume(more_meta); } - } + Ok(()) + })?; - body.push( + let reject = ctx.new_body(|ctx| { + if self.bump_if(frontend, TokenValue::Else).is_some() { + if let Some(more_meta) = self.parse_statement(frontend, ctx, &mut None)? { + meta.subsume(more_meta); + } + } + Ok(()) + })?; + + ctx.body.push( Statement::If { condition, accept, @@ -169,17 +166,16 @@ impl<'source> ParsingContext<'source> { let (selector, uint) = { let mut stmt = ctx.stmt_ctx(); - let expr = self.parse_expression(frontend, ctx, &mut stmt, body)?; - let (root, meta) = - ctx.lower_expect(stmt, frontend, expr, ExprPos::Rhs, body)?; - let uint = frontend.resolve_type(ctx, root, meta)?.scalar_kind() + let expr = self.parse_expression(frontend, ctx, &mut stmt)?; + let (root, meta) = ctx.lower_expect(stmt, frontend, expr, ExprPos::Rhs)?; + let uint = ctx.resolve_type(root, meta)?.scalar_kind() == Some(crate::ScalarKind::Uint); (root, uint) }; self.expect(frontend, TokenValue::RightParen)?; - ctx.emit_restart(body); + ctx.emit_restart(); let mut cases = Vec::new(); // Track if any default case is present in the switch statement. @@ -192,13 +188,18 @@ impl<'source> ParsingContext<'source> { self.bump(frontend)?; let mut stmt = ctx.stmt_ctx(); - let expr = self.parse_expression(frontend, ctx, &mut stmt, body)?; + let expr = self.parse_expression(frontend, ctx, &mut stmt)?; let (root, meta) = - ctx.lower_expect(stmt, frontend, expr, ExprPos::Rhs, body)?; - let const_expr = frontend.solve_constant(ctx, root, meta)?; + ctx.lower_expect(stmt, frontend, expr, ExprPos::Rhs)?; + let const_expr = ctx.solve_constant(root, meta)?; - match frontend.module.const_expressions[const_expr] { + match ctx.module.const_expressions[const_expr] { Expression::Literal(Literal::I32(value)) => match uint { + // This unchecked cast isn't good, but since + // we only reach this code when the selector + // is unsigned but the case label is signed, + // verification will reject the module + // anyway (which also matches GLSL's rules). true => crate::SwitchValue::U32(value as u32), false => crate::SwitchValue::I32(value), }, @@ -244,35 +245,32 @@ impl<'source> ParsingContext<'source> { self.expect(frontend, TokenValue::Colon)?; - let mut body = Block::new(); - - let mut case_terminator = None; - loop { - match self.expect_peek(frontend)?.value { - TokenValue::Case | TokenValue::Default | TokenValue::RightBrace => { - break - } - _ => { - self.parse_statement( - frontend, - ctx, - &mut body, - &mut case_terminator, - )?; - } - } - } - let mut fall_through = true; - if let Some(mut idx) = case_terminator { - if let Statement::Break = body[idx - 1] { - fall_through = false; - idx -= 1; + let body = ctx.new_body(|ctx| { + let mut case_terminator = None; + loop { + match self.expect_peek(frontend)?.value { + TokenValue::Case | TokenValue::Default | TokenValue::RightBrace => { + break + } + _ => { + self.parse_statement(frontend, ctx, &mut case_terminator)?; + } + } } - body.cull(idx..) - } + if let Some(mut idx) = case_terminator { + if let Statement::Break = ctx.body[idx - 1] { + fall_through = false; + idx -= 1; + } + + ctx.body.cull(idx..) + } + + Ok(()) + })?; cases.push(SwitchCase { value, @@ -317,51 +315,48 @@ impl<'source> ParsingContext<'source> { }) } - body.push(Statement::Switch { selector, cases }, meta); + ctx.body.push(Statement::Switch { selector, cases }, meta); meta } TokenValue::While => { let mut meta = self.bump(frontend)?.meta; - let mut loop_body = Block::new(); + let loop_body = ctx.new_body(|ctx| { + let mut stmt = ctx.stmt_ctx(); + self.expect(frontend, TokenValue::LeftParen)?; + let root = self.parse_expression(frontend, ctx, &mut stmt)?; + meta.subsume(self.expect(frontend, TokenValue::RightParen)?.meta); - let mut stmt = ctx.stmt_ctx(); - self.expect(frontend, TokenValue::LeftParen)?; - let root = self.parse_expression(frontend, ctx, &mut stmt, &mut loop_body)?; - meta.subsume(self.expect(frontend, TokenValue::RightParen)?.meta); + let (expr, expr_meta) = ctx.lower_expect(stmt, frontend, root, ExprPos::Rhs)?; + let condition = ctx.add_expression( + Expression::Unary { + op: UnaryOperator::Not, + expr, + }, + expr_meta, + )?; - let (expr, expr_meta) = - ctx.lower_expect(stmt, frontend, root, ExprPos::Rhs, &mut loop_body)?; - let condition = ctx.add_expression( - Expression::Unary { - op: UnaryOperator::Not, - expr, - }, - expr_meta, - &mut loop_body, - ); + ctx.emit_restart(); - ctx.emit_restart(&mut loop_body); + ctx.body.push( + Statement::If { + condition, + accept: new_break(), + reject: Block::new(), + }, + crate::Span::default(), + ); - loop_body.push( - Statement::If { - condition, - accept: new_break(), - reject: Block::new(), - }, - crate::Span::default(), - ); + meta.subsume(expr_meta); - meta.subsume(expr_meta); + if let Some(body_meta) = self.parse_statement(frontend, ctx, &mut None)? { + meta.subsume(body_meta); + } + Ok(()) + })?; - if let Some(body_meta) = - self.parse_statement(frontend, ctx, &mut loop_body, &mut None)? - { - meta.subsume(body_meta); - } - - body.push( + ctx.body.push( Statement::Loop { body: loop_body, continuing: Block::new(), @@ -375,47 +370,46 @@ impl<'source> ParsingContext<'source> { TokenValue::Do => { let mut meta = self.bump(frontend)?.meta; - let mut loop_body = Block::new(); + let loop_body = ctx.new_body(|ctx| { + let mut terminator = None; + self.parse_statement(frontend, ctx, &mut terminator)?; - let mut terminator = None; - self.parse_statement(frontend, ctx, &mut loop_body, &mut terminator)?; + let mut stmt = ctx.stmt_ctx(); - let mut stmt = ctx.stmt_ctx(); + self.expect(frontend, TokenValue::While)?; + self.expect(frontend, TokenValue::LeftParen)?; + let root = self.parse_expression(frontend, ctx, &mut stmt)?; + let end_meta = self.expect(frontend, TokenValue::RightParen)?.meta; - self.expect(frontend, TokenValue::While)?; - self.expect(frontend, TokenValue::LeftParen)?; - let root = self.parse_expression(frontend, ctx, &mut stmt, &mut loop_body)?; - let end_meta = self.expect(frontend, TokenValue::RightParen)?.meta; + meta.subsume(end_meta); - meta.subsume(end_meta); + let (expr, expr_meta) = ctx.lower_expect(stmt, frontend, root, ExprPos::Rhs)?; + let condition = ctx.add_expression( + Expression::Unary { + op: UnaryOperator::Not, + expr, + }, + expr_meta, + )?; - let (expr, expr_meta) = - ctx.lower_expect(stmt, frontend, root, ExprPos::Rhs, &mut loop_body)?; - let condition = ctx.add_expression( - Expression::Unary { - op: UnaryOperator::Not, - expr, - }, - expr_meta, - &mut loop_body, - ); + ctx.emit_restart(); - ctx.emit_restart(&mut loop_body); + ctx.body.push( + Statement::If { + condition, + accept: new_break(), + reject: Block::new(), + }, + crate::Span::default(), + ); - loop_body.push( - Statement::If { - condition, - accept: new_break(), - reject: Block::new(), - }, - crate::Span::default(), - ); + if let Some(idx) = terminator { + ctx.body.cull(idx..) + } + Ok(()) + })?; - if let Some(idx) = terminator { - loop_body.cull(idx..) - } - - body.push( + ctx.body.push( Statement::Loop { body: loop_body, continuing: Block::new(), @@ -434,96 +428,98 @@ impl<'source> ParsingContext<'source> { if self.bump_if(frontend, TokenValue::Semicolon).is_none() { if self.peek_type_name(frontend) || self.peek_type_qualifier(frontend) { - self.parse_declaration(frontend, ctx, body, false)?; + self.parse_declaration(frontend, ctx, false)?; } else { let mut stmt = ctx.stmt_ctx(); - let expr = self.parse_expression(frontend, ctx, &mut stmt, body)?; - ctx.lower(stmt, frontend, expr, ExprPos::Rhs, body)?; + let expr = self.parse_expression(frontend, ctx, &mut stmt)?; + ctx.lower(stmt, frontend, expr, ExprPos::Rhs)?; self.expect(frontend, TokenValue::Semicolon)?; } } - let (mut block, mut continuing) = (Block::new(), Block::new()); + let loop_body = ctx.new_body(|ctx| { + if self.bump_if(frontend, TokenValue::Semicolon).is_none() { + let (expr, expr_meta) = if self.peek_type_name(frontend) + || self.peek_type_qualifier(frontend) + { + let mut qualifiers = self.parse_type_qualifiers(frontend, ctx)?; + let (ty, mut meta) = self.parse_type_non_void(frontend, ctx)?; + let name = self.expect_ident(frontend)?.0; - if self.bump_if(frontend, TokenValue::Semicolon).is_none() { - let (expr, expr_meta) = if self.peek_type_name(frontend) - || self.peek_type_qualifier(frontend) - { - let mut qualifiers = self.parse_type_qualifiers(frontend)?; - let (ty, mut meta) = self.parse_type_non_void(frontend)?; - let name = self.expect_ident(frontend)?.0; + self.expect(frontend, TokenValue::Assign)?; - self.expect(frontend, TokenValue::Assign)?; + let (value, end_meta) = self.parse_initializer(frontend, ty, ctx)?; + meta.subsume(end_meta); - let (value, end_meta) = - self.parse_initializer(frontend, ty, ctx, &mut block)?; - meta.subsume(end_meta); + let decl = VarDeclaration { + qualifiers: &mut qualifiers, + ty, + name: Some(name), + init: None, + meta, + }; - let decl = VarDeclaration { - qualifiers: &mut qualifiers, - ty, - name: Some(name), - init: None, - meta, + let pointer = frontend.add_local_var(ctx, decl)?; + + ctx.emit_restart(); + + ctx.body.push(Statement::Store { pointer, value }, meta); + + (value, end_meta) + } else { + let mut stmt = ctx.stmt_ctx(); + let root = self.parse_expression(frontend, ctx, &mut stmt)?; + ctx.lower_expect(stmt, frontend, root, ExprPos::Rhs)? }; - let pointer = frontend.add_local_var(ctx, &mut block, decl)?; + let condition = ctx.add_expression( + Expression::Unary { + op: UnaryOperator::Not, + expr, + }, + expr_meta, + )?; - ctx.emit_restart(&mut block); + ctx.emit_restart(); - block.push(Statement::Store { pointer, value }, meta); + ctx.body.push( + Statement::If { + condition, + accept: new_break(), + reject: Block::new(), + }, + crate::Span::default(), + ); - (value, end_meta) - } else { - let mut stmt = ctx.stmt_ctx(); - let root = self.parse_expression(frontend, ctx, &mut stmt, &mut block)?; - ctx.lower_expect(stmt, frontend, root, ExprPos::Rhs, &mut block)? - }; - - let condition = ctx.add_expression( - Expression::Unary { - op: UnaryOperator::Not, - expr, - }, - expr_meta, - &mut block, - ); - - ctx.emit_restart(&mut block); - - block.push( - Statement::If { - condition, - accept: new_break(), - reject: Block::new(), - }, - crate::Span::default(), - ); - - self.expect(frontend, TokenValue::Semicolon)?; - } - - match self.expect_peek(frontend)?.value { - TokenValue::RightParen => {} - _ => { - let mut stmt = ctx.stmt_ctx(); - let rest = - self.parse_expression(frontend, ctx, &mut stmt, &mut continuing)?; - ctx.lower(stmt, frontend, rest, ExprPos::Rhs, &mut continuing)?; + self.expect(frontend, TokenValue::Semicolon)?; } - } + Ok(()) + })?; + + let continuing = ctx.new_body(|ctx| { + match self.expect_peek(frontend)?.value { + TokenValue::RightParen => {} + _ => { + let mut stmt = ctx.stmt_ctx(); + let rest = self.parse_expression(frontend, ctx, &mut stmt)?; + ctx.lower(stmt, frontend, rest, ExprPos::Rhs)?; + } + } + Ok(()) + })?; meta.subsume(self.expect(frontend, TokenValue::RightParen)?.meta); - if let Some(stmt_meta) = - self.parse_statement(frontend, ctx, &mut block, &mut None)? - { - meta.subsume(stmt_meta); - } + let loop_body = ctx.with_body(loop_body, |ctx| { + if let Some(stmt_meta) = self.parse_statement(frontend, ctx, &mut None)? { + meta.subsume(stmt_meta); + } + Ok(()) + })?; - body.push( + ctx.body.push( Statement::Loop { - body: block, + body: loop_body, continuing, break_if: None, }, @@ -535,22 +531,20 @@ impl<'source> ParsingContext<'source> { meta } TokenValue::LeftBrace => { - let meta = self.bump(frontend)?.meta; - - let mut block = Block::new(); + let mut meta = self.bump(frontend)?.meta; let mut block_terminator = None; - let meta = self.parse_compound_statement( - meta, - frontend, - ctx, - &mut block, - &mut block_terminator, - )?; - body.push(Statement::Block(block), meta); + let block = ctx.new_body(|ctx| { + let block_meta = + self.parse_compound_statement(meta, frontend, ctx, &mut block_terminator)?; + meta.subsume(block_meta); + Ok(()) + })?; + + ctx.body.push(Statement::Block(block), meta); if block_terminator.is_some() { - terminator.get_or_insert(body.len()); + terminator.get_or_insert(ctx.body.len()); } meta @@ -561,8 +555,8 @@ impl<'source> ParsingContext<'source> { // tokens. Unknown or invalid tokens will be caught there and // turned into an error. let mut stmt = ctx.stmt_ctx(); - let expr = self.parse_expression(frontend, ctx, &mut stmt, body)?; - ctx.lower(stmt, frontend, expr, ExprPos::Rhs, body)?; + let expr = self.parse_expression(frontend, ctx, &mut stmt)?; + ctx.lower(stmt, frontend, expr, ExprPos::Rhs)?; self.expect(frontend, TokenValue::Semicolon)?.meta } }; @@ -576,7 +570,6 @@ impl<'source> ParsingContext<'source> { mut meta: Span, frontend: &mut Frontend, ctx: &mut Context, - body: &mut Block, terminator: &mut Option, ) -> Result { ctx.symbol_table.push_scope(); @@ -590,7 +583,7 @@ impl<'source> ParsingContext<'source> { break; } - let stmt = self.parse_statement(frontend, ctx, body, terminator)?; + let stmt = self.parse_statement(frontend, ctx, terminator)?; if let Some(stmt_meta) = stmt { meta.subsume(stmt_meta); @@ -598,7 +591,7 @@ impl<'source> ParsingContext<'source> { } if let Some(idx) = *terminator { - body.cull(idx..) + ctx.body.cull(idx..) } ctx.symbol_table.pop_scope(); @@ -609,8 +602,7 @@ impl<'source> ParsingContext<'source> { pub fn parse_function_args( &mut self, frontend: &mut Frontend, - context: &mut Context, - body: &mut Block, + ctx: &mut Context, ) -> Result<()> { if self.bump_if(frontend, TokenValue::Void).is_some() { return Ok(()); @@ -619,19 +611,19 @@ impl<'source> ParsingContext<'source> { loop { if self.peek_type_name(frontend) || self.peek_parameter_qualifier(frontend) { let qualifier = self.parse_parameter_qualifier(frontend); - let mut ty = self.parse_type_non_void(frontend)?.0; + let mut ty = self.parse_type_non_void(frontend, ctx)?.0; match self.expect_peek(frontend)?.value { TokenValue::Comma => { self.bump(frontend)?; - context.add_function_arg(frontend, body, None, ty, qualifier); + ctx.add_function_arg(None, ty, qualifier)?; continue; } TokenValue::Identifier(_) => { let mut name = self.expect_ident(frontend)?; - self.parse_array_specifier(frontend, &mut name.1, &mut ty)?; + self.parse_array_specifier(frontend, ctx, &mut name.1, &mut ty)?; - context.add_function_arg(frontend, body, Some(name), ty, qualifier); + ctx.add_function_arg(Some(name), ty, qualifier)?; if self.bump_if(frontend, TokenValue::Comma).is_some() { continue; diff --git a/third_party/rust/naga/src/front/glsl/parser/types.rs b/third_party/rust/naga/src/front/glsl/parser/types.rs index 4761e8bc5305..d2d24b5dabc9 100644 --- a/third_party/rust/naga/src/front/glsl/parser/types.rs +++ b/third_party/rust/naga/src/front/glsl/parser/types.rs @@ -3,6 +3,7 @@ use std::num::NonZeroU32; use crate::{ front::glsl::{ ast::{QualifierKey, QualifierValue, StorageQualifier, StructLayout, TypeQualifiers}, + context::Context, error::ExpectedToken, parser::ParsingContext, token::{Token, TokenValue}, @@ -17,10 +18,11 @@ impl<'source> ParsingContext<'source> { pub fn parse_array_specifier( &mut self, frontend: &mut Frontend, + ctx: &mut Context, span: &mut Span, ty: &mut Handle, ) -> Result<()> { - while self.parse_array_specifier_single(frontend, span, ty)? {} + while self.parse_array_specifier_single(frontend, ctx, span, ty)? {} Ok(()) } @@ -28,6 +30,7 @@ impl<'source> ParsingContext<'source> { fn parse_array_specifier_single( &mut self, frontend: &mut Frontend, + ctx: &mut Context, span: &mut Span, ty: &mut Handle, ) -> Result { @@ -38,7 +41,7 @@ impl<'source> ParsingContext<'source> { span.subsume(meta); ArraySize::Dynamic } else { - let (value, constant_span) = self.parse_uint_constant(frontend)?; + let (value, constant_span) = self.parse_uint_constant(frontend, ctx)?; let size = NonZeroU32::new(value).ok_or(Error { kind: ErrorKind::SemanticError("Array size must be greater than zero".into()), meta: constant_span, @@ -48,9 +51,9 @@ impl<'source> ParsingContext<'source> { ArraySize::Constant(size) }; - frontend.layouter.update(frontend.module.to_ctx()).unwrap(); + frontend.layouter.update(ctx.module.to_ctx()).unwrap(); let stride = frontend.layouter[*ty].to_stride(); - *ty = frontend.module.types.insert( + *ty = ctx.module.types.insert( Type { name: None, inner: TypeInner::Array { @@ -68,11 +71,15 @@ impl<'source> ParsingContext<'source> { } } - pub fn parse_type(&mut self, frontend: &mut Frontend) -> Result<(Option>, Span)> { + pub fn parse_type( + &mut self, + frontend: &mut Frontend, + ctx: &mut Context, + ) -> Result<(Option>, Span)> { let token = self.bump(frontend)?; let mut handle = match token.value { TokenValue::Void => return Ok((None, token.meta)), - TokenValue::TypeName(ty) => frontend.module.types.insert(ty, token.meta), + TokenValue::TypeName(ty) => ctx.module.types.insert(ty, token.meta), TokenValue::Struct => { let mut meta = token.meta; let ty_name = self.expect_ident(frontend)?.0; @@ -80,12 +87,13 @@ impl<'source> ParsingContext<'source> { let mut members = Vec::new(); let span = self.parse_struct_declaration_list( frontend, + ctx, &mut members, StructLayout::Std140, )?; let end_meta = self.expect(frontend, TokenValue::RightBrace)?.meta; meta.subsume(end_meta); - let ty = frontend.module.types.insert( + let ty = ctx.module.types.insert( Type { name: Some(ty_name.clone()), inner: TypeInner::Struct { members, span }, @@ -120,12 +128,16 @@ impl<'source> ParsingContext<'source> { }; let mut span = token.meta; - self.parse_array_specifier(frontend, &mut span, &mut handle)?; + self.parse_array_specifier(frontend, ctx, &mut span, &mut handle)?; Ok((Some(handle), span)) } - pub fn parse_type_non_void(&mut self, frontend: &mut Frontend) -> Result<(Handle, Span)> { - let (maybe_ty, meta) = self.parse_type(frontend)?; + pub fn parse_type_non_void( + &mut self, + frontend: &mut Frontend, + ctx: &mut Context, + ) -> Result<(Handle, Span)> { + let (maybe_ty, meta) = self.parse_type(frontend, ctx)?; let ty = maybe_ty.ok_or_else(|| Error { kind: ErrorKind::SemanticError("Type can't be void".into()), meta, @@ -156,6 +168,7 @@ impl<'source> ParsingContext<'source> { pub fn parse_type_qualifiers<'a>( &mut self, frontend: &mut Frontend, + ctx: &mut Context, ) -> Result> { let mut qualifiers = TypeQualifiers::default(); @@ -164,7 +177,7 @@ impl<'source> ParsingContext<'source> { // Handle layout qualifiers outside the match since this can push multiple values if token.value == TokenValue::Layout { - self.parse_layout_qualifier_id_list(frontend, &mut qualifiers)?; + self.parse_layout_qualifier_id_list(frontend, ctx, &mut qualifiers)?; continue; } @@ -287,11 +300,12 @@ impl<'source> ParsingContext<'source> { pub fn parse_layout_qualifier_id_list( &mut self, frontend: &mut Frontend, + ctx: &mut Context, qualifiers: &mut TypeQualifiers, ) -> Result<()> { self.expect(frontend, TokenValue::LeftParen)?; loop { - self.parse_layout_qualifier_id(frontend, &mut qualifiers.layout_qualifiers)?; + self.parse_layout_qualifier_id(frontend, ctx, &mut qualifiers.layout_qualifiers)?; if self.bump_if(frontend, TokenValue::Comma).is_some() { continue; @@ -308,6 +322,7 @@ impl<'source> ParsingContext<'source> { pub fn parse_layout_qualifier_id( &mut self, frontend: &mut Frontend, + ctx: &mut Context, qualifiers: &mut crate::FastHashMap, ) -> Result<()> { // layout_qualifier_id: @@ -332,13 +347,14 @@ impl<'source> ParsingContext<'source> { } else { let key = QualifierKey::String(name.into()); let value = if self.bump_if(frontend, TokenValue::Assign).is_some() { - let (value, end_meta) = match self.parse_uint_constant(frontend) { - Ok(v) => v, - Err(e) => { - frontend.errors.push(e); - (0, Span::default()) - } - }; + let (value, end_meta) = + match self.parse_uint_constant(frontend, ctx) { + Ok(v) => v, + Err(e) => { + frontend.errors.push(e); + (0, Span::default()) + } + }; token.meta.subsume(end_meta); QualifierValue::Uint(value) diff --git a/third_party/rust/naga/src/front/glsl/types.rs b/third_party/rust/naga/src/front/glsl/types.rs index 513bc2275422..a91a0a9f2802 100644 --- a/third_party/rust/naga/src/front/glsl/types.rs +++ b/third_party/rust/naga/src/front/glsl/types.rs @@ -1,6 +1,4 @@ -use super::{ - constants::ConstantSolver, context::Context, Error, ErrorKind, Frontend, Result, Span, -}; +use super::{constants::ConstantSolver, context::Context, Error, ErrorKind, Result, Span}; use crate::{ proc::ResolveContext, Bytes, Expression, Handle, ImageClass, ImageDimension, ScalarKind, Type, TypeInner, VectorSize, @@ -226,7 +224,7 @@ pub const fn type_power(kind: ScalarKind, width: Bytes) -> Option { }) } -impl Frontend { +impl Context<'_> { /// Resolves the types of the expressions until `expr` (inclusive) /// /// This needs to be done before the [`typifier`] can be queried for @@ -240,16 +238,11 @@ impl Frontend { /// /// [`typifier`]: Context::typifier /// [`resolve_type`]: Self::resolve_type - pub(crate) fn typifier_grow( - &self, - ctx: &mut Context, - expr: Handle, - meta: Span, - ) -> Result<()> { - let resolve_ctx = ResolveContext::with_locals(&self.module, &ctx.locals, &ctx.arguments); + pub(crate) fn typifier_grow(&mut self, expr: Handle, meta: Span) -> Result<()> { + let resolve_ctx = ResolveContext::with_locals(self.module, &self.locals, &self.arguments); - ctx.typifier - .grow(expr, &ctx.expressions, &resolve_ctx) + self.typifier + .grow(expr, &self.expressions, &resolve_ctx) .map_err(|error| Error { kind: ErrorKind::SemanticError(format!("Can't resolve type: {error:?}").into()), meta, @@ -263,14 +256,13 @@ impl Frontend { /// /// [`typifier`]: Context::typifier /// [`typifier_grow`]: Self::typifier_grow - pub(crate) fn resolve_type<'b>( - &'b self, - ctx: &'b mut Context, + pub(crate) fn resolve_type( + &mut self, expr: Handle, meta: Span, - ) -> Result<&'b TypeInner> { - self.typifier_grow(ctx, expr, meta)?; - Ok(ctx.typifier.get(expr, &self.module.types)) + ) -> Result<&TypeInner> { + self.typifier_grow(expr, meta)?; + Ok(self.typifier.get(expr, &self.module.types)) } /// Gets the type handle for the result of the `expr` expression @@ -290,25 +282,23 @@ impl Frontend { /// [`resolve_type`]: Self::resolve_type pub(crate) fn resolve_type_handle( &mut self, - ctx: &mut Context, expr: Handle, meta: Span, ) -> Result> { - self.typifier_grow(ctx, expr, meta)?; - Ok(ctx.typifier.register_type(expr, &mut self.module.types)) + self.typifier_grow(expr, meta)?; + Ok(self.typifier.register_type(expr, &mut self.module.types)) } /// Invalidates the cached type resolution for `expr` forcing a recomputation - pub(crate) fn invalidate_expression<'b>( - &'b self, - ctx: &'b mut Context, + pub(crate) fn invalidate_expression( + &mut self, expr: Handle, meta: Span, ) -> Result<()> { - let resolve_ctx = ResolveContext::with_locals(&self.module, &ctx.locals, &ctx.arguments); + let resolve_ctx = ResolveContext::with_locals(self.module, &self.locals, &self.arguments); - ctx.typifier - .invalidate(expr, &ctx.expressions, &resolve_ctx) + self.typifier + .invalidate(expr, &self.expressions, &resolve_ctx) .map_err(|error| Error { kind: ErrorKind::SemanticError(format!("Can't resolve type: {error:?}").into()), meta, @@ -317,13 +307,12 @@ impl Frontend { pub(crate) fn solve_constant( &mut self, - ctx: &Context, root: Handle, meta: Span, ) -> Result> { let mut solver = ConstantSolver { types: &mut self.module.types, - expressions: &ctx.expressions, + expressions: &self.expressions, constants: &mut self.module.constants, const_expressions: &mut self.module.const_expressions, }; diff --git a/third_party/rust/naga/src/front/glsl/variables.rs b/third_party/rust/naga/src/front/glsl/variables.rs index a9a403e402e0..58cc31461ec5 100644 --- a/third_party/rust/naga/src/front/glsl/variables.rs +++ b/third_party/rust/naga/src/front/glsl/variables.rs @@ -5,9 +5,9 @@ use super::{ Frontend, Result, Span, }; use crate::{ - AddressSpace, Binding, Block, BuiltIn, Constant, Expression, GlobalVariable, Handle, - Interpolation, LocalVariable, ResourceBinding, ScalarKind, ShaderStage, SwizzleComponent, Type, - TypeInner, VectorSize, + AddressSpace, Binding, BuiltIn, Constant, Expression, GlobalVariable, Handle, Interpolation, + LocalVariable, ResourceBinding, ScalarKind, ShaderStage, SwizzleComponent, Type, TypeInner, + VectorSize, }; pub struct VarDeclaration<'a, 'key> { @@ -40,12 +40,11 @@ impl Frontend { fn add_builtin( &mut self, ctx: &mut Context, - body: &mut Block, name: &str, data: BuiltInData, meta: Span, - ) -> Option { - let ty = self.module.types.insert( + ) -> Result> { + let ty = ctx.module.types.insert( Type { name: None, inner: data.inner, @@ -53,7 +52,7 @@ impl Frontend { meta, ); - let handle = self.module.global_variables.append( + let handle = ctx.module.global_variables.append( GlobalVariable { name: Some(name.into()), space: AddressSpace::Private, @@ -81,7 +80,7 @@ impl Frontend { }, )); - let expr = ctx.add_expression(Expression::GlobalVariable(handle), meta, body); + let expr = ctx.add_expression(Expression::GlobalVariable(handle), meta)?; let var = VariableReference { expr, @@ -93,18 +92,17 @@ impl Frontend { ctx.symbol_table.add_root(name.into(), var.clone()); - Some(var) + Ok(Some(var)) } pub(crate) fn lookup_variable( &mut self, ctx: &mut Context, - body: &mut Block, name: &str, meta: Span, - ) -> Option { + ) -> Result> { if let Some(var) = ctx.symbol_table.lookup(name).cloned() { - return Some(var); + return Ok(Some(var)); } let data = match name { @@ -182,7 +180,7 @@ impl Frontend { storage: StorageQualifier::Output, }, "gl_ClipDistance" | "gl_CullDistance" => { - let base = self.module.types.insert( + let base = ctx.module.types.insert( Type { name: None, inner: TypeInner::Scalar { @@ -217,7 +215,7 @@ impl Frontend { "gl_VertexIndex" => BuiltIn::VertexIndex, "gl_SampleID" => BuiltIn::SampleIndex, "gl_LocalInvocationIndex" => BuiltIn::LocalInvocationIndex, - _ => return None, + _ => return Ok(None), }; BuiltInData { @@ -232,17 +230,16 @@ impl Frontend { } }; - self.add_builtin(ctx, body, name, data, meta) + self.add_builtin(ctx, name, data, meta) } pub(crate) fn make_variable_invariant( &mut self, ctx: &mut Context, - body: &mut Block, name: &str, meta: Span, - ) { - if let Some(var) = self.lookup_variable(ctx, body, name, meta) { + ) -> Result<()> { + if let Some(var) = self.lookup_variable(ctx, name, meta)? { if let Some(index) = var.entry_arg { if let Binding::BuiltIn(BuiltIn::Position { ref mut invariant }) = self.entry_args[index].binding @@ -251,19 +248,19 @@ impl Frontend { } } } + Ok(()) } pub(crate) fn field_selection( &mut self, ctx: &mut Context, pos: ExprPos, - body: &mut Block, expression: Handle, name: &str, meta: Span, ) -> Result> { - let (ty, is_pointer) = match *self.resolve_type(ctx, expression, meta)? { - TypeInner::Pointer { base, .. } => (&self.module.types[base].inner, true), + let (ty, is_pointer) = match *ctx.resolve_type(expression, meta)? { + TypeInner::Pointer { base, .. } => (&ctx.module.types[base].inner, true), ref ty => (ty, false), }; match *ty { @@ -281,12 +278,11 @@ impl Frontend { index: index as u32, }, meta, - body, - ); + )?; Ok(match pos { ExprPos::Rhs if is_pointer => { - ctx.add_expression(Expression::Load { pointer }, meta, body) + ctx.add_expression(Expression::Load { pointer }, meta)? } _ => pointer, }) @@ -358,19 +354,17 @@ impl Frontend { pointer: expression, }, meta, - body, - ); + )?; } _ => {} }; - return Ok(ctx.add_expression( + return ctx.add_expression( Expression::AccessIndex { base: expression, index: pattern[0].index(), }, meta, - body, - )); + ); } 2 => VectorSize::Bi, 3 => VectorSize::Tri, @@ -396,8 +390,7 @@ impl Frontend { pointer: expression, }, meta, - body, - ); + )?; } Ok(ctx.add_expression( @@ -407,8 +400,7 @@ impl Frontend { pattern, }, meta, - body, - )) + )?) } else { Err(Error { kind: ErrorKind::SemanticError( @@ -430,7 +422,6 @@ impl Frontend { pub(crate) fn add_global_var( &mut self, ctx: &mut Context, - body: &mut Block, VarDeclaration { qualifiers, mut ty, @@ -449,7 +440,7 @@ impl Frontend { .uint_layout_qualifier("location", &mut self.errors) .unwrap_or(0); let interpolation = qualifiers.interpolation.take().map(|(i, _)| i).or_else(|| { - let kind = self.module.types[ty].inner.scalar_kind()?; + let kind = ctx.module.types[ty].inner.scalar_kind()?; Some(match kind { ScalarKind::Float => Interpolation::Perspective, _ => Interpolation::Flat, @@ -457,7 +448,7 @@ impl Frontend { }); let sampling = qualifiers.sampling.take().map(|(s, _)| s); - let handle = self.module.global_variables.append( + let handle = ctx.module.global_variables.append( GlobalVariable { name: name.clone(), space: AddressSpace::Private, @@ -475,6 +466,7 @@ impl Frontend { location, interpolation, sampling, + second_blend_source: false, }, handle, storage, @@ -500,7 +492,7 @@ impl Frontend { ty, init, }; - let handle = self.module.constants.fetch_or_append(constant, meta); + let handle = ctx.module.constants.fetch_or_append(constant, meta); let lookup = GlobalLookup { kind: GlobalLookupKind::Constant(handle, ty), @@ -517,7 +509,7 @@ impl Frontend { *access = allowed_access; } } - AddressSpace::Uniform => match self.module.types[ty].inner { + AddressSpace::Uniform => match ctx.module.types[ty].inner { TypeInner::Image { class, dim, @@ -546,7 +538,7 @@ impl Frontend { _ => unreachable!(), } - ty = self.module.types.insert( + ty = ctx.module.types.insert( Type { name: None, inner: TypeInner::Image { @@ -592,7 +584,7 @@ impl Frontend { _ => None, }; - let handle = self.module.global_variables.append( + let handle = ctx.module.global_variables.append( GlobalVariable { name: name.clone(), space, @@ -614,7 +606,7 @@ impl Frontend { }; if let Some(name) = name { - ctx.add_global(self, &name, lookup, body); + ctx.add_global(&name, lookup)?; self.global_variables.push((name, lookup)); } @@ -627,7 +619,6 @@ impl Frontend { pub(crate) fn add_local_var( &mut self, ctx: &mut Context, - body: &mut Block, decl: VarDeclaration, ) -> Result> { let storage = decl.qualifiers.storage; @@ -651,7 +642,7 @@ impl Frontend { }, decl.meta, ); - let expr = ctx.add_expression(Expression::LocalVariable(handle), decl.meta, body); + let expr = ctx.add_expression(Expression::LocalVariable(handle), decl.meta)?; if let Some(name) = decl.name { let maybe_var = ctx.add_local_var(name.clone(), expr, mutable); diff --git a/third_party/rust/naga/src/front/interpolator.rs b/third_party/rust/naga/src/front/interpolator.rs index 96f5db6ff73f..0196a2254d79 100644 --- a/third_party/rust/naga/src/front/interpolator.rs +++ b/third_party/rust/naga/src/front/interpolator.rs @@ -43,6 +43,7 @@ impl crate::Binding { location: _, interpolation: ref mut interpolation @ None, ref mut sampling, + second_blend_source: _, } = *self { match ty.scalar_kind() { diff --git a/third_party/rust/naga/src/front/spv/mod.rs b/third_party/rust/naga/src/front/spv/mod.rs index a210e8c421b9..36108fdd9b22 100644 --- a/third_party/rust/naga/src/front/spv/mod.rs +++ b/third_party/rust/naga/src/front/spv/mod.rs @@ -255,6 +255,7 @@ impl Decoration { location, interpolation, sampling, + second_blend_source: false, }), _ => Err(Error::MissingDecoration(spirv::Decoration::Location)), } diff --git a/third_party/rust/naga/src/front/type_gen.rs b/third_party/rust/naga/src/front/type_gen.rs index 1ee454c448fe..0c608504c91c 100644 --- a/third_party/rust/naga/src/front/type_gen.rs +++ b/third_party/rust/naga/src/front/type_gen.rs @@ -5,55 +5,6 @@ Type generators. use crate::{arena::Handle, span::Span}; impl crate::Module { - pub fn generate_atomic_compare_exchange_result( - &mut self, - kind: crate::ScalarKind, - width: crate::Bytes, - ) -> Handle { - let bool_ty = self.types.insert( - crate::Type { - name: None, - inner: crate::TypeInner::Scalar { - kind: crate::ScalarKind::Bool, - width: crate::BOOL_WIDTH, - }, - }, - Span::UNDEFINED, - ); - let scalar_ty = self.types.insert( - crate::Type { - name: None, - inner: crate::TypeInner::Scalar { kind, width }, - }, - Span::UNDEFINED, - ); - - self.types.insert( - crate::Type { - name: Some(format!( - "__atomic_compare_exchange_result<{kind:?},{width}>" - )), - inner: crate::TypeInner::Struct { - members: vec![ - crate::StructMember { - name: Some("old_value".to_string()), - ty: scalar_ty, - binding: None, - offset: 0, - }, - crate::StructMember { - name: Some("exchanged".to_string()), - ty: bool_ty, - binding: None, - offset: 4, - }, - ], - span: 8, - }, - }, - Span::UNDEFINED, - ) - } /// Populate this module's [`SpecialTypes::ray_desc`] type. /// /// [`SpecialTypes::ray_desc`] is the type of the [`descriptor`] operand of @@ -311,4 +262,203 @@ impl crate::Module { self.special_types.ray_intersection = Some(handle); handle } + + /// Populate this module's [`SpecialTypes::predeclared_types`] type and return the handle. + /// + /// [`SpecialTypes::predeclared_types`]: crate::SpecialTypes::predeclared_types + pub fn generate_predeclared_type( + &mut self, + special_type: crate::PredeclaredType, + ) -> Handle { + use std::fmt::Write; + + if let Some(value) = self.special_types.predeclared_types.get(&special_type) { + return *value; + } + + let ty = match special_type { + crate::PredeclaredType::AtomicCompareExchangeWeakResult { kind, width } => { + let bool_ty = self.types.insert( + crate::Type { + name: None, + inner: crate::TypeInner::Scalar { + kind: crate::ScalarKind::Bool, + width: crate::BOOL_WIDTH, + }, + }, + Span::UNDEFINED, + ); + let scalar_ty = self.types.insert( + crate::Type { + name: None, + inner: crate::TypeInner::Scalar { kind, width }, + }, + Span::UNDEFINED, + ); + + crate::Type { + name: Some(format!( + "__atomic_compare_exchange_result<{kind:?},{width}>" + )), + inner: crate::TypeInner::Struct { + members: vec![ + crate::StructMember { + name: Some("old_value".to_string()), + ty: scalar_ty, + binding: None, + offset: 0, + }, + crate::StructMember { + name: Some("exchanged".to_string()), + ty: bool_ty, + binding: None, + offset: 4, + }, + ], + span: 8, + }, + } + } + crate::PredeclaredType::ModfResult { size, width } => { + let float_ty = self.types.insert( + crate::Type { + name: None, + inner: crate::TypeInner::Scalar { + kind: crate::ScalarKind::Float, + width, + }, + }, + Span::UNDEFINED, + ); + + let (member_ty, second_offset) = if let Some(size) = size { + let vec_ty = self.types.insert( + crate::Type { + name: None, + inner: crate::TypeInner::Vector { + size, + kind: crate::ScalarKind::Float, + width, + }, + }, + Span::UNDEFINED, + ); + (vec_ty, size as u32 * width as u32) + } else { + (float_ty, width as u32) + }; + + let mut type_name = "__modf_result_".to_string(); + if let Some(size) = size { + let _ = write!(type_name, "vec{}_", size as u8); + } + let _ = write!(type_name, "f{}", width * 8); + + crate::Type { + name: Some(type_name), + inner: crate::TypeInner::Struct { + members: vec![ + crate::StructMember { + name: Some("fract".to_string()), + ty: member_ty, + binding: None, + offset: 0, + }, + crate::StructMember { + name: Some("whole".to_string()), + ty: member_ty, + binding: None, + offset: second_offset, + }, + ], + span: second_offset * 2, + }, + } + } + crate::PredeclaredType::FrexpResult { size, width } => { + let float_ty = self.types.insert( + crate::Type { + name: None, + inner: crate::TypeInner::Scalar { + kind: crate::ScalarKind::Float, + width, + }, + }, + Span::UNDEFINED, + ); + + let int_ty = self.types.insert( + crate::Type { + name: None, + inner: crate::TypeInner::Scalar { + kind: crate::ScalarKind::Sint, + width, + }, + }, + Span::UNDEFINED, + ); + + let (fract_member_ty, exp_member_ty, second_offset) = if let Some(size) = size { + let vec_float_ty = self.types.insert( + crate::Type { + name: None, + inner: crate::TypeInner::Vector { + size, + kind: crate::ScalarKind::Float, + width, + }, + }, + Span::UNDEFINED, + ); + let vec_int_ty = self.types.insert( + crate::Type { + name: None, + inner: crate::TypeInner::Vector { + size, + kind: crate::ScalarKind::Sint, + width, + }, + }, + Span::UNDEFINED, + ); + (vec_float_ty, vec_int_ty, size as u32 * width as u32) + } else { + (float_ty, int_ty, width as u32) + }; + + let mut type_name = "__frexp_result_".to_string(); + if let Some(size) = size { + let _ = write!(type_name, "vec{}_", size as u8); + } + let _ = write!(type_name, "f{}", width * 8); + + crate::Type { + name: Some(type_name), + inner: crate::TypeInner::Struct { + members: vec![ + crate::StructMember { + name: Some("fract".to_string()), + ty: fract_member_ty, + binding: None, + offset: 0, + }, + crate::StructMember { + name: Some("exp".to_string()), + ty: exp_member_ty, + binding: None, + offset: second_offset, + }, + ], + span: second_offset * 2, + }, + } + } + }; + + let handle = self.types.insert(ty, Span::UNDEFINED); + self.special_types + .predeclared_types + .insert(special_type, handle); + handle + } } diff --git a/third_party/rust/naga/src/front/wgsl/error.rs b/third_party/rust/naga/src/front/wgsl/error.rs index a3355f861a96..7ce795fa08d1 100644 --- a/third_party/rust/naga/src/front/wgsl/error.rs +++ b/third_party/rust/naga/src/front/wgsl/error.rs @@ -242,6 +242,7 @@ pub enum Error<'a> { Other, ExpectedArraySize(Span), NonPositiveArrayLength(Span), + MissingWorkgroupSize(Span), } impl<'a> Error<'a> { @@ -433,7 +434,7 @@ impl<'a> Error<'a> { }, Error::RepeatedAttribute(bad_span) => ParseError { message: format!("repeated attribute: '{}'", &source[bad_span]), - labels: vec![(bad_span, "repated attribute".into())], + labels: vec![(bad_span, "repeated attribute".into())], notes: vec![], }, Error::UnknownAttribute(bad_span) => ParseError { @@ -704,6 +705,14 @@ impl<'a> Error<'a> { labels: vec![(span, "must be greater than zero".into())], notes: vec![], }, + Error::MissingWorkgroupSize(span) => ParseError { + message: "workgroup size is missing on compute shader entry point".to_string(), + labels: vec![( + span, + "must be paired with a @workgroup_size attribute".into(), + )], + notes: vec![], + }, } } } diff --git a/third_party/rust/naga/src/front/wgsl/lower/mod.rs b/third_party/rust/naga/src/front/wgsl/lower/mod.rs index 84c0d993e1dd..64ef43cb93af 100644 --- a/third_party/rust/naga/src/front/wgsl/lower/mod.rs +++ b/third_party/rust/naga/src/front/wgsl/lower/mod.rs @@ -504,22 +504,29 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> { } /// Insert splats, if needed by the non-'*' operations. + /// + /// See the "Binary arithmetic expressions with mixed scalar and vector operands" + /// table in the WebGPU Shading Language specification for relevant operators. + /// + /// Multiply is not handled here as backends are expected to handle vec*scalar + /// operations, so inserting splats into the IR increases size needlessly. fn binary_op_splat( &mut self, op: crate::BinaryOperator, left: &mut Handle, right: &mut Handle, ) -> Result<(), Error<'source>> { - if op != crate::BinaryOperator::Multiply { + if matches!( + op, + crate::BinaryOperator::Add + | crate::BinaryOperator::Subtract + | crate::BinaryOperator::Divide + | crate::BinaryOperator::Modulo + ) { self.grow_types(*left)?.grow_types(*right)?; - let left_size = match *self.resolved_inner(*left) { - crate::TypeInner::Vector { size, .. } => Some(size), - _ => None, - }; - - match (left_size, self.resolved_inner(*right)) { - (Some(size), &crate::TypeInner::Scalar { .. }) => { + match (self.resolved_inner(*left), self.resolved_inner(*right)) { + (&crate::TypeInner::Vector { size, .. }, &crate::TypeInner::Scalar { .. }) => { *right = self.append_expression( crate::Expression::Splat { size, @@ -528,7 +535,7 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> { self.get_expression_span(*right), ); } - (None, &crate::TypeInner::Vector { size, .. }) => { + (&crate::TypeInner::Scalar { .. }, &crate::TypeInner::Vector { size, .. }) => { *left = self.append_expression( crate::Expression::Splat { size, value: *left }, self.get_expression_span(*left), @@ -967,7 +974,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { name: f.name.name.to_string(), stage: entry.stage, early_depth_test: entry.early_depth_test, - workgroup_size: entry.workgroup_size, + workgroup_size: entry.workgroup_size.unwrap_or([0, 0, 0]), function, }); Ok(LoweredGlobalDecl::EntryPoint) @@ -1689,7 +1696,26 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { let argument = self.expression(args.next()?, ctx.reborrow())?; args.finish()?; - crate::Expression::Relational { fun, argument } + // Check for no-op all(bool) and any(bool): + let argument_unmodified = matches!( + fun, + crate::RelationalFunction::All | crate::RelationalFunction::Any + ) && { + ctx.grow_types(argument)?; + matches!( + ctx.resolved_inner(argument), + &crate::TypeInner::Scalar { + kind: crate::ScalarKind::Bool, + .. + } + ) + }; + + if argument_unmodified { + return Ok(Some(argument)); + } else { + crate::Expression::Relational { fun, argument } + } } else if let Some((axis, ctrl)) = conv::map_derivative(function.name) { let mut args = ctx.prepare_args(arguments, 1, span); let expr = self.expression(args.next()?, ctx.reborrow())?; @@ -1719,6 +1745,25 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { args.finish()?; + if fun == crate::MathFunction::Modf || fun == crate::MathFunction::Frexp { + ctx.grow_types(arg)?; + if let Some((size, width)) = match *ctx.resolved_inner(arg) { + crate::TypeInner::Scalar { width, .. } => Some((None, width)), + crate::TypeInner::Vector { size, width, .. } => { + Some((Some(size), width)) + } + _ => None, + } { + ctx.module.generate_predeclared_type( + if fun == crate::MathFunction::Modf { + crate::PredeclaredType::ModfResult { size, width } + } else { + crate::PredeclaredType::FrexpResult { size, width } + }, + ); + } + } + crate::Expression::Math { fun, arg, @@ -1854,10 +1899,12 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { let expression = match *ctx.resolved_inner(value) { crate::TypeInner::Scalar { kind, width } => { crate::Expression::AtomicResult { - //TODO: cache this to avoid generating duplicate types - ty: ctx - .module - .generate_atomic_compare_exchange_result(kind, width), + ty: ctx.module.generate_predeclared_type( + crate::PredeclaredType::AtomicCompareExchangeWeakResult { + kind, + width, + }, + ), comparison: true, } } diff --git a/third_party/rust/naga/src/front/wgsl/parse/ast.rs b/third_party/rust/naga/src/front/wgsl/parse/ast.rs index 9b7670e4a236..34aeb21a1a0d 100644 --- a/third_party/rust/naga/src/front/wgsl/parse/ast.rs +++ b/third_party/rust/naga/src/front/wgsl/parse/ast.rs @@ -103,7 +103,7 @@ pub struct FunctionResult<'a> { pub struct EntryPoint { pub stage: crate::ShaderStage, pub early_depth_test: Option, - pub workgroup_size: [u32; 3], + pub workgroup_size: Option<[u32; 3]>, } #[cfg(doc)] diff --git a/third_party/rust/naga/src/front/wgsl/parse/mod.rs b/third_party/rust/naga/src/front/wgsl/parse/mod.rs index b6798027ea2a..86dd12799d1b 100644 --- a/third_party/rust/naga/src/front/wgsl/parse/mod.rs +++ b/third_party/rust/naga/src/front/wgsl/parse/mod.rs @@ -2,7 +2,7 @@ use crate::front::wgsl::error::{Error, ExpectedToken}; use crate::front::wgsl::parse::lexer::{Lexer, Token}; use crate::front::wgsl::parse::number::Number; use crate::front::SymbolTable; -use crate::{Arena, FastHashSet, Handle, Span}; +use crate::{Arena, FastHashSet, Handle, ShaderStage, Span}; pub mod ast; pub mod conv; @@ -143,6 +143,7 @@ impl ParsedAttribute { #[derive(Default)] struct BindingParser { location: ParsedAttribute, + second_blend_source: ParsedAttribute, built_in: ParsedAttribute, interpolation: ParsedAttribute, sampling: ParsedAttribute, @@ -182,6 +183,9 @@ impl BindingParser { } lexer.expect(Token::Paren(')'))?; } + "second_blend_source" => { + self.second_blend_source.set(true, name_span)?; + } "invariant" => { self.invariant.set(true, name_span)?; } @@ -208,6 +212,7 @@ impl BindingParser { location, interpolation, sampling, + second_blend_source: self.second_blend_source.value.unwrap_or(false), })) } (None, Some(crate::BuiltIn::Position { .. }), None, None, invariant) => { @@ -2158,7 +2163,8 @@ impl Parser { // read attributes let mut binding = None; let mut stage = ParsedAttribute::default(); - let mut workgroup_size = [0u32; 3]; + let mut compute_span = Span::new(0, 0); + let mut workgroup_size = ParsedAttribute::default(); let mut early_depth_test = ParsedAttribute::default(); let (mut bind_index, mut bind_group) = (ParsedAttribute::default(), ParsedAttribute::default()); @@ -2184,11 +2190,12 @@ impl Parser { } ("compute", name_span) => { stage.set(crate::ShaderStage::Compute, name_span)?; + compute_span = name_span; } - ("workgroup_size", _) => { + ("workgroup_size", name_span) => { lexer.expect(Token::Paren('('))?; - workgroup_size = [1u32; 3]; - for (i, size) in workgroup_size.iter_mut().enumerate() { + let mut new_workgroup_size = [1u32; 3]; + for (i, size) in new_workgroup_size.iter_mut().enumerate() { *size = Self::generic_non_negative_int_literal(lexer)?; match lexer.next() { (Token::Paren(')'), _) => break, @@ -2201,6 +2208,7 @@ impl Parser { } } } + workgroup_size.set(new_workgroup_size, name_span)?; } ("early_depth_test", name_span) => { let conservative = if lexer.skip(Token::Paren('(')) { @@ -2281,11 +2289,18 @@ impl Parser { (Token::Word("fn"), _) => { let function = self.function_decl(lexer, out, &mut dependencies)?; Some(ast::GlobalDeclKind::Fn(ast::Function { - entry_point: stage.value.map(|stage| ast::EntryPoint { - stage, - early_depth_test: early_depth_test.value, - workgroup_size, - }), + entry_point: if let Some(stage) = stage.value { + if stage == ShaderStage::Compute && workgroup_size.value.is_none() { + return Err(Error::MissingWorkgroupSize(compute_span)); + } + Some(ast::EntryPoint { + stage, + early_depth_test: early_depth_test.value, + workgroup_size: workgroup_size.value, + }) + } else { + None + }, ..function })) } diff --git a/third_party/rust/naga/src/front/wgsl/tests.rs b/third_party/rust/naga/src/front/wgsl/tests.rs index 80ea261434c1..828f1e3c71af 100644 --- a/third_party/rust/naga/src/front/wgsl/tests.rs +++ b/third_party/rust/naga/src/front/wgsl/tests.rs @@ -387,13 +387,80 @@ fn parse_expressions() { }").unwrap(); } +#[test] +fn binary_expression_mixed_scalar_and_vector_operands() { + for (operand, expect_splat) in [ + ('<', false), + ('>', false), + ('&', false), + ('|', false), + ('+', true), + ('-', true), + ('*', false), + ('/', true), + ('%', true), + ] { + let module = parse_str(&format!( + " + const some_vec = vec3(1.0, 1.0, 1.0); + @fragment + fn main() -> @location(0) vec4 {{ + if (all(1.0 {operand} some_vec)) {{ + return vec4(0.0); + }} + return vec4(1.0); + }} + " + )) + .unwrap(); + + let expressions = &&module.entry_points[0].function.expressions; + + let found_expressions = expressions + .iter() + .filter(|&(_, e)| { + if let crate::Expression::Binary { left, .. } = *e { + matches!( + (expect_splat, &expressions[left]), + (false, &crate::Expression::Literal(crate::Literal::F32(..))) + | (true, &crate::Expression::Splat { .. }) + ) + } else { + false + } + }) + .count(); + + assert_eq!(found_expressions, 1); + } + + let module = parse_str( + "@fragment + fn main(mat: mat3x3) { + let vec = vec3(1.0, 1.0, 1.0); + let result = mat / vec; + }", + ) + .unwrap(); + let expressions = &&module.entry_points[0].function.expressions; + let found_splat = expressions.iter().any(|(_, e)| { + if let crate::Expression::Binary { left, .. } = *e { + matches!(&expressions[left], &crate::Expression::Splat { .. }) + } else { + false + } + }); + assert!(!found_splat, "'mat / vec' should not be splatted"); +} + #[test] fn parse_pointers() { parse_str( - "fn foo() { + "fn foo(a: ptr) -> f32 { return *a; } + fn bar() { var x: f32 = 1.0; let px = &x; - let py = frexp(0.5, px); + let py = foo(px); }", ) .unwrap(); @@ -534,6 +601,7 @@ fn parse_repeated_attributes() { ("size(16)", template_struct), ("vertex", template_stage), ("early_depth_test(less_equal)", template_resource), + ("workgroup_size(1)", template_stage), ] { let shader = template.replace("__REPLACE__", &format!("@{attribute} @{attribute}")); let name_length = attribute.rfind('(').unwrap_or(attribute.len()) as u32; @@ -548,3 +616,18 @@ fn parse_repeated_attributes() { )); } } + +#[test] +fn parse_missing_workgroup_size() { + use crate::{ + front::wgsl::{error::Error, Frontend}, + Span, + }; + + let shader = "@compute fn vs() -> vec4 { return vec4(0.0); }"; + let result = Frontend::new().inner(shader); + assert!(matches!( + result.unwrap_err(), + Error::MissingWorkgroupSize(span) if span == Span::new(1, 8) + )); +} diff --git a/third_party/rust/naga/src/lib.rs b/third_party/rust/naga/src/lib.rs index a1f7ef1654d7..49fd9d4e5ac6 100644 --- a/third_party/rust/naga/src/lib.rs +++ b/third_party/rust/naga/src/lib.rs @@ -922,6 +922,8 @@ pub enum Binding { /// [`Fragment`]: crate::ShaderStage::Fragment Location { location: u32, + /// Indicates the 2nd input to the blender when dual-source blending. + second_blend_source: bool, interpolation: Option, sampling: Option, }, @@ -1943,6 +1945,31 @@ pub struct EntryPoint { pub function: Function, } +/// Return types predeclared for the frexp, modf, and atomicCompareExchangeWeak built-in functions. +/// +/// These cannot be spelled in WGSL source. +/// +/// Stored in [`SpecialTypes::predeclared_types`] and created by [`Module::generate_predeclared_type`]. +#[derive(Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "clone", derive(Clone))] +#[cfg_attr(feature = "serialize", derive(Serialize))] +#[cfg_attr(feature = "deserialize", derive(Deserialize))] +#[cfg_attr(feature = "arbitrary", derive(Arbitrary))] +pub enum PredeclaredType { + AtomicCompareExchangeWeakResult { + kind: ScalarKind, + width: Bytes, + }, + ModfResult { + size: Option, + width: Bytes, + }, + FrexpResult { + size: Option, + width: Bytes, + }, +} + /// Set of special types that can be optionally generated by the frontends. #[derive(Debug, Default)] #[cfg_attr(feature = "clone", derive(Clone))] @@ -1961,6 +1988,12 @@ pub struct SpecialTypes { /// Call [`Module::generate_ray_intersection_type`] to populate /// this if needed and return the handle. pub ray_intersection: Option>, + + /// Types for predeclared wgsl types instantiated on demand. + /// + /// Call [`Module::generate_predeclared_type`] to populate this if + /// needed and return the handle. + pub predeclared_types: indexmap::IndexMap>, } /// Shader module. diff --git a/third_party/rust/naga/src/proc/mod.rs b/third_party/rust/naga/src/proc/mod.rs index 582c8870341f..bfb2b0d7ac67 100644 --- a/third_party/rust/naga/src/proc/mod.rs +++ b/third_party/rust/naga/src/proc/mod.rs @@ -375,8 +375,8 @@ impl super::MathFunction { Self::Round => 1, Self::Fract => 1, Self::Trunc => 1, - Self::Modf => 2, - Self::Frexp => 2, + Self::Modf => 1, + Self::Frexp => 1, Self::Ldexp => 2, // exponent Self::Exp => 1, diff --git a/third_party/rust/naga/src/proc/typifier.rs b/third_party/rust/naga/src/proc/typifier.rs index 6b79e0ead24a..a6130ad796fd 100644 --- a/third_party/rust/naga/src/proc/typifier.rs +++ b/third_party/rust/naga/src/proc/typifier.rs @@ -706,8 +706,6 @@ impl<'a> ResolveContext<'a> { Mf::Round | Mf::Fract | Mf::Trunc | - Mf::Modf | - Mf::Frexp | Mf::Ldexp | // exponent Mf::Exp | @@ -715,6 +713,31 @@ impl<'a> ResolveContext<'a> { Mf::Log | Mf::Log2 | Mf::Pow => res_arg.clone(), + Mf::Modf | Mf::Frexp => { + let (size, width) = match res_arg.inner_with(types) { + &Ti::Scalar { + kind: crate::ScalarKind::Float, + width, + } => (None, width), + &Ti::Vector { + kind: crate::ScalarKind::Float, + size, + width, + } => (Some(size), width), + ref other => + return Err(ResolveError::IncompatibleOperands(format!("{fun:?}({other:?}, _)"))) + }; + let result = self + .special_types + .predeclared_types + .get(&if fun == Mf::Modf { + crate::PredeclaredType::ModfResult { size, width } + } else { + crate::PredeclaredType::FrexpResult { size, width } + }) + .ok_or(ResolveError::MissingSpecialType)?; + TypeResolution::Handle(*result) + }, // geometry Mf::Dot => match *res_arg.inner_with(types) { Ti::Vector { diff --git a/third_party/rust/naga/src/valid/analyzer.rs b/third_party/rust/naga/src/valid/analyzer.rs index 1e75c5af6c02..e4162e15f53f 100644 --- a/third_party/rust/naga/src/valid/analyzer.rs +++ b/third_party/rust/naga/src/valid/analyzer.rs @@ -256,6 +256,9 @@ pub struct FunctionInfo { /// /// [`GlobalVariable`]: crate::GlobalVariable sampling: crate::FastHashSet, + + /// Indicates that the function is using dual source blending. + pub dual_source_blending: bool, } impl FunctionInfo { @@ -999,6 +1002,7 @@ impl ModuleInfo { global_uses: vec![GlobalUse::empty(); module.global_variables.len()].into_boxed_slice(), expressions: vec![ExpressionInfo::new(); fun.expressions.len()].into_boxed_slice(), sampling: crate::FastHashSet::default(), + dual_source_blending: false, }; let resolve_context = ResolveContext::with_locals(module, &fun.local_variables, &fun.arguments); @@ -1108,6 +1112,7 @@ fn uniform_control_flow() { global_uses: vec![GlobalUse::empty(); global_var_arena.len()].into_boxed_slice(), expressions: vec![ExpressionInfo::new(); expressions.len()].into_boxed_slice(), sampling: crate::FastHashSet::default(), + dual_source_blending: false, }; let resolve_context = ResolveContext { constants: &Arena::new(), diff --git a/third_party/rust/naga/src/valid/expression.rs b/third_party/rust/naga/src/valid/expression.rs index 1703d213e1ff..1d1d6c0b9919 100644 --- a/third_party/rust/naga/src/valid/expression.rs +++ b/third_party/rust/naga/src/valid/expression.rs @@ -893,7 +893,7 @@ impl super::Validator { let arg3_ty = arg3.map(resolve); match fun { Mf::Abs => { - if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() { + if arg1_ty.is_some() || arg2_ty.is_some() || arg3_ty.is_some() { return Err(ExpressionError::WrongArgumentCount(fun)); } let good = match *arg_ty { @@ -976,10 +976,9 @@ impl super::Validator { | Mf::Log | Mf::Log2 | Mf::Length - | Mf::Sign | Mf::Sqrt | Mf::InverseSqrt => { - if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() { + if arg1_ty.is_some() || arg2_ty.is_some() || arg3_ty.is_some() { return Err(ExpressionError::WrongArgumentCount(fun)); } match *arg_ty { @@ -992,6 +991,22 @@ impl super::Validator { _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)), } } + Mf::Sign => { + if arg1_ty.is_some() || arg2_ty.is_some() || arg3_ty.is_some() { + return Err(ExpressionError::WrongArgumentCount(fun)); + } + match *arg_ty { + Ti::Scalar { + kind: Sk::Float | Sk::Sint, + .. + } + | Ti::Vector { + kind: Sk::Float | Sk::Sint, + .. + } => {} + _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)), + } + } Mf::Atan2 | Mf::Pow | Mf::Distance | Mf::Step => { let arg1_ty = match (arg1_ty, arg2_ty, arg3_ty) { (Some(ty1), None, None) => ty1, @@ -1014,31 +1029,48 @@ impl super::Validator { )); } } - Mf::Modf | Mf::Frexp | Mf::Ldexp => { + Mf::Modf | Mf::Frexp => { + if arg1_ty.is_some() || arg2_ty.is_some() || arg3_ty.is_some() { + return Err(ExpressionError::WrongArgumentCount(fun)); + } + if !matches!( + *arg_ty, + Ti::Scalar { + kind: Sk::Float, + .. + } | Ti::Vector { + kind: Sk::Float, + .. + }, + ) { + return Err(ExpressionError::InvalidArgumentType(fun, 1, arg)); + } + } + Mf::Ldexp => { let arg1_ty = match (arg1_ty, arg2_ty, arg3_ty) { (Some(ty1), None, None) => ty1, _ => return Err(ExpressionError::WrongArgumentCount(fun)), }; - let (size0, width0) = match *arg_ty { + let size0 = match *arg_ty { Ti::Scalar { - kind: Sk::Float, - width, - } => (None, width), + kind: Sk::Float, .. + } => None, Ti::Vector { kind: Sk::Float, size, - width, - } => (Some(size), width), - _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)), + .. + } => Some(size), + _ => { + return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)); + } }; let good = match *arg1_ty { - Ti::Pointer { base, space: _ } => module.types[base].inner == *arg_ty, - Ti::ValuePointer { + Ti::Scalar { kind: Sk::Sint, .. } if size0.is_none() => true, + Ti::Vector { size, - kind: Sk::Float, - width, - space: _, - } => size == size0 && width == width0, + kind: Sk::Sint, + .. + } if Some(size) == size0 => true, _ => false, }; if !good { @@ -1130,7 +1162,7 @@ impl super::Validator { } } Mf::Normalize => { - if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() { + if arg1_ty.is_some() || arg2_ty.is_some() || arg3_ty.is_some() { return Err(ExpressionError::WrongArgumentCount(fun)); } match *arg_ty { @@ -1210,7 +1242,7 @@ impl super::Validator { } } Mf::Inverse | Mf::Determinant => { - if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() { + if arg1_ty.is_some() || arg2_ty.is_some() || arg3_ty.is_some() { return Err(ExpressionError::WrongArgumentCount(fun)); } let good = match *arg_ty { @@ -1222,7 +1254,7 @@ impl super::Validator { } } Mf::Transpose => { - if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() { + if arg1_ty.is_some() || arg2_ty.is_some() || arg3_ty.is_some() { return Err(ExpressionError::WrongArgumentCount(fun)); } match *arg_ty { @@ -1236,7 +1268,7 @@ impl super::Validator { | Mf::ReverseBits | Mf::FindLsb | Mf::FindMsb => { - if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() { + if arg1_ty.is_some() || arg2_ty.is_some() || arg3_ty.is_some() { return Err(ExpressionError::WrongArgumentCount(fun)); } match *arg_ty { @@ -1333,7 +1365,7 @@ impl super::Validator { } } Mf::Pack2x16unorm | Mf::Pack2x16snorm | Mf::Pack2x16float => { - if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() { + if arg1_ty.is_some() || arg2_ty.is_some() || arg3_ty.is_some() { return Err(ExpressionError::WrongArgumentCount(fun)); } match *arg_ty { @@ -1346,7 +1378,7 @@ impl super::Validator { } } Mf::Pack4x8snorm | Mf::Pack4x8unorm => { - if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() { + if arg1_ty.is_some() || arg2_ty.is_some() || arg3_ty.is_some() { return Err(ExpressionError::WrongArgumentCount(fun)); } match *arg_ty { @@ -1363,7 +1395,7 @@ impl super::Validator { | Mf::Unpack2x16unorm | Mf::Unpack4x8snorm | Mf::Unpack4x8unorm => { - if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() { + if arg1_ty.is_some() || arg2_ty.is_some() || arg3_ty.is_some() { return Err(ExpressionError::WrongArgumentCount(fun)); } match *arg_ty { diff --git a/third_party/rust/naga/src/valid/interface.rs b/third_party/rust/naga/src/valid/interface.rs index 2e54df24787d..2416e892163d 100644 --- a/third_party/rust/naga/src/valid/interface.rs +++ b/third_party/rust/naga/src/valid/interface.rs @@ -61,6 +61,17 @@ pub enum VaryingError { DuplicateBuiltIn(crate::BuiltIn), #[error("Capability {0:?} is not supported")] UnsupportedCapability(Capabilities), + #[error("The attribute {0:?} is only valid as an output for stage {1:?}")] + InvalidInputAttributeInStage(&'static str, crate::ShaderStage), + #[error("The attribute {0:?} is not valid for stage {1:?}")] + InvalidAttributeInStage(&'static str, crate::ShaderStage), + #[error( + "The location index {location} cannot be used together with the attribute {attribute:?}" + )] + InvalidLocationAttributeCombination { + location: u32, + attribute: &'static str, + }, } #[derive(Clone, Debug, thiserror::Error)] @@ -89,6 +100,10 @@ pub enum EntryPointError { InvalidIntegerInterpolation { location: u32 }, #[error(transparent)] Function(#[from] FunctionError), + #[error( + "Invalid locations {location_mask:?} are set while dual source blending. Only location 0 may be set." + )] + InvalidLocationsWhileDualSourceBlending { location_mask: BitSet }, } #[cfg(feature = "validate")] @@ -106,6 +121,7 @@ fn storage_usage(access: crate::StorageAccess) -> GlobalUse { struct VaryingContext<'a> { stage: crate::ShaderStage, output: bool, + second_blend_source: bool, types: &'a UniqueArena, type_info: &'a Vec, location_mask: &'a mut BitSet, @@ -293,6 +309,7 @@ impl VaryingContext<'_> { location, interpolation, sampling, + second_blend_source, } => { // Only IO-shareable types may be stored in locations. if !self.type_info[ty.index()] @@ -301,7 +318,37 @@ impl VaryingContext<'_> { { return Err(VaryingError::NotIOShareableType(ty)); } - if !self.location_mask.insert(location as usize) { + + if second_blend_source { + if !self + .capabilities + .contains(Capabilities::DUAL_SOURCE_BLENDING) + { + return Err(VaryingError::UnsupportedCapability( + Capabilities::DUAL_SOURCE_BLENDING, + )); + } + if self.stage != crate::ShaderStage::Fragment { + return Err(VaryingError::InvalidAttributeInStage( + "second_blend_source", + self.stage, + )); + } + if !self.output { + return Err(VaryingError::InvalidInputAttributeInStage( + "second_blend_source", + self.stage, + )); + } + if location != 0 { + return Err(VaryingError::InvalidLocationAttributeCombination { + location, + attribute: "second_blend_source", + }); + } + + self.second_blend_source = true; + } else if !self.location_mask.insert(location as usize) { #[cfg(feature = "validate")] if self.flags.contains(super::ValidationFlags::BINDINGS) { return Err(VaryingError::BindingCollision { location }); @@ -567,7 +614,8 @@ impl super::Validator { return Err(EntryPointError::UnexpectedWorkgroupSize.with_span()); } - let info = self + #[cfg_attr(not(feature = "validate"), allow(unused_mut))] + let mut info = self .validate_function(&ep.function, module, mod_info, true) .map_err(WithSpan::into_other)?; @@ -593,6 +641,7 @@ impl super::Validator { let mut ctx = VaryingContext { stage: ep.stage, output: false, + second_blend_source: false, types: &module.types, type_info: &self.types, location_mask: &mut self.location_mask, @@ -612,6 +661,7 @@ impl super::Validator { let mut ctx = VaryingContext { stage: ep.stage, output: true, + second_blend_source: false, types: &module.types, type_info: &self.types, location_mask: &mut self.location_mask, @@ -623,6 +673,18 @@ impl super::Validator { }; ctx.validate(fr.ty, fr.binding.as_ref()) .map_err_inner(|e| EntryPointError::Result(e).with_span())?; + #[cfg(feature = "validate")] + if ctx.second_blend_source { + // Only the first location may be used whhen dual source blending + if ctx.location_mask.len() == 1 && ctx.location_mask.contains(0) { + info.dual_source_blending = true; + } else { + return Err(EntryPointError::InvalidLocationsWhileDualSourceBlending { + location_mask: self.location_mask.clone(), + } + .with_span()); + } + } #[cfg(feature = "validate")] if ep.stage == crate::ShaderStage::Vertex diff --git a/third_party/rust/naga/src/valid/mod.rs b/third_party/rust/naga/src/valid/mod.rs index b04d69b5b45a..535128772540 100644 --- a/third_party/rust/naga/src/valid/mod.rs +++ b/third_party/rust/naga/src/valid/mod.rs @@ -112,6 +112,8 @@ bitflags::bitflags! { const MULTISAMPLED_SHADING = 0x800; /// Support for ray queries and acceleration structures. const RAY_QUERY = 0x1000; + /// Support for generating two sources for blending from fragement shaders + const DUAL_SOURCE_BLENDING = 0x2000; } } diff --git a/third_party/rust/wgpu-core/.cargo-checksum.json b/third_party/rust/wgpu-core/.cargo-checksum.json index 454a9b7c9fb0..454f78638c93 100644 --- a/third_party/rust/wgpu-core/.cargo-checksum.json +++ b/third_party/rust/wgpu-core/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"dd1ecc9d26c0bac60aafeb9e404fd076025cc5f4a5bc405adfa08d2ca38608ac","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","src/binding_model.rs":"3322f03854b92abeb4aeb65dda4ef776094713bce1277047fe85be73a9bc7b4e","src/command/bind.rs":"c243a4448b87e9b7274b10873b7091b385413ec0a4ea93cccd6d612214ec9abb","src/command/bundle.rs":"b26eb6cb877a19d203e9d2b8ac3b10e81f6a94b8b68617eac97a3b861cbe102b","src/command/clear.rs":"418ac36738d782ab72e8700aabef802638cdef1c873f4b036aa8a4c521cb9caf","src/command/compute.rs":"0f8492bdfddb58c413282b2640b1f2a2b934ee256106f661241ac144bfd63d28","src/command/draw.rs":"92facdd0e3fd553af590ecbc0de3491f212e237ea66494ff99f67dbf090d10df","src/command/memory_init.rs":"b50d3d20dbf659052f19da2e79469ba6435e06370f19d6ef45e1b1128d9900b7","src/command/mod.rs":"a63937a5b8a441b714329a5e1b0b4dd4b70ae2f39b52da633fd79edbe183edc6","src/command/query.rs":"d39e1b8cb6a054fd31333a916da5d79a6671a724212c90c490c13e55043a1685","src/command/render.rs":"e98d109e2fe3651a96f74cf1c40a2cc9c752bcf9ea8e893285d7fcad634724dc","src/command/transfer.rs":"c777c6e51afb459d2b5416e31071f24e4215c66f456fee3bd8f7395f9d1c5db1","src/conv.rs":"da95b36b7680ae74ebf810ad8f1decf01bd3eeaff44b3c5af1d4b3c3f0e2059a","src/device/global.rs":"5d7e852465ed0060f2cc5e6aee5831f9e7619cca492be73de1523fba4a83e668","src/device/life.rs":"4afecaf3602e23a4d8c795c29b9e5e148866e728b008884d55f658de29af4fe9","src/device/mod.rs":"dbb98ce046651fd70a26df2030913f7224557eceb5f84198daf433c266356c7c","src/device/queue.rs":"d2692b5c12d05dfaf325d437b5bffe069cfff43228ce40f25147cec2cda428ba","src/device/resource.rs":"ef5ef881a2cf1037d6f5b6bf3b497a9826707ceee00421873c4cf32f0e5c4510","src/device/trace.rs":"21408dfd2c99e3ce36a77d08ba86cf52f32bb376ed82690bbbf74937bfd42cbe","src/error.rs":"ca37282283985e2b7d184b2ab7ca6f53f726432d920f8d8477bfff6fab9b34e2","src/global.rs":"cf551de97c3eb5acd0c2710da09ebd92cc863ad0bb0f53c0fd4911bf8cd3ad97","src/hal_api.rs":"92a2f0cb80f192693530ed61048919bbad446742c2370bf0944c44b1c5df8362","src/hub.rs":"48ccada54672a88169c23975ddc3758cd32ed5de577c55ca4f665d0ed17d3233","src/id.rs":"f6245d024586c7fe63ded13b3cb926b940c191bbee56aedc655e8cef74bdd66b","src/identity.rs":"3ce6a3b57c7c4fc0808d13cd342d928c214f32368e45c79d8e2bbf8df887f97f","src/init_tracker/buffer.rs":"a0ebf54a1e6d269c7b4aa0ac7bb8b04fd2cea3221a1d058ff33cb683b2aea3e9","src/init_tracker/mod.rs":"0867f79f83555390d0982d1dc6dcf0d4340e10cb89aa633d3c3ecc45deb3c78c","src/init_tracker/texture.rs":"37b6584aaca11c407d91f77002dcbb48d8a4876e27edd1b71b7929ef966f901d","src/instance.rs":"18c53b6ff12237b794dd6d6e5ff9c6f879dcc7db9dce535b3b64862090b6ef55","src/lib.rs":"27ff8dd787d41cf412e90d0c4674aa70db59e608f9eb3be485c0bd18e9f13369","src/pipeline.rs":"669219add15448fdf5fe8bc5e03fd6fd1ada2b45b07047fd8c0a9bbbcdecad8b","src/present.rs":"afbc762a6103d1076670ab2ad1270f5a2b8448c89196ecf36348c7ab6929e1ee","src/registry.rs":"4098413de7f48e9ff15d0246793be47a0d54c95b4c8594baf9fafd222a90ba84","src/resource.rs":"7d1d841dd185a1a857814cab424a8b892aa8731dddf3373ea9436fa619d655b7","src/storage.rs":"bc70689ba299e9b4d9f4992c4d3f4dd36b1d8e71327595094981fdfd624f811a","src/track/buffer.rs":"dd6f632c6f31b15807148d705c516a8a1a8d72d02b137dd3b9d7c939447917cb","src/track/metadata.rs":"a80bd086ce825f7484ce6318a586c482d06fea0efc9c76bfa0124e480cc8b75e","src/track/mod.rs":"42b791d9a41eb6e62f6d79cae7abb5ab523eeb9e6030b0f95bbb0e26d56ad0ec","src/track/range.rs":"5bbfed6e103b3234d9de8e42057022da6d628c2cc1db6bb51b88f87f2d8adf8b","src/track/stateless.rs":"1d786b5e9558672243ba7d913736561065ef2bd5c6105c935e982486d10841f0","src/track/texture.rs":"7d60dc81ba7f7e2c2819525b90e6e6c7760cb0920e36aeefe98e76cedd49d26e","src/validation.rs":"6be9229cc34ef293ae99cfa520c6ad22bab39b83a53880a4aca36c42c53d40c3"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"7e5c00225497db0d65e2d91d19645c708402165126f655d26b77375ed70077af","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","src/binding_model.rs":"3322f03854b92abeb4aeb65dda4ef776094713bce1277047fe85be73a9bc7b4e","src/command/bind.rs":"c243a4448b87e9b7274b10873b7091b385413ec0a4ea93cccd6d612214ec9abb","src/command/bundle.rs":"b26eb6cb877a19d203e9d2b8ac3b10e81f6a94b8b68617eac97a3b861cbe102b","src/command/clear.rs":"418ac36738d782ab72e8700aabef802638cdef1c873f4b036aa8a4c521cb9caf","src/command/compute.rs":"0f8492bdfddb58c413282b2640b1f2a2b934ee256106f661241ac144bfd63d28","src/command/draw.rs":"92facdd0e3fd553af590ecbc0de3491f212e237ea66494ff99f67dbf090d10df","src/command/memory_init.rs":"b50d3d20dbf659052f19da2e79469ba6435e06370f19d6ef45e1b1128d9900b7","src/command/mod.rs":"a63937a5b8a441b714329a5e1b0b4dd4b70ae2f39b52da633fd79edbe183edc6","src/command/query.rs":"d39e1b8cb6a054fd31333a916da5d79a6671a724212c90c490c13e55043a1685","src/command/render.rs":"e98d109e2fe3651a96f74cf1c40a2cc9c752bcf9ea8e893285d7fcad634724dc","src/command/transfer.rs":"c777c6e51afb459d2b5416e31071f24e4215c66f456fee3bd8f7395f9d1c5db1","src/conv.rs":"da95b36b7680ae74ebf810ad8f1decf01bd3eeaff44b3c5af1d4b3c3f0e2059a","src/device/global.rs":"84ca385802eba1c119b571a30885c59ae1a4056438d6f69b13a837e06b2cd584","src/device/life.rs":"4afecaf3602e23a4d8c795c29b9e5e148866e728b008884d55f658de29af4fe9","src/device/mod.rs":"5ac7886bc8b2054c52dfb5955fe7b72fc9bf725b08b5e39121d6a952aa4f8f2b","src/device/queue.rs":"d2692b5c12d05dfaf325d437b5bffe069cfff43228ce40f25147cec2cda428ba","src/device/resource.rs":"ef5ef881a2cf1037d6f5b6bf3b497a9826707ceee00421873c4cf32f0e5c4510","src/device/trace.rs":"21408dfd2c99e3ce36a77d08ba86cf52f32bb376ed82690bbbf74937bfd42cbe","src/error.rs":"ca37282283985e2b7d184b2ab7ca6f53f726432d920f8d8477bfff6fab9b34e2","src/global.rs":"cf551de97c3eb5acd0c2710da09ebd92cc863ad0bb0f53c0fd4911bf8cd3ad97","src/hal_api.rs":"92a2f0cb80f192693530ed61048919bbad446742c2370bf0944c44b1c5df8362","src/hub.rs":"48ccada54672a88169c23975ddc3758cd32ed5de577c55ca4f665d0ed17d3233","src/id.rs":"f6245d024586c7fe63ded13b3cb926b940c191bbee56aedc655e8cef74bdd66b","src/identity.rs":"3ce6a3b57c7c4fc0808d13cd342d928c214f32368e45c79d8e2bbf8df887f97f","src/init_tracker/buffer.rs":"a0ebf54a1e6d269c7b4aa0ac7bb8b04fd2cea3221a1d058ff33cb683b2aea3e9","src/init_tracker/mod.rs":"0867f79f83555390d0982d1dc6dcf0d4340e10cb89aa633d3c3ecc45deb3c78c","src/init_tracker/texture.rs":"37b6584aaca11c407d91f77002dcbb48d8a4876e27edd1b71b7929ef966f901d","src/instance.rs":"2798b83772dd82a5461901cfca0b91c8b101bfcdf96095091dc59d1bd4b69cc1","src/lib.rs":"27ff8dd787d41cf412e90d0c4674aa70db59e608f9eb3be485c0bd18e9f13369","src/pipeline.rs":"669219add15448fdf5fe8bc5e03fd6fd1ada2b45b07047fd8c0a9bbbcdecad8b","src/present.rs":"b17400ba823e2fce9438947d3dfbfd34045f959666c6718286112a3f3925e387","src/registry.rs":"4098413de7f48e9ff15d0246793be47a0d54c95b4c8594baf9fafd222a90ba84","src/resource.rs":"7d1d841dd185a1a857814cab424a8b892aa8731dddf3373ea9436fa619d655b7","src/storage.rs":"bc70689ba299e9b4d9f4992c4d3f4dd36b1d8e71327595094981fdfd624f811a","src/track/buffer.rs":"dd6f632c6f31b15807148d705c516a8a1a8d72d02b137dd3b9d7c939447917cb","src/track/metadata.rs":"a80bd086ce825f7484ce6318a586c482d06fea0efc9c76bfa0124e480cc8b75e","src/track/mod.rs":"42b791d9a41eb6e62f6d79cae7abb5ab523eeb9e6030b0f95bbb0e26d56ad0ec","src/track/range.rs":"5bbfed6e103b3234d9de8e42057022da6d628c2cc1db6bb51b88f87f2d8adf8b","src/track/stateless.rs":"1d786b5e9558672243ba7d913736561065ef2bd5c6105c935e982486d10841f0","src/track/texture.rs":"7d60dc81ba7f7e2c2819525b90e6e6c7760cb0920e36aeefe98e76cedd49d26e","src/validation.rs":"66ee194d095b7fc54e0545f8b848120eb42d458a50beea67301ff3e5c88a4b3c"},"package":null} \ No newline at end of file diff --git a/third_party/rust/wgpu-core/Cargo.toml b/third_party/rust/wgpu-core/Cargo.toml index d6028e5833e7..a0d7328cf838 100644 --- a/third_party/rust/wgpu-core/Cargo.toml +++ b/third_party/rust/wgpu-core/Cargo.toml @@ -55,7 +55,7 @@ package = "wgpu-hal" [dependencies.naga] version = "0.13.0" git = "https://github.com/gfx-rs/naga" -rev = "7a19f3af909202c7eafd36633b5584bfbb353ecb" +rev = "cc87b8f9eb30bb55d0735b89d3df3e099e1a6e7c" features = [ "clone", "span", diff --git a/third_party/rust/wgpu-core/src/device/global.rs b/third_party/rust/wgpu-core/src/device/global.rs index 8fe5a6fcc91b..632c83e37f8a 100644 --- a/third_party/rust/wgpu-core/src/device/global.rs +++ b/third_party/rust/wgpu-core/src/device/global.rs @@ -2134,7 +2134,7 @@ impl Global { let (mut surface_guard, mut token) = self.surfaces.write(&mut token); let (adapter_guard, mut token) = hub.adapters.read(&mut token); - let (device_guard, _token) = hub.devices.read(&mut token); + let (device_guard, mut token) = hub.devices.read(&mut token); let error = 'outer: loop { let device = match device_guard.get(device_id) { @@ -2207,6 +2207,24 @@ impl Global { break error; } + // Wait for all work to finish before configuring the surface. + if let Err(e) = device.maintain(hub, wgt::Maintain::Wait, &mut token) { + break e.into(); + } + + // All textures must be destroyed before the surface can be re-configured. + if let Some(present) = surface.presentation.take() { + if present.acquired_texture.is_some() { + break E::PreviousOutputExists; + } + } + + // TODO: Texture views may still be alive that point to the texture. + // this will allow the user to render to the surface texture, long after + // it has been removed. + // + // https://github.com/gfx-rs/wgpu/issues/4105 + match unsafe { A::get_surface_mut(surface) .unwrap() @@ -2226,12 +2244,6 @@ impl Global { } } - if let Some(present) = surface.presentation.take() { - if present.acquired_texture.is_some() { - break E::PreviousOutputExists; - } - } - surface.presentation = Some(present::Presentation { device_id: Stored { value: id::Valid(device_id), diff --git a/third_party/rust/wgpu-core/src/device/mod.rs b/third_party/rust/wgpu-core/src/device/mod.rs index 0ae6d7a2dd0d..9a77bf95363c 100644 --- a/third_party/rust/wgpu-core/src/device/mod.rs +++ b/third_party/rust/wgpu-core/src/device/mod.rs @@ -1,6 +1,5 @@ use crate::{ binding_model, - device::life::WaitIdleError, hal_api::HalApi, hub::Hub, id, @@ -24,7 +23,7 @@ pub mod queue; pub mod resource; #[cfg(any(feature = "trace", feature = "replay"))] pub mod trace; -pub use resource::Device; +pub use {life::WaitIdleError, resource::Device}; pub const SHADER_STAGE_COUNT: usize = 3; // Should be large enough for the largest possible texture row. This diff --git a/third_party/rust/wgpu-core/src/instance.rs b/third_party/rust/wgpu-core/src/instance.rs index ae1a395d85b4..0aee56ac6ede 100644 --- a/third_party/rust/wgpu-core/src/instance.rs +++ b/third_party/rust/wgpu-core/src/instance.rs @@ -84,8 +84,22 @@ impl Instance { dx12_shader_compiler: instance_desc.dx12_shader_compiler.clone(), gles_minor_version: instance_desc.gles_minor_version, }; - unsafe { hal::Instance::init(&hal_desc).ok() } + match unsafe { hal::Instance::init(&hal_desc) } { + Ok(instance) => { + log::debug!("Instance::new: created {:?} backend", A::VARIANT); + Some(instance) + } + Err(err) => { + log::debug!( + "Instance::new: failed to create {:?} backend: {:?}", + A::VARIANT, + err + ); + None + } + } } else { + log::trace!("Instance::new: backend {:?} not requested", A::VARIANT); None } } diff --git a/third_party/rust/wgpu-core/src/present.rs b/third_party/rust/wgpu-core/src/present.rs index 1303769d29ea..7366934d2726 100644 --- a/third_party/rust/wgpu-core/src/present.rs +++ b/third_party/rust/wgpu-core/src/present.rs @@ -15,7 +15,7 @@ use std::borrow::Borrow; use crate::device::trace::Action; use crate::{ conv, - device::{DeviceError, MissingDownlevelFlags}, + device::{DeviceError, MissingDownlevelFlags, WaitIdleError}, global::Global, hal_api::HalApi, hub::Token, @@ -96,6 +96,18 @@ pub enum ConfigureSurfaceError { }, #[error("Requested usage is not supported")] UnsupportedUsage, + #[error("Gpu got stuck :(")] + StuckGpu, +} + +impl From for ConfigureSurfaceError { + fn from(e: WaitIdleError) -> Self { + match e { + WaitIdleError::Device(d) => ConfigureSurfaceError::Device(d), + WaitIdleError::WrongSubmissionIndex(..) => unreachable!(), + WaitIdleError::StuckGpu => ConfigureSurfaceError::StuckGpu, + } + } } #[repr(C)] diff --git a/third_party/rust/wgpu-core/src/validation.rs b/third_party/rust/wgpu-core/src/validation.rs index 84e1e71691dd..e3ecb916d341 100644 --- a/third_party/rust/wgpu-core/src/validation.rs +++ b/third_party/rust/wgpu-core/src/validation.rs @@ -812,6 +812,7 @@ impl Interface { location, interpolation, sampling, + .. // second_blend_source }) => Varying::Local { location, iv: InterfaceVar { diff --git a/third_party/rust/wgpu-hal/.cargo-checksum.json b/third_party/rust/wgpu-hal/.cargo-checksum.json index a86f00a0ea50..870afb286763 100644 --- a/third_party/rust/wgpu-hal/.cargo-checksum.json +++ b/third_party/rust/wgpu-hal/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"6fff19dc49401b0268c9666c1f61838069a652f15e61edc69d96c759dc72d1c9","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","README.md":"78377f5876fafd77963eff7e3c2ba3a7e3ad5cf9201b09ed5612e49c2288eb18","examples/halmark/main.rs":"a043d9fc0d99ab6b9c379f50f1fd26399a4339cf0002cace21ed1e338efff094","examples/halmark/shader.wgsl":"26c256ec36d6f0e9a1647431ca772766bee4382d64eaa718ba7b488dcfb6bcca","examples/raw-gles.em.html":"70fbe68394a1a4522192de1dcfaf7d399f60d7bdf5de70b708f9bb0417427546","examples/raw-gles.rs":"d7e0d311514555f41b633eef2fdf355737e22c0b01d045d6afa6ba1b95511b2b","src/auxil/dxgi/conv.rs":"c1e8d584e408712097d075455375e04d1895a0ff9a494305c16d658277ce7b90","src/auxil/dxgi/exception.rs":"baad31f4529f1cf9d10519c4cceccbb21ed9bba7d7ea99e4789c1d5ddf3a450b","src/auxil/dxgi/factory.rs":"50431981d7fce15722ab66b65b491cc2dbebfab03287375e02121797307a11b8","src/auxil/dxgi/mod.rs":"a202564d9ac97530b16a234b87d180cd345aae705e082a9b1177dcde813645f9","src/auxil/dxgi/result.rs":"20c8eb03d738062dff198feca6327addb9882ed0462be842c789eadf7dca0573","src/auxil/dxgi/time.rs":"b6f966b250e9424d5d7e4065f2108cba87197c1e30baae6d87083055d1bc5a4b","src/auxil/mod.rs":"c38f0d3b10804d1c1d7e3b8e4a975fcb87271f8b1904f2f4a3153cceddafb56b","src/auxil/renderdoc.rs":"c2f849f70f576b0c9b0d32dd155b6a6353f74dff59cbeeaa994a12789d047c0f","src/dx11/adapter.rs":"90ed68bb96cdb6d057da8aed23ebe6d72f9c3e0d8a4ce85d1a2d8dc373d525ab","src/dx11/command.rs":"32a759d36ebc6d92528a128b117a752dd7fb6f4f0b4d8eda3ed564e5b8d783c2","src/dx11/device.rs":"96ccd8d6645839f3daf832ddf569676643ac92d1b332ab9a0c8563b3b5026295","src/dx11/instance.rs":"e3a97b69eff157b4553fb604f4746ed5ffd92a3b9e3c77f7bb58c06c5fe8d493","src/dx11/library.rs":"4fb09475fb24bc45fb7a464a7c6a30b45e10fed0022aad2891a390b512c11ae1","src/dx11/mod.rs":"21bc698bc0ff8b36a4906ee8dfaf469b6ed35ad852b7c0a5f60c5e5007bba128","src/dx12/adapter.rs":"0cd2ae4c26255d2f5669b9612018c79f2eff4a1a8c266a238c200694674a8519","src/dx12/command.rs":"9074f4b3f80d9a9168b12b59518ca613a81bb7799f8756f5221e46c16cbeae8e","src/dx12/conv.rs":"6c6ca090d4976c6008304d7f44574d88f1e506c8d24f3a872f89d8f900fcf259","src/dx12/descriptor.rs":"d9e295c48dc7d1759fd121c927c2218c1bde90e9f1b35f2ad01b610b184b614e","src/dx12/device.rs":"97dd3190cdc48d7fe4f4f0ff9fd99e1f7aa400c583be249264659480545126db","src/dx12/instance.rs":"3f730a548eba3ddd86baab5e126cf96dda8bf9145ad25a90fe1879dccc0c95af","src/dx12/mod.rs":"d7a34fd7143f62db30d3909ea7b66cc129ba1d971c27ce4cb38cbe1028ea2785","src/dx12/shader_compilation.rs":"dcff4c2c37b4d8c971a1e940eb7a843a32a3016cc65ef26bad71372687a835dc","src/dx12/suballocation.rs":"f5eb7c11dfe9c8d319ec853fec2a1aec8abe6bc61a729faa60302b105265f677","src/dx12/types.rs":"29b11268d11c1b7437de3dac403af574ec8aa84fd9954a95a16d80f5808be44d","src/dx12/view.rs":"c09241520377e6a47ad8822c69075e6e16e6c558e18bb64398c8d7424fc57dcf","src/empty.rs":"98c4ad29fdf1bad55097d540393b9ef62cce23b9d5cfd2a131f790042e3bd8b8","src/gles/adapter.rs":"a28d74c3704dfc9961d16be9d7481e24e559f35fd1767adf7d79b6569687c974","src/gles/command.rs":"c7d6ff845b597d85d2fd61be625cf43554944d93f9324c98c2123995946cfd6b","src/gles/conv.rs":"1e1c4a0887fd0062b8e66c86a824e6ddb63b458dcd968e84fffbca519e7b5690","src/gles/device.rs":"11b99f2da55ee07db7549b4313ceb68e35a13f87041832643359e80e6f355034","src/gles/egl.rs":"f562f35c489d6831a58bffb5723cd78d14a4c623a809577ba8b6c2d48a295626","src/gles/emscripten.rs":"19bb73a9d140645f3f32cd48b002151711a9b8456e213eab5f3a2be79239e147","src/gles/mod.rs":"65996152dff84f00d6d491bfe5edc5c343f2302a4aa01eef14aadb4bdab096ed","src/gles/queue.rs":"5a85e6c2ad9e97779b6fec81d2811c1e05d71f82f7c5bee87b31eade64c1501e","src/gles/shaders/clear.frag":"aac702eed9ece5482db5ba6783a678b119a5e7802b1ecf93f4975dee8acab0b3","src/gles/shaders/clear.vert":"8f636168e1da2cac48091c466a543c3b09fb4a0dd8c60c1c9bf34cc890766740","src/gles/shaders/srgb_present.frag":"dd9a43c339a2fa4ccf7f6a1854c6f400cabf271a7d5e9230768e9f39d47f3ff5","src/gles/shaders/srgb_present.vert":"6e85d489403d80b81cc94790730bb53b309dfc5eeede8f1ea3412a660f31d357","src/gles/web.rs":"48669af52f759cf29715835e69b24b0c34c01c9ed25d670eaf7c9cf76b9abfe8","src/lib.rs":"7a2bb79bf1b97fff86eead977f862e3e03f62e22db3fe4d193be2c29de79f3ef","src/metal/adapter.rs":"18508f30cf93c7f1bc8abf6ef556f9d3e9ff63faad1c285e01dac3261896fe9e","src/metal/command.rs":"ba1f1f345c94176cefe23f8afe501a10a03ebbd3d3dcdc9acfbecf53882cae65","src/metal/conv.rs":"e4aeafcddc75b2f9b54245faedaf0566f1e63681807ae786ceb46ac35f0e13bf","src/metal/device.rs":"d2fb16e8d7cfc0c9e3141dcf1245a1f0ea8a891962c0cd83c0cd4450e7acaf36","src/metal/mod.rs":"662b964b9a457dc7c0cf12fa53b9777888b96c0d155377e694d84425dc3de439","src/metal/surface.rs":"f4b3f8364ec32a7540f7a1da3b4b7e8c6c1cf336aa5535a4515b4efb5b11c443","src/metal/time.rs":"c32d69f30e846dfcc0e39e01097fb80df63b2bebb6586143bb62494999850246","src/vulkan/adapter.rs":"c3445e2210e5bee535c4df4b9fe4e2e9794c0cca741fc6174fb8b19db7da1cd1","src/vulkan/command.rs":"08d9a43bd43820f2681efe4207a1be678f1aab47d779390c4dbb929d1b5450fa","src/vulkan/conv.rs":"284f002063260811ba3fcfe75d6dc1c4c2eb2bc8b6622eac781157b7683478cd","src/vulkan/device.rs":"12cba753b5b7ecbf85c81978e23dc2de30a124101c9a839ae557f46cf6301c20","src/vulkan/instance.rs":"8d91466b79e9251f9dd00d6629c79669e3a00b38aca533c991a6a9b1a2c073ff","src/vulkan/mod.rs":"1bef6c8213bfccf6dd23fe07414db2893a0f85a755bcf26f461371956c960173"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"0afcc8bdfadff54cc9f023364780d08dc622e15c7aa450ca99d4a37a0abcee19","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","README.md":"78377f5876fafd77963eff7e3c2ba3a7e3ad5cf9201b09ed5612e49c2288eb18","examples/halmark/main.rs":"a043d9fc0d99ab6b9c379f50f1fd26399a4339cf0002cace21ed1e338efff094","examples/halmark/shader.wgsl":"26c256ec36d6f0e9a1647431ca772766bee4382d64eaa718ba7b488dcfb6bcca","examples/raw-gles.em.html":"70fbe68394a1a4522192de1dcfaf7d399f60d7bdf5de70b708f9bb0417427546","examples/raw-gles.rs":"d7e0d311514555f41b633eef2fdf355737e22c0b01d045d6afa6ba1b95511b2b","src/auxil/dxgi/conv.rs":"c1e8d584e408712097d075455375e04d1895a0ff9a494305c16d658277ce7b90","src/auxil/dxgi/exception.rs":"baad31f4529f1cf9d10519c4cceccbb21ed9bba7d7ea99e4789c1d5ddf3a450b","src/auxil/dxgi/factory.rs":"50431981d7fce15722ab66b65b491cc2dbebfab03287375e02121797307a11b8","src/auxil/dxgi/mod.rs":"a202564d9ac97530b16a234b87d180cd345aae705e082a9b1177dcde813645f9","src/auxil/dxgi/result.rs":"20c8eb03d738062dff198feca6327addb9882ed0462be842c789eadf7dca0573","src/auxil/dxgi/time.rs":"b6f966b250e9424d5d7e4065f2108cba87197c1e30baae6d87083055d1bc5a4b","src/auxil/mod.rs":"c38f0d3b10804d1c1d7e3b8e4a975fcb87271f8b1904f2f4a3153cceddafb56b","src/auxil/renderdoc.rs":"c2f849f70f576b0c9b0d32dd155b6a6353f74dff59cbeeaa994a12789d047c0f","src/dx11/adapter.rs":"90ed68bb96cdb6d057da8aed23ebe6d72f9c3e0d8a4ce85d1a2d8dc373d525ab","src/dx11/command.rs":"32a759d36ebc6d92528a128b117a752dd7fb6f4f0b4d8eda3ed564e5b8d783c2","src/dx11/device.rs":"96ccd8d6645839f3daf832ddf569676643ac92d1b332ab9a0c8563b3b5026295","src/dx11/instance.rs":"e3a97b69eff157b4553fb604f4746ed5ffd92a3b9e3c77f7bb58c06c5fe8d493","src/dx11/library.rs":"4fb09475fb24bc45fb7a464a7c6a30b45e10fed0022aad2891a390b512c11ae1","src/dx11/mod.rs":"21bc698bc0ff8b36a4906ee8dfaf469b6ed35ad852b7c0a5f60c5e5007bba128","src/dx12/adapter.rs":"0cd2ae4c26255d2f5669b9612018c79f2eff4a1a8c266a238c200694674a8519","src/dx12/command.rs":"9074f4b3f80d9a9168b12b59518ca613a81bb7799f8756f5221e46c16cbeae8e","src/dx12/conv.rs":"6c6ca090d4976c6008304d7f44574d88f1e506c8d24f3a872f89d8f900fcf259","src/dx12/descriptor.rs":"d9e295c48dc7d1759fd121c927c2218c1bde90e9f1b35f2ad01b610b184b614e","src/dx12/device.rs":"9d86e55f729302941d579b7ebc6ebb8bfd74afa3b8227fec2fd08c71eb1f2668","src/dx12/instance.rs":"3f730a548eba3ddd86baab5e126cf96dda8bf9145ad25a90fe1879dccc0c95af","src/dx12/mod.rs":"138cd0723aa20179cb92009753cf6327627fba58ce08f865a7f1fd64cdf57e6e","src/dx12/shader_compilation.rs":"dcff4c2c37b4d8c971a1e940eb7a843a32a3016cc65ef26bad71372687a835dc","src/dx12/suballocation.rs":"f5eb7c11dfe9c8d319ec853fec2a1aec8abe6bc61a729faa60302b105265f677","src/dx12/types.rs":"29b11268d11c1b7437de3dac403af574ec8aa84fd9954a95a16d80f5808be44d","src/dx12/view.rs":"c09241520377e6a47ad8822c69075e6e16e6c558e18bb64398c8d7424fc57dcf","src/empty.rs":"98c4ad29fdf1bad55097d540393b9ef62cce23b9d5cfd2a131f790042e3bd8b8","src/gles/adapter.rs":"a28d74c3704dfc9961d16be9d7481e24e559f35fd1767adf7d79b6569687c974","src/gles/command.rs":"c7d6ff845b597d85d2fd61be625cf43554944d93f9324c98c2123995946cfd6b","src/gles/conv.rs":"1e1c4a0887fd0062b8e66c86a824e6ddb63b458dcd968e84fffbca519e7b5690","src/gles/device.rs":"11b99f2da55ee07db7549b4313ceb68e35a13f87041832643359e80e6f355034","src/gles/egl.rs":"f562f35c489d6831a58bffb5723cd78d14a4c623a809577ba8b6c2d48a295626","src/gles/emscripten.rs":"19bb73a9d140645f3f32cd48b002151711a9b8456e213eab5f3a2be79239e147","src/gles/mod.rs":"65996152dff84f00d6d491bfe5edc5c343f2302a4aa01eef14aadb4bdab096ed","src/gles/queue.rs":"5a85e6c2ad9e97779b6fec81d2811c1e05d71f82f7c5bee87b31eade64c1501e","src/gles/shaders/clear.frag":"aac702eed9ece5482db5ba6783a678b119a5e7802b1ecf93f4975dee8acab0b3","src/gles/shaders/clear.vert":"8f636168e1da2cac48091c466a543c3b09fb4a0dd8c60c1c9bf34cc890766740","src/gles/shaders/srgb_present.frag":"dd9a43c339a2fa4ccf7f6a1854c6f400cabf271a7d5e9230768e9f39d47f3ff5","src/gles/shaders/srgb_present.vert":"6e85d489403d80b81cc94790730bb53b309dfc5eeede8f1ea3412a660f31d357","src/gles/web.rs":"48669af52f759cf29715835e69b24b0c34c01c9ed25d670eaf7c9cf76b9abfe8","src/lib.rs":"10cf339bba80cf908e127394c92f9e7d14027422a21ca0cd8484221989bc8eb2","src/metal/adapter.rs":"18508f30cf93c7f1bc8abf6ef556f9d3e9ff63faad1c285e01dac3261896fe9e","src/metal/command.rs":"ba1f1f345c94176cefe23f8afe501a10a03ebbd3d3dcdc9acfbecf53882cae65","src/metal/conv.rs":"e4aeafcddc75b2f9b54245faedaf0566f1e63681807ae786ceb46ac35f0e13bf","src/metal/device.rs":"d2fb16e8d7cfc0c9e3141dcf1245a1f0ea8a891962c0cd83c0cd4450e7acaf36","src/metal/mod.rs":"662b964b9a457dc7c0cf12fa53b9777888b96c0d155377e694d84425dc3de439","src/metal/surface.rs":"f4b3f8364ec32a7540f7a1da3b4b7e8c6c1cf336aa5535a4515b4efb5b11c443","src/metal/time.rs":"c32d69f30e846dfcc0e39e01097fb80df63b2bebb6586143bb62494999850246","src/vulkan/adapter.rs":"c3445e2210e5bee535c4df4b9fe4e2e9794c0cca741fc6174fb8b19db7da1cd1","src/vulkan/command.rs":"08d9a43bd43820f2681efe4207a1be678f1aab47d779390c4dbb929d1b5450fa","src/vulkan/conv.rs":"284f002063260811ba3fcfe75d6dc1c4c2eb2bc8b6622eac781157b7683478cd","src/vulkan/device.rs":"46221186c22f1bb10c5aba4a1860eebf6c36d99481fc1d1783848f47babaf9d8","src/vulkan/instance.rs":"2341788015174730de81117790525a7943d8932bbc5e201857203561c6646970","src/vulkan/mod.rs":"1bef6c8213bfccf6dd23fe07414db2893a0f85a755bcf26f461371956c960173"},"package":null} \ No newline at end of file diff --git a/third_party/rust/wgpu-hal/Cargo.toml b/third_party/rust/wgpu-hal/Cargo.toml index ba3b5ff2d9c6..bee440c39405 100644 --- a/third_party/rust/wgpu-hal/Cargo.toml +++ b/third_party/rust/wgpu-hal/Cargo.toml @@ -64,7 +64,7 @@ optional = true [dependencies.naga] version = "0.13.0" git = "https://github.com/gfx-rs/naga" -rev = "7a19f3af909202c7eafd36633b5584bfbb353ecb" +rev = "cc87b8f9eb30bb55d0735b89d3df3e099e1a6e7c" features = ["clone"] [dependencies.profiling] @@ -83,7 +83,7 @@ env_logger = "0.10" [dev-dependencies.naga] version = "0.13.0" git = "https://github.com/gfx-rs/naga" -rev = "7a19f3af909202c7eafd36633b5584bfbb353ecb" +rev = "cc87b8f9eb30bb55d0735b89d3df3e099e1a6e7c" features = ["wgsl-in"] [dev-dependencies.winit] diff --git a/third_party/rust/wgpu-hal/src/dx12/device.rs b/third_party/rust/wgpu-hal/src/dx12/device.rs index 1a44d98f0d0f..4ad43cc1659b 100644 --- a/third_party/rust/wgpu-hal/src/dx12/device.rs +++ b/third_party/rust/wgpu-hal/src/dx12/device.rs @@ -181,7 +181,10 @@ impl super::Device { }) } - pub(super) unsafe fn wait_idle(&self) -> Result<(), crate::DeviceError> { + // Blocks until the dedicated present queue is finished with all of its work. + // + // Once this method completes, the surface is able to be resized or deleted. + pub(super) unsafe fn wait_for_present_queue_idle(&self) -> Result<(), crate::DeviceError> { let cur_value = self.idler.fence.get_value(); if cur_value == !0 { return Err(crate::DeviceError::Lost); diff --git a/third_party/rust/wgpu-hal/src/dx12/mod.rs b/third_party/rust/wgpu-hal/src/dx12/mod.rs index 564bc349c6ba..a2316195120c 100644 --- a/third_party/rust/wgpu-hal/src/dx12/mod.rs +++ b/third_party/rust/wgpu-hal/src/dx12/mod.rs @@ -613,19 +613,23 @@ impl crate::Surface for Surface { let mut flags = dxgi::DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; // We always set ALLOW_TEARING on the swapchain no matter // what kind of swapchain we want because ResizeBuffers - // cannot change if ALLOW_TEARING is applied to the swapchain. + // cannot change the swapchain's ALLOW_TEARING flag. + // + // This does not change the behavior of the swapchain, just + // allow present calls to use tearing. if self.supports_allow_tearing { flags |= dxgi::DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; } + // While `configure`s contract ensures that no work on the GPU's main queues + // are in flight, we still need to wait for the present queue to be idle. + unsafe { device.wait_for_present_queue_idle() }?; + let non_srgb_format = auxil::dxgi::conv::map_texture_format_nosrgb(config.format); let swap_chain = match self.swap_chain.take() { //Note: this path doesn't properly re-initialize all of the things Some(sc) => { - // can't have image resources in flight used by GPU - let _ = unsafe { device.wait_idle() }; - let raw = unsafe { sc.release_resources() }; let result = unsafe { raw.ResizeBuffers( @@ -773,12 +777,16 @@ impl crate::Surface for Surface { } unsafe fn unconfigure(&mut self, device: &Device) { - if let Some(mut sc) = self.swap_chain.take() { + if let Some(sc) = self.swap_chain.take() { unsafe { - let _ = sc.wait(None); - //TODO: this shouldn't be needed, - // but it complains that the queue is still used otherwise - let _ = device.wait_idle(); + // While `unconfigure`s contract ensures that no work on the GPU's main queues + // are in flight, we still need to wait for the present queue to be idle. + + // The major failure mode of this function is device loss, + // which if we have lost the device, we should just continue + // cleaning up, without error. + let _ = device.wait_for_present_queue_idle(); + let _raw = sc.release_resources(); } } @@ -837,6 +845,13 @@ impl crate::Queue for Queue { .signal(&fence.raw, value) .into_device_result("Signal fence")?; } + + // Note the lack of synchronization here between the main Direct queue + // and the dedicated presentation queue. This is automatically handled + // by the D3D runtime by detecting uses of resources derived from the + // swapchain. This automatic detection is why you cannot use a swapchain + // as an UAV in D3D12. + Ok(()) } unsafe fn present( diff --git a/third_party/rust/wgpu-hal/src/lib.rs b/third_party/rust/wgpu-hal/src/lib.rs index 4bff6b8d8ffb..f1f4b2109e60 100644 --- a/third_party/rust/wgpu-hal/src/lib.rs +++ b/third_party/rust/wgpu-hal/src/lib.rs @@ -227,12 +227,28 @@ pub trait Instance: Sized + WasmNotSend + WasmNotSync { } pub trait Surface: WasmNotSend + WasmNotSync { + /// Configures the surface to use the given device. + /// + /// # Safety + /// + /// - All gpu work that uses the surface must have been completed. + /// - All [`AcquiredSurfaceTexture`]s must have been destroyed. + /// - All [`Api::TextureView`]s derived from the [`AcquiredSurfaceTexture`]s must have been destroyed. + /// - All surfaces created using other devices must have been unconfigured before this call. unsafe fn configure( &mut self, device: &A::Device, config: &SurfaceConfiguration, ) -> Result<(), SurfaceError>; + /// Unconfigures the surface on the given device. + /// + /// # Safety + /// + /// - All gpu work that uses the surface must have been completed. + /// - All [`AcquiredSurfaceTexture`]s must have been destroyed. + /// - All [`Api::TextureView`]s derived from the [`AcquiredSurfaceTexture`]s must have been destroyed. + /// - The surface must have been configured on the given device. unsafe fn unconfigure(&mut self, device: &A::Device); /// Returns the next texture to be presented by the swapchain for drawing diff --git a/third_party/rust/wgpu-hal/src/vulkan/device.rs b/third_party/rust/wgpu-hal/src/vulkan/device.rs index 4f2a0feb8afe..cb955e8318c8 100644 --- a/third_party/rust/wgpu-hal/src/vulkan/device.rs +++ b/third_party/rust/wgpu-hal/src/vulkan/device.rs @@ -1143,7 +1143,7 @@ impl crate::Device for super::Device { } if desc.anisotropy_clamp != 1 { - // We only enable anisotropy if it is supported, and wgpu-hal interface guarentees + // We only enable anisotropy if it is supported, and wgpu-hal interface guarantees // the clamp is in the range [1, 16] which is always supported if anisotropy is. vk_info = vk_info .anisotropy_enable(true) diff --git a/third_party/rust/wgpu-hal/src/vulkan/instance.rs b/third_party/rust/wgpu-hal/src/vulkan/instance.rs index 18b141a0701a..18269fff772a 100644 --- a/third_party/rust/wgpu-hal/src/vulkan/instance.rs +++ b/third_party/rust/wgpu-hal/src/vulkan/instance.rs @@ -152,12 +152,11 @@ unsafe extern "system" fn debug_utils_messenger_callback( } impl super::Swapchain { + /// # Safety + /// + /// - The device must have been made idle before calling this function. unsafe fn release_resources(self, device: &ash::Device) -> Self { profiling::scope!("Swapchain::release_resources"); - { - profiling::scope!("vkDeviceWaitIdle"); - let _ = unsafe { device.device_wait_idle() }; - }; unsafe { device.destroy_fence(self.fence, None) }; self } @@ -186,7 +185,20 @@ impl super::Instance { &self.shared } - pub fn required_extensions( + /// Return the instance extension names wgpu would like to enable. + /// + /// Return a vector of the names of instance extensions actually available + /// on `entry` that wgpu would like to enable. + /// + /// The `driver_api_version` argument should be the instance's Vulkan API + /// version, as obtained from `vkEnumerateInstanceVersion`. This is the same + /// space of values as the `VK_API_VERSION` constants. + /// + /// Note that wgpu can function without many of these extensions (for + /// example, `VK_KHR_wayland_surface` is certainly not going to be available + /// everywhere), but if one of these extensions is available at all, wgpu + /// assumes that it has been enabled. + pub fn desired_extensions( entry: &ash::Entry, _driver_api_version: u32, flags: crate::InstanceFlags, @@ -265,7 +277,7 @@ impl super::Instance { /// /// - `raw_instance` must be created from `entry` /// - `raw_instance` must be created respecting `driver_api_version`, `extensions` and `flags` - /// - `extensions` must be a superset of `required_extensions()` and must be created from the + /// - `extensions` must be a superset of `desired_extensions()` and must be created from the /// same entry, driver_api_version and flags. /// - `android_sdk_version` is ignored and can be `0` for all platforms besides Android /// @@ -592,7 +604,7 @@ impl crate::Instance for super::Instance { }, ); - let extensions = Self::required_extensions(&entry, driver_api_version, desc.flags)?; + let extensions = Self::desired_extensions(&entry, driver_api_version, desc.flags)?; let instance_layers = entry.enumerate_instance_layer_properties().map_err(|e| { log::info!("enumerate_instance_layer_properties: {:?}", e); @@ -786,13 +798,22 @@ impl crate::Instance for super::Instance { if exposed.info.device_type == wgt::DeviceType::IntegratedGpu && exposed.info.vendor == db::intel::VENDOR { - // See https://gitlab.freedesktop.org/mesa/mesa/-/issues/4688 - log::warn!( - "Disabling presentation on '{}' (id {:?}) because of NV Optimus (on Linux)", - exposed.info.name, - exposed.adapter.raw - ); - exposed.adapter.private_caps.can_present = false; + // Check if mesa driver and version less than 21.2 + if let Some(version) = exposed.info.driver_info.split_once("Mesa ").map(|s| { + s.1.rsplit_once('.') + .map(|v| v.0.parse::().unwrap_or_default()) + .unwrap_or_default() + }) { + if version < 21.2 { + // See https://gitlab.freedesktop.org/mesa/mesa/-/issues/4688 + log::warn!( + "Disabling presentation on '{}' (id {:?}) due to NV Optimus and Intel Mesa < v21.2", + exposed.info.name, + exposed.adapter.raw + ); + exposed.adapter.private_caps.can_present = false; + } + } } } } @@ -807,6 +828,7 @@ impl crate::Surface for super::Surface { device: &super::Device, config: &crate::SurfaceConfiguration, ) -> Result<(), crate::SurfaceError> { + // Safety: `configure`'s contract guarantees there are no resources derived from the swapchain in use. let old = self .swapchain .take() @@ -820,6 +842,7 @@ impl crate::Surface for super::Surface { unsafe fn unconfigure(&mut self, device: &super::Device) { if let Some(sc) = self.swapchain.take() { + // Safety: `unconfigure`'s contract guarantees there are no resources derived from the swapchain in use. let swapchain = unsafe { sc.release_resources(&device.shared.raw) }; unsafe { swapchain.functor.destroy_swapchain(swapchain.raw, None) }; } diff --git a/third_party/rust/wgpu-types/.cargo-checksum.json b/third_party/rust/wgpu-types/.cargo-checksum.json index 1967acba3b8e..b96d798df907 100644 --- a/third_party/rust/wgpu-types/.cargo-checksum.json +++ b/third_party/rust/wgpu-types/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"77707bfd609ceefcb527b361673fc735670cfd54db55b010386d90f2b9dac5d5","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","src/assertions.rs":"3fe98027aa73970c8ab7874a3e13dbfd6faa87df2081beb5c83aeec4c60f372f","src/lib.rs":"d65636e17a80dd44eb06b7bee735020869a7165b63505f11b126ab1eb76a5107","src/math.rs":"4d03039736dd6926feb139bc68734cb59df34ede310427bbf059e5c925e0af3b"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"9f4a8846579ca480d493e80ad1488dcd18feb08c79aa833e2733808f0473d79b","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","src/assertions.rs":"3fe98027aa73970c8ab7874a3e13dbfd6faa87df2081beb5c83aeec4c60f372f","src/lib.rs":"d65636e17a80dd44eb06b7bee735020869a7165b63505f11b126ab1eb76a5107","src/math.rs":"4d03039736dd6926feb139bc68734cb59df34ede310427bbf059e5c925e0af3b"},"package":null} \ No newline at end of file diff --git a/third_party/rust/wgpu-types/Cargo.toml b/third_party/rust/wgpu-types/Cargo.toml index 9b810003da6f..1680b5ae8b21 100644 --- a/third_party/rust/wgpu-types/Cargo.toml +++ b/third_party/rust/wgpu-types/Cargo.toml @@ -44,7 +44,7 @@ features = ["serde_derive"] optional = true [dev-dependencies] -serde_json = "1.0.105" +serde_json = "1.0.106" [dev-dependencies.serde] version = "1"