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"
|
rev = "43c22248d136c8b38fe42ea709d08da6355cf04b"
|
||||||
replace-with = "vendored-sources"
|
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"
|
git = "https://github.com/gfx-rs/naga"
|
||||||
rev = "7a19f3af909202c7eafd36633b5584bfbb353ecb"
|
rev = "cc87b8f9eb30bb55d0735b89d3df3e099e1a6e7c"
|
||||||
replace-with = "vendored-sources"
|
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"
|
git = "https://github.com/gfx-rs/wgpu"
|
||||||
rev = "332cd0325da52675432830870584ec9766679c34"
|
rev = "7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e"
|
||||||
replace-with = "vendored-sources"
|
replace-with = "vendored-sources"
|
||||||
|
|
||||||
[source."git+https://github.com/glandium/prost?rev=95964e9d33df3c2a9c3f14285e262867cab6f96b"]
|
[source."git+https://github.com/glandium/prost?rev=95964e9d33df3c2a9c3f14285e262867cab6f96b"]
|
||||||
|
|
|
||||||
8
Cargo.lock
generated
8
Cargo.lock
generated
|
|
@ -3724,7 +3724,7 @@ checksum = "a2983372caf4480544083767bf2d27defafe32af49ab4df3a0b7fc90793a3664"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "naga"
|
name = "naga"
|
||||||
version = "0.13.0"
|
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 = [
|
dependencies = [
|
||||||
"bit-set",
|
"bit-set",
|
||||||
"bitflags 2.999.999",
|
"bitflags 2.999.999",
|
||||||
|
|
@ -6301,7 +6301,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wgpu-core"
|
name = "wgpu-core"
|
||||||
version = "0.17.0"
|
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 = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"bit-vec",
|
"bit-vec",
|
||||||
|
|
@ -6324,7 +6324,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wgpu-hal"
|
name = "wgpu-hal"
|
||||||
version = "0.17.0"
|
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 = [
|
dependencies = [
|
||||||
"android_system_properties",
|
"android_system_properties",
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
|
|
@ -6360,7 +6360,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wgpu-types"
|
name = "wgpu-types"
|
||||||
version = "0.17.0"
|
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 = [
|
dependencies = [
|
||||||
"bitflags 2.999.999",
|
"bitflags 2.999.999",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ default = []
|
||||||
[dependencies.wgc]
|
[dependencies.wgc]
|
||||||
package = "wgpu-core"
|
package = "wgpu-core"
|
||||||
git = "https://github.com/gfx-rs/wgpu"
|
git = "https://github.com/gfx-rs/wgpu"
|
||||||
rev = "332cd0325da52675432830870584ec9766679c34"
|
rev = "7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e"
|
||||||
#Note: "replay" shouldn't ideally be needed,
|
#Note: "replay" shouldn't ideally be needed,
|
||||||
# but it allows us to serialize everything across IPC.
|
# but it allows us to serialize everything across IPC.
|
||||||
features = ["replay", "trace", "serial-pass", "strict_asserts", "wgsl"]
|
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]
|
[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies.wgc]
|
||||||
package = "wgpu-core"
|
package = "wgpu-core"
|
||||||
git = "https://github.com/gfx-rs/wgpu"
|
git = "https://github.com/gfx-rs/wgpu"
|
||||||
rev = "332cd0325da52675432830870584ec9766679c34"
|
rev = "7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e"
|
||||||
features = ["metal"]
|
features = ["metal"]
|
||||||
|
|
||||||
# We want the wgpu-core Direct3D backends on Windows.
|
# We want the wgpu-core Direct3D backends on Windows.
|
||||||
[target.'cfg(windows)'.dependencies.wgc]
|
[target.'cfg(windows)'.dependencies.wgc]
|
||||||
package = "wgpu-core"
|
package = "wgpu-core"
|
||||||
git = "https://github.com/gfx-rs/wgpu"
|
git = "https://github.com/gfx-rs/wgpu"
|
||||||
rev = "332cd0325da52675432830870584ec9766679c34"
|
rev = "7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e"
|
||||||
features = ["dx11", "dx12"]
|
features = ["dx11", "dx12"]
|
||||||
|
|
||||||
# We want the wgpu-core Vulkan backend on Linux and Windows.
|
# 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]
|
[target.'cfg(any(windows, all(unix, not(any(target_os = "macos", target_os = "ios")))))'.dependencies.wgc]
|
||||||
package = "wgpu-core"
|
package = "wgpu-core"
|
||||||
git = "https://github.com/gfx-rs/wgpu"
|
git = "https://github.com/gfx-rs/wgpu"
|
||||||
rev = "332cd0325da52675432830870584ec9766679c34"
|
rev = "7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e"
|
||||||
features = ["vulkan"]
|
features = ["vulkan"]
|
||||||
|
|
||||||
[dependencies.wgt]
|
[dependencies.wgt]
|
||||||
package = "wgpu-types"
|
package = "wgpu-types"
|
||||||
git = "https://github.com/gfx-rs/wgpu"
|
git = "https://github.com/gfx-rs/wgpu"
|
||||||
rev = "332cd0325da52675432830870584ec9766679c34"
|
rev = "7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e"
|
||||||
|
|
||||||
[dependencies.wgh]
|
[dependencies.wgh]
|
||||||
package = "wgpu-hal"
|
package = "wgpu-hal"
|
||||||
git = "https://github.com/gfx-rs/wgpu"
|
git = "https://github.com/gfx-rs/wgpu"
|
||||||
rev = "332cd0325da52675432830870584ec9766679c34"
|
rev = "7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
d3d12 = "0.7.0"
|
d3d12 = "0.7.0"
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,11 @@ origin:
|
||||||
|
|
||||||
# Human-readable identifier for this version/release
|
# Human-readable identifier for this version/release
|
||||||
# Generally "version NNN", "tag SSS", "bookmark SSS"
|
# Generally "version NNN", "tag SSS", "bookmark SSS"
|
||||||
release: commit 332cd0325da52675432830870584ec9766679c34
|
release: commit 7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e
|
||||||
|
|
||||||
# Revision to pull in
|
# Revision to pull in
|
||||||
# Must be a long or short commit SHA (long preferred)
|
# Must be a long or short commit SHA (long preferred)
|
||||||
revision: 332cd0325da52675432830870584ec9766679c34
|
revision: 7fea9e934efd8d5dc03b9aa3e06b775c1ac4a23e
|
||||||
|
|
||||||
license: ['MIT', 'Apache-2.0']
|
license: ['MIT', 'Apache-2.0']
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2283,6 +2283,11 @@ who = "Teodor Tanasoaia <ttanasoaia@mozilla.com>"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
delta = "0.12.0@git:b99d58ea435090e561377949f428bce2c18451bb -> 0.12.0@git:76003dc0035d53a474d366dcdf49d2e4d12e921f"
|
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]]
|
[[audits.naga]]
|
||||||
who = "Erich Gubler <egubler@mozilla.com"
|
who = "Erich Gubler <egubler@mozilla.com"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
|
|
@ -3992,6 +3997,11 @@ who = "Erich Gubler <erichdongubler@gmail.com>"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
delta = "0.17.0@git:09b010b26af6876ce84991576a168a572172f08d -> 0.17.0@git:7c6b85756237f77bfe8d6231dfc7a1412ff662b6"
|
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]]
|
[[audits.wgpu-core]]
|
||||||
who = "Erich Gubler <erichdongubler@gmail.com>"
|
who = "Erich Gubler <erichdongubler@gmail.com>"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
|
|
@ -4100,6 +4110,11 @@ who = "Erich Gubler <erichdongubler@gmail.com>"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
delta = "0.17.0@git:09b010b26af6876ce84991576a168a572172f08d -> 0.17.0@git:7c6b85756237f77bfe8d6231dfc7a1412ff662b6"
|
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]]
|
[[audits.wgpu-hal]]
|
||||||
who = "Erich Gubler <erichdongubler@gmail.com>"
|
who = "Erich Gubler <erichdongubler@gmail.com>"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
|
|
@ -4208,6 +4223,11 @@ who = "Erich Gubler <erichdongubler@gmail.com>"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
delta = "0.17.0@git:09b010b26af6876ce84991576a168a572172f08d -> 0.17.0@git:7c6b85756237f77bfe8d6231dfc7a1412ff662b6"
|
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]]
|
[[audits.wgpu-types]]
|
||||||
who = "Erich Gubler <erichdongubler@gmail.com>"
|
who = "Erich Gubler <erichdongubler@gmail.com>"
|
||||||
criteria = "safe-to-deploy"
|
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;
|
const TEXTURE_LEVELS = 1 << 19;
|
||||||
/// Image size query
|
/// Image size query
|
||||||
const IMAGE_SIZE = 1 << 20;
|
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!(CULL_DISTANCE, 450, 300 /* with extension */);
|
||||||
check_feature!(SAMPLE_VARIABLES, 400, 300);
|
check_feature!(SAMPLE_VARIABLES, 400, 300);
|
||||||
check_feature!(DYNAMIC_ARRAY_SIZE, 430, 310);
|
check_feature!(DYNAMIC_ARRAY_SIZE, 430, 310);
|
||||||
|
check_feature!(DUAL_SOURCE_BLENDING, 330, 300 /* with extension */);
|
||||||
match version {
|
match version {
|
||||||
Version::Embedded { is_webgl: true, .. } => check_feature!(MULTI_VIEW, 140, 300),
|
Version::Embedded { is_webgl: true, .. } => check_feature!(MULTI_VIEW, 140, 300),
|
||||||
_ => check_feature!(MULTI_VIEW, 140, 310),
|
_ => 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
|
// https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_query_levels.txt
|
||||||
writeln!(out, "#extension GL_ARB_texture_query_levels : require")?;
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -497,6 +504,7 @@ impl<'a, W> Writer<'a, W> {
|
||||||
location: _,
|
location: _,
|
||||||
interpolation,
|
interpolation,
|
||||||
sampling,
|
sampling,
|
||||||
|
second_blend_source,
|
||||||
} => {
|
} => {
|
||||||
if interpolation == Some(Interpolation::Linear) {
|
if interpolation == Some(Interpolation::Linear) {
|
||||||
self.features.request(Features::NOPERSPECTIVE_QUALIFIER);
|
self.features.request(Features::NOPERSPECTIVE_QUALIFIER);
|
||||||
|
|
@ -504,6 +512,9 @@ impl<'a, W> Writer<'a, W> {
|
||||||
if sampling == Some(Sampling::Sample) {
|
if sampling == Some(Sampling::Sample) {
|
||||||
self.features.request(Features::SAMPLE_QUALIFIER);
|
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)
|
// entry point name (should not be shadowed)
|
||||||
//
|
//
|
||||||
"main",
|
"main",
|
||||||
|
// Naga utilities:
|
||||||
|
super::MODF_FUNCTION,
|
||||||
|
super::FREXP_FUNCTION,
|
||||||
];
|
];
|
||||||
|
|
|
||||||
72
third_party/rust/naga/src/back/glsl/mod.rs
vendored
72
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`
|
/// of detail for bounds checking in `ImageLoad`
|
||||||
const CLAMPED_LOD_SUFFIX: &str = "_clamped_lod";
|
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.
|
/// Mapping between resources and bindings.
|
||||||
pub type BindingMap = std::collections::BTreeMap<crate::ResourceBinding, u8>;
|
pub type BindingMap = std::collections::BTreeMap<crate::ResourceBinding, u8>;
|
||||||
|
|
||||||
|
|
@ -333,6 +336,12 @@ struct VaryingName<'a> {
|
||||||
impl fmt::Display for VaryingName<'_> {
|
impl fmt::Display for VaryingName<'_> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match *self.binding {
|
match *self.binding {
|
||||||
|
crate::Binding::Location {
|
||||||
|
second_blend_source: true,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
write!(f, "_fs2p_location1",)
|
||||||
|
}
|
||||||
crate::Binding::Location { location, .. } => {
|
crate::Binding::Location { location, .. } => {
|
||||||
let prefix = match (self.stage, self.output) {
|
let prefix = match (self.stage, self.output) {
|
||||||
(ShaderStage::Compute, _) => unreachable!(),
|
(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
|
// Write all named constants
|
||||||
let mut constants = self
|
let mut constants = self
|
||||||
.module
|
.module
|
||||||
|
|
@ -1235,12 +1291,13 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||||
Some(binding) => binding,
|
Some(binding) => binding,
|
||||||
};
|
};
|
||||||
|
|
||||||
let (location, interpolation, sampling) = match *binding {
|
let (location, interpolation, sampling, second_blend_source) = match *binding {
|
||||||
crate::Binding::Location {
|
crate::Binding::Location {
|
||||||
location,
|
location,
|
||||||
interpolation,
|
interpolation,
|
||||||
sampling,
|
sampling,
|
||||||
} => (location, interpolation, sampling),
|
second_blend_source,
|
||||||
|
} => (location, interpolation, sampling, second_blend_source),
|
||||||
crate::Binding::BuiltIn(built_in) => {
|
crate::Binding::BuiltIn(built_in) => {
|
||||||
if let crate::BuiltIn::Position { invariant: true } = built_in {
|
if let crate::BuiltIn::Position { invariant: true } = built_in {
|
||||||
match (self.options.version, self.entry_point.stage) {
|
match (self.options.version, self.entry_point.stage) {
|
||||||
|
|
@ -1281,7 +1338,11 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||||
|
|
||||||
// Write the I/O locations, if allowed
|
// Write the I/O locations, if allowed
|
||||||
if self.options.version.supports_explicit_locations() || !emit_interpolation_and_auxiliary {
|
if self.options.version.supports_explicit_locations() || !emit_interpolation_and_auxiliary {
|
||||||
write!(self.out, "layout(location = {location}) ")?;
|
if second_blend_source {
|
||||||
|
write!(self.out, "layout(location = {location}, index = 1) ")?;
|
||||||
|
} else {
|
||||||
|
write!(self.out, "layout(location = {location}) ")?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the interpolation qualifier.
|
// Write the interpolation qualifier.
|
||||||
|
|
@ -1318,6 +1379,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||||
location,
|
location,
|
||||||
interpolation: None,
|
interpolation: None,
|
||||||
sampling: None,
|
sampling: None,
|
||||||
|
second_blend_source,
|
||||||
},
|
},
|
||||||
stage: self.entry_point.stage,
|
stage: self.entry_point.stage,
|
||||||
output,
|
output,
|
||||||
|
|
@ -2985,8 +3047,8 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||||
Mf::Round => "roundEven",
|
Mf::Round => "roundEven",
|
||||||
Mf::Fract => "fract",
|
Mf::Fract => "fract",
|
||||||
Mf::Trunc => "trunc",
|
Mf::Trunc => "trunc",
|
||||||
Mf::Modf => "modf",
|
Mf::Modf => MODF_FUNCTION,
|
||||||
Mf::Frexp => "frexp",
|
Mf::Frexp => FREXP_FUNCTION,
|
||||||
Mf::Ldexp => "ldexp",
|
Mf::Ldexp => "ldexp",
|
||||||
// exponent
|
// exponent
|
||||||
Mf::Exp => "exp",
|
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(())
|
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
|
/// Helper function that writes compose wrapped functions
|
||||||
pub(super) fn write_wrapped_compose_functions(
|
pub(super) fn write_wrapped_compose_functions(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
||||||
|
|
@ -814,6 +814,9 @@ pub const RESERVED: &[&str] = &[
|
||||||
"TextureBuffer",
|
"TextureBuffer",
|
||||||
"ConstantBuffer",
|
"ConstantBuffer",
|
||||||
"RayQuery",
|
"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
|
// 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_BASE_INSTANCE: &str = "base_instance";
|
||||||
const SPECIAL_OTHER: &str = "other";
|
const SPECIAL_OTHER: &str = "other";
|
||||||
|
|
||||||
|
pub(crate) const MODF_FUNCTION: &str = "naga_modf";
|
||||||
|
pub(crate) const FREXP_FUNCTION: &str = "naga_frexp";
|
||||||
|
|
||||||
struct EpStructMember {
|
struct EpStructMember {
|
||||||
name: String,
|
name: String,
|
||||||
ty: Handle<crate::Type>,
|
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)?;
|
self.write_wrapped_compose_functions(module, &module.const_expressions)?;
|
||||||
|
|
||||||
// Write all named constants
|
// Write all named constants
|
||||||
|
|
@ -416,7 +421,17 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
||||||
let builtin_str = builtin.to_hlsl_str()?;
|
let builtin_str = builtin.to_hlsl_str()?;
|
||||||
write!(self.out, " : {builtin_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)) {
|
if stage == Some((crate::ShaderStage::Fragment, Io::Output)) {
|
||||||
write!(self.out, " : SV_Target{location}")?;
|
write!(self.out, " : SV_Target{location}")?;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2665,8 +2680,8 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
||||||
Mf::Round => Function::Regular("round"),
|
Mf::Round => Function::Regular("round"),
|
||||||
Mf::Fract => Function::Regular("frac"),
|
Mf::Fract => Function::Regular("frac"),
|
||||||
Mf::Trunc => Function::Regular("trunc"),
|
Mf::Trunc => Function::Regular("trunc"),
|
||||||
Mf::Modf => Function::Regular("modf"),
|
Mf::Modf => Function::Regular(MODF_FUNCTION),
|
||||||
Mf::Frexp => Function::Regular("frexp"),
|
Mf::Frexp => Function::Regular(FREXP_FUNCTION),
|
||||||
Mf::Ldexp => Function::Regular("ldexp"),
|
Mf::Ldexp => Function::Regular("ldexp"),
|
||||||
// exponent
|
// exponent
|
||||||
Mf::Exp => Function::Regular("exp"),
|
Mf::Exp => Function::Regular("exp"),
|
||||||
|
|
|
||||||
|
|
@ -214,4 +214,6 @@ pub const RESERVED: &[&str] = &[
|
||||||
// Naga utilities
|
// Naga utilities
|
||||||
"DefaultConstructible",
|
"DefaultConstructible",
|
||||||
"clamped_lod_e",
|
"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 {
|
enum ResolvedBinding {
|
||||||
BuiltIn(crate::BuiltIn),
|
BuiltIn(crate::BuiltIn),
|
||||||
Attribute(u32),
|
Attribute(u32),
|
||||||
Color(u32),
|
Color {
|
||||||
|
location: u32,
|
||||||
|
second_blend_source: bool,
|
||||||
|
},
|
||||||
User {
|
User {
|
||||||
prefix: &'static str,
|
prefix: &'static str,
|
||||||
index: u32,
|
index: u32,
|
||||||
|
|
@ -245,9 +248,20 @@ impl Options {
|
||||||
location,
|
location,
|
||||||
interpolation,
|
interpolation,
|
||||||
sampling,
|
sampling,
|
||||||
|
second_blend_source,
|
||||||
} => match mode {
|
} => match mode {
|
||||||
LocationMode::VertexInput => Ok(ResolvedBinding::Attribute(location)),
|
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 => {
|
LocationMode::VertexOutput | LocationMode::FragmentInput => {
|
||||||
Ok(ResolvedBinding::User {
|
Ok(ResolvedBinding::User {
|
||||||
prefix: if self.spirv_cross_compatibility {
|
prefix: if self.spirv_cross_compatibility {
|
||||||
|
|
@ -404,7 +418,16 @@ impl ResolvedBinding {
|
||||||
write!(out, "{name}")?;
|
write!(out, "{name}")?;
|
||||||
}
|
}
|
||||||
Self::Attribute(index) => write!(out, "attribute({index})")?,
|
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 {
|
Self::User {
|
||||||
prefix,
|
prefix,
|
||||||
index,
|
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_FIELD_READY: &str = "ready";
|
||||||
const RAY_QUERY_FUN_MAP_INTERSECTION: &str = "_map_intersection_type";
|
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.
|
/// Write the Metal name for a Naga numeric type: scalar, vector, or matrix.
|
||||||
///
|
///
|
||||||
/// The `sizes` slice determines whether this function writes a
|
/// The `sizes` slice determines whether this function writes a
|
||||||
|
|
@ -1181,6 +1184,31 @@ impl<W: Write> Writer<W> {
|
||||||
Ok(())
|
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(
|
fn put_const_expression(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr_handle: Handle<crate::Expression>,
|
expr_handle: Handle<crate::Expression>,
|
||||||
|
|
@ -1644,8 +1672,9 @@ impl<W: Write> Writer<W> {
|
||||||
} => {
|
} => {
|
||||||
use crate::MathFunction as Mf;
|
use crate::MathFunction as Mf;
|
||||||
|
|
||||||
let scalar_argument = match *context.resolve_type(arg) {
|
let arg_type = context.resolve_type(arg);
|
||||||
crate::TypeInner::Scalar { .. } => true,
|
let scalar_argument = match arg_type {
|
||||||
|
&crate::TypeInner::Scalar { .. } => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1678,8 +1707,8 @@ impl<W: Write> Writer<W> {
|
||||||
Mf::Round => "rint",
|
Mf::Round => "rint",
|
||||||
Mf::Fract => "fract",
|
Mf::Fract => "fract",
|
||||||
Mf::Trunc => "trunc",
|
Mf::Trunc => "trunc",
|
||||||
Mf::Modf => "modf",
|
Mf::Modf => MODF_FUNCTION,
|
||||||
Mf::Frexp => "frexp",
|
Mf::Frexp => FREXP_FUNCTION,
|
||||||
Mf::Ldexp => "ldexp",
|
Mf::Ldexp => "ldexp",
|
||||||
// exponent
|
// exponent
|
||||||
Mf::Exp => "exp",
|
Mf::Exp => "exp",
|
||||||
|
|
@ -1710,7 +1739,12 @@ impl<W: Write> Writer<W> {
|
||||||
Mf::Reflect => "reflect",
|
Mf::Reflect => "reflect",
|
||||||
Mf::Refract => "refract",
|
Mf::Refract => "refract",
|
||||||
// computational
|
// 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::Fma => "fma",
|
||||||
Mf::Mix => "mix",
|
Mf::Mix => "mix",
|
||||||
Mf::Step => "step",
|
Mf::Step => "step",
|
||||||
|
|
@ -1813,6 +1847,9 @@ impl<W: Write> Writer<W> {
|
||||||
write!(self.out, "((")?;
|
write!(self.out, "((")?;
|
||||||
self.put_expression(arg, context, false)?;
|
self.put_expression(arg, context, false)?;
|
||||||
write!(self.out, ") * 57.295779513082322865)")?;
|
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 {
|
} else {
|
||||||
write!(self.out, "{NAMESPACE}::{fun_name}")?;
|
write!(self.out, "{NAMESPACE}::{fun_name}")?;
|
||||||
self.put_call_parameters(
|
self.put_call_parameters(
|
||||||
|
|
@ -2417,6 +2454,16 @@ impl<W: Write> Writer<W> {
|
||||||
crate::MathFunction::FindMsb => {
|
crate::MathFunction::FindMsb => {
|
||||||
self.need_bake_expressions.insert(arg);
|
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(())
|
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::Floor => MathOp::Ext(spirv::GLOp::Floor),
|
||||||
Mf::Fract => MathOp::Ext(spirv::GLOp::Fract),
|
Mf::Fract => MathOp::Ext(spirv::GLOp::Fract),
|
||||||
Mf::Trunc => MathOp::Ext(spirv::GLOp::Trunc),
|
Mf::Trunc => MathOp::Ext(spirv::GLOp::Trunc),
|
||||||
Mf::Modf => MathOp::Ext(spirv::GLOp::Modf),
|
Mf::Modf => MathOp::Ext(spirv::GLOp::ModfStruct),
|
||||||
Mf::Frexp => MathOp::Ext(spirv::GLOp::Frexp),
|
Mf::Frexp => MathOp::Ext(spirv::GLOp::FrexpStruct),
|
||||||
Mf::Ldexp => MathOp::Ext(spirv::GLOp::Ldexp),
|
Mf::Ldexp => MathOp::Ext(spirv::GLOp::Ldexp),
|
||||||
// geometry
|
// geometry
|
||||||
Mf::Dot => match *self.fun_info[arg].ty.inner_with(&self.ir_module.types) {
|
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,
|
location,
|
||||||
interpolation,
|
interpolation,
|
||||||
sampling,
|
sampling,
|
||||||
|
second_blend_source,
|
||||||
} => {
|
} => {
|
||||||
self.decorate(id, Decoration::Location, &[location]);
|
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) => {
|
crate::Binding::BuiltIn(built_in) => {
|
||||||
use crate::BuiltIn as Bi;
|
use crate::BuiltIn as Bi;
|
||||||
|
|
|
||||||
35
third_party/rust/naga/src/back/wgsl/writer.rs
vendored
35
third_party/rust/naga/src/back/wgsl/writer.rs
vendored
|
|
@ -17,6 +17,7 @@ enum Attribute {
|
||||||
Invariant,
|
Invariant,
|
||||||
Interpolate(Option<crate::Interpolation>, Option<crate::Sampling>),
|
Interpolate(Option<crate::Interpolation>, Option<crate::Sampling>),
|
||||||
Location(u32),
|
Location(u32),
|
||||||
|
SecondBlendSource,
|
||||||
Stage(ShaderStage),
|
Stage(ShaderStage),
|
||||||
WorkGroupSize([u32; 3]),
|
WorkGroupSize([u32; 3]),
|
||||||
}
|
}
|
||||||
|
|
@ -96,6 +97,14 @@ impl<W: Write> Writer<W> {
|
||||||
self.ep_results.clear();
|
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 {
|
pub fn write(&mut self, module: &Module, info: &valid::ModuleInfo) -> BackendResult {
|
||||||
self.reset(module);
|
self.reset(module);
|
||||||
|
|
||||||
|
|
@ -108,13 +117,13 @@ impl<W: Write> Writer<W> {
|
||||||
|
|
||||||
// Write all structs
|
// Write all structs
|
||||||
for (handle, ty) in module.types.iter() {
|
for (handle, ty) in module.types.iter() {
|
||||||
if let TypeInner::Struct {
|
if let TypeInner::Struct { ref members, .. } = ty.inner {
|
||||||
ref members,
|
{
|
||||||
span: _,
|
if !self.is_builtin_wgsl_struct(module, handle) {
|
||||||
} = ty.inner
|
self.write_struct(module, handle, members)?;
|
||||||
{
|
writeln!(self.out)?;
|
||||||
self.write_struct(module, handle, members)?;
|
}
|
||||||
writeln!(self.out)?;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -319,6 +328,7 @@ impl<W: Write> Writer<W> {
|
||||||
for attribute in attributes {
|
for attribute in attributes {
|
||||||
match *attribute {
|
match *attribute {
|
||||||
Attribute::Location(id) => write!(self.out, "@location({id}) ")?,
|
Attribute::Location(id) => write!(self.out, "@location({id}) ")?,
|
||||||
|
Attribute::SecondBlendSource => write!(self.out, "@second_blend_source ")?,
|
||||||
Attribute::BuiltIn(builtin_attrib) => {
|
Attribute::BuiltIn(builtin_attrib) => {
|
||||||
let builtin = builtin_str(builtin_attrib)?;
|
let builtin = builtin_str(builtin_attrib)?;
|
||||||
write!(self.out, "@builtin({builtin}) ")?;
|
write!(self.out, "@builtin({builtin}) ")?;
|
||||||
|
|
@ -1917,9 +1927,20 @@ fn map_binding_to_attribute(binding: &crate::Binding) -> Vec<Attribute> {
|
||||||
location,
|
location,
|
||||||
interpolation,
|
interpolation,
|
||||||
sampling,
|
sampling,
|
||||||
|
second_blend_source: false,
|
||||||
} => vec![
|
} => vec![
|
||||||
Attribute::Location(location),
|
Attribute::Location(location),
|
||||||
Attribute::Interpolate(interpolation, sampling),
|
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,
|
Error, ErrorKind, Frontend, Result,
|
||||||
};
|
};
|
||||||
use crate::{
|
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,
|
ImageClass, ImageDimension as Dim, ImageQuery, MathFunction, Module, RelationalFunction,
|
||||||
SampleLevel, ScalarKind as Sk, Span, Type, TypeInner, UnaryOperator, VectorSize,
|
SampleLevel, ScalarKind as Sk, Span, Type, TypeInner, UnaryOperator, VectorSize,
|
||||||
};
|
};
|
||||||
|
|
@ -1280,14 +1280,14 @@ fn inject_common_builtin(
|
||||||
0b10 => Some(VectorSize::Tri),
|
0b10 => Some(VectorSize::Tri),
|
||||||
_ => Some(VectorSize::Quad),
|
_ => Some(VectorSize::Quad),
|
||||||
};
|
};
|
||||||
let ty = || match size {
|
let ty = |kind| match size {
|
||||||
Some(size) => TypeInner::Vector {
|
Some(size) => TypeInner::Vector {
|
||||||
size,
|
size,
|
||||||
kind: Sk::Float,
|
kind,
|
||||||
width: float_width,
|
width: float_width,
|
||||||
},
|
},
|
||||||
None => TypeInner::Scalar {
|
None => TypeInner::Scalar {
|
||||||
kind: Sk::Float,
|
kind,
|
||||||
width: float_width,
|
width: float_width,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -1300,9 +1300,15 @@ fn inject_common_builtin(
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let second_kind = if fun == MacroCall::MathFunction(MathFunction::Ldexp) {
|
||||||
|
Sk::Sint
|
||||||
|
} else {
|
||||||
|
Sk::Float
|
||||||
|
};
|
||||||
|
|
||||||
declaration
|
declaration
|
||||||
.overloads
|
.overloads
|
||||||
.push(module.add_builtin(vec![ty(), ty()], fun))
|
.push(module.add_builtin(vec![ty(Sk::Float), ty(second_kind)], fun))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"transpose" => {
|
"transpose" => {
|
||||||
|
|
@ -1678,7 +1684,6 @@ impl MacroCall {
|
||||||
&self,
|
&self,
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
body: &mut Block,
|
|
||||||
args: &mut [Handle<Expression>],
|
args: &mut [Handle<Expression>],
|
||||||
meta: Span,
|
meta: Span,
|
||||||
) -> Result<Option<Handle<Expression>>> {
|
) -> Result<Option<Handle<Expression>>> {
|
||||||
|
|
@ -1688,14 +1693,8 @@ impl MacroCall {
|
||||||
args[0]
|
args[0]
|
||||||
}
|
}
|
||||||
MacroCall::SamplerShadow => {
|
MacroCall::SamplerShadow => {
|
||||||
sampled_to_depth(
|
sampled_to_depth(ctx, args[0], meta, &mut frontend.errors);
|
||||||
&mut frontend.module,
|
ctx.invalidate_expression(args[0], meta)?;
|
||||||
ctx,
|
|
||||||
args[0],
|
|
||||||
meta,
|
|
||||||
&mut frontend.errors,
|
|
||||||
);
|
|
||||||
frontend.invalidate_expression(ctx, args[0], meta)?;
|
|
||||||
ctx.samplers.insert(args[0], args[1]);
|
ctx.samplers.insert(args[0], args[1]);
|
||||||
args[0]
|
args[0]
|
||||||
}
|
}
|
||||||
|
|
@ -1708,7 +1707,7 @@ impl MacroCall {
|
||||||
let mut coords = args[1];
|
let mut coords = args[1];
|
||||||
|
|
||||||
if proj {
|
if proj {
|
||||||
let size = match *frontend.resolve_type(ctx, coords, meta)? {
|
let size = match *ctx.resolve_type(coords, meta)? {
|
||||||
TypeInner::Vector { size, .. } => size,
|
TypeInner::Vector { size, .. } => size,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
@ -1718,8 +1717,7 @@ impl MacroCall {
|
||||||
index: size as u32 - 1,
|
index: size as u32 - 1,
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?;
|
||||||
);
|
|
||||||
let left = if let VectorSize::Bi = size {
|
let left = if let VectorSize::Bi = size {
|
||||||
ctx.add_expression(
|
ctx.add_expression(
|
||||||
Expression::AccessIndex {
|
Expression::AccessIndex {
|
||||||
|
|
@ -1727,8 +1725,7 @@ impl MacroCall {
|
||||||
index: 0,
|
index: 0,
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
let size = match size {
|
let size = match size {
|
||||||
VectorSize::Tri => VectorSize::Bi,
|
VectorSize::Tri => VectorSize::Bi,
|
||||||
|
|
@ -1737,9 +1734,8 @@ impl MacroCall {
|
||||||
right = ctx.add_expression(
|
right = ctx.add_expression(
|
||||||
Expression::Splat { size, value: right },
|
Expression::Splat { size, value: right },
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?;
|
||||||
);
|
ctx.vector_resize(size, coords, Span::default())?
|
||||||
ctx.vector_resize(size, coords, Span::default(), body)
|
|
||||||
};
|
};
|
||||||
coords = ctx.add_expression(
|
coords = ctx.add_expression(
|
||||||
Expression::Binary {
|
Expression::Binary {
|
||||||
|
|
@ -1748,13 +1744,11 @@ impl MacroCall {
|
||||||
right,
|
right,
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?;
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let extra = args.get(2).copied();
|
let extra = args.get(2).copied();
|
||||||
let comps =
|
let comps = frontend.coordinate_components(ctx, args[0], coords, extra, meta)?;
|
||||||
frontend.coordinate_components(ctx, args[0], coords, extra, meta, body)?;
|
|
||||||
|
|
||||||
let mut num_args = 2;
|
let mut num_args = 2;
|
||||||
|
|
||||||
|
|
@ -1801,7 +1795,7 @@ impl MacroCall {
|
||||||
true => {
|
true => {
|
||||||
let offset_arg = args[num_args];
|
let offset_arg = args[num_args];
|
||||||
num_args += 1;
|
num_args += 1;
|
||||||
match frontend.solve_constant(ctx, offset_arg, meta) {
|
match ctx.solve_constant(offset_arg, meta) {
|
||||||
Ok(v) => Some(v),
|
Ok(v) => Some(v),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
frontend.errors.push(e);
|
frontend.errors.push(e);
|
||||||
|
|
@ -1820,7 +1814,7 @@ impl MacroCall {
|
||||||
.map_or(SampleLevel::Auto, SampleLevel::Bias);
|
.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 } => {
|
MacroCall::TextureSize { arrayed } => {
|
||||||
|
|
@ -1832,20 +1826,18 @@ impl MacroCall {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?;
|
||||||
);
|
|
||||||
|
|
||||||
if arrayed {
|
if arrayed {
|
||||||
let mut components = Vec::with_capacity(4);
|
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, .. } => {
|
TypeInner::Vector { size: ori_size, .. } => {
|
||||||
for index in 0..(ori_size as u32) {
|
for index in 0..(ori_size as u32) {
|
||||||
components.push(ctx.add_expression(
|
components.push(ctx.add_expression(
|
||||||
Expression::AccessIndex { base: expr, index },
|
Expression::AccessIndex { base: expr, index },
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?)
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match ori_size {
|
match ori_size {
|
||||||
|
|
@ -1865,10 +1857,9 @@ impl MacroCall {
|
||||||
query: ImageQuery::NumLayers,
|
query: ImageQuery::NumLayers,
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?);
|
||||||
));
|
|
||||||
|
|
||||||
let ty = frontend.module.types.insert(
|
let ty = ctx.module.types.insert(
|
||||||
Type {
|
Type {
|
||||||
name: None,
|
name: None,
|
||||||
inner: TypeInner::Vector {
|
inner: TypeInner::Vector {
|
||||||
|
|
@ -1880,7 +1871,7 @@ impl MacroCall {
|
||||||
Span::default(),
|
Span::default(),
|
||||||
);
|
);
|
||||||
|
|
||||||
expr = ctx.add_expression(Expression::Compose { components, ty }, meta, body)
|
expr = ctx.add_expression(Expression::Compose { components, ty }, meta)?
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.add_expression(
|
ctx.add_expression(
|
||||||
|
|
@ -1890,12 +1881,10 @@ impl MacroCall {
|
||||||
convert: Some(4),
|
convert: Some(4),
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?
|
||||||
)
|
|
||||||
}
|
}
|
||||||
MacroCall::ImageLoad { multi } => {
|
MacroCall::ImageLoad { multi } => {
|
||||||
let comps =
|
let comps = frontend.coordinate_components(ctx, args[0], args[1], None, meta)?;
|
||||||
frontend.coordinate_components(ctx, args[0], args[1], None, meta, body)?;
|
|
||||||
let (sample, level) = match (multi, args.get(2)) {
|
let (sample, level) = match (multi, args.get(2)) {
|
||||||
(_, None) => (None, None),
|
(_, None) => (None, None),
|
||||||
(true, Some(&arg)) => (Some(arg), None),
|
(true, Some(&arg)) => (Some(arg), None),
|
||||||
|
|
@ -1910,14 +1899,12 @@ impl MacroCall {
|
||||||
level,
|
level,
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?
|
||||||
)
|
|
||||||
}
|
}
|
||||||
MacroCall::ImageStore => {
|
MacroCall::ImageStore => {
|
||||||
let comps =
|
let comps = frontend.coordinate_components(ctx, args[0], args[1], None, meta)?;
|
||||||
frontend.coordinate_components(ctx, args[0], args[1], None, meta, body)?;
|
ctx.emit_restart();
|
||||||
ctx.emit_restart(body);
|
ctx.body.push(
|
||||||
body.push(
|
|
||||||
crate::Statement::ImageStore {
|
crate::Statement::ImageStore {
|
||||||
image: args[0],
|
image: args[0],
|
||||||
coordinate: comps.coordinate,
|
coordinate: comps.coordinate,
|
||||||
|
|
@ -1937,8 +1924,7 @@ impl MacroCall {
|
||||||
arg3: args.get(3).copied(),
|
arg3: args.get(3).copied(),
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?,
|
||||||
),
|
|
||||||
mc @ (MacroCall::FindLsbUint | MacroCall::FindMsbUint) => {
|
mc @ (MacroCall::FindLsbUint | MacroCall::FindMsbUint) => {
|
||||||
let fun = match mc {
|
let fun = match mc {
|
||||||
MacroCall::FindLsbUint => MathFunction::FindLsb,
|
MacroCall::FindLsbUint => MathFunction::FindLsb,
|
||||||
|
|
@ -1954,8 +1940,7 @@ impl MacroCall {
|
||||||
arg3: None,
|
arg3: None,
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?;
|
||||||
);
|
|
||||||
ctx.add_expression(
|
ctx.add_expression(
|
||||||
Expression::As {
|
Expression::As {
|
||||||
expr: res,
|
expr: res,
|
||||||
|
|
@ -1963,8 +1948,7 @@ impl MacroCall {
|
||||||
convert: Some(4),
|
convert: Some(4),
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?
|
||||||
)
|
|
||||||
}
|
}
|
||||||
MacroCall::BitfieldInsert => {
|
MacroCall::BitfieldInsert => {
|
||||||
let conv_arg_2 = ctx.add_expression(
|
let conv_arg_2 = ctx.add_expression(
|
||||||
|
|
@ -1974,8 +1958,7 @@ impl MacroCall {
|
||||||
convert: Some(4),
|
convert: Some(4),
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?;
|
||||||
);
|
|
||||||
let conv_arg_3 = ctx.add_expression(
|
let conv_arg_3 = ctx.add_expression(
|
||||||
Expression::As {
|
Expression::As {
|
||||||
expr: args[3],
|
expr: args[3],
|
||||||
|
|
@ -1983,8 +1966,7 @@ impl MacroCall {
|
||||||
convert: Some(4),
|
convert: Some(4),
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?;
|
||||||
);
|
|
||||||
ctx.add_expression(
|
ctx.add_expression(
|
||||||
Expression::Math {
|
Expression::Math {
|
||||||
fun: MathFunction::InsertBits,
|
fun: MathFunction::InsertBits,
|
||||||
|
|
@ -1994,8 +1976,7 @@ impl MacroCall {
|
||||||
arg3: Some(conv_arg_3),
|
arg3: Some(conv_arg_3),
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?
|
||||||
)
|
|
||||||
}
|
}
|
||||||
MacroCall::BitfieldExtract => {
|
MacroCall::BitfieldExtract => {
|
||||||
let conv_arg_1 = ctx.add_expression(
|
let conv_arg_1 = ctx.add_expression(
|
||||||
|
|
@ -2005,8 +1986,7 @@ impl MacroCall {
|
||||||
convert: Some(4),
|
convert: Some(4),
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?;
|
||||||
);
|
|
||||||
let conv_arg_2 = ctx.add_expression(
|
let conv_arg_2 = ctx.add_expression(
|
||||||
Expression::As {
|
Expression::As {
|
||||||
expr: args[2],
|
expr: args[2],
|
||||||
|
|
@ -2014,8 +1994,7 @@ impl MacroCall {
|
||||||
convert: Some(4),
|
convert: Some(4),
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?;
|
||||||
);
|
|
||||||
ctx.add_expression(
|
ctx.add_expression(
|
||||||
Expression::Math {
|
Expression::Math {
|
||||||
fun: MathFunction::ExtractBits,
|
fun: MathFunction::ExtractBits,
|
||||||
|
|
@ -2025,8 +2004,7 @@ impl MacroCall {
|
||||||
arg3: None,
|
arg3: None,
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?
|
||||||
)
|
|
||||||
}
|
}
|
||||||
MacroCall::Relational(fun) => ctx.add_expression(
|
MacroCall::Relational(fun) => ctx.add_expression(
|
||||||
Expression::Relational {
|
Expression::Relational {
|
||||||
|
|
@ -2034,13 +2012,10 @@ impl MacroCall {
|
||||||
argument: args[0],
|
argument: args[0],
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?,
|
||||||
),
|
MacroCall::Unary(op) => {
|
||||||
MacroCall::Unary(op) => ctx.add_expression(
|
ctx.add_expression(Expression::Unary { op, expr: args[0] }, Span::default())?
|
||||||
Expression::Unary { op, expr: args[0] },
|
}
|
||||||
Span::default(),
|
|
||||||
body,
|
|
||||||
),
|
|
||||||
MacroCall::Binary(op) => ctx.add_expression(
|
MacroCall::Binary(op) => ctx.add_expression(
|
||||||
Expression::Binary {
|
Expression::Binary {
|
||||||
op,
|
op,
|
||||||
|
|
@ -2048,10 +2023,9 @@ impl MacroCall {
|
||||||
right: args[1],
|
right: args[1],
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?,
|
||||||
),
|
|
||||||
MacroCall::Mod(size) => {
|
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)
|
// x - y * floor(x / y)
|
||||||
|
|
||||||
|
|
@ -2062,8 +2036,7 @@ impl MacroCall {
|
||||||
right: args[1],
|
right: args[1],
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?;
|
||||||
);
|
|
||||||
let floor = ctx.add_expression(
|
let floor = ctx.add_expression(
|
||||||
Expression::Math {
|
Expression::Math {
|
||||||
fun: MathFunction::Floor,
|
fun: MathFunction::Floor,
|
||||||
|
|
@ -2073,8 +2046,7 @@ impl MacroCall {
|
||||||
arg3: None,
|
arg3: None,
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?;
|
||||||
);
|
|
||||||
let mult = ctx.add_expression(
|
let mult = ctx.add_expression(
|
||||||
Expression::Binary {
|
Expression::Binary {
|
||||||
op: BinaryOperator::Multiply,
|
op: BinaryOperator::Multiply,
|
||||||
|
|
@ -2082,8 +2054,7 @@ impl MacroCall {
|
||||||
right: args[1],
|
right: args[1],
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?;
|
||||||
);
|
|
||||||
ctx.add_expression(
|
ctx.add_expression(
|
||||||
Expression::Binary {
|
Expression::Binary {
|
||||||
op: BinaryOperator::Subtract,
|
op: BinaryOperator::Subtract,
|
||||||
|
|
@ -2091,11 +2062,10 @@ impl MacroCall {
|
||||||
right: mult,
|
right: mult,
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?
|
||||||
)
|
|
||||||
}
|
}
|
||||||
MacroCall::Splatted(fun, size, i) => {
|
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(
|
ctx.add_expression(
|
||||||
Expression::Math {
|
Expression::Math {
|
||||||
|
|
@ -2106,8 +2076,7 @@ impl MacroCall {
|
||||||
arg3: args.get(3).copied(),
|
arg3: args.get(3).copied(),
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?
|
||||||
)
|
|
||||||
}
|
}
|
||||||
MacroCall::MixBoolean => ctx.add_expression(
|
MacroCall::MixBoolean => ctx.add_expression(
|
||||||
Expression::Select {
|
Expression::Select {
|
||||||
|
|
@ -2116,11 +2085,10 @@ impl MacroCall {
|
||||||
reject: args[0],
|
reject: args[0],
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?,
|
||||||
),
|
|
||||||
MacroCall::Clamp(size) => {
|
MacroCall::Clamp(size) => {
|
||||||
ctx.implicit_splat(frontend, &mut args[1], meta, size)?;
|
ctx.implicit_splat(&mut args[1], meta, size)?;
|
||||||
ctx.implicit_splat(frontend, &mut args[2], meta, size)?;
|
ctx.implicit_splat(&mut args[2], meta, size)?;
|
||||||
|
|
||||||
ctx.add_expression(
|
ctx.add_expression(
|
||||||
Expression::Math {
|
Expression::Math {
|
||||||
|
|
@ -2131,8 +2099,7 @@ impl MacroCall {
|
||||||
arg3: args.get(3).copied(),
|
arg3: args.get(3).copied(),
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?
|
||||||
)
|
|
||||||
}
|
}
|
||||||
MacroCall::BitCast(kind) => ctx.add_expression(
|
MacroCall::BitCast(kind) => ctx.add_expression(
|
||||||
Expression::As {
|
Expression::As {
|
||||||
|
|
@ -2141,8 +2108,7 @@ impl MacroCall {
|
||||||
convert: None,
|
convert: None,
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?,
|
||||||
),
|
|
||||||
MacroCall::Derivate(axis, ctrl) => ctx.add_expression(
|
MacroCall::Derivate(axis, ctrl) => ctx.add_expression(
|
||||||
Expression::Derivative {
|
Expression::Derivative {
|
||||||
axis,
|
axis,
|
||||||
|
|
@ -2150,16 +2116,16 @@ impl MacroCall {
|
||||||
expr: args[0],
|
expr: args[0],
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?,
|
||||||
),
|
|
||||||
MacroCall::Barrier => {
|
MacroCall::Barrier => {
|
||||||
ctx.emit_restart(body);
|
ctx.emit_restart();
|
||||||
body.push(crate::Statement::Barrier(crate::Barrier::all()), meta);
|
ctx.body
|
||||||
|
.push(crate::Statement::Barrier(crate::Barrier::all()), meta);
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
MacroCall::SmoothStep { splatted } => {
|
MacroCall::SmoothStep { splatted } => {
|
||||||
ctx.implicit_splat(frontend, &mut args[0], meta, splatted)?;
|
ctx.implicit_splat(&mut args[0], meta, splatted)?;
|
||||||
ctx.implicit_splat(frontend, &mut args[1], meta, splatted)?;
|
ctx.implicit_splat(&mut args[1], meta, splatted)?;
|
||||||
|
|
||||||
ctx.add_expression(
|
ctx.add_expression(
|
||||||
Expression::Math {
|
Expression::Math {
|
||||||
|
|
@ -2170,8 +2136,7 @@ impl MacroCall {
|
||||||
arg3: None,
|
arg3: None,
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
@ -2183,7 +2148,6 @@ fn texture_call(
|
||||||
level: SampleLevel,
|
level: SampleLevel,
|
||||||
comps: CoordComponents,
|
comps: CoordComponents,
|
||||||
offset: Option<Handle<Expression>>,
|
offset: Option<Handle<Expression>>,
|
||||||
body: &mut Block,
|
|
||||||
meta: Span,
|
meta: Span,
|
||||||
) -> Result<Handle<Expression>> {
|
) -> Result<Handle<Expression>> {
|
||||||
if let Some(sampler) = ctx.samplers.get(&image).copied() {
|
if let Some(sampler) = ctx.samplers.get(&image).copied() {
|
||||||
|
|
@ -2205,8 +2169,7 @@ fn texture_call(
|
||||||
depth_ref: comps.depth_ref,
|
depth_ref: comps.depth_ref,
|
||||||
},
|
},
|
||||||
meta,
|
meta,
|
||||||
body,
|
)?)
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
Err(Error {
|
Err(Error {
|
||||||
kind: ErrorKind::SemanticError("Bad call".into()),
|
kind: ErrorKind::SemanticError("Bad call".into()),
|
||||||
|
|
@ -2235,13 +2198,12 @@ impl Frontend {
|
||||||
coord: Handle<Expression>,
|
coord: Handle<Expression>,
|
||||||
extra: Option<Handle<Expression>>,
|
extra: Option<Handle<Expression>>,
|
||||||
meta: Span,
|
meta: Span,
|
||||||
body: &mut Block,
|
|
||||||
) -> Result<CoordComponents> {
|
) -> Result<CoordComponents> {
|
||||||
if let TypeInner::Image {
|
if let TypeInner::Image {
|
||||||
dim,
|
dim,
|
||||||
arrayed,
|
arrayed,
|
||||||
class,
|
class,
|
||||||
} = *self.resolve_type(ctx, image, meta)?
|
} = *ctx.resolve_type(image, meta)?
|
||||||
{
|
{
|
||||||
let image_size = match dim {
|
let image_size = match dim {
|
||||||
Dim::D1 => None,
|
Dim::D1 => None,
|
||||||
|
|
@ -2249,7 +2211,7 @@ impl Frontend {
|
||||||
Dim::D3 => Some(VectorSize::Tri),
|
Dim::D3 => Some(VectorSize::Tri),
|
||||||
Dim::Cube => 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),
|
TypeInner::Vector { size, .. } => Some(size),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
@ -2261,7 +2223,7 @@ impl Frontend {
|
||||||
|
|
||||||
let coordinate = match (image_size, coord_size) {
|
let coordinate = match (image_size, coord_size) {
|
||||||
(Some(size), Some(coord_s)) if size != coord_s => {
|
(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(
|
(None, Some(_)) => ctx.add_expression(
|
||||||
Expression::AccessIndex {
|
Expression::AccessIndex {
|
||||||
|
|
@ -2269,8 +2231,7 @@ impl Frontend {
|
||||||
index: 0,
|
index: 0,
|
||||||
},
|
},
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?,
|
||||||
),
|
|
||||||
_ => coord,
|
_ => coord,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -2283,8 +2244,7 @@ impl Frontend {
|
||||||
Some(ctx.add_expression(
|
Some(ctx.add_expression(
|
||||||
Expression::AccessIndex { base: coord, index },
|
Expression::AccessIndex { base: coord, index },
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?)
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
@ -2300,8 +2260,7 @@ impl Frontend {
|
||||||
Some(ctx.add_expression(
|
Some(ctx.add_expression(
|
||||||
Expression::AccessIndex { base: coord, index },
|
Expression::AccessIndex { base: coord, index },
|
||||||
Span::default(),
|
Span::default(),
|
||||||
body,
|
)?)
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
false => None,
|
false => None,
|
||||||
|
|
@ -2332,7 +2291,6 @@ impl Frontend {
|
||||||
/// Helper function to cast a expression holding a sampled image to a
|
/// Helper function to cast a expression holding a sampled image to a
|
||||||
/// depth image.
|
/// depth image.
|
||||||
pub fn sampled_to_depth(
|
pub fn sampled_to_depth(
|
||||||
module: &mut Module,
|
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
image: Handle<Expression>,
|
image: Handle<Expression>,
|
||||||
meta: Span,
|
meta: Span,
|
||||||
|
|
@ -2340,7 +2298,7 @@ pub fn sampled_to_depth(
|
||||||
) {
|
) {
|
||||||
// Get the a mutable type handle of the underlying image storage
|
// Get the a mutable type handle of the underlying image storage
|
||||||
let ty = match ctx[image] {
|
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) => {
|
Expression::FunctionArgument(i) => {
|
||||||
// Mark the function argument as carrying a depth texture
|
// Mark the function argument as carrying a depth texture
|
||||||
ctx.parameters_info[i as usize].depth = true;
|
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
|
// Update the image class to depth in case it already isn't
|
||||||
TypeInner::Image {
|
TypeInner::Image {
|
||||||
class,
|
class,
|
||||||
|
|
@ -2364,7 +2322,7 @@ pub fn sampled_to_depth(
|
||||||
arrayed,
|
arrayed,
|
||||||
} => match class {
|
} => match class {
|
||||||
ImageClass::Sampled { multi, .. } => {
|
ImageClass::Sampled { multi, .. } => {
|
||||||
*ty = module.types.insert(
|
*ty = ctx.module.types.insert(
|
||||||
Type {
|
Type {
|
||||||
name: None,
|
name: None,
|
||||||
inner: TypeInner::Image {
|
inner: TypeInner::Image {
|
||||||
|
|
|
||||||
626
third_party/rust/naga/src/front/glsl/context.rs
vendored
626
third_party/rust/naga/src/front/glsl/context.rs
vendored
File diff suppressed because it is too large
Load diff
682
third_party/rust/naga/src/front/glsl/functions.rs
vendored
682
third_party/rust/naga/src/front/glsl/functions.rs
vendored
File diff suppressed because it is too large
Load diff
26
third_party/rust/naga/src/front/glsl/mod.rs
vendored
26
third_party/rust/naga/src/front/glsl/mod.rs
vendored
|
|
@ -175,8 +175,6 @@ pub struct Frontend {
|
||||||
layouter: Layouter,
|
layouter: Layouter,
|
||||||
|
|
||||||
errors: Vec<Error>,
|
errors: Vec<Error>,
|
||||||
|
|
||||||
module: Module,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Frontend {
|
impl Frontend {
|
||||||
|
|
@ -188,10 +186,6 @@ impl Frontend {
|
||||||
self.global_variables.clear();
|
self.global_variables.clear();
|
||||||
self.entry_args.clear();
|
self.entry_args.clear();
|
||||||
self.layouter.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
|
/// Parses a shader either outputting a shader [`Module`](Module) or a list
|
||||||
|
|
@ -208,14 +202,18 @@ impl Frontend {
|
||||||
let lexer = lex::Lexer::new(source, &options.defines);
|
let lexer = lex::Lexer::new(source, &options.defines);
|
||||||
let mut ctx = ParsingContext::new(lexer);
|
let mut ctx = ParsingContext::new(lexer);
|
||||||
|
|
||||||
if let Err(e) = ctx.parse(self) {
|
match ctx.parse(self) {
|
||||||
self.errors.push(e);
|
Ok(module) => {
|
||||||
}
|
if self.errors.is_empty() {
|
||||||
|
Ok(module)
|
||||||
if self.errors.is_empty() {
|
} else {
|
||||||
Ok(std::mem::take(&mut self.module))
|
Err(std::mem::take(&mut self.errors))
|
||||||
} else {
|
}
|
||||||
Err(std::mem::take(&mut self.errors))
|
}
|
||||||
|
Err(e) => {
|
||||||
|
self.errors.push(e);
|
||||||
|
Err(std::mem::take(&mut self.errors))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
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},
|
variables::{GlobalOrConstant, VarDeclaration},
|
||||||
Frontend, Result,
|
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 pp_rs::token::{PreprocessorError, Token as PPToken, TokenValue as PPTokenValue};
|
||||||
use std::iter::Peekable;
|
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
|
// Body and expression arena for global initialization
|
||||||
let mut body = Block::new();
|
let mut ctx = Context::new(frontend, &mut module)?;
|
||||||
let mut ctx = Context::new(frontend, &mut body);
|
|
||||||
|
|
||||||
while self.peek(frontend).is_some() {
|
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
|
// Add an `EntryPoint` to `parser.module` for `main`, if a
|
||||||
|
|
@ -177,8 +178,8 @@ impl<'source> ParsingContext<'source> {
|
||||||
for decl in declaration.overloads.iter() {
|
for decl in declaration.overloads.iter() {
|
||||||
if let FunctionKind::Call(handle) = decl.kind {
|
if let FunctionKind::Call(handle) = decl.kind {
|
||||||
if decl.defined && decl.parameters.is_empty() {
|
if decl.defined && decl.parameters.is_empty() {
|
||||||
frontend.add_entry_point(handle, body, ctx.expressions);
|
frontend.add_entry_point(handle, ctx)?;
|
||||||
return Ok(());
|
return Ok(module);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -190,10 +191,14 @@ impl<'source> ParsingContext<'source> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_uint_constant(&mut self, frontend: &mut Frontend) -> Result<(u32, Span)> {
|
fn parse_uint_constant(
|
||||||
let (const_expr, meta) = self.parse_constant_expression(frontend)?;
|
&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 {
|
let int = match res {
|
||||||
Ok(value) => Ok(value),
|
Ok(value) => Ok(value),
|
||||||
|
|
@ -213,16 +218,15 @@ impl<'source> ParsingContext<'source> {
|
||||||
fn parse_constant_expression(
|
fn parse_constant_expression(
|
||||||
&mut self,
|
&mut self,
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
|
module: &mut Module,
|
||||||
) -> Result<(Handle<Expression>, Span)> {
|
) -> Result<(Handle<Expression>, Span)> {
|
||||||
let mut block = Block::new();
|
let mut ctx = Context::new(frontend, module)?;
|
||||||
|
|
||||||
let mut ctx = Context::new(frontend, &mut block);
|
|
||||||
|
|
||||||
let mut stmt_ctx = ctx.stmt_ctx();
|
let mut stmt_ctx = ctx.stmt_ctx();
|
||||||
let expr = self.parse_conditional(frontend, &mut ctx, &mut stmt_ctx, &mut block, None)?;
|
let expr = self.parse_conditional(frontend, &mut ctx, &mut stmt_ctx, None)?;
|
||||||
let (root, meta) = ctx.lower_expect(stmt_ctx, frontend, expr, ExprPos::Rhs, &mut block)?;
|
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>,
|
qualifiers: TypeQualifiers<'qualifiers>,
|
||||||
/// Indicates a global declaration
|
/// Indicates a global declaration
|
||||||
external: bool,
|
external: bool,
|
||||||
|
ctx: &'ctx mut Context<'a>,
|
||||||
ctx: &'ctx mut Context,
|
|
||||||
body: &'ctx mut Block,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx, 'qualifiers> DeclarationContext<'ctx, 'qualifiers> {
|
impl<'ctx, 'qualifiers, 'a> DeclarationContext<'ctx, 'qualifiers, 'a> {
|
||||||
fn add_var(
|
fn add_var(
|
||||||
&mut self,
|
&mut self,
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
|
|
@ -415,24 +417,14 @@ impl<'ctx, 'qualifiers> DeclarationContext<'ctx, 'qualifiers> {
|
||||||
|
|
||||||
match self.external {
|
match self.external {
|
||||||
true => {
|
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 {
|
let expr = match global {
|
||||||
GlobalOrConstant::Global(handle) => Expression::GlobalVariable(handle),
|
GlobalOrConstant::Global(handle) => Expression::GlobalVariable(handle),
|
||||||
GlobalOrConstant::Constant(handle) => Expression::Constant(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,
|
Error, ErrorKind, Frontend, Span,
|
||||||
},
|
},
|
||||||
proc::Alignment,
|
proc::Alignment,
|
||||||
AddressSpace, Block, Expression, FunctionResult, Handle, ScalarKind, Statement, StructMember,
|
AddressSpace, Expression, FunctionResult, Handle, ScalarKind, Statement, StructMember, Type,
|
||||||
Type, TypeInner,
|
TypeInner,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{DeclarationContext, ParsingContext, Result};
|
use super::{DeclarationContext, ParsingContext, Result};
|
||||||
|
|
@ -73,10 +73,9 @@ impl<'source> ParsingContext<'source> {
|
||||||
&mut self,
|
&mut self,
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
global_ctx: &mut Context,
|
global_ctx: &mut Context,
|
||||||
global_body: &mut Block,
|
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if self
|
if self
|
||||||
.parse_declaration(frontend, global_ctx, global_body, true)?
|
.parse_declaration(frontend, global_ctx, true)?
|
||||||
.is_none()
|
.is_none()
|
||||||
{
|
{
|
||||||
let token = self.bump(frontend)?;
|
let token = self.bump(frontend)?;
|
||||||
|
|
@ -103,7 +102,6 @@ impl<'source> ParsingContext<'source> {
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
ty: Handle<Type>,
|
ty: Handle<Type>,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
body: &mut Block,
|
|
||||||
) -> Result<(Handle<Expression>, Span)> {
|
) -> Result<(Handle<Expression>, Span)> {
|
||||||
// initializer:
|
// initializer:
|
||||||
// assignment_expression
|
// assignment_expression
|
||||||
|
|
@ -118,10 +116,9 @@ impl<'source> ParsingContext<'source> {
|
||||||
let mut components = Vec::new();
|
let mut components = Vec::new();
|
||||||
loop {
|
loop {
|
||||||
// The type expected to be parsed inside the initializer list
|
// The type expected to be parsed inside the initializer list
|
||||||
let new_ty =
|
let new_ty = element_or_member_type(ty, components.len(), &mut ctx.module.types);
|
||||||
element_or_member_type(ty, components.len(), &mut frontend.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)?;
|
let token = self.bump(frontend)?;
|
||||||
match token.value {
|
match token.value {
|
||||||
|
|
@ -150,18 +147,17 @@ impl<'source> ParsingContext<'source> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
ctx.add_expression(Expression::Compose { ty, components }, meta, body),
|
ctx.add_expression(Expression::Compose { ty, components }, meta)?,
|
||||||
meta,
|
meta,
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
let mut stmt = ctx.stmt_ctx();
|
let mut stmt = ctx.stmt_ctx();
|
||||||
let expr = self.parse_assignment(frontend, ctx, &mut stmt, body)?;
|
let expr = self.parse_assignment(frontend, ctx, &mut stmt)?;
|
||||||
let (mut init, init_meta) =
|
let (mut init, init_meta) = ctx.lower_expect(stmt, frontend, expr, ExprPos::Rhs)?;
|
||||||
ctx.lower_expect(stmt, frontend, expr, ExprPos::Rhs, body)?;
|
|
||||||
|
|
||||||
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 {
|
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))
|
Ok((init, init_meta))
|
||||||
|
|
@ -223,18 +219,17 @@ impl<'source> ParsingContext<'source> {
|
||||||
// parse an array specifier if it exists
|
// parse an array specifier if it exists
|
||||||
// NOTE: unlike other parse methods this one doesn't expect an array specifier and
|
// 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
|
// 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
|
let init = self
|
||||||
.bump_if(frontend, TokenValue::Assign)
|
.bump_if(frontend, TokenValue::Assign)
|
||||||
.map::<Result<_>, _>(|_| {
|
.map::<Result<_>, _>(|_| {
|
||||||
let (mut expr, init_meta) =
|
let (mut expr, init_meta) = self.parse_initializer(frontend, ty, ctx.ctx)?;
|
||||||
self.parse_initializer(frontend, ty, ctx.ctx, ctx.body)?;
|
|
||||||
|
|
||||||
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 {
|
if let Some((kind, width)) = scalar_components {
|
||||||
ctx.ctx
|
ctx.ctx
|
||||||
.implicit_conversion(frontend, &mut expr, init_meta, kind, width)?;
|
.implicit_conversion(&mut expr, init_meta, kind, width)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
meta.subsume(init_meta);
|
meta.subsume(init_meta);
|
||||||
|
|
@ -246,7 +241,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
let is_const = ctx.qualifiers.storage.0 == StorageQualifier::Const;
|
let is_const = ctx.qualifiers.storage.0 == StorageQualifier::Const;
|
||||||
let maybe_const_expr = if ctx.external {
|
let maybe_const_expr = if ctx.external {
|
||||||
if let Some((root, meta)) = init {
|
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),
|
Ok(res) => Some(res),
|
||||||
// If the declaration is external (global scope) and is constant qualified
|
// If the declaration is external (global scope) and is constant qualified
|
||||||
// then the initializer must be a constant expression
|
// 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)?;
|
let pointer = ctx.add_var(frontend, ty, name, maybe_const_expr, meta)?;
|
||||||
|
|
||||||
if let Some((value, _)) = init.filter(|_| maybe_const_expr.is_none()) {
|
if let Some((value, _)) = init.filter(|_| maybe_const_expr.is_none()) {
|
||||||
ctx.flush_expressions();
|
ctx.ctx.emit_restart();
|
||||||
ctx.body.push(Statement::Store { pointer, value }, meta);
|
ctx.ctx.body.push(Statement::Store { pointer, value }, meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
let token = self.bump(frontend)?;
|
let token = self.bump(frontend)?;
|
||||||
|
|
@ -291,7 +286,6 @@ impl<'source> ParsingContext<'source> {
|
||||||
&mut self,
|
&mut self,
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
body: &mut Block,
|
|
||||||
external: bool,
|
external: bool,
|
||||||
) -> Result<Option<Span>> {
|
) -> Result<Option<Span>> {
|
||||||
//declaration:
|
//declaration:
|
||||||
|
|
@ -307,12 +301,12 @@ impl<'source> ParsingContext<'source> {
|
||||||
// type_qualifier IDENTIFIER identifier_list SEMICOLON
|
// type_qualifier IDENTIFIER identifier_list SEMICOLON
|
||||||
|
|
||||||
if self.peek_type_qualifier(frontend) || self.peek_type_name(frontend) {
|
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) {
|
if self.peek_type_name(frontend) {
|
||||||
// This branch handles variables and function prototypes and if
|
// This branch handles variables and function prototypes and if
|
||||||
// external is true also function definitions
|
// 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 = self.bump(frontend)?;
|
||||||
let token_fallthrough = match token.value {
|
let token_fallthrough = match token.value {
|
||||||
|
|
@ -322,11 +316,10 @@ impl<'source> ParsingContext<'source> {
|
||||||
self.bump(frontend)?;
|
self.bump(frontend)?;
|
||||||
|
|
||||||
let result = ty.map(|ty| FunctionResult { ty, binding: None });
|
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;
|
let end_meta = self.expect(frontend, TokenValue::RightParen)?.meta;
|
||||||
meta.subsume(end_meta);
|
meta.subsume(end_meta);
|
||||||
|
|
@ -349,11 +342,10 @@ impl<'source> ParsingContext<'source> {
|
||||||
token.meta,
|
token.meta,
|
||||||
frontend,
|
frontend,
|
||||||
&mut context,
|
&mut context,
|
||||||
&mut body,
|
|
||||||
&mut None,
|
&mut None,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
frontend.add_function(context, name, result, body, meta);
|
frontend.add_function(context, name, result, meta);
|
||||||
|
|
||||||
Ok(Some(meta))
|
Ok(Some(meta))
|
||||||
}
|
}
|
||||||
|
|
@ -394,7 +386,6 @@ impl<'source> ParsingContext<'source> {
|
||||||
qualifiers,
|
qualifiers,
|
||||||
external,
|
external,
|
||||||
ctx,
|
ctx,
|
||||||
body,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.backtrack(token_fallthrough)?;
|
self.backtrack(token_fallthrough)?;
|
||||||
|
|
@ -419,7 +410,6 @@ impl<'source> ParsingContext<'source> {
|
||||||
self.parse_block_declaration(
|
self.parse_block_declaration(
|
||||||
frontend,
|
frontend,
|
||||||
ctx,
|
ctx,
|
||||||
body,
|
|
||||||
&mut qualifiers,
|
&mut qualifiers,
|
||||||
ty_name,
|
ty_name,
|
||||||
token.meta,
|
token.meta,
|
||||||
|
|
@ -427,7 +417,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
.map(Some)
|
.map(Some)
|
||||||
} else {
|
} else {
|
||||||
if qualifiers.invariant.take().is_some() {
|
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);
|
qualifiers.unused_errors(&mut frontend.errors);
|
||||||
self.expect(frontend, TokenValue::Semicolon)?;
|
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 {
|
TypeInner::Scalar {
|
||||||
kind: ScalarKind::Float | ScalarKind::Sint,
|
kind: ScalarKind::Float | ScalarKind::Sint,
|
||||||
..
|
..
|
||||||
|
|
@ -528,7 +518,6 @@ impl<'source> ParsingContext<'source> {
|
||||||
&mut self,
|
&mut self,
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
body: &mut Block,
|
|
||||||
qualifiers: &mut TypeQualifiers,
|
qualifiers: &mut TypeQualifiers,
|
||||||
ty_name: String,
|
ty_name: String,
|
||||||
mut meta: Span,
|
mut meta: Span,
|
||||||
|
|
@ -548,10 +537,10 @@ impl<'source> ParsingContext<'source> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut members = Vec::new();
|
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)?;
|
self.expect(frontend, TokenValue::RightBrace)?;
|
||||||
|
|
||||||
let mut ty = frontend.module.types.insert(
|
let mut ty = ctx.module.types.insert(
|
||||||
Type {
|
Type {
|
||||||
name: Some(ty_name),
|
name: Some(ty_name),
|
||||||
inner: TypeInner::Struct {
|
inner: TypeInner::Struct {
|
||||||
|
|
@ -566,7 +555,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
let name = match token.value {
|
let name = match token.value {
|
||||||
TokenValue::Semicolon => None,
|
TokenValue::Semicolon => None,
|
||||||
TokenValue::Identifier(name) => {
|
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)?;
|
self.expect(frontend, TokenValue::Semicolon)?;
|
||||||
|
|
||||||
|
|
@ -585,7 +574,6 @@ impl<'source> ParsingContext<'source> {
|
||||||
|
|
||||||
let global = frontend.add_global_var(
|
let global = frontend.add_global_var(
|
||||||
ctx,
|
ctx,
|
||||||
body,
|
|
||||||
VarDeclaration {
|
VarDeclaration {
|
||||||
qualifiers,
|
qualifiers,
|
||||||
ty,
|
ty,
|
||||||
|
|
@ -607,7 +595,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
entry_arg: None,
|
entry_arg: None,
|
||||||
mutable: true,
|
mutable: true,
|
||||||
};
|
};
|
||||||
ctx.add_global(frontend, &k, lookup, body);
|
ctx.add_global(&k, lookup)?;
|
||||||
|
|
||||||
frontend.global_variables.push((k, lookup));
|
frontend.global_variables.push((k, lookup));
|
||||||
}
|
}
|
||||||
|
|
@ -619,6 +607,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
pub fn parse_struct_declaration_list(
|
pub fn parse_struct_declaration_list(
|
||||||
&mut self,
|
&mut self,
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
|
ctx: &mut Context,
|
||||||
members: &mut Vec<StructMember>,
|
members: &mut Vec<StructMember>,
|
||||||
layout: StructLayout,
|
layout: StructLayout,
|
||||||
) -> Result<u32> {
|
) -> Result<u32> {
|
||||||
|
|
@ -628,12 +617,12 @@ impl<'source> ParsingContext<'source> {
|
||||||
loop {
|
loop {
|
||||||
// TODO: type_qualifier
|
// 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 {
|
loop {
|
||||||
let (name, name_meta) = self.expect_ident(frontend)?;
|
let (name, name_meta) = self.expect_ident(frontend)?;
|
||||||
let mut ty = base_ty;
|
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);
|
meta.subsume(name_meta);
|
||||||
|
|
||||||
|
|
@ -641,7 +630,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
ty,
|
ty,
|
||||||
meta,
|
meta,
|
||||||
layout,
|
layout,
|
||||||
&mut frontend.module.types,
|
&mut ctx.module.types,
|
||||||
&mut frontend.errors,
|
&mut frontend.errors,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use crate::{
|
||||||
token::{Token, TokenValue},
|
token::{Token, TokenValue},
|
||||||
Error, Frontend, Result, Span,
|
Error, Frontend, Result, Span,
|
||||||
},
|
},
|
||||||
ArraySize, BinaryOperator, Block, Handle, Literal, Type, TypeInner, UnaryOperator,
|
ArraySize, BinaryOperator, Handle, Literal, Type, TypeInner, UnaryOperator,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<'source> ParsingContext<'source> {
|
impl<'source> ParsingContext<'source> {
|
||||||
|
|
@ -18,7 +18,6 @@ impl<'source> ParsingContext<'source> {
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
stmt: &mut StmtContext,
|
stmt: &mut StmtContext,
|
||||||
body: &mut Block,
|
|
||||||
) -> Result<Handle<HirExpr>> {
|
) -> Result<Handle<HirExpr>> {
|
||||||
let mut token = self.bump(frontend)?;
|
let mut token = self.bump(frontend)?;
|
||||||
|
|
||||||
|
|
@ -47,7 +46,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
}
|
}
|
||||||
TokenValue::BoolConstant(value) => Literal::Bool(value),
|
TokenValue::BoolConstant(value) => Literal::Bool(value),
|
||||||
TokenValue::LeftParen => {
|
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;
|
let meta = self.expect(frontend, TokenValue::RightParen)?.meta;
|
||||||
|
|
||||||
token.meta.subsume(meta);
|
token.meta.subsume(meta);
|
||||||
|
|
@ -84,7 +83,6 @@ impl<'source> ParsingContext<'source> {
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
stmt: &mut StmtContext,
|
stmt: &mut StmtContext,
|
||||||
body: &mut Block,
|
|
||||||
meta: &mut Span,
|
meta: &mut Span,
|
||||||
) -> Result<Vec<Handle<HirExpr>>> {
|
) -> Result<Vec<Handle<HirExpr>>> {
|
||||||
let mut args = Vec::new();
|
let mut args = Vec::new();
|
||||||
|
|
@ -92,7 +90,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
meta.subsume(token.meta);
|
meta.subsume(token.meta);
|
||||||
} else {
|
} else {
|
||||||
loop {
|
loop {
|
||||||
args.push(self.parse_assignment(frontend, ctx, stmt, body)?);
|
args.push(self.parse_assignment(frontend, ctx, stmt)?);
|
||||||
|
|
||||||
let token = self.bump(frontend)?;
|
let token = self.bump(frontend)?;
|
||||||
match token.value {
|
match token.value {
|
||||||
|
|
@ -122,21 +120,20 @@ impl<'source> ParsingContext<'source> {
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
stmt: &mut StmtContext,
|
stmt: &mut StmtContext,
|
||||||
body: &mut Block,
|
|
||||||
) -> Result<Handle<HirExpr>> {
|
) -> Result<Handle<HirExpr>> {
|
||||||
let mut base = if self.peek_type_name(frontend) {
|
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)?;
|
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 {
|
if let TypeInner::Array {
|
||||||
size: ArraySize::Dynamic,
|
size: ArraySize::Dynamic,
|
||||||
stride,
|
stride,
|
||||||
base,
|
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())
|
let size = u32::try_from(args.len())
|
||||||
.ok()
|
.ok()
|
||||||
|
|
@ -148,7 +145,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
meta,
|
meta,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
handle = frontend.module.types.insert(
|
handle = ctx.module.types.insert(
|
||||||
Type {
|
Type {
|
||||||
name: None,
|
name: None,
|
||||||
inner: TypeInner::Array {
|
inner: TypeInner::Array {
|
||||||
|
|
@ -175,7 +172,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
let (name, mut meta) = self.expect_ident(frontend)?;
|
let (name, mut meta) = self.expect_ident(frontend)?;
|
||||||
|
|
||||||
let expr = if self.bump_if(frontend, TokenValue::LeftParen).is_some() {
|
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) {
|
let kind = match frontend.lookup_type.get(&name) {
|
||||||
Some(ty) => FunctionCallKind::TypeConstructor(*ty),
|
Some(ty) => FunctionCallKind::TypeConstructor(*ty),
|
||||||
|
|
@ -187,7 +184,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
meta,
|
meta,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let var = match frontend.lookup_variable(ctx, body, &name, meta) {
|
let var = match frontend.lookup_variable(ctx, &name, meta)? {
|
||||||
Some(var) => var,
|
Some(var) => var,
|
||||||
None => {
|
None => {
|
||||||
return Err(Error {
|
return Err(Error {
|
||||||
|
|
@ -205,7 +202,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
|
|
||||||
stmt.hir_exprs.append(expr, Default::default())
|
stmt.hir_exprs.append(expr, Default::default())
|
||||||
} else {
|
} else {
|
||||||
self.parse_primary(frontend, ctx, stmt, body)?
|
self.parse_primary(frontend, ctx, stmt)?
|
||||||
};
|
};
|
||||||
|
|
||||||
while let TokenValue::LeftBracket
|
while let TokenValue::LeftBracket
|
||||||
|
|
@ -217,7 +214,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
|
|
||||||
match value {
|
match value {
|
||||||
TokenValue::LeftBracket => {
|
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;
|
let end_meta = self.expect(frontend, TokenValue::RightBracket)?.meta;
|
||||||
|
|
||||||
meta.subsume(end_meta);
|
meta.subsume(end_meta);
|
||||||
|
|
@ -233,8 +230,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
let (field, end_meta) = self.expect_ident(frontend)?;
|
let (field, end_meta) = self.expect_ident(frontend)?;
|
||||||
|
|
||||||
if self.bump_if(frontend, TokenValue::LeftParen).is_some() {
|
if self.bump_if(frontend, TokenValue::LeftParen).is_some() {
|
||||||
let args =
|
let args = self.parse_function_call_args(frontend, ctx, stmt, &mut meta)?;
|
||||||
self.parse_function_call_args(frontend, ctx, stmt, body, &mut meta)?;
|
|
||||||
|
|
||||||
base = stmt.hir_exprs.append(
|
base = stmt.hir_exprs.append(
|
||||||
HirExpr {
|
HirExpr {
|
||||||
|
|
@ -287,13 +283,12 @@ impl<'source> ParsingContext<'source> {
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
stmt: &mut StmtContext,
|
stmt: &mut StmtContext,
|
||||||
body: &mut Block,
|
|
||||||
) -> Result<Handle<HirExpr>> {
|
) -> Result<Handle<HirExpr>> {
|
||||||
Ok(match self.expect_peek(frontend)?.value {
|
Ok(match self.expect_peek(frontend)?.value {
|
||||||
TokenValue::Plus | TokenValue::Dash | TokenValue::Bang | TokenValue::Tilde => {
|
TokenValue::Plus | TokenValue::Dash | TokenValue::Bang | TokenValue::Tilde => {
|
||||||
let Token { value, mut meta } = self.bump(frontend)?;
|
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 end_meta = stmt.hir_exprs[expr].meta;
|
||||||
|
|
||||||
let kind = match value {
|
let kind = match value {
|
||||||
|
|
@ -315,7 +310,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
TokenValue::Increment | TokenValue::Decrement => {
|
TokenValue::Increment | TokenValue::Decrement => {
|
||||||
let Token { value, meta } = self.bump(frontend)?;
|
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(
|
stmt.hir_exprs.append(
|
||||||
HirExpr {
|
HirExpr {
|
||||||
|
|
@ -332,7 +327,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
Default::default(),
|
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,
|
frontend: &mut Frontend,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
stmt: &mut StmtContext,
|
stmt: &mut StmtContext,
|
||||||
body: &mut Block,
|
|
||||||
passthrough: Option<Handle<HirExpr>>,
|
passthrough: Option<Handle<HirExpr>>,
|
||||||
min_bp: u8,
|
min_bp: u8,
|
||||||
) -> Result<Handle<HirExpr>> {
|
) -> Result<Handle<HirExpr>> {
|
||||||
let mut left = passthrough
|
let mut left = passthrough
|
||||||
.ok_or(ErrorKind::EndOfFile /* Dummy error */)
|
.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;
|
let mut meta = stmt.hir_exprs[left].meta;
|
||||||
|
|
||||||
while let Some((l_bp, r_bp)) = binding_power(&self.expect_peek(frontend)?.value) {
|
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 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;
|
let end_meta = stmt.hir_exprs[right].meta;
|
||||||
|
|
||||||
meta.subsume(end_meta);
|
meta.subsume(end_meta);
|
||||||
|
|
@ -403,16 +397,15 @@ impl<'source> ParsingContext<'source> {
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
stmt: &mut StmtContext,
|
stmt: &mut StmtContext,
|
||||||
body: &mut Block,
|
|
||||||
passthrough: Option<Handle<HirExpr>>,
|
passthrough: Option<Handle<HirExpr>>,
|
||||||
) -> Result<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;
|
let mut meta = stmt.hir_exprs[condition].meta;
|
||||||
|
|
||||||
if self.bump_if(frontend, TokenValue::Question).is_some() {
|
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)?;
|
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;
|
let end_meta = stmt.hir_exprs[reject].meta;
|
||||||
|
|
||||||
meta.subsume(end_meta);
|
meta.subsume(end_meta);
|
||||||
|
|
@ -437,15 +430,14 @@ impl<'source> ParsingContext<'source> {
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
stmt: &mut StmtContext,
|
stmt: &mut StmtContext,
|
||||||
body: &mut Block,
|
|
||||||
) -> Result<Handle<HirExpr>> {
|
) -> 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;
|
let mut meta = stmt.hir_exprs[tgt].meta;
|
||||||
|
|
||||||
Ok(match self.expect_peek(frontend)?.value {
|
Ok(match self.expect_peek(frontend)?.value {
|
||||||
TokenValue::Assign => {
|
TokenValue::Assign => {
|
||||||
self.bump(frontend)?;
|
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;
|
let end_meta = stmt.hir_exprs[value].meta;
|
||||||
|
|
||||||
meta.subsume(end_meta);
|
meta.subsume(end_meta);
|
||||||
|
|
@ -468,7 +460,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
| TokenValue::RightShiftAssign
|
| TokenValue::RightShiftAssign
|
||||||
| TokenValue::XorAssign => {
|
| TokenValue::XorAssign => {
|
||||||
let token = self.bump(frontend)?;
|
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;
|
let end_meta = stmt.hir_exprs[right].meta;
|
||||||
|
|
||||||
meta.subsume(end_meta);
|
meta.subsume(end_meta);
|
||||||
|
|
@ -504,7 +496,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
Default::default(),
|
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,
|
frontend: &mut Frontend,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
stmt: &mut StmtContext,
|
stmt: &mut StmtContext,
|
||||||
body: &mut Block,
|
|
||||||
) -> Result<Handle<HirExpr>> {
|
) -> 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 {
|
while let TokenValue::Comma = self.expect_peek(frontend)?.value {
|
||||||
self.bump(frontend)?;
|
self.bump(frontend)?;
|
||||||
expr = self.parse_assignment(frontend, ctx, stmt, body)?;
|
expr = self.parse_assignment(frontend, ctx, stmt)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(expr)
|
Ok(expr)
|
||||||
|
|
|
||||||
|
|
@ -40,12 +40,11 @@ impl<'source> ParsingContext<'source> {
|
||||||
&mut self,
|
&mut self,
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
body: &mut Block,
|
|
||||||
terminator: &mut Option<usize>,
|
terminator: &mut Option<usize>,
|
||||||
) -> Result<Option<Span>> {
|
) -> Result<Option<Span>> {
|
||||||
// Type qualifiers always identify a declaration statement
|
// Type qualifiers always identify a declaration statement
|
||||||
if self.peek_type_qualifier(frontend) {
|
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
|
// Type names can identify either declaration statements or type constructors
|
||||||
|
|
@ -61,7 +60,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
self.backtrack(token)?;
|
self.backtrack(token)?;
|
||||||
|
|
||||||
if declaration {
|
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 {
|
let meta_rest = match *value {
|
||||||
TokenValue::Continue => {
|
TokenValue::Continue => {
|
||||||
let meta = self.bump(frontend)?.meta;
|
let meta = self.bump(frontend)?.meta;
|
||||||
body.push(Statement::Continue, meta);
|
ctx.body.push(Statement::Continue, meta);
|
||||||
terminator.get_or_insert(body.len());
|
terminator.get_or_insert(ctx.body.len());
|
||||||
self.expect(frontend, TokenValue::Semicolon)?.meta
|
self.expect(frontend, TokenValue::Semicolon)?.meta
|
||||||
}
|
}
|
||||||
TokenValue::Break => {
|
TokenValue::Break => {
|
||||||
let meta = self.bump(frontend)?.meta;
|
let meta = self.bump(frontend)?.meta;
|
||||||
body.push(Statement::Break, meta);
|
ctx.body.push(Statement::Break, meta);
|
||||||
terminator.get_or_insert(body.len());
|
terminator.get_or_insert(ctx.body.len());
|
||||||
self.expect(frontend, TokenValue::Semicolon)?.meta
|
self.expect(frontend, TokenValue::Semicolon)?.meta
|
||||||
}
|
}
|
||||||
TokenValue::Return => {
|
TokenValue::Return => {
|
||||||
|
|
@ -96,25 +95,25 @@ impl<'source> ParsingContext<'source> {
|
||||||
_ => {
|
_ => {
|
||||||
// TODO: Implicit conversions
|
// TODO: Implicit conversions
|
||||||
let mut stmt = ctx.stmt_ctx();
|
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)?;
|
self.expect(frontend, TokenValue::Semicolon)?;
|
||||||
let (handle, meta) =
|
let (handle, meta) =
|
||||||
ctx.lower_expect(stmt, frontend, expr, ExprPos::Rhs, body)?;
|
ctx.lower_expect(stmt, frontend, expr, ExprPos::Rhs)?;
|
||||||
(Some(handle), meta)
|
(Some(handle), meta)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ctx.emit_restart(body);
|
ctx.emit_restart();
|
||||||
|
|
||||||
body.push(Statement::Return { value }, meta);
|
ctx.body.push(Statement::Return { value }, meta);
|
||||||
terminator.get_or_insert(body.len());
|
terminator.get_or_insert(ctx.body.len());
|
||||||
|
|
||||||
meta
|
meta
|
||||||
}
|
}
|
||||||
TokenValue::Discard => {
|
TokenValue::Discard => {
|
||||||
let meta = self.bump(frontend)?.meta;
|
let meta = self.bump(frontend)?.meta;
|
||||||
body.push(Statement::Kill, meta);
|
ctx.body.push(Statement::Kill, meta);
|
||||||
terminator.get_or_insert(body.len());
|
terminator.get_or_insert(ctx.body.len());
|
||||||
|
|
||||||
self.expect(frontend, TokenValue::Semicolon)?.meta
|
self.expect(frontend, TokenValue::Semicolon)?.meta
|
||||||
}
|
}
|
||||||
|
|
@ -124,33 +123,31 @@ impl<'source> ParsingContext<'source> {
|
||||||
self.expect(frontend, TokenValue::LeftParen)?;
|
self.expect(frontend, TokenValue::LeftParen)?;
|
||||||
let condition = {
|
let condition = {
|
||||||
let mut stmt = ctx.stmt_ctx();
|
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) =
|
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);
|
meta.subsume(more_meta);
|
||||||
handle
|
handle
|
||||||
};
|
};
|
||||||
self.expect(frontend, TokenValue::RightParen)?;
|
self.expect(frontend, TokenValue::RightParen)?;
|
||||||
|
|
||||||
ctx.emit_restart(body);
|
let accept = ctx.new_body(|ctx| {
|
||||||
|
if let Some(more_meta) = self.parse_statement(frontend, ctx, &mut None)? {
|
||||||
let mut accept = Block::new();
|
|
||||||
if let Some(more_meta) =
|
|
||||||
self.parse_statement(frontend, ctx, &mut accept, &mut None)?
|
|
||||||
{
|
|
||||||
meta.subsume(more_meta)
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut reject = Block::new();
|
|
||||||
if self.bump_if(frontend, TokenValue::Else).is_some() {
|
|
||||||
if let Some(more_meta) =
|
|
||||||
self.parse_statement(frontend, ctx, &mut reject, &mut None)?
|
|
||||||
{
|
|
||||||
meta.subsume(more_meta);
|
meta.subsume(more_meta);
|
||||||
}
|
}
|
||||||
}
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
body.push(
|
let reject = ctx.new_body(|ctx| {
|
||||||
|
if self.bump_if(frontend, TokenValue::Else).is_some() {
|
||||||
|
if let Some(more_meta) = self.parse_statement(frontend, ctx, &mut None)? {
|
||||||
|
meta.subsume(more_meta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
ctx.body.push(
|
||||||
Statement::If {
|
Statement::If {
|
||||||
condition,
|
condition,
|
||||||
accept,
|
accept,
|
||||||
|
|
@ -169,17 +166,16 @@ impl<'source> ParsingContext<'source> {
|
||||||
|
|
||||||
let (selector, uint) = {
|
let (selector, uint) = {
|
||||||
let mut stmt = ctx.stmt_ctx();
|
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) =
|
let (root, meta) = ctx.lower_expect(stmt, frontend, expr, ExprPos::Rhs)?;
|
||||||
ctx.lower_expect(stmt, frontend, expr, ExprPos::Rhs, body)?;
|
let uint = ctx.resolve_type(root, meta)?.scalar_kind()
|
||||||
let uint = frontend.resolve_type(ctx, root, meta)?.scalar_kind()
|
|
||||||
== Some(crate::ScalarKind::Uint);
|
== Some(crate::ScalarKind::Uint);
|
||||||
(root, uint)
|
(root, uint)
|
||||||
};
|
};
|
||||||
|
|
||||||
self.expect(frontend, TokenValue::RightParen)?;
|
self.expect(frontend, TokenValue::RightParen)?;
|
||||||
|
|
||||||
ctx.emit_restart(body);
|
ctx.emit_restart();
|
||||||
|
|
||||||
let mut cases = Vec::new();
|
let mut cases = Vec::new();
|
||||||
// Track if any default case is present in the switch statement.
|
// Track if any default case is present in the switch statement.
|
||||||
|
|
@ -192,13 +188,18 @@ impl<'source> ParsingContext<'source> {
|
||||||
self.bump(frontend)?;
|
self.bump(frontend)?;
|
||||||
|
|
||||||
let mut stmt = ctx.stmt_ctx();
|
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) =
|
let (root, meta) =
|
||||||
ctx.lower_expect(stmt, frontend, expr, ExprPos::Rhs, body)?;
|
ctx.lower_expect(stmt, frontend, expr, ExprPos::Rhs)?;
|
||||||
let const_expr = frontend.solve_constant(ctx, root, meta)?;
|
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 {
|
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),
|
true => crate::SwitchValue::U32(value as u32),
|
||||||
false => crate::SwitchValue::I32(value),
|
false => crate::SwitchValue::I32(value),
|
||||||
},
|
},
|
||||||
|
|
@ -244,35 +245,32 @@ impl<'source> ParsingContext<'source> {
|
||||||
|
|
||||||
self.expect(frontend, TokenValue::Colon)?;
|
self.expect(frontend, TokenValue::Colon)?;
|
||||||
|
|
||||||
let mut body = Block::new();
|
|
||||||
|
|
||||||
let mut case_terminator = None;
|
|
||||||
loop {
|
|
||||||
match self.expect_peek(frontend)?.value {
|
|
||||||
TokenValue::Case | TokenValue::Default | TokenValue::RightBrace => {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
self.parse_statement(
|
|
||||||
frontend,
|
|
||||||
ctx,
|
|
||||||
&mut body,
|
|
||||||
&mut case_terminator,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut fall_through = true;
|
let mut fall_through = true;
|
||||||
|
|
||||||
if let Some(mut idx) = case_terminator {
|
let body = ctx.new_body(|ctx| {
|
||||||
if let Statement::Break = body[idx - 1] {
|
let mut case_terminator = None;
|
||||||
fall_through = false;
|
loop {
|
||||||
idx -= 1;
|
match self.expect_peek(frontend)?.value {
|
||||||
|
TokenValue::Case | TokenValue::Default | TokenValue::RightBrace => {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.parse_statement(frontend, ctx, &mut case_terminator)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
body.cull(idx..)
|
if let Some(mut idx) = case_terminator {
|
||||||
}
|
if let Statement::Break = ctx.body[idx - 1] {
|
||||||
|
fall_through = false;
|
||||||
|
idx -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.body.cull(idx..)
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
cases.push(SwitchCase {
|
cases.push(SwitchCase {
|
||||||
value,
|
value,
|
||||||
|
|
@ -317,51 +315,48 @@ impl<'source> ParsingContext<'source> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
body.push(Statement::Switch { selector, cases }, meta);
|
ctx.body.push(Statement::Switch { selector, cases }, meta);
|
||||||
|
|
||||||
meta
|
meta
|
||||||
}
|
}
|
||||||
TokenValue::While => {
|
TokenValue::While => {
|
||||||
let mut meta = self.bump(frontend)?.meta;
|
let mut meta = self.bump(frontend)?.meta;
|
||||||
|
|
||||||
let mut loop_body = Block::new();
|
let loop_body = ctx.new_body(|ctx| {
|
||||||
|
let mut stmt = ctx.stmt_ctx();
|
||||||
|
self.expect(frontend, TokenValue::LeftParen)?;
|
||||||
|
let root = self.parse_expression(frontend, ctx, &mut stmt)?;
|
||||||
|
meta.subsume(self.expect(frontend, TokenValue::RightParen)?.meta);
|
||||||
|
|
||||||
let mut stmt = ctx.stmt_ctx();
|
let (expr, expr_meta) = ctx.lower_expect(stmt, frontend, root, ExprPos::Rhs)?;
|
||||||
self.expect(frontend, TokenValue::LeftParen)?;
|
let condition = ctx.add_expression(
|
||||||
let root = self.parse_expression(frontend, ctx, &mut stmt, &mut loop_body)?;
|
Expression::Unary {
|
||||||
meta.subsume(self.expect(frontend, TokenValue::RightParen)?.meta);
|
op: UnaryOperator::Not,
|
||||||
|
expr,
|
||||||
|
},
|
||||||
|
expr_meta,
|
||||||
|
)?;
|
||||||
|
|
||||||
let (expr, expr_meta) =
|
ctx.emit_restart();
|
||||||
ctx.lower_expect(stmt, frontend, root, ExprPos::Rhs, &mut loop_body)?;
|
|
||||||
let condition = ctx.add_expression(
|
|
||||||
Expression::Unary {
|
|
||||||
op: UnaryOperator::Not,
|
|
||||||
expr,
|
|
||||||
},
|
|
||||||
expr_meta,
|
|
||||||
&mut loop_body,
|
|
||||||
);
|
|
||||||
|
|
||||||
ctx.emit_restart(&mut loop_body);
|
ctx.body.push(
|
||||||
|
Statement::If {
|
||||||
|
condition,
|
||||||
|
accept: new_break(),
|
||||||
|
reject: Block::new(),
|
||||||
|
},
|
||||||
|
crate::Span::default(),
|
||||||
|
);
|
||||||
|
|
||||||
loop_body.push(
|
meta.subsume(expr_meta);
|
||||||
Statement::If {
|
|
||||||
condition,
|
|
||||||
accept: new_break(),
|
|
||||||
reject: Block::new(),
|
|
||||||
},
|
|
||||||
crate::Span::default(),
|
|
||||||
);
|
|
||||||
|
|
||||||
meta.subsume(expr_meta);
|
if let Some(body_meta) = self.parse_statement(frontend, ctx, &mut None)? {
|
||||||
|
meta.subsume(body_meta);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
if let Some(body_meta) =
|
ctx.body.push(
|
||||||
self.parse_statement(frontend, ctx, &mut loop_body, &mut None)?
|
|
||||||
{
|
|
||||||
meta.subsume(body_meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
body.push(
|
|
||||||
Statement::Loop {
|
Statement::Loop {
|
||||||
body: loop_body,
|
body: loop_body,
|
||||||
continuing: Block::new(),
|
continuing: Block::new(),
|
||||||
|
|
@ -375,47 +370,46 @@ impl<'source> ParsingContext<'source> {
|
||||||
TokenValue::Do => {
|
TokenValue::Do => {
|
||||||
let mut meta = self.bump(frontend)?.meta;
|
let mut meta = self.bump(frontend)?.meta;
|
||||||
|
|
||||||
let mut loop_body = Block::new();
|
let loop_body = ctx.new_body(|ctx| {
|
||||||
|
let mut terminator = None;
|
||||||
|
self.parse_statement(frontend, ctx, &mut terminator)?;
|
||||||
|
|
||||||
let mut terminator = None;
|
let mut stmt = ctx.stmt_ctx();
|
||||||
self.parse_statement(frontend, ctx, &mut loop_body, &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)?;
|
||||||
|
let end_meta = self.expect(frontend, TokenValue::RightParen)?.meta;
|
||||||
|
|
||||||
self.expect(frontend, TokenValue::While)?;
|
meta.subsume(end_meta);
|
||||||
self.expect(frontend, TokenValue::LeftParen)?;
|
|
||||||
let root = self.parse_expression(frontend, ctx, &mut stmt, &mut loop_body)?;
|
|
||||||
let end_meta = self.expect(frontend, TokenValue::RightParen)?.meta;
|
|
||||||
|
|
||||||
meta.subsume(end_meta);
|
let (expr, expr_meta) = ctx.lower_expect(stmt, frontend, root, ExprPos::Rhs)?;
|
||||||
|
let condition = ctx.add_expression(
|
||||||
|
Expression::Unary {
|
||||||
|
op: UnaryOperator::Not,
|
||||||
|
expr,
|
||||||
|
},
|
||||||
|
expr_meta,
|
||||||
|
)?;
|
||||||
|
|
||||||
let (expr, expr_meta) =
|
ctx.emit_restart();
|
||||||
ctx.lower_expect(stmt, frontend, root, ExprPos::Rhs, &mut loop_body)?;
|
|
||||||
let condition = ctx.add_expression(
|
|
||||||
Expression::Unary {
|
|
||||||
op: UnaryOperator::Not,
|
|
||||||
expr,
|
|
||||||
},
|
|
||||||
expr_meta,
|
|
||||||
&mut loop_body,
|
|
||||||
);
|
|
||||||
|
|
||||||
ctx.emit_restart(&mut loop_body);
|
ctx.body.push(
|
||||||
|
Statement::If {
|
||||||
|
condition,
|
||||||
|
accept: new_break(),
|
||||||
|
reject: Block::new(),
|
||||||
|
},
|
||||||
|
crate::Span::default(),
|
||||||
|
);
|
||||||
|
|
||||||
loop_body.push(
|
if let Some(idx) = terminator {
|
||||||
Statement::If {
|
ctx.body.cull(idx..)
|
||||||
condition,
|
}
|
||||||
accept: new_break(),
|
Ok(())
|
||||||
reject: Block::new(),
|
})?;
|
||||||
},
|
|
||||||
crate::Span::default(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Some(idx) = terminator {
|
ctx.body.push(
|
||||||
loop_body.cull(idx..)
|
|
||||||
}
|
|
||||||
|
|
||||||
body.push(
|
|
||||||
Statement::Loop {
|
Statement::Loop {
|
||||||
body: loop_body,
|
body: loop_body,
|
||||||
continuing: Block::new(),
|
continuing: Block::new(),
|
||||||
|
|
@ -434,96 +428,98 @@ impl<'source> ParsingContext<'source> {
|
||||||
|
|
||||||
if self.bump_if(frontend, TokenValue::Semicolon).is_none() {
|
if self.bump_if(frontend, TokenValue::Semicolon).is_none() {
|
||||||
if self.peek_type_name(frontend) || self.peek_type_qualifier(frontend) {
|
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 {
|
} else {
|
||||||
let mut stmt = ctx.stmt_ctx();
|
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)?;
|
||||||
ctx.lower(stmt, frontend, expr, ExprPos::Rhs, body)?;
|
ctx.lower(stmt, frontend, expr, ExprPos::Rhs)?;
|
||||||
self.expect(frontend, TokenValue::Semicolon)?;
|
self.expect(frontend, TokenValue::Semicolon)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (mut block, mut continuing) = (Block::new(), Block::new());
|
let loop_body = ctx.new_body(|ctx| {
|
||||||
|
if self.bump_if(frontend, TokenValue::Semicolon).is_none() {
|
||||||
|
let (expr, expr_meta) = if self.peek_type_name(frontend)
|
||||||
|
|| self.peek_type_qualifier(frontend)
|
||||||
|
{
|
||||||
|
let mut qualifiers = self.parse_type_qualifiers(frontend, ctx)?;
|
||||||
|
let (ty, mut meta) = self.parse_type_non_void(frontend, ctx)?;
|
||||||
|
let name = self.expect_ident(frontend)?.0;
|
||||||
|
|
||||||
if self.bump_if(frontend, TokenValue::Semicolon).is_none() {
|
self.expect(frontend, TokenValue::Assign)?;
|
||||||
let (expr, expr_meta) = if self.peek_type_name(frontend)
|
|
||||||
|| self.peek_type_qualifier(frontend)
|
|
||||||
{
|
|
||||||
let mut qualifiers = self.parse_type_qualifiers(frontend)?;
|
|
||||||
let (ty, mut meta) = self.parse_type_non_void(frontend)?;
|
|
||||||
let name = self.expect_ident(frontend)?.0;
|
|
||||||
|
|
||||||
self.expect(frontend, TokenValue::Assign)?;
|
let (value, end_meta) = self.parse_initializer(frontend, ty, ctx)?;
|
||||||
|
meta.subsume(end_meta);
|
||||||
|
|
||||||
let (value, end_meta) =
|
let decl = VarDeclaration {
|
||||||
self.parse_initializer(frontend, ty, ctx, &mut block)?;
|
qualifiers: &mut qualifiers,
|
||||||
meta.subsume(end_meta);
|
ty,
|
||||||
|
name: Some(name),
|
||||||
|
init: None,
|
||||||
|
meta,
|
||||||
|
};
|
||||||
|
|
||||||
let decl = VarDeclaration {
|
let pointer = frontend.add_local_var(ctx, decl)?;
|
||||||
qualifiers: &mut qualifiers,
|
|
||||||
ty,
|
ctx.emit_restart();
|
||||||
name: Some(name),
|
|
||||||
init: None,
|
ctx.body.push(Statement::Store { pointer, value }, meta);
|
||||||
meta,
|
|
||||||
|
(value, end_meta)
|
||||||
|
} else {
|
||||||
|
let mut stmt = ctx.stmt_ctx();
|
||||||
|
let root = self.parse_expression(frontend, ctx, &mut stmt)?;
|
||||||
|
ctx.lower_expect(stmt, frontend, root, ExprPos::Rhs)?
|
||||||
};
|
};
|
||||||
|
|
||||||
let pointer = frontend.add_local_var(ctx, &mut block, decl)?;
|
let condition = ctx.add_expression(
|
||||||
|
Expression::Unary {
|
||||||
|
op: UnaryOperator::Not,
|
||||||
|
expr,
|
||||||
|
},
|
||||||
|
expr_meta,
|
||||||
|
)?;
|
||||||
|
|
||||||
ctx.emit_restart(&mut block);
|
ctx.emit_restart();
|
||||||
|
|
||||||
block.push(Statement::Store { pointer, value }, meta);
|
ctx.body.push(
|
||||||
|
Statement::If {
|
||||||
|
condition,
|
||||||
|
accept: new_break(),
|
||||||
|
reject: Block::new(),
|
||||||
|
},
|
||||||
|
crate::Span::default(),
|
||||||
|
);
|
||||||
|
|
||||||
(value, end_meta)
|
self.expect(frontend, TokenValue::Semicolon)?;
|
||||||
} else {
|
|
||||||
let mut stmt = ctx.stmt_ctx();
|
|
||||||
let root = self.parse_expression(frontend, ctx, &mut stmt, &mut block)?;
|
|
||||||
ctx.lower_expect(stmt, frontend, root, ExprPos::Rhs, &mut block)?
|
|
||||||
};
|
|
||||||
|
|
||||||
let condition = ctx.add_expression(
|
|
||||||
Expression::Unary {
|
|
||||||
op: UnaryOperator::Not,
|
|
||||||
expr,
|
|
||||||
},
|
|
||||||
expr_meta,
|
|
||||||
&mut block,
|
|
||||||
);
|
|
||||||
|
|
||||||
ctx.emit_restart(&mut block);
|
|
||||||
|
|
||||||
block.push(
|
|
||||||
Statement::If {
|
|
||||||
condition,
|
|
||||||
accept: new_break(),
|
|
||||||
reject: Block::new(),
|
|
||||||
},
|
|
||||||
crate::Span::default(),
|
|
||||||
);
|
|
||||||
|
|
||||||
self.expect(frontend, TokenValue::Semicolon)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.expect_peek(frontend)?.value {
|
|
||||||
TokenValue::RightParen => {}
|
|
||||||
_ => {
|
|
||||||
let mut stmt = ctx.stmt_ctx();
|
|
||||||
let rest =
|
|
||||||
self.parse_expression(frontend, ctx, &mut stmt, &mut continuing)?;
|
|
||||||
ctx.lower(stmt, frontend, rest, ExprPos::Rhs, &mut continuing)?;
|
|
||||||
}
|
}
|
||||||
}
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let continuing = ctx.new_body(|ctx| {
|
||||||
|
match self.expect_peek(frontend)?.value {
|
||||||
|
TokenValue::RightParen => {}
|
||||||
|
_ => {
|
||||||
|
let mut stmt = ctx.stmt_ctx();
|
||||||
|
let rest = self.parse_expression(frontend, ctx, &mut stmt)?;
|
||||||
|
ctx.lower(stmt, frontend, rest, ExprPos::Rhs)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
meta.subsume(self.expect(frontend, TokenValue::RightParen)?.meta);
|
meta.subsume(self.expect(frontend, TokenValue::RightParen)?.meta);
|
||||||
|
|
||||||
if let Some(stmt_meta) =
|
let loop_body = ctx.with_body(loop_body, |ctx| {
|
||||||
self.parse_statement(frontend, ctx, &mut block, &mut None)?
|
if let Some(stmt_meta) = self.parse_statement(frontend, ctx, &mut None)? {
|
||||||
{
|
meta.subsume(stmt_meta);
|
||||||
meta.subsume(stmt_meta);
|
}
|
||||||
}
|
Ok(())
|
||||||
|
})?;
|
||||||
|
|
||||||
body.push(
|
ctx.body.push(
|
||||||
Statement::Loop {
|
Statement::Loop {
|
||||||
body: block,
|
body: loop_body,
|
||||||
continuing,
|
continuing,
|
||||||
break_if: None,
|
break_if: None,
|
||||||
},
|
},
|
||||||
|
|
@ -535,22 +531,20 @@ impl<'source> ParsingContext<'source> {
|
||||||
meta
|
meta
|
||||||
}
|
}
|
||||||
TokenValue::LeftBrace => {
|
TokenValue::LeftBrace => {
|
||||||
let meta = self.bump(frontend)?.meta;
|
let mut meta = self.bump(frontend)?.meta;
|
||||||
|
|
||||||
let mut block = Block::new();
|
|
||||||
|
|
||||||
let mut block_terminator = None;
|
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() {
|
if block_terminator.is_some() {
|
||||||
terminator.get_or_insert(body.len());
|
terminator.get_or_insert(ctx.body.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
meta
|
meta
|
||||||
|
|
@ -561,8 +555,8 @@ impl<'source> ParsingContext<'source> {
|
||||||
// tokens. Unknown or invalid tokens will be caught there and
|
// tokens. Unknown or invalid tokens will be caught there and
|
||||||
// turned into an error.
|
// turned into an error.
|
||||||
let mut stmt = ctx.stmt_ctx();
|
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)?;
|
||||||
ctx.lower(stmt, frontend, expr, ExprPos::Rhs, body)?;
|
ctx.lower(stmt, frontend, expr, ExprPos::Rhs)?;
|
||||||
self.expect(frontend, TokenValue::Semicolon)?.meta
|
self.expect(frontend, TokenValue::Semicolon)?.meta
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -576,7 +570,6 @@ impl<'source> ParsingContext<'source> {
|
||||||
mut meta: Span,
|
mut meta: Span,
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
body: &mut Block,
|
|
||||||
terminator: &mut Option<usize>,
|
terminator: &mut Option<usize>,
|
||||||
) -> Result<Span> {
|
) -> Result<Span> {
|
||||||
ctx.symbol_table.push_scope();
|
ctx.symbol_table.push_scope();
|
||||||
|
|
@ -590,7 +583,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let stmt = self.parse_statement(frontend, ctx, body, terminator)?;
|
let stmt = self.parse_statement(frontend, ctx, terminator)?;
|
||||||
|
|
||||||
if let Some(stmt_meta) = stmt {
|
if let Some(stmt_meta) = stmt {
|
||||||
meta.subsume(stmt_meta);
|
meta.subsume(stmt_meta);
|
||||||
|
|
@ -598,7 +591,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(idx) = *terminator {
|
if let Some(idx) = *terminator {
|
||||||
body.cull(idx..)
|
ctx.body.cull(idx..)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.symbol_table.pop_scope();
|
ctx.symbol_table.pop_scope();
|
||||||
|
|
@ -609,8 +602,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
pub fn parse_function_args(
|
pub fn parse_function_args(
|
||||||
&mut self,
|
&mut self,
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
context: &mut Context,
|
ctx: &mut Context,
|
||||||
body: &mut Block,
|
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if self.bump_if(frontend, TokenValue::Void).is_some() {
|
if self.bump_if(frontend, TokenValue::Void).is_some() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
@ -619,19 +611,19 @@ impl<'source> ParsingContext<'source> {
|
||||||
loop {
|
loop {
|
||||||
if self.peek_type_name(frontend) || self.peek_parameter_qualifier(frontend) {
|
if self.peek_type_name(frontend) || self.peek_parameter_qualifier(frontend) {
|
||||||
let qualifier = self.parse_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 {
|
match self.expect_peek(frontend)?.value {
|
||||||
TokenValue::Comma => {
|
TokenValue::Comma => {
|
||||||
self.bump(frontend)?;
|
self.bump(frontend)?;
|
||||||
context.add_function_arg(frontend, body, None, ty, qualifier);
|
ctx.add_function_arg(None, ty, qualifier)?;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TokenValue::Identifier(_) => {
|
TokenValue::Identifier(_) => {
|
||||||
let mut name = self.expect_ident(frontend)?;
|
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() {
|
if self.bump_if(frontend, TokenValue::Comma).is_some() {
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ use std::num::NonZeroU32;
|
||||||
use crate::{
|
use crate::{
|
||||||
front::glsl::{
|
front::glsl::{
|
||||||
ast::{QualifierKey, QualifierValue, StorageQualifier, StructLayout, TypeQualifiers},
|
ast::{QualifierKey, QualifierValue, StorageQualifier, StructLayout, TypeQualifiers},
|
||||||
|
context::Context,
|
||||||
error::ExpectedToken,
|
error::ExpectedToken,
|
||||||
parser::ParsingContext,
|
parser::ParsingContext,
|
||||||
token::{Token, TokenValue},
|
token::{Token, TokenValue},
|
||||||
|
|
@ -17,10 +18,11 @@ impl<'source> ParsingContext<'source> {
|
||||||
pub fn parse_array_specifier(
|
pub fn parse_array_specifier(
|
||||||
&mut self,
|
&mut self,
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
|
ctx: &mut Context,
|
||||||
span: &mut Span,
|
span: &mut Span,
|
||||||
ty: &mut Handle<Type>,
|
ty: &mut Handle<Type>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
while self.parse_array_specifier_single(frontend, span, ty)? {}
|
while self.parse_array_specifier_single(frontend, ctx, span, ty)? {}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -28,6 +30,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
fn parse_array_specifier_single(
|
fn parse_array_specifier_single(
|
||||||
&mut self,
|
&mut self,
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
|
ctx: &mut Context,
|
||||||
span: &mut Span,
|
span: &mut Span,
|
||||||
ty: &mut Handle<Type>,
|
ty: &mut Handle<Type>,
|
||||||
) -> Result<bool> {
|
) -> Result<bool> {
|
||||||
|
|
@ -38,7 +41,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
span.subsume(meta);
|
span.subsume(meta);
|
||||||
ArraySize::Dynamic
|
ArraySize::Dynamic
|
||||||
} else {
|
} 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 {
|
let size = NonZeroU32::new(value).ok_or(Error {
|
||||||
kind: ErrorKind::SemanticError("Array size must be greater than zero".into()),
|
kind: ErrorKind::SemanticError("Array size must be greater than zero".into()),
|
||||||
meta: constant_span,
|
meta: constant_span,
|
||||||
|
|
@ -48,9 +51,9 @@ impl<'source> ParsingContext<'source> {
|
||||||
ArraySize::Constant(size)
|
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();
|
let stride = frontend.layouter[*ty].to_stride();
|
||||||
*ty = frontend.module.types.insert(
|
*ty = ctx.module.types.insert(
|
||||||
Type {
|
Type {
|
||||||
name: None,
|
name: None,
|
||||||
inner: TypeInner::Array {
|
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 token = self.bump(frontend)?;
|
||||||
let mut handle = match token.value {
|
let mut handle = match token.value {
|
||||||
TokenValue::Void => return Ok((None, token.meta)),
|
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 => {
|
TokenValue::Struct => {
|
||||||
let mut meta = token.meta;
|
let mut meta = token.meta;
|
||||||
let ty_name = self.expect_ident(frontend)?.0;
|
let ty_name = self.expect_ident(frontend)?.0;
|
||||||
|
|
@ -80,12 +87,13 @@ impl<'source> ParsingContext<'source> {
|
||||||
let mut members = Vec::new();
|
let mut members = Vec::new();
|
||||||
let span = self.parse_struct_declaration_list(
|
let span = self.parse_struct_declaration_list(
|
||||||
frontend,
|
frontend,
|
||||||
|
ctx,
|
||||||
&mut members,
|
&mut members,
|
||||||
StructLayout::Std140,
|
StructLayout::Std140,
|
||||||
)?;
|
)?;
|
||||||
let end_meta = self.expect(frontend, TokenValue::RightBrace)?.meta;
|
let end_meta = self.expect(frontend, TokenValue::RightBrace)?.meta;
|
||||||
meta.subsume(end_meta);
|
meta.subsume(end_meta);
|
||||||
let ty = frontend.module.types.insert(
|
let ty = ctx.module.types.insert(
|
||||||
Type {
|
Type {
|
||||||
name: Some(ty_name.clone()),
|
name: Some(ty_name.clone()),
|
||||||
inner: TypeInner::Struct { members, span },
|
inner: TypeInner::Struct { members, span },
|
||||||
|
|
@ -120,12 +128,16 @@ impl<'source> ParsingContext<'source> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut span = token.meta;
|
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))
|
Ok((Some(handle), span))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_type_non_void(&mut self, frontend: &mut Frontend) -> Result<(Handle<Type>, Span)> {
|
pub fn parse_type_non_void(
|
||||||
let (maybe_ty, meta) = self.parse_type(frontend)?;
|
&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 {
|
let ty = maybe_ty.ok_or_else(|| Error {
|
||||||
kind: ErrorKind::SemanticError("Type can't be void".into()),
|
kind: ErrorKind::SemanticError("Type can't be void".into()),
|
||||||
meta,
|
meta,
|
||||||
|
|
@ -156,6 +168,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
pub fn parse_type_qualifiers<'a>(
|
pub fn parse_type_qualifiers<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
|
ctx: &mut Context,
|
||||||
) -> Result<TypeQualifiers<'a>> {
|
) -> Result<TypeQualifiers<'a>> {
|
||||||
let mut qualifiers = TypeQualifiers::default();
|
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
|
// Handle layout qualifiers outside the match since this can push multiple values
|
||||||
if token.value == TokenValue::Layout {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -287,11 +300,12 @@ impl<'source> ParsingContext<'source> {
|
||||||
pub fn parse_layout_qualifier_id_list(
|
pub fn parse_layout_qualifier_id_list(
|
||||||
&mut self,
|
&mut self,
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
|
ctx: &mut Context,
|
||||||
qualifiers: &mut TypeQualifiers,
|
qualifiers: &mut TypeQualifiers,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
self.expect(frontend, TokenValue::LeftParen)?;
|
self.expect(frontend, TokenValue::LeftParen)?;
|
||||||
loop {
|
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() {
|
if self.bump_if(frontend, TokenValue::Comma).is_some() {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -308,6 +322,7 @@ impl<'source> ParsingContext<'source> {
|
||||||
pub fn parse_layout_qualifier_id(
|
pub fn parse_layout_qualifier_id(
|
||||||
&mut self,
|
&mut self,
|
||||||
frontend: &mut Frontend,
|
frontend: &mut Frontend,
|
||||||
|
ctx: &mut Context,
|
||||||
qualifiers: &mut crate::FastHashMap<QualifierKey, (QualifierValue, Span)>,
|
qualifiers: &mut crate::FastHashMap<QualifierKey, (QualifierValue, Span)>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// layout_qualifier_id:
|
// layout_qualifier_id:
|
||||||
|
|
@ -332,13 +347,14 @@ impl<'source> ParsingContext<'source> {
|
||||||
} else {
|
} else {
|
||||||
let key = QualifierKey::String(name.into());
|
let key = QualifierKey::String(name.into());
|
||||||
let value = if self.bump_if(frontend, TokenValue::Assign).is_some() {
|
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) =
|
||||||
Ok(v) => v,
|
match self.parse_uint_constant(frontend, ctx) {
|
||||||
Err(e) => {
|
Ok(v) => v,
|
||||||
frontend.errors.push(e);
|
Err(e) => {
|
||||||
(0, Span::default())
|
frontend.errors.push(e);
|
||||||
}
|
(0, Span::default())
|
||||||
};
|
}
|
||||||
|
};
|
||||||
token.meta.subsume(end_meta);
|
token.meta.subsume(end_meta);
|
||||||
|
|
||||||
QualifierValue::Uint(value)
|
QualifierValue::Uint(value)
|
||||||
|
|
|
||||||
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::{
|
use super::{constants::ConstantSolver, context::Context, Error, ErrorKind, Result, Span};
|
||||||
constants::ConstantSolver, context::Context, Error, ErrorKind, Frontend, Result, Span,
|
|
||||||
};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
proc::ResolveContext, Bytes, Expression, Handle, ImageClass, ImageDimension, ScalarKind, Type,
|
proc::ResolveContext, Bytes, Expression, Handle, ImageClass, ImageDimension, ScalarKind, Type,
|
||||||
TypeInner, VectorSize,
|
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)
|
/// Resolves the types of the expressions until `expr` (inclusive)
|
||||||
///
|
///
|
||||||
/// This needs to be done before the [`typifier`] can be queried for
|
/// This needs to be done before the [`typifier`] can be queried for
|
||||||
|
|
@ -240,16 +238,11 @@ impl Frontend {
|
||||||
///
|
///
|
||||||
/// [`typifier`]: Context::typifier
|
/// [`typifier`]: Context::typifier
|
||||||
/// [`resolve_type`]: Self::resolve_type
|
/// [`resolve_type`]: Self::resolve_type
|
||||||
pub(crate) fn typifier_grow(
|
pub(crate) fn typifier_grow(&mut self, expr: Handle<Expression>, meta: Span) -> Result<()> {
|
||||||
&self,
|
let resolve_ctx = ResolveContext::with_locals(self.module, &self.locals, &self.arguments);
|
||||||
ctx: &mut Context,
|
|
||||||
expr: Handle<Expression>,
|
|
||||||
meta: Span,
|
|
||||||
) -> Result<()> {
|
|
||||||
let resolve_ctx = ResolveContext::with_locals(&self.module, &ctx.locals, &ctx.arguments);
|
|
||||||
|
|
||||||
ctx.typifier
|
self.typifier
|
||||||
.grow(expr, &ctx.expressions, &resolve_ctx)
|
.grow(expr, &self.expressions, &resolve_ctx)
|
||||||
.map_err(|error| Error {
|
.map_err(|error| Error {
|
||||||
kind: ErrorKind::SemanticError(format!("Can't resolve type: {error:?}").into()),
|
kind: ErrorKind::SemanticError(format!("Can't resolve type: {error:?}").into()),
|
||||||
meta,
|
meta,
|
||||||
|
|
@ -263,14 +256,13 @@ impl Frontend {
|
||||||
///
|
///
|
||||||
/// [`typifier`]: Context::typifier
|
/// [`typifier`]: Context::typifier
|
||||||
/// [`typifier_grow`]: Self::typifier_grow
|
/// [`typifier_grow`]: Self::typifier_grow
|
||||||
pub(crate) fn resolve_type<'b>(
|
pub(crate) fn resolve_type(
|
||||||
&'b self,
|
&mut self,
|
||||||
ctx: &'b mut Context,
|
|
||||||
expr: Handle<Expression>,
|
expr: Handle<Expression>,
|
||||||
meta: Span,
|
meta: Span,
|
||||||
) -> Result<&'b TypeInner> {
|
) -> Result<&TypeInner> {
|
||||||
self.typifier_grow(ctx, expr, meta)?;
|
self.typifier_grow(expr, meta)?;
|
||||||
Ok(ctx.typifier.get(expr, &self.module.types))
|
Ok(self.typifier.get(expr, &self.module.types))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the type handle for the result of the `expr` expression
|
/// Gets the type handle for the result of the `expr` expression
|
||||||
|
|
@ -290,25 +282,23 @@ impl Frontend {
|
||||||
/// [`resolve_type`]: Self::resolve_type
|
/// [`resolve_type`]: Self::resolve_type
|
||||||
pub(crate) fn resolve_type_handle(
|
pub(crate) fn resolve_type_handle(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &mut Context,
|
|
||||||
expr: Handle<Expression>,
|
expr: Handle<Expression>,
|
||||||
meta: Span,
|
meta: Span,
|
||||||
) -> Result<Handle<Type>> {
|
) -> Result<Handle<Type>> {
|
||||||
self.typifier_grow(ctx, expr, meta)?;
|
self.typifier_grow(expr, meta)?;
|
||||||
Ok(ctx.typifier.register_type(expr, &mut self.module.types))
|
Ok(self.typifier.register_type(expr, &mut self.module.types))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invalidates the cached type resolution for `expr` forcing a recomputation
|
/// Invalidates the cached type resolution for `expr` forcing a recomputation
|
||||||
pub(crate) fn invalidate_expression<'b>(
|
pub(crate) fn invalidate_expression(
|
||||||
&'b self,
|
&mut self,
|
||||||
ctx: &'b mut Context,
|
|
||||||
expr: Handle<Expression>,
|
expr: Handle<Expression>,
|
||||||
meta: Span,
|
meta: Span,
|
||||||
) -> Result<()> {
|
) -> 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
|
self.typifier
|
||||||
.invalidate(expr, &ctx.expressions, &resolve_ctx)
|
.invalidate(expr, &self.expressions, &resolve_ctx)
|
||||||
.map_err(|error| Error {
|
.map_err(|error| Error {
|
||||||
kind: ErrorKind::SemanticError(format!("Can't resolve type: {error:?}").into()),
|
kind: ErrorKind::SemanticError(format!("Can't resolve type: {error:?}").into()),
|
||||||
meta,
|
meta,
|
||||||
|
|
@ -317,13 +307,12 @@ impl Frontend {
|
||||||
|
|
||||||
pub(crate) fn solve_constant(
|
pub(crate) fn solve_constant(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &Context,
|
|
||||||
root: Handle<Expression>,
|
root: Handle<Expression>,
|
||||||
meta: Span,
|
meta: Span,
|
||||||
) -> Result<Handle<Expression>> {
|
) -> Result<Handle<Expression>> {
|
||||||
let mut solver = ConstantSolver {
|
let mut solver = ConstantSolver {
|
||||||
types: &mut self.module.types,
|
types: &mut self.module.types,
|
||||||
expressions: &ctx.expressions,
|
expressions: &self.expressions,
|
||||||
constants: &mut self.module.constants,
|
constants: &mut self.module.constants,
|
||||||
const_expressions: &mut self.module.const_expressions,
|
const_expressions: &mut self.module.const_expressions,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ use super::{
|
||||||
Frontend, Result, Span,
|
Frontend, Result, Span,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
AddressSpace, Binding, Block, BuiltIn, Constant, Expression, GlobalVariable, Handle,
|
AddressSpace, Binding, BuiltIn, Constant, Expression, GlobalVariable, Handle, Interpolation,
|
||||||
Interpolation, LocalVariable, ResourceBinding, ScalarKind, ShaderStage, SwizzleComponent, Type,
|
LocalVariable, ResourceBinding, ScalarKind, ShaderStage, SwizzleComponent, Type, TypeInner,
|
||||||
TypeInner, VectorSize,
|
VectorSize,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct VarDeclaration<'a, 'key> {
|
pub struct VarDeclaration<'a, 'key> {
|
||||||
|
|
@ -40,12 +40,11 @@ impl Frontend {
|
||||||
fn add_builtin(
|
fn add_builtin(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
body: &mut Block,
|
|
||||||
name: &str,
|
name: &str,
|
||||||
data: BuiltInData,
|
data: BuiltInData,
|
||||||
meta: Span,
|
meta: Span,
|
||||||
) -> Option<VariableReference> {
|
) -> Result<Option<VariableReference>> {
|
||||||
let ty = self.module.types.insert(
|
let ty = ctx.module.types.insert(
|
||||||
Type {
|
Type {
|
||||||
name: None,
|
name: None,
|
||||||
inner: data.inner,
|
inner: data.inner,
|
||||||
|
|
@ -53,7 +52,7 @@ impl Frontend {
|
||||||
meta,
|
meta,
|
||||||
);
|
);
|
||||||
|
|
||||||
let handle = self.module.global_variables.append(
|
let handle = ctx.module.global_variables.append(
|
||||||
GlobalVariable {
|
GlobalVariable {
|
||||||
name: Some(name.into()),
|
name: Some(name.into()),
|
||||||
space: AddressSpace::Private,
|
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 {
|
let var = VariableReference {
|
||||||
expr,
|
expr,
|
||||||
|
|
@ -93,18 +92,17 @@ impl Frontend {
|
||||||
|
|
||||||
ctx.symbol_table.add_root(name.into(), var.clone());
|
ctx.symbol_table.add_root(name.into(), var.clone());
|
||||||
|
|
||||||
Some(var)
|
Ok(Some(var))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn lookup_variable(
|
pub(crate) fn lookup_variable(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
body: &mut Block,
|
|
||||||
name: &str,
|
name: &str,
|
||||||
meta: Span,
|
meta: Span,
|
||||||
) -> Option<VariableReference> {
|
) -> Result<Option<VariableReference>> {
|
||||||
if let Some(var) = ctx.symbol_table.lookup(name).cloned() {
|
if let Some(var) = ctx.symbol_table.lookup(name).cloned() {
|
||||||
return Some(var);
|
return Ok(Some(var));
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = match name {
|
let data = match name {
|
||||||
|
|
@ -182,7 +180,7 @@ impl Frontend {
|
||||||
storage: StorageQualifier::Output,
|
storage: StorageQualifier::Output,
|
||||||
},
|
},
|
||||||
"gl_ClipDistance" | "gl_CullDistance" => {
|
"gl_ClipDistance" | "gl_CullDistance" => {
|
||||||
let base = self.module.types.insert(
|
let base = ctx.module.types.insert(
|
||||||
Type {
|
Type {
|
||||||
name: None,
|
name: None,
|
||||||
inner: TypeInner::Scalar {
|
inner: TypeInner::Scalar {
|
||||||
|
|
@ -217,7 +215,7 @@ impl Frontend {
|
||||||
"gl_VertexIndex" => BuiltIn::VertexIndex,
|
"gl_VertexIndex" => BuiltIn::VertexIndex,
|
||||||
"gl_SampleID" => BuiltIn::SampleIndex,
|
"gl_SampleID" => BuiltIn::SampleIndex,
|
||||||
"gl_LocalInvocationIndex" => BuiltIn::LocalInvocationIndex,
|
"gl_LocalInvocationIndex" => BuiltIn::LocalInvocationIndex,
|
||||||
_ => return None,
|
_ => return Ok(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
BuiltInData {
|
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(
|
pub(crate) fn make_variable_invariant(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
body: &mut Block,
|
|
||||||
name: &str,
|
name: &str,
|
||||||
meta: Span,
|
meta: Span,
|
||||||
) {
|
) -> Result<()> {
|
||||||
if let Some(var) = self.lookup_variable(ctx, body, name, meta) {
|
if let Some(var) = self.lookup_variable(ctx, name, meta)? {
|
||||||
if let Some(index) = var.entry_arg {
|
if let Some(index) = var.entry_arg {
|
||||||
if let Binding::BuiltIn(BuiltIn::Position { ref mut invariant }) =
|
if let Binding::BuiltIn(BuiltIn::Position { ref mut invariant }) =
|
||||||
self.entry_args[index].binding
|
self.entry_args[index].binding
|
||||||
|
|
@ -251,19 +248,19 @@ impl Frontend {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn field_selection(
|
pub(crate) fn field_selection(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
pos: ExprPos,
|
pos: ExprPos,
|
||||||
body: &mut Block,
|
|
||||||
expression: Handle<Expression>,
|
expression: Handle<Expression>,
|
||||||
name: &str,
|
name: &str,
|
||||||
meta: Span,
|
meta: Span,
|
||||||
) -> Result<Handle<Expression>> {
|
) -> Result<Handle<Expression>> {
|
||||||
let (ty, is_pointer) = match *self.resolve_type(ctx, expression, meta)? {
|
let (ty, is_pointer) = match *ctx.resolve_type(expression, meta)? {
|
||||||
TypeInner::Pointer { base, .. } => (&self.module.types[base].inner, true),
|
TypeInner::Pointer { base, .. } => (&ctx.module.types[base].inner, true),
|
||||||
ref ty => (ty, false),
|
ref ty => (ty, false),
|
||||||
};
|
};
|
||||||
match *ty {
|
match *ty {
|
||||||
|
|
@ -281,12 +278,11 @@ impl Frontend {
|
||||||
index: index as u32,
|
index: index as u32,
|
||||||
},
|
},
|
||||||
meta,
|
meta,
|
||||||
body,
|
)?;
|
||||||
);
|
|
||||||
|
|
||||||
Ok(match pos {
|
Ok(match pos {
|
||||||
ExprPos::Rhs if is_pointer => {
|
ExprPos::Rhs if is_pointer => {
|
||||||
ctx.add_expression(Expression::Load { pointer }, meta, body)
|
ctx.add_expression(Expression::Load { pointer }, meta)?
|
||||||
}
|
}
|
||||||
_ => pointer,
|
_ => pointer,
|
||||||
})
|
})
|
||||||
|
|
@ -358,19 +354,17 @@ impl Frontend {
|
||||||
pointer: expression,
|
pointer: expression,
|
||||||
},
|
},
|
||||||
meta,
|
meta,
|
||||||
body,
|
)?;
|
||||||
);
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
return Ok(ctx.add_expression(
|
return ctx.add_expression(
|
||||||
Expression::AccessIndex {
|
Expression::AccessIndex {
|
||||||
base: expression,
|
base: expression,
|
||||||
index: pattern[0].index(),
|
index: pattern[0].index(),
|
||||||
},
|
},
|
||||||
meta,
|
meta,
|
||||||
body,
|
);
|
||||||
));
|
|
||||||
}
|
}
|
||||||
2 => VectorSize::Bi,
|
2 => VectorSize::Bi,
|
||||||
3 => VectorSize::Tri,
|
3 => VectorSize::Tri,
|
||||||
|
|
@ -396,8 +390,7 @@ impl Frontend {
|
||||||
pointer: expression,
|
pointer: expression,
|
||||||
},
|
},
|
||||||
meta,
|
meta,
|
||||||
body,
|
)?;
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ctx.add_expression(
|
Ok(ctx.add_expression(
|
||||||
|
|
@ -407,8 +400,7 @@ impl Frontend {
|
||||||
pattern,
|
pattern,
|
||||||
},
|
},
|
||||||
meta,
|
meta,
|
||||||
body,
|
)?)
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
Err(Error {
|
Err(Error {
|
||||||
kind: ErrorKind::SemanticError(
|
kind: ErrorKind::SemanticError(
|
||||||
|
|
@ -430,7 +422,6 @@ impl Frontend {
|
||||||
pub(crate) fn add_global_var(
|
pub(crate) fn add_global_var(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
body: &mut Block,
|
|
||||||
VarDeclaration {
|
VarDeclaration {
|
||||||
qualifiers,
|
qualifiers,
|
||||||
mut ty,
|
mut ty,
|
||||||
|
|
@ -449,7 +440,7 @@ impl Frontend {
|
||||||
.uint_layout_qualifier("location", &mut self.errors)
|
.uint_layout_qualifier("location", &mut self.errors)
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
let interpolation = qualifiers.interpolation.take().map(|(i, _)| i).or_else(|| {
|
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 {
|
Some(match kind {
|
||||||
ScalarKind::Float => Interpolation::Perspective,
|
ScalarKind::Float => Interpolation::Perspective,
|
||||||
_ => Interpolation::Flat,
|
_ => Interpolation::Flat,
|
||||||
|
|
@ -457,7 +448,7 @@ impl Frontend {
|
||||||
});
|
});
|
||||||
let sampling = qualifiers.sampling.take().map(|(s, _)| s);
|
let sampling = qualifiers.sampling.take().map(|(s, _)| s);
|
||||||
|
|
||||||
let handle = self.module.global_variables.append(
|
let handle = ctx.module.global_variables.append(
|
||||||
GlobalVariable {
|
GlobalVariable {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
space: AddressSpace::Private,
|
space: AddressSpace::Private,
|
||||||
|
|
@ -475,6 +466,7 @@ impl Frontend {
|
||||||
location,
|
location,
|
||||||
interpolation,
|
interpolation,
|
||||||
sampling,
|
sampling,
|
||||||
|
second_blend_source: false,
|
||||||
},
|
},
|
||||||
handle,
|
handle,
|
||||||
storage,
|
storage,
|
||||||
|
|
@ -500,7 +492,7 @@ impl Frontend {
|
||||||
ty,
|
ty,
|
||||||
init,
|
init,
|
||||||
};
|
};
|
||||||
let handle = self.module.constants.fetch_or_append(constant, meta);
|
let handle = ctx.module.constants.fetch_or_append(constant, meta);
|
||||||
|
|
||||||
let lookup = GlobalLookup {
|
let lookup = GlobalLookup {
|
||||||
kind: GlobalLookupKind::Constant(handle, ty),
|
kind: GlobalLookupKind::Constant(handle, ty),
|
||||||
|
|
@ -517,7 +509,7 @@ impl Frontend {
|
||||||
*access = allowed_access;
|
*access = allowed_access;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AddressSpace::Uniform => match self.module.types[ty].inner {
|
AddressSpace::Uniform => match ctx.module.types[ty].inner {
|
||||||
TypeInner::Image {
|
TypeInner::Image {
|
||||||
class,
|
class,
|
||||||
dim,
|
dim,
|
||||||
|
|
@ -546,7 +538,7 @@ impl Frontend {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
ty = self.module.types.insert(
|
ty = ctx.module.types.insert(
|
||||||
Type {
|
Type {
|
||||||
name: None,
|
name: None,
|
||||||
inner: TypeInner::Image {
|
inner: TypeInner::Image {
|
||||||
|
|
@ -592,7 +584,7 @@ impl Frontend {
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let handle = self.module.global_variables.append(
|
let handle = ctx.module.global_variables.append(
|
||||||
GlobalVariable {
|
GlobalVariable {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
space,
|
space,
|
||||||
|
|
@ -614,7 +606,7 @@ impl Frontend {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(name) = name {
|
if let Some(name) = name {
|
||||||
ctx.add_global(self, &name, lookup, body);
|
ctx.add_global(&name, lookup)?;
|
||||||
|
|
||||||
self.global_variables.push((name, lookup));
|
self.global_variables.push((name, lookup));
|
||||||
}
|
}
|
||||||
|
|
@ -627,7 +619,6 @@ impl Frontend {
|
||||||
pub(crate) fn add_local_var(
|
pub(crate) fn add_local_var(
|
||||||
&mut self,
|
&mut self,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
body: &mut Block,
|
|
||||||
decl: VarDeclaration,
|
decl: VarDeclaration,
|
||||||
) -> Result<Handle<Expression>> {
|
) -> Result<Handle<Expression>> {
|
||||||
let storage = decl.qualifiers.storage;
|
let storage = decl.qualifiers.storage;
|
||||||
|
|
@ -651,7 +642,7 @@ impl Frontend {
|
||||||
},
|
},
|
||||||
decl.meta,
|
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 {
|
if let Some(name) = decl.name {
|
||||||
let maybe_var = ctx.add_local_var(name.clone(), expr, mutable);
|
let maybe_var = ctx.add_local_var(name.clone(), expr, mutable);
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ impl crate::Binding {
|
||||||
location: _,
|
location: _,
|
||||||
interpolation: ref mut interpolation @ None,
|
interpolation: ref mut interpolation @ None,
|
||||||
ref mut sampling,
|
ref mut sampling,
|
||||||
|
second_blend_source: _,
|
||||||
} = *self
|
} = *self
|
||||||
{
|
{
|
||||||
match ty.scalar_kind() {
|
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,
|
location,
|
||||||
interpolation,
|
interpolation,
|
||||||
sampling,
|
sampling,
|
||||||
|
second_blend_source: false,
|
||||||
}),
|
}),
|
||||||
_ => Err(Error::MissingDecoration(spirv::Decoration::Location)),
|
_ => 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};
|
use crate::{arena::Handle, span::Span};
|
||||||
|
|
||||||
impl crate::Module {
|
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.
|
/// Populate this module's [`SpecialTypes::ray_desc`] type.
|
||||||
///
|
///
|
||||||
/// [`SpecialTypes::ray_desc`] is the type of the [`descriptor`] operand of
|
/// [`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);
|
self.special_types.ray_intersection = Some(handle);
|
||||||
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,
|
Other,
|
||||||
ExpectedArraySize(Span),
|
ExpectedArraySize(Span),
|
||||||
NonPositiveArrayLength(Span),
|
NonPositiveArrayLength(Span),
|
||||||
|
MissingWorkgroupSize(Span),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Error<'a> {
|
impl<'a> Error<'a> {
|
||||||
|
|
@ -433,7 +434,7 @@ impl<'a> Error<'a> {
|
||||||
},
|
},
|
||||||
Error::RepeatedAttribute(bad_span) => ParseError {
|
Error::RepeatedAttribute(bad_span) => ParseError {
|
||||||
message: format!("repeated attribute: '{}'", &source[bad_span]),
|
message: format!("repeated attribute: '{}'", &source[bad_span]),
|
||||||
labels: vec![(bad_span, "repated attribute".into())],
|
labels: vec![(bad_span, "repeated attribute".into())],
|
||||||
notes: vec![],
|
notes: vec![],
|
||||||
},
|
},
|
||||||
Error::UnknownAttribute(bad_span) => ParseError {
|
Error::UnknownAttribute(bad_span) => ParseError {
|
||||||
|
|
@ -704,6 +705,14 @@ impl<'a> Error<'a> {
|
||||||
labels: vec![(span, "must be greater than zero".into())],
|
labels: vec![(span, "must be greater than zero".into())],
|
||||||
notes: vec![],
|
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.
|
/// 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(
|
fn binary_op_splat(
|
||||||
&mut self,
|
&mut self,
|
||||||
op: crate::BinaryOperator,
|
op: crate::BinaryOperator,
|
||||||
left: &mut Handle<crate::Expression>,
|
left: &mut Handle<crate::Expression>,
|
||||||
right: &mut Handle<crate::Expression>,
|
right: &mut Handle<crate::Expression>,
|
||||||
) -> Result<(), Error<'source>> {
|
) -> 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)?;
|
self.grow_types(*left)?.grow_types(*right)?;
|
||||||
|
|
||||||
let left_size = match *self.resolved_inner(*left) {
|
match (self.resolved_inner(*left), self.resolved_inner(*right)) {
|
||||||
crate::TypeInner::Vector { size, .. } => Some(size),
|
(&crate::TypeInner::Vector { size, .. }, &crate::TypeInner::Scalar { .. }) => {
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
match (left_size, self.resolved_inner(*right)) {
|
|
||||||
(Some(size), &crate::TypeInner::Scalar { .. }) => {
|
|
||||||
*right = self.append_expression(
|
*right = self.append_expression(
|
||||||
crate::Expression::Splat {
|
crate::Expression::Splat {
|
||||||
size,
|
size,
|
||||||
|
|
@ -528,7 +535,7 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
|
||||||
self.get_expression_span(*right),
|
self.get_expression_span(*right),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
(None, &crate::TypeInner::Vector { size, .. }) => {
|
(&crate::TypeInner::Scalar { .. }, &crate::TypeInner::Vector { size, .. }) => {
|
||||||
*left = self.append_expression(
|
*left = self.append_expression(
|
||||||
crate::Expression::Splat { size, value: *left },
|
crate::Expression::Splat { size, value: *left },
|
||||||
self.get_expression_span(*left),
|
self.get_expression_span(*left),
|
||||||
|
|
@ -967,7 +974,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
||||||
name: f.name.name.to_string(),
|
name: f.name.name.to_string(),
|
||||||
stage: entry.stage,
|
stage: entry.stage,
|
||||||
early_depth_test: entry.early_depth_test,
|
early_depth_test: entry.early_depth_test,
|
||||||
workgroup_size: entry.workgroup_size,
|
workgroup_size: entry.workgroup_size.unwrap_or([0, 0, 0]),
|
||||||
function,
|
function,
|
||||||
});
|
});
|
||||||
Ok(LoweredGlobalDecl::EntryPoint)
|
Ok(LoweredGlobalDecl::EntryPoint)
|
||||||
|
|
@ -1689,7 +1696,26 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
||||||
let argument = self.expression(args.next()?, ctx.reborrow())?;
|
let argument = self.expression(args.next()?, ctx.reborrow())?;
|
||||||
args.finish()?;
|
args.finish()?;
|
||||||
|
|
||||||
crate::Expression::Relational { fun, argument }
|
// Check for no-op all(bool) and any(bool):
|
||||||
|
let argument_unmodified = matches!(
|
||||||
|
fun,
|
||||||
|
crate::RelationalFunction::All | crate::RelationalFunction::Any
|
||||||
|
) && {
|
||||||
|
ctx.grow_types(argument)?;
|
||||||
|
matches!(
|
||||||
|
ctx.resolved_inner(argument),
|
||||||
|
&crate::TypeInner::Scalar {
|
||||||
|
kind: crate::ScalarKind::Bool,
|
||||||
|
..
|
||||||
|
}
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if argument_unmodified {
|
||||||
|
return Ok(Some(argument));
|
||||||
|
} else {
|
||||||
|
crate::Expression::Relational { fun, argument }
|
||||||
|
}
|
||||||
} else if let Some((axis, ctrl)) = conv::map_derivative(function.name) {
|
} else if let Some((axis, ctrl)) = conv::map_derivative(function.name) {
|
||||||
let mut args = ctx.prepare_args(arguments, 1, span);
|
let mut args = ctx.prepare_args(arguments, 1, span);
|
||||||
let expr = self.expression(args.next()?, ctx.reborrow())?;
|
let expr = self.expression(args.next()?, ctx.reborrow())?;
|
||||||
|
|
@ -1719,6 +1745,25 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
||||||
|
|
||||||
args.finish()?;
|
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 {
|
crate::Expression::Math {
|
||||||
fun,
|
fun,
|
||||||
arg,
|
arg,
|
||||||
|
|
@ -1854,10 +1899,12 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
||||||
let expression = match *ctx.resolved_inner(value) {
|
let expression = match *ctx.resolved_inner(value) {
|
||||||
crate::TypeInner::Scalar { kind, width } => {
|
crate::TypeInner::Scalar { kind, width } => {
|
||||||
crate::Expression::AtomicResult {
|
crate::Expression::AtomicResult {
|
||||||
//TODO: cache this to avoid generating duplicate types
|
ty: ctx.module.generate_predeclared_type(
|
||||||
ty: ctx
|
crate::PredeclaredType::AtomicCompareExchangeWeakResult {
|
||||||
.module
|
kind,
|
||||||
.generate_atomic_compare_exchange_result(kind, width),
|
width,
|
||||||
|
},
|
||||||
|
),
|
||||||
comparison: true,
|
comparison: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ pub struct FunctionResult<'a> {
|
||||||
pub struct EntryPoint {
|
pub struct EntryPoint {
|
||||||
pub stage: crate::ShaderStage,
|
pub stage: crate::ShaderStage,
|
||||||
pub early_depth_test: Option<crate::EarlyDepthTest>,
|
pub early_depth_test: Option<crate::EarlyDepthTest>,
|
||||||
pub workgroup_size: [u32; 3],
|
pub workgroup_size: Option<[u32; 3]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(doc)]
|
#[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::lexer::{Lexer, Token};
|
||||||
use crate::front::wgsl::parse::number::Number;
|
use crate::front::wgsl::parse::number::Number;
|
||||||
use crate::front::SymbolTable;
|
use crate::front::SymbolTable;
|
||||||
use crate::{Arena, FastHashSet, Handle, Span};
|
use crate::{Arena, FastHashSet, Handle, ShaderStage, Span};
|
||||||
|
|
||||||
pub mod ast;
|
pub mod ast;
|
||||||
pub mod conv;
|
pub mod conv;
|
||||||
|
|
@ -143,6 +143,7 @@ impl<T> ParsedAttribute<T> {
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct BindingParser {
|
struct BindingParser {
|
||||||
location: ParsedAttribute<u32>,
|
location: ParsedAttribute<u32>,
|
||||||
|
second_blend_source: ParsedAttribute<bool>,
|
||||||
built_in: ParsedAttribute<crate::BuiltIn>,
|
built_in: ParsedAttribute<crate::BuiltIn>,
|
||||||
interpolation: ParsedAttribute<crate::Interpolation>,
|
interpolation: ParsedAttribute<crate::Interpolation>,
|
||||||
sampling: ParsedAttribute<crate::Sampling>,
|
sampling: ParsedAttribute<crate::Sampling>,
|
||||||
|
|
@ -182,6 +183,9 @@ impl BindingParser {
|
||||||
}
|
}
|
||||||
lexer.expect(Token::Paren(')'))?;
|
lexer.expect(Token::Paren(')'))?;
|
||||||
}
|
}
|
||||||
|
"second_blend_source" => {
|
||||||
|
self.second_blend_source.set(true, name_span)?;
|
||||||
|
}
|
||||||
"invariant" => {
|
"invariant" => {
|
||||||
self.invariant.set(true, name_span)?;
|
self.invariant.set(true, name_span)?;
|
||||||
}
|
}
|
||||||
|
|
@ -208,6 +212,7 @@ impl BindingParser {
|
||||||
location,
|
location,
|
||||||
interpolation,
|
interpolation,
|
||||||
sampling,
|
sampling,
|
||||||
|
second_blend_source: self.second_blend_source.value.unwrap_or(false),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
(None, Some(crate::BuiltIn::Position { .. }), None, None, invariant) => {
|
(None, Some(crate::BuiltIn::Position { .. }), None, None, invariant) => {
|
||||||
|
|
@ -2158,7 +2163,8 @@ impl Parser {
|
||||||
// read attributes
|
// read attributes
|
||||||
let mut binding = None;
|
let mut binding = None;
|
||||||
let mut stage = ParsedAttribute::default();
|
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 early_depth_test = ParsedAttribute::default();
|
||||||
let (mut bind_index, mut bind_group) =
|
let (mut bind_index, mut bind_group) =
|
||||||
(ParsedAttribute::default(), ParsedAttribute::default());
|
(ParsedAttribute::default(), ParsedAttribute::default());
|
||||||
|
|
@ -2184,11 +2190,12 @@ impl Parser {
|
||||||
}
|
}
|
||||||
("compute", name_span) => {
|
("compute", name_span) => {
|
||||||
stage.set(crate::ShaderStage::Compute, name_span)?;
|
stage.set(crate::ShaderStage::Compute, name_span)?;
|
||||||
|
compute_span = name_span;
|
||||||
}
|
}
|
||||||
("workgroup_size", _) => {
|
("workgroup_size", name_span) => {
|
||||||
lexer.expect(Token::Paren('('))?;
|
lexer.expect(Token::Paren('('))?;
|
||||||
workgroup_size = [1u32; 3];
|
let mut new_workgroup_size = [1u32; 3];
|
||||||
for (i, size) in workgroup_size.iter_mut().enumerate() {
|
for (i, size) in new_workgroup_size.iter_mut().enumerate() {
|
||||||
*size = Self::generic_non_negative_int_literal(lexer)?;
|
*size = Self::generic_non_negative_int_literal(lexer)?;
|
||||||
match lexer.next() {
|
match lexer.next() {
|
||||||
(Token::Paren(')'), _) => break,
|
(Token::Paren(')'), _) => break,
|
||||||
|
|
@ -2201,6 +2208,7 @@ impl Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
workgroup_size.set(new_workgroup_size, name_span)?;
|
||||||
}
|
}
|
||||||
("early_depth_test", name_span) => {
|
("early_depth_test", name_span) => {
|
||||||
let conservative = if lexer.skip(Token::Paren('(')) {
|
let conservative = if lexer.skip(Token::Paren('(')) {
|
||||||
|
|
@ -2281,11 +2289,18 @@ impl Parser {
|
||||||
(Token::Word("fn"), _) => {
|
(Token::Word("fn"), _) => {
|
||||||
let function = self.function_decl(lexer, out, &mut dependencies)?;
|
let function = self.function_decl(lexer, out, &mut dependencies)?;
|
||||||
Some(ast::GlobalDeclKind::Fn(ast::Function {
|
Some(ast::GlobalDeclKind::Fn(ast::Function {
|
||||||
entry_point: stage.value.map(|stage| ast::EntryPoint {
|
entry_point: if let Some(stage) = stage.value {
|
||||||
stage,
|
if stage == ShaderStage::Compute && workgroup_size.value.is_none() {
|
||||||
early_depth_test: early_depth_test.value,
|
return Err(Error::MissingWorkgroupSize(compute_span));
|
||||||
workgroup_size,
|
}
|
||||||
}),
|
Some(ast::EntryPoint {
|
||||||
|
stage,
|
||||||
|
early_depth_test: early_depth_test.value,
|
||||||
|
workgroup_size: workgroup_size.value,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
..function
|
..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();
|
}").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]
|
#[test]
|
||||||
fn parse_pointers() {
|
fn parse_pointers() {
|
||||||
parse_str(
|
parse_str(
|
||||||
"fn foo() {
|
"fn foo(a: ptr<private, f32>) -> f32 { return *a; }
|
||||||
|
fn bar() {
|
||||||
var x: f32 = 1.0;
|
var x: f32 = 1.0;
|
||||||
let px = &x;
|
let px = &x;
|
||||||
let py = frexp(0.5, px);
|
let py = foo(px);
|
||||||
}",
|
}",
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
@ -534,6 +601,7 @@ fn parse_repeated_attributes() {
|
||||||
("size(16)", template_struct),
|
("size(16)", template_struct),
|
||||||
("vertex", template_stage),
|
("vertex", template_stage),
|
||||||
("early_depth_test(less_equal)", template_resource),
|
("early_depth_test(less_equal)", template_resource),
|
||||||
|
("workgroup_size(1)", template_stage),
|
||||||
] {
|
] {
|
||||||
let shader = template.replace("__REPLACE__", &format!("@{attribute} @{attribute}"));
|
let shader = template.replace("__REPLACE__", &format!("@{attribute} @{attribute}"));
|
||||||
let name_length = attribute.rfind('(').unwrap_or(attribute.len()) as u32;
|
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
|
/// [`Fragment`]: crate::ShaderStage::Fragment
|
||||||
Location {
|
Location {
|
||||||
location: u32,
|
location: u32,
|
||||||
|
/// Indicates the 2nd input to the blender when dual-source blending.
|
||||||
|
second_blend_source: bool,
|
||||||
interpolation: Option<Interpolation>,
|
interpolation: Option<Interpolation>,
|
||||||
sampling: Option<Sampling>,
|
sampling: Option<Sampling>,
|
||||||
},
|
},
|
||||||
|
|
@ -1943,6 +1945,31 @@ pub struct EntryPoint {
|
||||||
pub function: Function,
|
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.
|
/// Set of special types that can be optionally generated by the frontends.
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
#[cfg_attr(feature = "clone", derive(Clone))]
|
#[cfg_attr(feature = "clone", derive(Clone))]
|
||||||
|
|
@ -1961,6 +1988,12 @@ pub struct SpecialTypes {
|
||||||
/// Call [`Module::generate_ray_intersection_type`] to populate
|
/// Call [`Module::generate_ray_intersection_type`] to populate
|
||||||
/// this if needed and return the handle.
|
/// this if needed and return the handle.
|
||||||
pub ray_intersection: Option<Handle<Type>>,
|
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.
|
/// 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::Round => 1,
|
||||||
Self::Fract => 1,
|
Self::Fract => 1,
|
||||||
Self::Trunc => 1,
|
Self::Trunc => 1,
|
||||||
Self::Modf => 2,
|
Self::Modf => 1,
|
||||||
Self::Frexp => 2,
|
Self::Frexp => 1,
|
||||||
Self::Ldexp => 2,
|
Self::Ldexp => 2,
|
||||||
// exponent
|
// exponent
|
||||||
Self::Exp => 1,
|
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::Round |
|
||||||
Mf::Fract |
|
Mf::Fract |
|
||||||
Mf::Trunc |
|
Mf::Trunc |
|
||||||
Mf::Modf |
|
|
||||||
Mf::Frexp |
|
|
||||||
Mf::Ldexp |
|
Mf::Ldexp |
|
||||||
// exponent
|
// exponent
|
||||||
Mf::Exp |
|
Mf::Exp |
|
||||||
|
|
@ -715,6 +713,31 @@ impl<'a> ResolveContext<'a> {
|
||||||
Mf::Log |
|
Mf::Log |
|
||||||
Mf::Log2 |
|
Mf::Log2 |
|
||||||
Mf::Pow => res_arg.clone(),
|
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
|
// geometry
|
||||||
Mf::Dot => match *res_arg.inner_with(types) {
|
Mf::Dot => match *res_arg.inner_with(types) {
|
||||||
Ti::Vector {
|
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
|
/// [`GlobalVariable`]: crate::GlobalVariable
|
||||||
sampling: crate::FastHashSet<Sampling>,
|
sampling: crate::FastHashSet<Sampling>,
|
||||||
|
|
||||||
|
/// Indicates that the function is using dual source blending.
|
||||||
|
pub dual_source_blending: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionInfo {
|
impl FunctionInfo {
|
||||||
|
|
@ -999,6 +1002,7 @@ impl ModuleInfo {
|
||||||
global_uses: vec![GlobalUse::empty(); module.global_variables.len()].into_boxed_slice(),
|
global_uses: vec![GlobalUse::empty(); module.global_variables.len()].into_boxed_slice(),
|
||||||
expressions: vec![ExpressionInfo::new(); fun.expressions.len()].into_boxed_slice(),
|
expressions: vec![ExpressionInfo::new(); fun.expressions.len()].into_boxed_slice(),
|
||||||
sampling: crate::FastHashSet::default(),
|
sampling: crate::FastHashSet::default(),
|
||||||
|
dual_source_blending: false,
|
||||||
};
|
};
|
||||||
let resolve_context =
|
let resolve_context =
|
||||||
ResolveContext::with_locals(module, &fun.local_variables, &fun.arguments);
|
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(),
|
global_uses: vec![GlobalUse::empty(); global_var_arena.len()].into_boxed_slice(),
|
||||||
expressions: vec![ExpressionInfo::new(); expressions.len()].into_boxed_slice(),
|
expressions: vec![ExpressionInfo::new(); expressions.len()].into_boxed_slice(),
|
||||||
sampling: crate::FastHashSet::default(),
|
sampling: crate::FastHashSet::default(),
|
||||||
|
dual_source_blending: false,
|
||||||
};
|
};
|
||||||
let resolve_context = ResolveContext {
|
let resolve_context = ResolveContext {
|
||||||
constants: &Arena::new(),
|
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);
|
let arg3_ty = arg3.map(resolve);
|
||||||
match fun {
|
match fun {
|
||||||
Mf::Abs => {
|
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));
|
return Err(ExpressionError::WrongArgumentCount(fun));
|
||||||
}
|
}
|
||||||
let good = match *arg_ty {
|
let good = match *arg_ty {
|
||||||
|
|
@ -976,10 +976,9 @@ impl super::Validator {
|
||||||
| Mf::Log
|
| Mf::Log
|
||||||
| Mf::Log2
|
| Mf::Log2
|
||||||
| Mf::Length
|
| Mf::Length
|
||||||
| Mf::Sign
|
|
||||||
| Mf::Sqrt
|
| Mf::Sqrt
|
||||||
| Mf::InverseSqrt => {
|
| 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));
|
return Err(ExpressionError::WrongArgumentCount(fun));
|
||||||
}
|
}
|
||||||
match *arg_ty {
|
match *arg_ty {
|
||||||
|
|
@ -992,6 +991,22 @@ impl super::Validator {
|
||||||
_ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
|
_ => 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 => {
|
Mf::Atan2 | Mf::Pow | Mf::Distance | Mf::Step => {
|
||||||
let arg1_ty = match (arg1_ty, arg2_ty, arg3_ty) {
|
let arg1_ty = match (arg1_ty, arg2_ty, arg3_ty) {
|
||||||
(Some(ty1), None, None) => ty1,
|
(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) {
|
let arg1_ty = match (arg1_ty, arg2_ty, arg3_ty) {
|
||||||
(Some(ty1), None, None) => ty1,
|
(Some(ty1), None, None) => ty1,
|
||||||
_ => return Err(ExpressionError::WrongArgumentCount(fun)),
|
_ => return Err(ExpressionError::WrongArgumentCount(fun)),
|
||||||
};
|
};
|
||||||
let (size0, width0) = match *arg_ty {
|
let size0 = match *arg_ty {
|
||||||
Ti::Scalar {
|
Ti::Scalar {
|
||||||
kind: Sk::Float,
|
kind: Sk::Float, ..
|
||||||
width,
|
} => None,
|
||||||
} => (None, width),
|
|
||||||
Ti::Vector {
|
Ti::Vector {
|
||||||
kind: Sk::Float,
|
kind: Sk::Float,
|
||||||
size,
|
size,
|
||||||
width,
|
..
|
||||||
} => (Some(size), width),
|
} => Some(size),
|
||||||
_ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
|
_ => {
|
||||||
|
return Err(ExpressionError::InvalidArgumentType(fun, 0, arg));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let good = match *arg1_ty {
|
let good = match *arg1_ty {
|
||||||
Ti::Pointer { base, space: _ } => module.types[base].inner == *arg_ty,
|
Ti::Scalar { kind: Sk::Sint, .. } if size0.is_none() => true,
|
||||||
Ti::ValuePointer {
|
Ti::Vector {
|
||||||
size,
|
size,
|
||||||
kind: Sk::Float,
|
kind: Sk::Sint,
|
||||||
width,
|
..
|
||||||
space: _,
|
} if Some(size) == size0 => true,
|
||||||
} => size == size0 && width == width0,
|
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
if !good {
|
if !good {
|
||||||
|
|
@ -1130,7 +1162,7 @@ impl super::Validator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Mf::Normalize => {
|
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));
|
return Err(ExpressionError::WrongArgumentCount(fun));
|
||||||
}
|
}
|
||||||
match *arg_ty {
|
match *arg_ty {
|
||||||
|
|
@ -1210,7 +1242,7 @@ impl super::Validator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Mf::Inverse | Mf::Determinant => {
|
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));
|
return Err(ExpressionError::WrongArgumentCount(fun));
|
||||||
}
|
}
|
||||||
let good = match *arg_ty {
|
let good = match *arg_ty {
|
||||||
|
|
@ -1222,7 +1254,7 @@ impl super::Validator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Mf::Transpose => {
|
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));
|
return Err(ExpressionError::WrongArgumentCount(fun));
|
||||||
}
|
}
|
||||||
match *arg_ty {
|
match *arg_ty {
|
||||||
|
|
@ -1236,7 +1268,7 @@ impl super::Validator {
|
||||||
| Mf::ReverseBits
|
| Mf::ReverseBits
|
||||||
| Mf::FindLsb
|
| Mf::FindLsb
|
||||||
| Mf::FindMsb => {
|
| 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));
|
return Err(ExpressionError::WrongArgumentCount(fun));
|
||||||
}
|
}
|
||||||
match *arg_ty {
|
match *arg_ty {
|
||||||
|
|
@ -1333,7 +1365,7 @@ impl super::Validator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Mf::Pack2x16unorm | Mf::Pack2x16snorm | Mf::Pack2x16float => {
|
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));
|
return Err(ExpressionError::WrongArgumentCount(fun));
|
||||||
}
|
}
|
||||||
match *arg_ty {
|
match *arg_ty {
|
||||||
|
|
@ -1346,7 +1378,7 @@ impl super::Validator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Mf::Pack4x8snorm | Mf::Pack4x8unorm => {
|
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));
|
return Err(ExpressionError::WrongArgumentCount(fun));
|
||||||
}
|
}
|
||||||
match *arg_ty {
|
match *arg_ty {
|
||||||
|
|
@ -1363,7 +1395,7 @@ impl super::Validator {
|
||||||
| Mf::Unpack2x16unorm
|
| Mf::Unpack2x16unorm
|
||||||
| Mf::Unpack4x8snorm
|
| Mf::Unpack4x8snorm
|
||||||
| Mf::Unpack4x8unorm => {
|
| 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));
|
return Err(ExpressionError::WrongArgumentCount(fun));
|
||||||
}
|
}
|
||||||
match *arg_ty {
|
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),
|
DuplicateBuiltIn(crate::BuiltIn),
|
||||||
#[error("Capability {0:?} is not supported")]
|
#[error("Capability {0:?} is not supported")]
|
||||||
UnsupportedCapability(Capabilities),
|
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)]
|
#[derive(Clone, Debug, thiserror::Error)]
|
||||||
|
|
@ -89,6 +100,10 @@ pub enum EntryPointError {
|
||||||
InvalidIntegerInterpolation { location: u32 },
|
InvalidIntegerInterpolation { location: u32 },
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Function(#[from] FunctionError),
|
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")]
|
#[cfg(feature = "validate")]
|
||||||
|
|
@ -106,6 +121,7 @@ fn storage_usage(access: crate::StorageAccess) -> GlobalUse {
|
||||||
struct VaryingContext<'a> {
|
struct VaryingContext<'a> {
|
||||||
stage: crate::ShaderStage,
|
stage: crate::ShaderStage,
|
||||||
output: bool,
|
output: bool,
|
||||||
|
second_blend_source: bool,
|
||||||
types: &'a UniqueArena<crate::Type>,
|
types: &'a UniqueArena<crate::Type>,
|
||||||
type_info: &'a Vec<super::r#type::TypeInfo>,
|
type_info: &'a Vec<super::r#type::TypeInfo>,
|
||||||
location_mask: &'a mut BitSet,
|
location_mask: &'a mut BitSet,
|
||||||
|
|
@ -293,6 +309,7 @@ impl VaryingContext<'_> {
|
||||||
location,
|
location,
|
||||||
interpolation,
|
interpolation,
|
||||||
sampling,
|
sampling,
|
||||||
|
second_blend_source,
|
||||||
} => {
|
} => {
|
||||||
// Only IO-shareable types may be stored in locations.
|
// Only IO-shareable types may be stored in locations.
|
||||||
if !self.type_info[ty.index()]
|
if !self.type_info[ty.index()]
|
||||||
|
|
@ -301,7 +318,37 @@ impl VaryingContext<'_> {
|
||||||
{
|
{
|
||||||
return Err(VaryingError::NotIOShareableType(ty));
|
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")]
|
#[cfg(feature = "validate")]
|
||||||
if self.flags.contains(super::ValidationFlags::BINDINGS) {
|
if self.flags.contains(super::ValidationFlags::BINDINGS) {
|
||||||
return Err(VaryingError::BindingCollision { location });
|
return Err(VaryingError::BindingCollision { location });
|
||||||
|
|
@ -567,7 +614,8 @@ impl super::Validator {
|
||||||
return Err(EntryPointError::UnexpectedWorkgroupSize.with_span());
|
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)
|
.validate_function(&ep.function, module, mod_info, true)
|
||||||
.map_err(WithSpan::into_other)?;
|
.map_err(WithSpan::into_other)?;
|
||||||
|
|
||||||
|
|
@ -593,6 +641,7 @@ impl super::Validator {
|
||||||
let mut ctx = VaryingContext {
|
let mut ctx = VaryingContext {
|
||||||
stage: ep.stage,
|
stage: ep.stage,
|
||||||
output: false,
|
output: false,
|
||||||
|
second_blend_source: false,
|
||||||
types: &module.types,
|
types: &module.types,
|
||||||
type_info: &self.types,
|
type_info: &self.types,
|
||||||
location_mask: &mut self.location_mask,
|
location_mask: &mut self.location_mask,
|
||||||
|
|
@ -612,6 +661,7 @@ impl super::Validator {
|
||||||
let mut ctx = VaryingContext {
|
let mut ctx = VaryingContext {
|
||||||
stage: ep.stage,
|
stage: ep.stage,
|
||||||
output: true,
|
output: true,
|
||||||
|
second_blend_source: false,
|
||||||
types: &module.types,
|
types: &module.types,
|
||||||
type_info: &self.types,
|
type_info: &self.types,
|
||||||
location_mask: &mut self.location_mask,
|
location_mask: &mut self.location_mask,
|
||||||
|
|
@ -623,6 +673,18 @@ impl super::Validator {
|
||||||
};
|
};
|
||||||
ctx.validate(fr.ty, fr.binding.as_ref())
|
ctx.validate(fr.ty, fr.binding.as_ref())
|
||||||
.map_err_inner(|e| EntryPointError::Result(e).with_span())?;
|
.map_err_inner(|e| EntryPointError::Result(e).with_span())?;
|
||||||
|
#[cfg(feature = "validate")]
|
||||||
|
if ctx.second_blend_source {
|
||||||
|
// 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")]
|
#[cfg(feature = "validate")]
|
||||||
if ep.stage == crate::ShaderStage::Vertex
|
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;
|
const MULTISAMPLED_SHADING = 0x800;
|
||||||
/// Support for ray queries and acceleration structures.
|
/// Support for ray queries and acceleration structures.
|
||||||
const RAY_QUERY = 0x1000;
|
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]
|
[dependencies.naga]
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
git = "https://github.com/gfx-rs/naga"
|
git = "https://github.com/gfx-rs/naga"
|
||||||
rev = "7a19f3af909202c7eafd36633b5584bfbb353ecb"
|
rev = "cc87b8f9eb30bb55d0735b89d3df3e099e1a6e7c"
|
||||||
features = [
|
features = [
|
||||||
"clone",
|
"clone",
|
||||||
"span",
|
"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 (mut surface_guard, mut token) = self.surfaces.write(&mut token);
|
||||||
let (adapter_guard, mut token) = hub.adapters.read(&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 error = 'outer: loop {
|
||||||
let device = match device_guard.get(device_id) {
|
let device = match device_guard.get(device_id) {
|
||||||
|
|
@ -2207,6 +2207,24 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||||
break error;
|
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 {
|
match unsafe {
|
||||||
A::get_surface_mut(surface)
|
A::get_surface_mut(surface)
|
||||||
.unwrap()
|
.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 {
|
surface.presentation = Some(present::Presentation {
|
||||||
device_id: Stored {
|
device_id: Stored {
|
||||||
value: id::Valid(device_id),
|
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::{
|
use crate::{
|
||||||
binding_model,
|
binding_model,
|
||||||
device::life::WaitIdleError,
|
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::Hub,
|
hub::Hub,
|
||||||
id,
|
id,
|
||||||
|
|
@ -24,7 +23,7 @@ pub mod queue;
|
||||||
pub mod resource;
|
pub mod resource;
|
||||||
#[cfg(any(feature = "trace", feature = "replay"))]
|
#[cfg(any(feature = "trace", feature = "replay"))]
|
||||||
pub mod trace;
|
pub mod trace;
|
||||||
pub use resource::Device;
|
pub use {life::WaitIdleError, resource::Device};
|
||||||
|
|
||||||
pub const SHADER_STAGE_COUNT: usize = 3;
|
pub const SHADER_STAGE_COUNT: usize = 3;
|
||||||
// Should be large enough for the largest possible texture row. This
|
// 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(),
|
dx12_shader_compiler: instance_desc.dx12_shader_compiler.clone(),
|
||||||
gles_minor_version: instance_desc.gles_minor_version,
|
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 {
|
} else {
|
||||||
|
log::trace!("Instance::new: backend {:?} not requested", A::VARIANT);
|
||||||
None
|
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::device::trace::Action;
|
||||||
use crate::{
|
use crate::{
|
||||||
conv,
|
conv,
|
||||||
device::{DeviceError, MissingDownlevelFlags},
|
device::{DeviceError, MissingDownlevelFlags, WaitIdleError},
|
||||||
global::Global,
|
global::Global,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
hub::Token,
|
hub::Token,
|
||||||
|
|
@ -96,6 +96,18 @@ pub enum ConfigureSurfaceError {
|
||||||
},
|
},
|
||||||
#[error("Requested usage is not supported")]
|
#[error("Requested usage is not supported")]
|
||||||
UnsupportedUsage,
|
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)]
|
#[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,
|
location,
|
||||||
interpolation,
|
interpolation,
|
||||||
sampling,
|
sampling,
|
||||||
|
.. // second_blend_source
|
||||||
}) => Varying::Local {
|
}) => Varying::Local {
|
||||||
location,
|
location,
|
||||||
iv: InterfaceVar {
|
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]
|
[dependencies.naga]
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
git = "https://github.com/gfx-rs/naga"
|
git = "https://github.com/gfx-rs/naga"
|
||||||
rev = "7a19f3af909202c7eafd36633b5584bfbb353ecb"
|
rev = "cc87b8f9eb30bb55d0735b89d3df3e099e1a6e7c"
|
||||||
features = ["clone"]
|
features = ["clone"]
|
||||||
|
|
||||||
[dependencies.profiling]
|
[dependencies.profiling]
|
||||||
|
|
@ -83,7 +83,7 @@ env_logger = "0.10"
|
||||||
[dev-dependencies.naga]
|
[dev-dependencies.naga]
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
git = "https://github.com/gfx-rs/naga"
|
git = "https://github.com/gfx-rs/naga"
|
||||||
rev = "7a19f3af909202c7eafd36633b5584bfbb353ecb"
|
rev = "cc87b8f9eb30bb55d0735b89d3df3e099e1a6e7c"
|
||||||
features = ["wgsl-in"]
|
features = ["wgsl-in"]
|
||||||
|
|
||||||
[dev-dependencies.winit]
|
[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();
|
let cur_value = self.idler.fence.get_value();
|
||||||
if cur_value == !0 {
|
if cur_value == !0 {
|
||||||
return Err(crate::DeviceError::Lost);
|
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;
|
let mut flags = dxgi::DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
|
||||||
// We always set ALLOW_TEARING on the swapchain no matter
|
// We always set ALLOW_TEARING on the swapchain no matter
|
||||||
// what kind of swapchain we want because ResizeBuffers
|
// 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 {
|
if self.supports_allow_tearing {
|
||||||
flags |= dxgi::DXGI_SWAP_CHAIN_FLAG_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 non_srgb_format = auxil::dxgi::conv::map_texture_format_nosrgb(config.format);
|
||||||
|
|
||||||
let swap_chain = match self.swap_chain.take() {
|
let swap_chain = match self.swap_chain.take() {
|
||||||
//Note: this path doesn't properly re-initialize all of the things
|
//Note: this path doesn't properly re-initialize all of the things
|
||||||
Some(sc) => {
|
Some(sc) => {
|
||||||
// can't have image resources in flight used by GPU
|
|
||||||
let _ = unsafe { device.wait_idle() };
|
|
||||||
|
|
||||||
let raw = unsafe { sc.release_resources() };
|
let raw = unsafe { sc.release_resources() };
|
||||||
let result = unsafe {
|
let result = unsafe {
|
||||||
raw.ResizeBuffers(
|
raw.ResizeBuffers(
|
||||||
|
|
@ -773,12 +777,16 @@ impl crate::Surface<Api> for Surface {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn unconfigure(&mut self, device: &Device) {
|
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 {
|
unsafe {
|
||||||
let _ = sc.wait(None);
|
// While `unconfigure`s contract ensures that no work on the GPU's main queues
|
||||||
//TODO: this shouldn't be needed,
|
// are in flight, we still need to wait for the present queue to be idle.
|
||||||
// but it complains that the queue is still used otherwise
|
|
||||||
let _ = device.wait_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();
|
let _raw = sc.release_resources();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -837,6 +845,13 @@ impl crate::Queue<Api> for Queue {
|
||||||
.signal(&fence.raw, value)
|
.signal(&fence.raw, value)
|
||||||
.into_device_result("Signal fence")?;
|
.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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
unsafe fn present(
|
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 {
|
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(
|
unsafe fn configure(
|
||||||
&mut self,
|
&mut self,
|
||||||
device: &A::Device,
|
device: &A::Device,
|
||||||
config: &SurfaceConfiguration,
|
config: &SurfaceConfiguration,
|
||||||
) -> Result<(), SurfaceError>;
|
) -> 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);
|
unsafe fn unconfigure(&mut self, device: &A::Device);
|
||||||
|
|
||||||
/// Returns the next texture to be presented by the swapchain for drawing
|
/// 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 {
|
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.
|
// the clamp is in the range [1, 16] which is always supported if anisotropy is.
|
||||||
vk_info = vk_info
|
vk_info = vk_info
|
||||||
.anisotropy_enable(true)
|
.anisotropy_enable(true)
|
||||||
|
|
|
||||||
51
third_party/rust/wgpu-hal/src/vulkan/instance.rs
vendored
51
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 {
|
impl super::Swapchain {
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// - The device must have been made idle before calling this function.
|
||||||
unsafe fn release_resources(self, device: &ash::Device) -> Self {
|
unsafe fn release_resources(self, device: &ash::Device) -> Self {
|
||||||
profiling::scope!("Swapchain::release_resources");
|
profiling::scope!("Swapchain::release_resources");
|
||||||
{
|
|
||||||
profiling::scope!("vkDeviceWaitIdle");
|
|
||||||
let _ = unsafe { device.device_wait_idle() };
|
|
||||||
};
|
|
||||||
unsafe { device.destroy_fence(self.fence, None) };
|
unsafe { device.destroy_fence(self.fence, None) };
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
@ -186,7 +185,20 @@ impl super::Instance {
|
||||||
&self.shared
|
&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,
|
entry: &ash::Entry,
|
||||||
_driver_api_version: u32,
|
_driver_api_version: u32,
|
||||||
flags: crate::InstanceFlags,
|
flags: crate::InstanceFlags,
|
||||||
|
|
@ -265,7 +277,7 @@ impl super::Instance {
|
||||||
///
|
///
|
||||||
/// - `raw_instance` must be created from `entry`
|
/// - `raw_instance` must be created from `entry`
|
||||||
/// - `raw_instance` must be created respecting `driver_api_version`, `extensions` and `flags`
|
/// - `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.
|
/// same entry, driver_api_version and flags.
|
||||||
/// - `android_sdk_version` is ignored and can be `0` for all platforms besides Android
|
/// - `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| {
|
let instance_layers = entry.enumerate_instance_layer_properties().map_err(|e| {
|
||||||
log::info!("enumerate_instance_layer_properties: {:?}", e);
|
log::info!("enumerate_instance_layer_properties: {:?}", e);
|
||||||
|
|
@ -786,13 +798,22 @@ impl crate::Instance<super::Api> for super::Instance {
|
||||||
if exposed.info.device_type == wgt::DeviceType::IntegratedGpu
|
if exposed.info.device_type == wgt::DeviceType::IntegratedGpu
|
||||||
&& exposed.info.vendor == db::intel::VENDOR
|
&& exposed.info.vendor == db::intel::VENDOR
|
||||||
{
|
{
|
||||||
// See https://gitlab.freedesktop.org/mesa/mesa/-/issues/4688
|
// Check if mesa driver and version less than 21.2
|
||||||
log::warn!(
|
if let Some(version) = exposed.info.driver_info.split_once("Mesa ").map(|s| {
|
||||||
"Disabling presentation on '{}' (id {:?}) because of NV Optimus (on Linux)",
|
s.1.rsplit_once('.')
|
||||||
exposed.info.name,
|
.map(|v| v.0.parse::<f32>().unwrap_or_default())
|
||||||
exposed.adapter.raw
|
.unwrap_or_default()
|
||||||
);
|
}) {
|
||||||
exposed.adapter.private_caps.can_present = false;
|
if version < 21.2 {
|
||||||
|
// See https://gitlab.freedesktop.org/mesa/mesa/-/issues/4688
|
||||||
|
log::warn!(
|
||||||
|
"Disabling presentation on '{}' (id {:?}) due to NV Optimus and Intel Mesa < v21.2",
|
||||||
|
exposed.info.name,
|
||||||
|
exposed.adapter.raw
|
||||||
|
);
|
||||||
|
exposed.adapter.private_caps.can_present = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -807,6 +828,7 @@ impl crate::Surface<super::Api> for super::Surface {
|
||||||
device: &super::Device,
|
device: &super::Device,
|
||||||
config: &crate::SurfaceConfiguration,
|
config: &crate::SurfaceConfiguration,
|
||||||
) -> Result<(), crate::SurfaceError> {
|
) -> Result<(), crate::SurfaceError> {
|
||||||
|
// Safety: `configure`'s contract guarantees there are no resources derived from the swapchain in use.
|
||||||
let old = self
|
let old = self
|
||||||
.swapchain
|
.swapchain
|
||||||
.take()
|
.take()
|
||||||
|
|
@ -820,6 +842,7 @@ impl crate::Surface<super::Api> for super::Surface {
|
||||||
|
|
||||||
unsafe fn unconfigure(&mut self, device: &super::Device) {
|
unsafe fn unconfigure(&mut self, device: &super::Device) {
|
||||||
if let Some(sc) = self.swapchain.take() {
|
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) };
|
let swapchain = unsafe { sc.release_resources(&device.shared.raw) };
|
||||||
unsafe { swapchain.functor.destroy_swapchain(swapchain.raw, None) };
|
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
|
optional = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde_json = "1.0.105"
|
serde_json = "1.0.106"
|
||||||
|
|
||||||
[dev-dependencies.serde]
|
[dev-dependencies.serde]
|
||||||
version = "1"
|
version = "1"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue