forked from mirrors/gecko-dev
Bug 1853105 - Update wgpu to revision 7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e. r=webgpu-reviewers,supply-chain-reviewers,ErichDonGubler
Differential Revision: https://phabricator.services.mozilla.com/D188214
This commit is contained in:
parent
9aba49cf43
commit
d135870658
60 changed files with 2153 additions and 1456 deletions
|
|
@ -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"]
|
||||
|
|
|
|||
8
Cargo.lock
generated
8
Cargo.lock
generated
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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']
|
||||
|
||||
|
|
|
|||
|
|
@ -2283,6 +2283,11 @@ who = "Teodor Tanasoaia <ttanasoaia@mozilla.com>"
|
|||
criteria = "safe-to-deploy"
|
||||
delta = "0.12.0@git:b99d58ea435090e561377949f428bce2c18451bb -> 0.12.0@git:76003dc0035d53a474d366dcdf49d2e4d12e921f"
|
||||
|
||||
[[audits.naga]]
|
||||
who = "Nicolas Silva <nical@fastmail.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.13.0@git:7a19f3af909202c7eafd36633b5584bfbb353ecb -> 0.13.0@git:cc87b8f9eb30bb55d0735b89d3df3e099e1a6e7c"
|
||||
|
||||
[[audits.naga]]
|
||||
who = "Erich Gubler <egubler@mozilla.com"
|
||||
criteria = "safe-to-deploy"
|
||||
|
|
@ -3992,6 +3997,11 @@ who = "Erich Gubler <erichdongubler@gmail.com>"
|
|||
criteria = "safe-to-deploy"
|
||||
delta = "0.17.0@git:09b010b26af6876ce84991576a168a572172f08d -> 0.17.0@git:7c6b85756237f77bfe8d6231dfc7a1412ff662b6"
|
||||
|
||||
[[audits.wgpu-core]]
|
||||
who = "Nicolas Silva <nical@fastmail.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.17.0@git:332cd0325da52675432830870584ec9766679c34 -> 0.17.0@git:7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e"
|
||||
|
||||
[[audits.wgpu-core]]
|
||||
who = "Erich Gubler <erichdongubler@gmail.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
|
|
@ -4100,6 +4110,11 @@ who = "Erich Gubler <erichdongubler@gmail.com>"
|
|||
criteria = "safe-to-deploy"
|
||||
delta = "0.17.0@git:09b010b26af6876ce84991576a168a572172f08d -> 0.17.0@git:7c6b85756237f77bfe8d6231dfc7a1412ff662b6"
|
||||
|
||||
[[audits.wgpu-hal]]
|
||||
who = "Nicolas Silva <nical@fastmail.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.17.0@git:332cd0325da52675432830870584ec9766679c34 -> 0.17.0@git:7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e"
|
||||
|
||||
[[audits.wgpu-hal]]
|
||||
who = "Erich Gubler <erichdongubler@gmail.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
|
|
@ -4208,6 +4223,11 @@ who = "Erich Gubler <erichdongubler@gmail.com>"
|
|||
criteria = "safe-to-deploy"
|
||||
delta = "0.17.0@git:09b010b26af6876ce84991576a168a572172f08d -> 0.17.0@git:7c6b85756237f77bfe8d6231dfc7a1412ff662b6"
|
||||
|
||||
[[audits.wgpu-types]]
|
||||
who = "Nicolas Silva <nical@fastmail.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.17.0@git:332cd0325da52675432830870584ec9766679c34 -> 0.17.0@git:7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e"
|
||||
|
||||
[[audits.wgpu-types]]
|
||||
who = "Erich Gubler <erichdongubler@gmail.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
|
|
|
|||
2
third_party/rust/naga/.cargo-checksum.json
vendored
2
third_party/rust/naga/.cargo-checksum.json
vendored
File diff suppressed because one or more lines are too long
11
third_party/rust/naga/src/back/glsl/features.rs
vendored
11
third_party/rust/naga/src/back/glsl/features.rs
vendored
|
|
@ -41,6 +41,8 @@ bitflags::bitflags! {
|
|||
const TEXTURE_LEVELS = 1 << 19;
|
||||
/// Image size query
|
||||
const IMAGE_SIZE = 1 << 20;
|
||||
/// Dual source blending
|
||||
const DUAL_SOURCE_BLENDING = 1 << 21;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -104,6 +106,7 @@ impl FeaturesManager {
|
|||
check_feature!(CULL_DISTANCE, 450, 300 /* with extension */);
|
||||
check_feature!(SAMPLE_VARIABLES, 400, 300);
|
||||
check_feature!(DYNAMIC_ARRAY_SIZE, 430, 310);
|
||||
check_feature!(DUAL_SOURCE_BLENDING, 330, 300 /* with extension */);
|
||||
match version {
|
||||
Version::Embedded { is_webgl: true, .. } => 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
];
|
||||
|
|
|
|||
70
third_party/rust/naga/src/back/glsl/mod.rs
vendored
70
third_party/rust/naga/src/back/glsl/mod.rs
vendored
|
|
@ -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<crate::ResourceBinding, u8>;
|
||||
|
||||
|
|
@ -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,8 +1338,12 @@ 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 {
|
||||
if second_blend_source {
|
||||
write!(self.out, "layout(location = {location}, index = 1) ")?;
|
||||
} else {
|
||||
write!(self.out, "layout(location = {location}) ")?;
|
||||
}
|
||||
}
|
||||
|
||||
// Write the interpolation qualifier.
|
||||
if let Some(interp) = interpolation {
|
||||
|
|
@ -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",
|
||||
|
|
|
|||
53
third_party/rust/naga/src/back/hlsl/help.rs
vendored
53
third_party/rust/naga/src/back/hlsl/help.rs
vendored
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
21
third_party/rust/naga/src/back/hlsl/writer.rs
vendored
21
third_party/rust/naga/src/back/hlsl/writer.rs
vendored
|
|
@ -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<crate::Type>,
|
||||
|
|
@ -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"),
|
||||
|
|
|
|||
|
|
@ -214,4 +214,6 @@ pub const RESERVED: &[&str] = &[
|
|||
// Naga utilities
|
||||
"DefaultConstructible",
|
||||
"clamped_lod_e",
|
||||
super::writer::FREXP_FUNCTION,
|
||||
super::writer::MODF_FUNCTION,
|
||||
];
|
||||
|
|
|
|||
29
third_party/rust/naga/src/back/msl/mod.rs
vendored
29
third_party/rust/naga/src/back/msl/mod.rs
vendored
|
|
@ -82,7 +82,10 @@ pub type EntryPointResourceMap = std::collections::BTreeMap<String, EntryPointRe
|
|||
enum ResolvedBinding {
|
||||
BuiltIn(crate::BuiltIn),
|
||||
Attribute(u32),
|
||||
Color(u32),
|
||||
Color {
|
||||
location: u32,
|
||||
second_blend_source: bool,
|
||||
},
|
||||
User {
|
||||
prefix: &'static str,
|
||||
index: u32,
|
||||
|
|
@ -245,9 +248,20 @@ impl Options {
|
|||
location,
|
||||
interpolation,
|
||||
sampling,
|
||||
second_blend_source,
|
||||
} => 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,
|
||||
|
|
|
|||
108
third_party/rust/naga/src/back/msl/writer.rs
vendored
108
third_party/rust/naga/src/back/msl/writer.rs
vendored
|
|
@ -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<W: Write> Writer<W> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Emit code for the sign(i32) expression.
|
||||
///
|
||||
fn put_isign(
|
||||
&mut self,
|
||||
arg: Handle<crate::Expression>,
|
||||
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<crate::Expression>,
|
||||
|
|
@ -1644,8 +1672,9 @@ impl<W: Write> Writer<W> {
|
|||
} => {
|
||||
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<W: Write> Writer<W> {
|
|||
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<W: Write> Writer<W> {
|
|||
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<W: Write> Writer<W> {
|
|||
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<W: Write> Writer<W> {
|
|||
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<W: Write> Writer<W> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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(())
|
||||
}
|
||||
|
||||
|
|
|
|||
4
third_party/rust/naga/src/back/spv/block.rs
vendored
4
third_party/rust/naga/src/back/spv/block.rs
vendored
|
|
@ -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) {
|
||||
|
|
|
|||
4
third_party/rust/naga/src/back/spv/writer.rs
vendored
4
third_party/rust/naga/src/back/spv/writer.rs
vendored
|
|
@ -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;
|
||||
|
|
|
|||
29
third_party/rust/naga/src/back/wgsl/writer.rs
vendored
29
third_party/rust/naga/src/back/wgsl/writer.rs
vendored
|
|
@ -17,6 +17,7 @@ enum Attribute {
|
|||
Invariant,
|
||||
Interpolate(Option<crate::Interpolation>, Option<crate::Sampling>),
|
||||
Location(u32),
|
||||
SecondBlendSource,
|
||||
Stage(ShaderStage),
|
||||
WorkGroupSize([u32; 3]),
|
||||
}
|
||||
|
|
@ -96,6 +97,14 @@ impl<W: Write> Writer<W> {
|
|||
self.ep_results.clear();
|
||||
}
|
||||
|
||||
fn is_builtin_wgsl_struct(&self, module: &Module, handle: Handle<crate::Type>) -> 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,15 +117,15 @@ impl<W: Write> Writer<W> {
|
|||
|
||||
// Write all structs
|
||||
for (handle, ty) in module.types.iter() {
|
||||
if let TypeInner::Struct {
|
||||
ref members,
|
||||
span: _,
|
||||
} = ty.inner
|
||||
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)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write all named constants
|
||||
let mut constants = module
|
||||
|
|
@ -319,6 +328,7 @@ impl<W: Write> Writer<W> {
|
|||
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<Attribute> {
|
|||
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),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
|
|
|||
196
third_party/rust/naga/src/front/glsl/builtins.rs
vendored
196
third_party/rust/naga/src/front/glsl/builtins.rs
vendored
|
|
@ -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<Expression>],
|
||||
meta: Span,
|
||||
) -> Result<Option<Handle<Expression>>> {
|
||||
|
|
@ -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<Handle<Expression>>,
|
||||
body: &mut Block,
|
||||
meta: Span,
|
||||
) -> Result<Handle<Expression>> {
|
||||
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<Expression>,
|
||||
extra: Option<Handle<Expression>>,
|
||||
meta: Span,
|
||||
body: &mut Block,
|
||||
) -> Result<CoordComponents> {
|
||||
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<Expression>,
|
||||
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 {
|
||||
|
|
|
|||
574
third_party/rust/naga/src/front/glsl/context.rs
vendored
574
third_party/rust/naga/src/front/glsl/context.rs
vendored
File diff suppressed because it is too large
Load diff
674
third_party/rust/naga/src/front/glsl/functions.rs
vendored
674
third_party/rust/naga/src/front/glsl/functions.rs
vendored
File diff suppressed because it is too large
Load diff
20
third_party/rust/naga/src/front/glsl/mod.rs
vendored
20
third_party/rust/naga/src/front/glsl/mod.rs
vendored
|
|
@ -175,8 +175,6 @@ pub struct Frontend {
|
|||
layouter: Layouter,
|
||||
|
||||
errors: Vec<Error>,
|
||||
|
||||
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,16 +202,20 @@ 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);
|
||||
}
|
||||
|
||||
match ctx.parse(self) {
|
||||
Ok(module) => {
|
||||
if self.errors.is_empty() {
|
||||
Ok(std::mem::take(&mut self.module))
|
||||
Ok(module)
|
||||
} else {
|
||||
Err(std::mem::take(&mut self.errors))
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
self.errors.push(e);
|
||||
Err(std::mem::take(&mut self.errors))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns additional information about the parsed shader which might not be
|
||||
/// stored in the [`Module`](Module), see the documentation for
|
||||
|
|
|
|||
60
third_party/rust/naga/src/front/glsl/parser.rs
vendored
60
third_party/rust/naga/src/front/glsl/parser.rs
vendored
|
|
@ -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<Module> {
|
||||
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<Expression>, 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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Type>,
|
||||
ctx: &mut Context,
|
||||
body: &mut Block,
|
||||
) -> Result<(Handle<Expression>, 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::<Result<_>, _>(|_| {
|
||||
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<Option<Span>> {
|
||||
//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<StructMember>,
|
||||
layout: StructLayout,
|
||||
) -> Result<u32> {
|
||||
|
|
@ -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,
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Handle<HirExpr>> {
|
||||
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<Vec<Handle<HirExpr>>> {
|
||||
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<Handle<HirExpr>> {
|
||||
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<Handle<HirExpr>> {
|
||||
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<Handle<HirExpr>>,
|
||||
min_bp: u8,
|
||||
) -> Result<Handle<HirExpr>> {
|
||||
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<Handle<HirExpr>>,
|
||||
) -> Result<Handle<HirExpr>> {
|
||||
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<Handle<HirExpr>> {
|
||||
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<Handle<HirExpr>> {
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -40,12 +40,11 @@ impl<'source> ParsingContext<'source> {
|
|||
&mut self,
|
||||
frontend: &mut Frontend,
|
||||
ctx: &mut Context,
|
||||
body: &mut Block,
|
||||
terminator: &mut Option<usize>,
|
||||
) -> Result<Option<Span>> {
|
||||
// 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 accept = ctx.new_body(|ctx| {
|
||||
if let Some(more_meta) = self.parse_statement(frontend, ctx, &mut None)? {
|
||||
meta.subsume(more_meta);
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
let mut reject = Block::new();
|
||||
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 reject, &mut None)?
|
||||
{
|
||||
if let Some(more_meta) = self.parse_statement(frontend, ctx, &mut None)? {
|
||||
meta.subsume(more_meta);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
body.push(
|
||||
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,8 +245,9 @@ impl<'source> ParsingContext<'source> {
|
|||
|
||||
self.expect(frontend, TokenValue::Colon)?;
|
||||
|
||||
let mut body = Block::new();
|
||||
let mut fall_through = true;
|
||||
|
||||
let body = ctx.new_body(|ctx| {
|
||||
let mut case_terminator = None;
|
||||
loop {
|
||||
match self.expect_peek(frontend)?.value {
|
||||
|
|
@ -253,27 +255,23 @@ impl<'source> ParsingContext<'source> {
|
|||
break
|
||||
}
|
||||
_ => {
|
||||
self.parse_statement(
|
||||
frontend,
|
||||
ctx,
|
||||
&mut body,
|
||||
&mut case_terminator,
|
||||
)?;
|
||||
self.parse_statement(frontend, ctx, &mut case_terminator)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut fall_through = true;
|
||||
|
||||
if let Some(mut idx) = case_terminator {
|
||||
if let Statement::Break = body[idx - 1] {
|
||||
if let Statement::Break = ctx.body[idx - 1] {
|
||||
fall_through = false;
|
||||
idx -= 1;
|
||||
}
|
||||
|
||||
body.cull(idx..)
|
||||
ctx.body.cull(idx..)
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
cases.push(SwitchCase {
|
||||
value,
|
||||
body,
|
||||
|
|
@ -317,34 +315,31 @@ 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, &mut loop_body)?;
|
||||
let root = self.parse_expression(frontend, ctx, &mut stmt)?;
|
||||
meta.subsume(self.expect(frontend, TokenValue::RightParen)?.meta);
|
||||
|
||||
let (expr, expr_meta) =
|
||||
ctx.lower_expect(stmt, frontend, root, ExprPos::Rhs, &mut loop_body)?;
|
||||
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,
|
||||
&mut loop_body,
|
||||
);
|
||||
)?;
|
||||
|
||||
ctx.emit_restart(&mut loop_body);
|
||||
ctx.emit_restart();
|
||||
|
||||
loop_body.push(
|
||||
ctx.body.push(
|
||||
Statement::If {
|
||||
condition,
|
||||
accept: new_break(),
|
||||
|
|
@ -355,13 +350,13 @@ impl<'source> ParsingContext<'source> {
|
|||
|
||||
meta.subsume(expr_meta);
|
||||
|
||||
if let Some(body_meta) =
|
||||
self.parse_statement(frontend, ctx, &mut loop_body, &mut None)?
|
||||
{
|
||||
if let Some(body_meta) = self.parse_statement(frontend, ctx, &mut None)? {
|
||||
meta.subsume(body_meta);
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
body.push(
|
||||
ctx.body.push(
|
||||
Statement::Loop {
|
||||
body: loop_body,
|
||||
continuing: Block::new(),
|
||||
|
|
@ -375,34 +370,31 @@ 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 loop_body, &mut terminator)?;
|
||||
self.parse_statement(frontend, ctx, &mut terminator)?;
|
||||
|
||||
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, &mut loop_body)?;
|
||||
let root = self.parse_expression(frontend, ctx, &mut stmt)?;
|
||||
let end_meta = self.expect(frontend, TokenValue::RightParen)?.meta;
|
||||
|
||||
meta.subsume(end_meta);
|
||||
|
||||
let (expr, expr_meta) =
|
||||
ctx.lower_expect(stmt, frontend, root, ExprPos::Rhs, &mut loop_body)?;
|
||||
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,
|
||||
&mut loop_body,
|
||||
);
|
||||
)?;
|
||||
|
||||
ctx.emit_restart(&mut loop_body);
|
||||
ctx.emit_restart();
|
||||
|
||||
loop_body.push(
|
||||
ctx.body.push(
|
||||
Statement::If {
|
||||
condition,
|
||||
accept: new_break(),
|
||||
|
|
@ -412,10 +404,12 @@ impl<'source> ParsingContext<'source> {
|
|||
);
|
||||
|
||||
if let Some(idx) = terminator {
|
||||
loop_body.cull(idx..)
|
||||
ctx.body.cull(idx..)
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
body.push(
|
||||
ctx.body.push(
|
||||
Statement::Loop {
|
||||
body: loop_body,
|
||||
continuing: Block::new(),
|
||||
|
|
@ -434,29 +428,27 @@ 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)?;
|
||||
let (ty, mut meta) = self.parse_type_non_void(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;
|
||||
|
||||
self.expect(frontend, TokenValue::Assign)?;
|
||||
|
||||
let (value, end_meta) =
|
||||
self.parse_initializer(frontend, ty, ctx, &mut block)?;
|
||||
let (value, end_meta) = self.parse_initializer(frontend, ty, ctx)?;
|
||||
meta.subsume(end_meta);
|
||||
|
||||
let decl = VarDeclaration {
|
||||
|
|
@ -467,17 +459,17 @@ impl<'source> ParsingContext<'source> {
|
|||
meta,
|
||||
};
|
||||
|
||||
let pointer = frontend.add_local_var(ctx, &mut block, decl)?;
|
||||
let pointer = frontend.add_local_var(ctx, decl)?;
|
||||
|
||||
ctx.emit_restart(&mut block);
|
||||
ctx.emit_restart();
|
||||
|
||||
block.push(Statement::Store { pointer, value }, meta);
|
||||
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, &mut block)?;
|
||||
ctx.lower_expect(stmt, frontend, root, ExprPos::Rhs, &mut block)?
|
||||
let root = self.parse_expression(frontend, ctx, &mut stmt)?;
|
||||
ctx.lower_expect(stmt, frontend, root, ExprPos::Rhs)?
|
||||
};
|
||||
|
||||
let condition = ctx.add_expression(
|
||||
|
|
@ -486,12 +478,11 @@ impl<'source> ParsingContext<'source> {
|
|||
expr,
|
||||
},
|
||||
expr_meta,
|
||||
&mut block,
|
||||
);
|
||||
)?;
|
||||
|
||||
ctx.emit_restart(&mut block);
|
||||
ctx.emit_restart();
|
||||
|
||||
block.push(
|
||||
ctx.body.push(
|
||||
Statement::If {
|
||||
condition,
|
||||
accept: new_break(),
|
||||
|
|
@ -502,28 +493,33 @@ impl<'source> ParsingContext<'source> {
|
|||
|
||||
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, &mut continuing)?;
|
||||
ctx.lower(stmt, frontend, rest, ExprPos::Rhs, &mut continuing)?;
|
||||
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)?
|
||||
{
|
||||
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<usize>,
|
||||
) -> Result<Span> {
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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<Type>,
|
||||
) -> 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<Type>,
|
||||
) -> Result<bool> {
|
||||
|
|
@ -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<Handle<Type>>, Span)> {
|
||||
pub fn parse_type(
|
||||
&mut self,
|
||||
frontend: &mut Frontend,
|
||||
ctx: &mut Context,
|
||||
) -> Result<(Option<Handle<Type>>, 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<Type>, 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<Type>, 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<TypeQualifiers<'a>> {
|
||||
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<QualifierKey, (QualifierValue, Span)>,
|
||||
) -> Result<()> {
|
||||
// layout_qualifier_id:
|
||||
|
|
@ -332,7 +347,8 @@ 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) {
|
||||
let (value, end_meta) =
|
||||
match self.parse_uint_constant(frontend, ctx) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
frontend.errors.push(e);
|
||||
|
|
|
|||
49
third_party/rust/naga/src/front/glsl/types.rs
vendored
49
third_party/rust/naga/src/front/glsl/types.rs
vendored
|
|
@ -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<u32> {
|
|||
})
|
||||
}
|
||||
|
||||
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<Expression>,
|
||||
meta: Span,
|
||||
) -> Result<()> {
|
||||
let resolve_ctx = ResolveContext::with_locals(&self.module, &ctx.locals, &ctx.arguments);
|
||||
pub(crate) fn typifier_grow(&mut self, expr: Handle<Expression>, 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<Expression>,
|
||||
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<Expression>,
|
||||
meta: Span,
|
||||
) -> Result<Handle<Type>> {
|
||||
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<Expression>,
|
||||
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<Expression>,
|
||||
meta: Span,
|
||||
) -> Result<Handle<Expression>> {
|
||||
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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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<VariableReference> {
|
||||
let ty = self.module.types.insert(
|
||||
) -> Result<Option<VariableReference>> {
|
||||
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<VariableReference> {
|
||||
) -> Result<Option<VariableReference>> {
|
||||
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<Expression>,
|
||||
name: &str,
|
||||
meta: Span,
|
||||
) -> Result<Handle<Expression>> {
|
||||
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<Handle<Expression>> {
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ impl crate::Binding {
|
|||
location: _,
|
||||
interpolation: ref mut interpolation @ None,
|
||||
ref mut sampling,
|
||||
second_blend_source: _,
|
||||
} = *self
|
||||
{
|
||||
match ty.scalar_kind() {
|
||||
|
|
|
|||
1
third_party/rust/naga/src/front/spv/mod.rs
vendored
1
third_party/rust/naga/src/front/spv/mod.rs
vendored
|
|
@ -255,6 +255,7 @@ impl Decoration {
|
|||
location,
|
||||
interpolation,
|
||||
sampling,
|
||||
second_blend_source: false,
|
||||
}),
|
||||
_ => Err(Error::MissingDecoration(spirv::Decoration::Location)),
|
||||
}
|
||||
|
|
|
|||
248
third_party/rust/naga/src/front/type_gen.rs
vendored
248
third_party/rust/naga/src/front/type_gen.rs
vendored
|
|
@ -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<crate::Type> {
|
||||
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<crate::Type> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
11
third_party/rust/naga/src/front/wgsl/error.rs
vendored
11
third_party/rust/naga/src/front/wgsl/error.rs
vendored
|
|
@ -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![],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<crate::Expression>,
|
||||
right: &mut Handle<crate::Expression>,
|
||||
) -> 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()?;
|
||||
|
||||
// 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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ pub struct FunctionResult<'a> {
|
|||
pub struct EntryPoint {
|
||||
pub stage: crate::ShaderStage,
|
||||
pub early_depth_test: Option<crate::EarlyDepthTest>,
|
||||
pub workgroup_size: [u32; 3],
|
||||
pub workgroup_size: Option<[u32; 3]>,
|
||||
}
|
||||
|
||||
#[cfg(doc)]
|
||||
|
|
|
|||
|
|
@ -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<T> ParsedAttribute<T> {
|
|||
#[derive(Default)]
|
||||
struct BindingParser {
|
||||
location: ParsedAttribute<u32>,
|
||||
second_blend_source: ParsedAttribute<bool>,
|
||||
built_in: ParsedAttribute<crate::BuiltIn>,
|
||||
interpolation: ParsedAttribute<crate::Interpolation>,
|
||||
sampling: ParsedAttribute<crate::Sampling>,
|
||||
|
|
@ -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 {
|
||||
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: workgroup_size.value,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
},
|
||||
..function
|
||||
}))
|
||||
}
|
||||
|
|
|
|||
87
third_party/rust/naga/src/front/wgsl/tests.rs
vendored
87
third_party/rust/naga/src/front/wgsl/tests.rs
vendored
|
|
@ -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<f32>(1.0, 1.0, 1.0);
|
||||
@fragment
|
||||
fn main() -> @location(0) vec4<f32> {{
|
||||
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<f32>) {
|
||||
let vec = vec3<f32>(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<private, f32>) -> 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<f32> { return vec4<f32>(0.0); }";
|
||||
let result = Frontend::new().inner(shader);
|
||||
assert!(matches!(
|
||||
result.unwrap_err(),
|
||||
Error::MissingWorkgroupSize(span) if span == Span::new(1, 8)
|
||||
));
|
||||
}
|
||||
|
|
|
|||
33
third_party/rust/naga/src/lib.rs
vendored
33
third_party/rust/naga/src/lib.rs
vendored
|
|
@ -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<Interpolation>,
|
||||
sampling: Option<Sampling>,
|
||||
},
|
||||
|
|
@ -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<VectorSize>,
|
||||
width: Bytes,
|
||||
},
|
||||
FrexpResult {
|
||||
size: Option<VectorSize>,
|
||||
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<Handle<Type>>,
|
||||
|
||||
/// 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<PredeclaredType, Handle<Type>>,
|
||||
}
|
||||
|
||||
/// Shader module.
|
||||
|
|
|
|||
4
third_party/rust/naga/src/proc/mod.rs
vendored
4
third_party/rust/naga/src/proc/mod.rs
vendored
|
|
@ -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,
|
||||
|
|
|
|||
27
third_party/rust/naga/src/proc/typifier.rs
vendored
27
third_party/rust/naga/src/proc/typifier.rs
vendored
|
|
@ -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 {
|
||||
|
|
|
|||
5
third_party/rust/naga/src/valid/analyzer.rs
vendored
5
third_party/rust/naga/src/valid/analyzer.rs
vendored
|
|
@ -256,6 +256,9 @@ pub struct FunctionInfo {
|
|||
///
|
||||
/// [`GlobalVariable`]: crate::GlobalVariable
|
||||
sampling: crate::FastHashSet<Sampling>,
|
||||
|
||||
/// 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(),
|
||||
|
|
|
|||
80
third_party/rust/naga/src/valid/expression.rs
vendored
80
third_party/rust/naga/src/valid/expression.rs
vendored
|
|
@ -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 {
|
||||
|
|
|
|||
66
third_party/rust/naga/src/valid/interface.rs
vendored
66
third_party/rust/naga/src/valid/interface.rs
vendored
|
|
@ -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<crate::Type>,
|
||||
type_info: &'a Vec<super::r#type::TypeInfo>,
|
||||
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
|
||||
|
|
|
|||
2
third_party/rust/naga/src/valid/mod.rs
vendored
2
third_party/rust/naga/src/valid/mod.rs
vendored
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
{"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}
|
||||
2
third_party/rust/wgpu-core/Cargo.toml
vendored
2
third_party/rust/wgpu-core/Cargo.toml
vendored
|
|
@ -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",
|
||||
|
|
|
|||
26
third_party/rust/wgpu-core/src/device/global.rs
vendored
26
third_party/rust/wgpu-core/src/device/global.rs
vendored
|
|
@ -2134,7 +2134,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
|
||||
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<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
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<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
}
|
||||
}
|
||||
|
||||
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),
|
||||
|
|
|
|||
3
third_party/rust/wgpu-core/src/device/mod.rs
vendored
3
third_party/rust/wgpu-core/src/device/mod.rs
vendored
|
|
@ -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
|
||||
|
|
|
|||
16
third_party/rust/wgpu-core/src/instance.rs
vendored
16
third_party/rust/wgpu-core/src/instance.rs
vendored
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
14
third_party/rust/wgpu-core/src/present.rs
vendored
14
third_party/rust/wgpu-core/src/present.rs
vendored
|
|
@ -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<WaitIdleError> for ConfigureSurfaceError {
|
||||
fn from(e: WaitIdleError) -> Self {
|
||||
match e {
|
||||
WaitIdleError::Device(d) => ConfigureSurfaceError::Device(d),
|
||||
WaitIdleError::WrongSubmissionIndex(..) => unreachable!(),
|
||||
WaitIdleError::StuckGpu => ConfigureSurfaceError::StuckGpu,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
|
|
|||
1
third_party/rust/wgpu-core/src/validation.rs
vendored
1
third_party/rust/wgpu-core/src/validation.rs
vendored
|
|
@ -812,6 +812,7 @@ impl Interface {
|
|||
location,
|
||||
interpolation,
|
||||
sampling,
|
||||
.. // second_blend_source
|
||||
}) => Varying::Local {
|
||||
location,
|
||||
iv: InterfaceVar {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
4
third_party/rust/wgpu-hal/Cargo.toml
vendored
4
third_party/rust/wgpu-hal/Cargo.toml
vendored
|
|
@ -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]
|
||||
|
|
|
|||
5
third_party/rust/wgpu-hal/src/dx12/device.rs
vendored
5
third_party/rust/wgpu-hal/src/dx12/device.rs
vendored
|
|
@ -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);
|
||||
|
|
|
|||
33
third_party/rust/wgpu-hal/src/dx12/mod.rs
vendored
33
third_party/rust/wgpu-hal/src/dx12/mod.rs
vendored
|
|
@ -613,19 +613,23 @@ impl crate::Surface<Api> 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<Api> 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<Api> 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(
|
||||
|
|
|
|||
16
third_party/rust/wgpu-hal/src/lib.rs
vendored
16
third_party/rust/wgpu-hal/src/lib.rs
vendored
|
|
@ -227,12 +227,28 @@ pub trait Instance<A: Api>: Sized + WasmNotSend + WasmNotSync {
|
|||
}
|
||||
|
||||
pub trait Surface<A: Api>: 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
|
||||
|
|
|
|||
|
|
@ -1143,7 +1143,7 @@ impl crate::Device<super::Api> 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)
|
||||
|
|
|
|||
39
third_party/rust/wgpu-hal/src/vulkan/instance.rs
vendored
39
third_party/rust/wgpu-hal/src/vulkan/instance.rs
vendored
|
|
@ -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<super::Api> 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,9 +798,16 @@ impl crate::Instance<super::Api> for super::Instance {
|
|||
if exposed.info.device_type == wgt::DeviceType::IntegratedGpu
|
||||
&& exposed.info.vendor == db::intel::VENDOR
|
||||
{
|
||||
// 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::<f32>().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 {:?}) because of NV Optimus (on Linux)",
|
||||
"Disabling presentation on '{}' (id {:?}) due to NV Optimus and Intel Mesa < v21.2",
|
||||
exposed.info.name,
|
||||
exposed.adapter.raw
|
||||
);
|
||||
|
|
@ -796,6 +815,8 @@ impl crate::Instance<super::Api> for super::Instance {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exposed_adapters
|
||||
}
|
||||
|
|
@ -807,6 +828,7 @@ impl crate::Surface<super::Api> 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<super::Api> 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) };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
{"files":{"Cargo.toml":"9f4a8846579ca480d493e80ad1488dcd18feb08c79aa833e2733808f0473d79b","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","src/assertions.rs":"3fe98027aa73970c8ab7874a3e13dbfd6faa87df2081beb5c83aeec4c60f372f","src/lib.rs":"d65636e17a80dd44eb06b7bee735020869a7165b63505f11b126ab1eb76a5107","src/math.rs":"4d03039736dd6926feb139bc68734cb59df34ede310427bbf059e5c925e0af3b"},"package":null}
|
||||
2
third_party/rust/wgpu-types/Cargo.toml
vendored
2
third_party/rust/wgpu-types/Cargo.toml
vendored
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Reference in a new issue