зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1862689 - Update `wgpu` to revision 49b7ec97c164bac9ee877f45cdd806fbefecc5a4. r=webgpu-reviewers,ErichDonGubler
Depends on D192648 Differential Revision: https://phabricator.services.mozilla.com/D192649
This commit is contained in:
Родитель
d8dc0b9d25
Коммит
bd70a71e6c
|
@ -25,19 +25,14 @@ git = "https://github.com/franziskuskiefer/cose-rust"
|
|||
rev = "43c22248d136c8b38fe42ea709d08da6355cf04b"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."git+https://github.com/gfx-rs/metal-rs/?rev=d24f1a4"]
|
||||
git = "https://github.com/gfx-rs/metal-rs/"
|
||||
rev = "d24f1a4"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."git+https://github.com/gfx-rs/naga?rev=e25280df9316434ef7752970016d01a3aede3f17"]
|
||||
[source."git+https://github.com/gfx-rs/naga?rev=92e41b43e437146b5d946eb238de963be1168016"]
|
||||
git = "https://github.com/gfx-rs/naga"
|
||||
rev = "e25280df9316434ef7752970016d01a3aede3f17"
|
||||
rev = "92e41b43e437146b5d946eb238de963be1168016"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."git+https://github.com/gfx-rs/wgpu?rev=75989192a9c8f70893882ce0f4373ac217d380c3"]
|
||||
[source."git+https://github.com/gfx-rs/wgpu?rev=49b7ec97c164bac9ee877f45cdd806fbefecc5a4"]
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "75989192a9c8f70893882ce0f4373ac217d380c3"
|
||||
rev = "49b7ec97c164bac9ee877f45cdd806fbefecc5a4"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."git+https://github.com/glandium/warp?rev=4af45fae95bc98b0eba1ef0db17e1dac471bb23d"]
|
||||
|
|
|
@ -3382,8 +3382,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "metal"
|
||||
version = "0.26.0"
|
||||
source = "git+https://github.com/gfx-rs/metal-rs/?rev=d24f1a4#d24f1a4ae92470bf87a0c65ecfe78c9299835505"
|
||||
version = "0.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c43f73953f8cbe511f021b58f18c3ce1c3d1ae13fe953293e13345bf83217f25"
|
||||
dependencies = [
|
||||
"bitflags 2.4.0",
|
||||
"block",
|
||||
|
@ -3758,8 +3759,8 @@ checksum = "a2983372caf4480544083767bf2d27defafe32af49ab4df3a0b7fc90793a3664"
|
|||
|
||||
[[package]]
|
||||
name = "naga"
|
||||
version = "0.13.0"
|
||||
source = "git+https://github.com/gfx-rs/naga?rev=e25280df9316434ef7752970016d01a3aede3f17#e25280df9316434ef7752970016d01a3aede3f17"
|
||||
version = "0.14.0"
|
||||
source = "git+https://github.com/gfx-rs/naga?rev=92e41b43e437146b5d946eb238de963be1168016#92e41b43e437146b5d946eb238de963be1168016"
|
||||
dependencies = [
|
||||
"bit-set",
|
||||
"bitflags 2.4.0",
|
||||
|
@ -6346,8 +6347,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wgpu-core"
|
||||
version = "0.17.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=75989192a9c8f70893882ce0f4373ac217d380c3#75989192a9c8f70893882ce0f4373ac217d380c3"
|
||||
version = "0.18.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=49b7ec97c164bac9ee877f45cdd806fbefecc5a4#49b7ec97c164bac9ee877f45cdd806fbefecc5a4"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bit-vec",
|
||||
|
@ -6369,8 +6370,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wgpu-hal"
|
||||
version = "0.17.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=75989192a9c8f70893882ce0f4373ac217d380c3#75989192a9c8f70893882ce0f4373ac217d380c3"
|
||||
version = "0.18.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=49b7ec97c164bac9ee877f45cdd806fbefecc5a4#49b7ec97c164bac9ee877f45cdd806fbefecc5a4"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"arrayvec",
|
||||
|
@ -6406,8 +6407,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wgpu-types"
|
||||
version = "0.17.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=75989192a9c8f70893882ce0f4373ac217d380c3#75989192a9c8f70893882ce0f4373ac217d380c3"
|
||||
version = "0.18.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=49b7ec97c164bac9ee877f45cdd806fbefecc5a4#49b7ec97c164bac9ee877f45cdd806fbefecc5a4"
|
||||
dependencies = [
|
||||
"bitflags 2.4.0",
|
||||
"js-sys",
|
||||
|
|
|
@ -17,7 +17,7 @@ default = []
|
|||
[dependencies.wgc]
|
||||
package = "wgpu-core"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "75989192a9c8f70893882ce0f4373ac217d380c3"
|
||||
rev = "49b7ec97c164bac9ee877f45cdd806fbefecc5a4"
|
||||
#Note: "replay" shouldn't ideally be needed,
|
||||
# but it allows us to serialize everything across IPC.
|
||||
features = ["replay", "trace", "serial-pass", "strict_asserts", "wgsl"]
|
||||
|
@ -27,32 +27,32 @@ features = ["replay", "trace", "serial-pass", "strict_asserts", "wgsl"]
|
|||
[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies.wgc]
|
||||
package = "wgpu-core"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "75989192a9c8f70893882ce0f4373ac217d380c3"
|
||||
rev = "49b7ec97c164bac9ee877f45cdd806fbefecc5a4"
|
||||
features = ["metal"]
|
||||
|
||||
# We want the wgpu-core Direct3D backends on Windows.
|
||||
[target.'cfg(windows)'.dependencies.wgc]
|
||||
package = "wgpu-core"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "75989192a9c8f70893882ce0f4373ac217d380c3"
|
||||
rev = "49b7ec97c164bac9ee877f45cdd806fbefecc5a4"
|
||||
features = ["dx11", "dx12"]
|
||||
|
||||
# We want the wgpu-core Vulkan backend on Linux and Windows.
|
||||
[target.'cfg(any(windows, all(unix, not(any(target_os = "macos", target_os = "ios")))))'.dependencies.wgc]
|
||||
package = "wgpu-core"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "75989192a9c8f70893882ce0f4373ac217d380c3"
|
||||
rev = "49b7ec97c164bac9ee877f45cdd806fbefecc5a4"
|
||||
features = ["vulkan"]
|
||||
|
||||
[dependencies.wgt]
|
||||
package = "wgpu-types"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "75989192a9c8f70893882ce0f4373ac217d380c3"
|
||||
rev = "49b7ec97c164bac9ee877f45cdd806fbefecc5a4"
|
||||
|
||||
[dependencies.wgh]
|
||||
package = "wgpu-hal"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "75989192a9c8f70893882ce0f4373ac217d380c3"
|
||||
rev = "49b7ec97c164bac9ee877f45cdd806fbefecc5a4"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
d3d12 = "0.7.0"
|
||||
|
|
|
@ -20,11 +20,11 @@ origin:
|
|||
|
||||
# Human-readable identifier for this version/release
|
||||
# Generally "version NNN", "tag SSS", "bookmark SSS"
|
||||
release: commit 75989192a9c8f70893882ce0f4373ac217d380c3
|
||||
release: commit 49b7ec97c164bac9ee877f45cdd806fbefecc5a4
|
||||
|
||||
# Revision to pull in
|
||||
# Must be a long or short commit SHA (long preferred)
|
||||
revision: 75989192a9c8f70893882ce0f4373ac217d380c3
|
||||
revision: 49b7ec97c164bac9ee877f45cdd806fbefecc5a4
|
||||
|
||||
license: ['MIT', 'Apache-2.0']
|
||||
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1,51 +0,0 @@
|
|||
name: ci
|
||||
|
||||
on: [pull_request, push]
|
||||
|
||||
env:
|
||||
RUST_BACKTRACE: 1
|
||||
CARGO_INCREMENTAL: 0
|
||||
RUSTFLAGS: "-Cdebuginfo=0 --deny=warnings"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
channel: [stable, nightly]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: ${{ matrix.channel }}
|
||||
|
||||
- name: Rust Version Info
|
||||
run: rustc --version && cargo --version
|
||||
|
||||
- name: Cache cargo registry
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cargo/registry
|
||||
key: ${{ runner.os }}-${{ matrix.channel }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Cache cargo index
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cargo/git
|
||||
key: ${{ runner.os }}-${{ matrix.channel }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Cache cargo build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: target
|
||||
key: ${{ runner.os }}-${{ matrix.channel }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: cargo check
|
||||
run: cargo check --all-features
|
||||
|
||||
- name: Run all tests
|
||||
run: cargo test --all-features
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -12,7 +12,7 @@
|
|||
[package]
|
||||
edition = "2021"
|
||||
name = "metal"
|
||||
version = "0.26.0"
|
||||
version = "0.27.0"
|
||||
authors = ["gfx-rs developers"]
|
||||
exclude = [
|
||||
"guide/**/*",
|
||||
|
@ -90,36 +90,55 @@ required-features = ["dispatch"]
|
|||
[[example]]
|
||||
name = "fence"
|
||||
|
||||
[dependencies]
|
||||
bitflags = "2"
|
||||
block = "0.1.6"
|
||||
core-graphics-types = "0.1"
|
||||
foreign-types = "0.5"
|
||||
log = "0.4"
|
||||
paste = "1"
|
||||
[dependencies.bitflags]
|
||||
version = "2"
|
||||
|
||||
[dependencies.block]
|
||||
version = "0.1.6"
|
||||
|
||||
[dependencies.core-graphics-types]
|
||||
version = "0.1"
|
||||
|
||||
[dependencies.dispatch]
|
||||
version = "0.2"
|
||||
optional = true
|
||||
|
||||
[dependencies.foreign-types]
|
||||
version = "0.5"
|
||||
|
||||
[dependencies.log]
|
||||
version = "0.4"
|
||||
|
||||
[dependencies.objc]
|
||||
version = "0.2.4"
|
||||
features = ["objc_exception"]
|
||||
|
||||
[dev-dependencies]
|
||||
cocoa = "0.24.0"
|
||||
cty = "0.2.1"
|
||||
glam = "0.22"
|
||||
png = "0.17"
|
||||
rand = "0.8"
|
||||
sema = "0.1.4"
|
||||
winit = "0.27"
|
||||
[dependencies.paste]
|
||||
version = "1"
|
||||
|
||||
[dev-dependencies.cocoa]
|
||||
version = "0.24.0"
|
||||
|
||||
[dev-dependencies.cty]
|
||||
version = "0.2.1"
|
||||
|
||||
[dev-dependencies.glam]
|
||||
version = "0.22"
|
||||
|
||||
[dev-dependencies.png]
|
||||
version = "0.17"
|
||||
|
||||
[dev-dependencies.rand]
|
||||
version = "0.8"
|
||||
|
||||
[dev-dependencies.sema]
|
||||
version = "0.1.4"
|
||||
|
||||
[dev-dependencies.winit]
|
||||
version = "0.27"
|
||||
|
||||
[features]
|
||||
default = ["link"]
|
||||
link = []
|
||||
mps = []
|
||||
private = []
|
||||
|
||||
[workspace]
|
||||
members = ["examples/texture"]
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
out.png
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1,10 +1,94 @@
|
|||
# Change Log
|
||||
|
||||
## Unreleased
|
||||
## v0.14 (2023-10-25)
|
||||
|
||||
#### GENERAL
|
||||
|
||||
- Bump MSRV to 1.65 ([#2420](https://github.com/gfx-rs/naga/pull/2420)) **@jimblandy**
|
||||
- Add support for const-expressions. ([#2309](https://github.com/gfx-rs/naga/pull/2309)) **@teoxoy**, **@jimblandy**
|
||||
- Add support for the `rgb10a2uint` storage format. ([#2525](https://github.com/gfx-rs/naga/pull/2525)) **@teoxoy**
|
||||
- Implement module compaction for snapshot testing and the CLI. ([#2472](https://github.com/gfx-rs/naga/pull/2472)) **@jimblandy**
|
||||
- Fix validation and GLSL parsing of `ldexp`. ([#2449](https://github.com/gfx-rs/naga/pull/2449)) **@fornwall**
|
||||
- Add support for dual source blending. ([#2427](https://github.com/gfx-rs/naga/pull/2427)) **@freqmod**
|
||||
- Bump `indexmap` to v2. ([#2426](https://github.com/gfx-rs/naga/pull/2426)) **@daxpedda**
|
||||
- Bump MSRV to 1.65. ([#2420](https://github.com/gfx-rs/naga/pull/2420)) **@jimblandy**
|
||||
|
||||
#### API
|
||||
|
||||
- Split `UnaryOperator::Not` into `UnaryOperator::LogicalNot` & `UnaryOperator::BitwiseNot`. ([#2554](https://github.com/gfx-rs/naga/pull/2554)) **@teoxoy**
|
||||
- Remove `IsFinite` & `IsNormal` relational functions. ([#2532](https://github.com/gfx-rs/naga/pull/2532)) **@teoxoy**
|
||||
- Derive `PartialEq` on `Expression`. ([#2417](https://github.com/gfx-rs/naga/pull/2417)) **@robtfm**
|
||||
- Use `FastIndexMap` for `SpecialTypes::predeclared_types`. ([#2495](https://github.com/gfx-rs/naga/pull/2495)) **@jimblandy**
|
||||
|
||||
#### CLI
|
||||
|
||||
- Change `--generate-debug-symbols` from an `option` to a `switch`. ([#2472](https://github.com/gfx-rs/naga/pull/2472)) **@jimblandy**
|
||||
- Add support for `.{vert,frag,comp}.glsl` files. ([#2462](https://github.com/gfx-rs/naga/pull/2462)) **@eliemichel**
|
||||
|
||||
#### VALIDATOR
|
||||
|
||||
- Require `Capabilities::FLOAT64` for 64-bit floating-point literals. ([#2567](https://github.com/gfx-rs/naga/pull/2567)) **@jimblandy**
|
||||
- Add `Capabilities::CUBE_ARRAY_TEXTURES`. ([#2530](https://github.com/gfx-rs/naga/pull/2530)) **@teoxoy**
|
||||
- Disallow passing pointers to variables in the workgroup address space to functions. ([#2507](https://github.com/gfx-rs/naga/pull/2507)) **@teoxoy**
|
||||
- Avoid OOM with large sparse resource bindings. ([#2561](https://github.com/gfx-rs/naga/pull/2561)) **@teoxoy**
|
||||
- Require that `Function` and `Private` variables be `CONSTRUCTIBLE`. ([#2545](https://github.com/gfx-rs/naga/pull/2545)) **@jimblandy**
|
||||
- Disallow floating-point NaNs and infinities. ([#2508](https://github.com/gfx-rs/naga/pull/2508)) **@teoxoy**
|
||||
- Temporarily disable uniformity analysis for the fragment stage. ([#2515](https://github.com/gfx-rs/naga/pull/2515)) **@teoxoy**
|
||||
- Validate that `textureSampleBias` is only used in the fragment stage. ([#2515](https://github.com/gfx-rs/naga/pull/2515)) **@teoxoy**
|
||||
- Validate variable initializer for address spaces. ([#2513](https://github.com/gfx-rs/naga/pull/2513)) **@teoxoy**
|
||||
- Prevent using multiple push constant variables in one entry point. ([#2484](https://github.com/gfx-rs/naga/pull/2484)) **@andriyDev**
|
||||
- Validate `binding_array` variable address space. ([#2422](https://github.com/gfx-rs/naga/pull/2422)) **@teoxoy**
|
||||
- Validate storage buffer access. ([#2415](https://github.com/gfx-rs/naga/pull/2415)) **@teoxoy**
|
||||
|
||||
#### WGSL-IN
|
||||
|
||||
- Fix expected min arg count of `textureLoad`. ([#2584](https://github.com/gfx-rs/naga/pull/2584)) **@teoxoy**
|
||||
- Turn `Error::Other` into `Error::Internal`, to help devs. ([#2574](https://github.com/gfx-rs/naga/pull/2574)) **@jimblandy**
|
||||
- Fix OOB typifier indexing. ([#2570](https://github.com/gfx-rs/naga/pull/2570)) **@teoxoy**
|
||||
- Add support for the `bgra8unorm` storage format. ([#2542](https://github.com/gfx-rs/naga/pull/2542) & [#2550](https://github.com/gfx-rs/naga/pull/2550)) **@nical**
|
||||
- Remove the `outerProduct` built-in function. ([#2535](https://github.com/gfx-rs/naga/pull/2535)) **@teoxoy**
|
||||
- Add support for `i32` overload of the `sign` built-in function. ([#2463](https://github.com/gfx-rs/naga/pull/2463)) **@fornwall**
|
||||
- Properly implement `modf` and `frexp`. ([#2454](https://github.com/gfx-rs/naga/pull/2454)) **@fornwall**
|
||||
- Add support for scalar overloads of `all` & `any` built-in functions. ([#2445](https://github.com/gfx-rs/naga/pull/2445)) **@fornwall**
|
||||
- Don't splat the left hand operand of a binary operation if it's not a scalar. ([#2444](https://github.com/gfx-rs/naga/pull/2444)) **@fornwall**
|
||||
- Avoid splatting all binary operator expressions. ([#2440](https://github.com/gfx-rs/naga/pull/2440)) **@fornwall**
|
||||
- Error on repeated or missing `@workgroup_size()`. ([#2435](https://github.com/gfx-rs/naga/pull/2435)) **@fornwall**
|
||||
- Error on repeated attributes. ([#2428](https://github.com/gfx-rs/naga/pull/2428)) **@fornwall**
|
||||
- Fix error message for invalid `texture{Load,Store}()` on arrayed textures. ([#2432](https://github.com/gfx-rs/naga/pull/2432)) **@fornwall**
|
||||
|
||||
#### SPV-IN
|
||||
|
||||
- Disable `Modf` & `Frexp` and translate `ModfStruct` & `FrexpStruct` to their IR equivalents. ([#2527](https://github.com/gfx-rs/naga/pull/2527)) **@teoxoy**
|
||||
- Don't advertise support for `Capability::ImageMSArray` & `Capability::InterpolationFunction`. ([#2529](https://github.com/gfx-rs/naga/pull/2529)) **@teoxoy**
|
||||
- Fix `OpImageQueries` to allow Uints. ([#2404](https://github.com/gfx-rs/naga/pull/2404)) **@evahop**
|
||||
|
||||
#### GLSL-IN
|
||||
|
||||
- Disable `modf` & `frexp`. ([#2527](https://github.com/gfx-rs/naga/pull/2527)) **@teoxoy**
|
||||
|
||||
#### SPV-OUT
|
||||
|
||||
- Require `ClipDistance` & `CullDistance` capabilities if necessary. ([#2528](https://github.com/gfx-rs/naga/pull/2528)) **@teoxoy**
|
||||
- Change `naga::back::spv::DebugInfo::file_name` to a `&Path`. ([#2501](https://github.com/gfx-rs/naga/pull/2501)) **@jimblandy**
|
||||
- Always give structs with runtime arrays a `Block` decoration. ([#2455](https://github.com/gfx-rs/naga/pull/2455)) **@TheoDulka**
|
||||
- Decorate the result of the `OpLoad` with `NonUniform` (not the access chain) when loading images/samplers (resources in the Handle address space). ([#2422](https://github.com/gfx-rs/naga/pull/2422)) **@teoxoy**
|
||||
- Cache `OpConstantNull`. ([#2414](https://github.com/gfx-rs/naga/pull/2414)) **@evahop**
|
||||
|
||||
#### MSL-OUT
|
||||
|
||||
- Add and fix minimum Metal version checks for optional functionality. ([#2486](https://github.com/gfx-rs/naga/pull/2486)) **@teoxoy**
|
||||
- Make varyings' struct members unique. ([#2521](https://github.com/gfx-rs/naga/pull/2521)) **@evahop**
|
||||
|
||||
#### GLSL-OUT
|
||||
|
||||
- Cull functions that should not be available for a given stage. ([#2531](https://github.com/gfx-rs/naga/pull/2531)) **@teoxoy**
|
||||
- Rename identifiers containing double underscores. ([#2510](https://github.com/gfx-rs/naga/pull/2510)) **@evahop**
|
||||
- Polyfill `frexp`. ([#2504](https://github.com/gfx-rs/naga/pull/2504)) **@evahop**
|
||||
- Add built-in functions to keywords. ([#2410](https://github.com/gfx-rs/naga/pull/2410)) **@fornwall**
|
||||
|
||||
#### WGSL-OUT
|
||||
|
||||
- Generate correct code for bit complement on integers. ([#2548](https://github.com/gfx-rs/naga/pull/2548)) **@jimblandy**
|
||||
- Don't include type parameter in splat expressions. ([#2469](https://github.com/gfx-rs/naga/pull/2469)) **@jimblandy**
|
||||
|
||||
## v0.13 (2023-07-21)
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
edition = "2021"
|
||||
rust-version = "1.65"
|
||||
name = "naga"
|
||||
version = "0.13.0"
|
||||
version = "0.14.0"
|
||||
authors = ["Naga Developers"]
|
||||
exclude = [
|
||||
"bin/**/*",
|
||||
|
|
|
@ -41,10 +41,7 @@ pub struct Handle<T> {
|
|||
|
||||
impl<T> Clone for Handle<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Handle {
|
||||
index: self.index,
|
||||
marker: self.marker,
|
||||
}
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +57,7 @@ impl<T> Eq for Handle<T> {}
|
|||
|
||||
impl<T> PartialOrd for Handle<T> {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
self.index.partial_cmp(&other.index)
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -98,7 +98,6 @@ impl FeaturesManager {
|
|||
check_feature!(ARRAY_OF_ARRAYS, 120, 310);
|
||||
check_feature!(IMAGE_LOAD_STORE, 130, 310);
|
||||
check_feature!(CONSERVATIVE_DEPTH, 130, 300);
|
||||
check_feature!(CONSERVATIVE_DEPTH, 130, 300);
|
||||
check_feature!(NOPERSPECTIVE_QUALIFIER, 130);
|
||||
check_feature!(SAMPLE_QUALIFIER, 400, 320);
|
||||
check_feature!(CLIP_DISTANCE, 130, 300 /* with extension */);
|
||||
|
|
|
@ -55,6 +55,7 @@ use std::{
|
|||
cmp::Ordering,
|
||||
fmt,
|
||||
fmt::{Error as FmtError, Write},
|
||||
mem,
|
||||
};
|
||||
use thiserror::Error;
|
||||
|
||||
|
@ -64,7 +65,7 @@ mod features;
|
|||
mod keywords;
|
||||
|
||||
/// List of supported `core` GLSL versions.
|
||||
pub const SUPPORTED_CORE_VERSIONS: &[u16] = &[330, 400, 410, 420, 430, 440, 450];
|
||||
pub const SUPPORTED_CORE_VERSIONS: &[u16] = &[140, 150, 330, 400, 410, 420, 430, 440, 450, 460];
|
||||
/// List of supported `es` GLSL versions.
|
||||
pub const SUPPORTED_ES_VERSIONS: &[u16] = &[300, 310, 320];
|
||||
|
||||
|
@ -163,6 +164,10 @@ impl Version {
|
|||
}
|
||||
}
|
||||
|
||||
fn supports_io_locations(&self) -> bool {
|
||||
*self >= Version::Desktop(330) || *self >= Version::new_gles(300)
|
||||
}
|
||||
|
||||
/// Checks if the version supports all of the explicit layouts:
|
||||
/// - `location=` qualifiers for bindings
|
||||
/// - `binding=` qualifiers for resources
|
||||
|
@ -285,12 +290,25 @@ pub struct PipelineOptions {
|
|||
pub multiview: Option<std::num::NonZeroU32>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VaryingLocation {
|
||||
/// The location of the global.
|
||||
/// This corresponds to `layout(location = ..)` in GLSL.
|
||||
pub location: u32,
|
||||
/// The index which can be used for dual source blending.
|
||||
/// This corresponds to `layout(index = ..)` in GLSL.
|
||||
pub index: u32,
|
||||
}
|
||||
|
||||
/// Reflection info for texture mappings and uniforms.
|
||||
#[derive(Debug)]
|
||||
pub struct ReflectionInfo {
|
||||
/// Mapping between texture names and variables/samplers.
|
||||
pub texture_mapping: crate::FastHashMap<String, TextureMapping>,
|
||||
/// Mapping between uniform variables and names.
|
||||
pub uniforms: crate::FastHashMap<Handle<crate::GlobalVariable>, String>,
|
||||
/// Mapping between names and attribute locations.
|
||||
pub varying: crate::FastHashMap<String, VaryingLocation>,
|
||||
}
|
||||
|
||||
/// Mapping between a texture and its sampler, if it exists.
|
||||
|
@ -463,6 +481,8 @@ pub struct Writer<'a, W> {
|
|||
need_bake_expressions: back::NeedBakeExpressions,
|
||||
/// How many views to render to, if doing multiview rendering.
|
||||
multiview: Option<std::num::NonZeroU32>,
|
||||
/// Mapping of varying variables to their location. Needed for reflections.
|
||||
varying: crate::FastHashMap<String, VaryingLocation>,
|
||||
}
|
||||
|
||||
impl<'a, W: Write> Writer<'a, W> {
|
||||
|
@ -525,6 +545,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
block_id: IdGenerator::default(),
|
||||
named_expressions: Default::default(),
|
||||
need_bake_expressions: Default::default(),
|
||||
varying: Default::default(),
|
||||
};
|
||||
|
||||
// Find all features required to print this module
|
||||
|
@ -1006,9 +1027,16 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
Ic::Storage { format, .. } => ("image", format.into(), "", ""),
|
||||
};
|
||||
|
||||
let precision = if self.options.version.is_es() {
|
||||
"highp "
|
||||
} else {
|
||||
""
|
||||
};
|
||||
|
||||
write!(
|
||||
self.out,
|
||||
"highp {}{}{}{}{}{}",
|
||||
"{}{}{}{}{}{}{}",
|
||||
precision,
|
||||
glsl_scalar(kind, 4)?.prefix,
|
||||
base,
|
||||
glsl_dimension(dim),
|
||||
|
@ -1367,13 +1395,25 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
};
|
||||
|
||||
// Write the I/O locations, if allowed
|
||||
if self.options.version.supports_explicit_locations() || !emit_interpolation_and_auxiliary {
|
||||
let io_location = if self.options.version.supports_explicit_locations()
|
||||
|| !emit_interpolation_and_auxiliary
|
||||
{
|
||||
if self.options.version.supports_io_locations() {
|
||||
if second_blend_source {
|
||||
write!(self.out, "layout(location = {location}, index = 1) ")?;
|
||||
} else {
|
||||
write!(self.out, "layout(location = {location}) ")?;
|
||||
}
|
||||
None
|
||||
} else {
|
||||
Some(VaryingLocation {
|
||||
location,
|
||||
index: second_blend_source as u32,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Write the interpolation qualifier.
|
||||
if let Some(interp) = interpolation {
|
||||
|
@ -1417,6 +1457,10 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
};
|
||||
writeln!(self.out, " {vname};")?;
|
||||
|
||||
if let Some(location) = io_location {
|
||||
self.varying.insert(vname.to_string(), location);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1828,8 +1872,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
// This is where we can generate intermediate constants for some expression types.
|
||||
Statement::Emit(ref range) => {
|
||||
for handle in range.clone() {
|
||||
let info = &ctx.info[handle];
|
||||
let ptr_class = info.ty.inner_with(&self.module.types).pointer_space();
|
||||
let ptr_class = ctx.resolve_type(handle, &self.module.types).pointer_space();
|
||||
let expr_name = if ptr_class.is_some() {
|
||||
// GLSL can't save a pointer-valued expression in a variable,
|
||||
// but we shouldn't ever need to: they should never be named expressions,
|
||||
|
@ -1859,7 +1902,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
if let TypeInner::Image {
|
||||
class: crate::ImageClass::Sampled { .. },
|
||||
..
|
||||
} = *ctx.info[image].ty.inner_with(&self.module.types)
|
||||
} = *ctx.resolve_type(image, &self.module.types)
|
||||
{
|
||||
if let proc::BoundsCheckPolicy::Restrict = self.policies.image_load {
|
||||
write!(self.out, "{level}")?;
|
||||
|
@ -2225,7 +2268,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
} => {
|
||||
write!(self.out, "{level}")?;
|
||||
let res_name = format!("{}{}", back::BAKE_PREFIX, result.index());
|
||||
let res_ty = ctx.info[result].ty.inner_with(&self.module.types);
|
||||
let res_ty = ctx.resolve_type(result, &self.module.types);
|
||||
self.write_value_type(res_ty)?;
|
||||
write!(self.out, " {res_name} = ")?;
|
||||
self.named_expressions.insert(result, res_name);
|
||||
|
@ -2484,7 +2527,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
level,
|
||||
depth_ref,
|
||||
} => {
|
||||
let dim = match *ctx.info[image].ty.inner_with(&self.module.types) {
|
||||
let dim = match *ctx.resolve_type(image, &self.module.types) {
|
||||
TypeInner::Image { dim, .. } => dim,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
@ -2545,7 +2588,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
|
||||
// We need to get the coordinates vector size to later build a vector that's `size + 1`
|
||||
// if `depth_ref` is some, if it isn't a vector we panic as that's not a valid expression
|
||||
let mut coord_dim = match *ctx.info[coordinate].ty.inner_with(&self.module.types) {
|
||||
let mut coord_dim = match *ctx.resolve_type(coordinate, &self.module.types) {
|
||||
TypeInner::Vector { size, .. } => size as u8,
|
||||
TypeInner::Scalar { .. } => 1,
|
||||
_ => unreachable!(),
|
||||
|
@ -2672,7 +2715,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
use crate::ImageClass;
|
||||
|
||||
// This will only panic if the module is invalid
|
||||
let (dim, class) = match *ctx.info[image].ty.inner_with(&self.module.types) {
|
||||
let (dim, class) = match *ctx.resolve_type(image, &self.module.types) {
|
||||
TypeInner::Image {
|
||||
dim,
|
||||
arrayed: _,
|
||||
|
@ -2704,7 +2747,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
self.write_expr(image, ctx)?;
|
||||
if let Some(expr) = level {
|
||||
let cast_to_int = matches!(
|
||||
*ctx.info[expr].ty.inner_with(&self.module.types),
|
||||
*ctx.resolve_type(expr, &self.module.types),
|
||||
crate::TypeInner::Scalar {
|
||||
kind: crate::ScalarKind::Uint,
|
||||
..
|
||||
|
@ -2779,7 +2822,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
let operator_or_fn = match op {
|
||||
crate::UnaryOperator::Negate => "-",
|
||||
crate::UnaryOperator::LogicalNot => {
|
||||
match *ctx.info[expr].ty.inner_with(&self.module.types) {
|
||||
match *ctx.resolve_type(expr, &self.module.types) {
|
||||
TypeInner::Vector { .. } => "not",
|
||||
_ => "!",
|
||||
}
|
||||
|
@ -2805,8 +2848,8 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
// implemented as a function call
|
||||
use crate::{BinaryOperator as Bo, ScalarKind as Sk, TypeInner as Ti};
|
||||
|
||||
let left_inner = ctx.info[left].ty.inner_with(&self.module.types);
|
||||
let right_inner = ctx.info[right].ty.inner_with(&self.module.types);
|
||||
let left_inner = ctx.resolve_type(left, &self.module.types);
|
||||
let right_inner = ctx.resolve_type(right, &self.module.types);
|
||||
|
||||
let function = match (left_inner, right_inner) {
|
||||
(&Ti::Vector { kind, .. }, &Ti::Vector { .. }) => match op {
|
||||
|
@ -2935,7 +2978,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
accept,
|
||||
reject,
|
||||
} => {
|
||||
let cond_ty = ctx.info[condition].ty.inner_with(&self.module.types);
|
||||
let cond_ty = ctx.resolve_type(condition, &self.module.types);
|
||||
let vec_select = if let TypeInner::Vector { .. } = *cond_ty {
|
||||
true
|
||||
} else {
|
||||
|
@ -3025,7 +3068,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
|
||||
self.write_expr(arg, ctx)?;
|
||||
|
||||
match *ctx.info[arg].ty.inner_with(&self.module.types) {
|
||||
match *ctx.resolve_type(arg, &self.module.types) {
|
||||
crate::TypeInner::Vector { size, .. } => write!(
|
||||
self.out,
|
||||
", vec{}(0.0), vec{0}(1.0)",
|
||||
|
@ -3072,7 +3115,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
Mf::Log2 => "log2",
|
||||
Mf::Pow => "pow",
|
||||
// geometry
|
||||
Mf::Dot => match *ctx.info[arg].ty.inner_with(&self.module.types) {
|
||||
Mf::Dot => match *ctx.resolve_type(arg, &self.module.types) {
|
||||
crate::TypeInner::Vector {
|
||||
kind: crate::ScalarKind::Float,
|
||||
..
|
||||
|
@ -3128,7 +3171,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
Mf::Determinant => "determinant",
|
||||
// bits
|
||||
Mf::CountTrailingZeros => {
|
||||
match *ctx.info[arg].ty.inner_with(&self.module.types) {
|
||||
match *ctx.resolve_type(arg, &self.module.types) {
|
||||
crate::TypeInner::Vector { size, kind, .. } => {
|
||||
let s = back::vector_size_str(size);
|
||||
if let crate::ScalarKind::Uint = kind {
|
||||
|
@ -3158,7 +3201,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
}
|
||||
Mf::CountLeadingZeros => {
|
||||
if self.options.version.supports_integer_functions() {
|
||||
match *ctx.info[arg].ty.inner_with(&self.module.types) {
|
||||
match *ctx.resolve_type(arg, &self.module.types) {
|
||||
crate::TypeInner::Vector { size, kind, .. } => {
|
||||
let s = back::vector_size_str(size);
|
||||
|
||||
|
@ -3189,7 +3232,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
_ => unreachable!(),
|
||||
};
|
||||
} else {
|
||||
match *ctx.info[arg].ty.inner_with(&self.module.types) {
|
||||
match *ctx.resolve_type(arg, &self.module.types) {
|
||||
crate::TypeInner::Vector { size, kind, .. } => {
|
||||
let s = back::vector_size_str(size);
|
||||
|
||||
|
@ -3262,7 +3305,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
|
||||
// Check if the argument is an unsigned integer and return the vector size
|
||||
// in case it's a vector
|
||||
let maybe_uint_size = match *ctx.info[arg].ty.inner_with(&self.module.types) {
|
||||
let maybe_uint_size = match *ctx.resolve_type(arg, &self.module.types) {
|
||||
crate::TypeInner::Scalar {
|
||||
kind: crate::ScalarKind::Uint,
|
||||
..
|
||||
|
@ -3349,7 +3392,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
kind: target_kind,
|
||||
convert,
|
||||
} => {
|
||||
let inner = ctx.info[expr].ty.inner_with(&self.module.types);
|
||||
let inner = ctx.resolve_type(expr, &self.module.types);
|
||||
match convert {
|
||||
Some(width) => {
|
||||
// this is similar to `write_type`, but with the target kind
|
||||
|
@ -3515,7 +3558,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
}
|
||||
// Otherwise write just the expression (and the 1D hack if needed)
|
||||
None => {
|
||||
let uvec_size = match *ctx.info[coordinate].ty.inner_with(&self.module.types) {
|
||||
let uvec_size = match *ctx.resolve_type(coordinate, &self.module.types) {
|
||||
TypeInner::Scalar {
|
||||
kind: crate::ScalarKind::Uint,
|
||||
..
|
||||
|
@ -3563,7 +3606,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
// so we don't need to generate bounds checks (OpenGL 4.2 Core §3.9.20)
|
||||
|
||||
// This will only panic if the module is invalid
|
||||
let dim = match *ctx.info[image].ty.inner_with(&self.module.types) {
|
||||
let dim = match *ctx.resolve_type(image, &self.module.types) {
|
||||
TypeInner::Image { dim, .. } => dim,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
@ -3626,7 +3669,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
// in bounds (`ReadZeroSkipWrite`) or make them a valid texel (`Restrict`).
|
||||
|
||||
// This will only panic if the module is invalid
|
||||
let (dim, class) = match *ctx.info[image].ty.inner_with(&self.module.types) {
|
||||
let (dim, class) = match *ctx.resolve_type(image, &self.module.types) {
|
||||
TypeInner::Image {
|
||||
dim,
|
||||
arrayed: _,
|
||||
|
@ -3891,8 +3934,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
}
|
||||
}
|
||||
|
||||
let base_ty_res = &ctx.info[named].ty;
|
||||
let resolved = base_ty_res.inner_with(&self.module.types);
|
||||
let resolved = ctx.resolve_type(named, &self.module.types);
|
||||
|
||||
write!(self.out, " {name}")?;
|
||||
if let TypeInner::Array { base, size, .. } = *resolved {
|
||||
|
@ -4002,7 +4044,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
}
|
||||
|
||||
/// Helper method used to produce the reflection info that's returned to the user
|
||||
fn collect_reflection_info(&self) -> Result<ReflectionInfo, Error> {
|
||||
fn collect_reflection_info(&mut self) -> Result<ReflectionInfo, Error> {
|
||||
use std::collections::hash_map::Entry;
|
||||
let info = self.info.get_entry_point(self.entry_point_idx as usize);
|
||||
let mut texture_mapping = crate::FastHashMap::default();
|
||||
|
@ -4059,6 +4101,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
Ok(ReflectionInfo {
|
||||
texture_mapping,
|
||||
uniforms,
|
||||
varying: mem::take(&mut self.varying),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -244,7 +244,7 @@ impl<'a, W: Write> super::Writer<'a, W> {
|
|||
const MIP_LEVEL_PARAM: &str = "mip_level";
|
||||
|
||||
// Write function return type and name
|
||||
let ret_ty = func_ctx.info[expr_handle].ty.inner_with(&module.types);
|
||||
let ret_ty = func_ctx.resolve_type(expr_handle, &module.types);
|
||||
self.write_value_type(module, ret_ty)?;
|
||||
write!(self.out, " ")?;
|
||||
self.write_wrapped_image_query_function_name(wiq)?;
|
||||
|
@ -891,7 +891,7 @@ impl<'a, W: Write> super::Writer<'a, W> {
|
|||
}
|
||||
}
|
||||
crate::Expression::ImageQuery { image, query } => {
|
||||
let wiq = match *func_ctx.info[image].ty.inner_with(&module.types) {
|
||||
let wiq = match *func_ctx.resolve_type(image, &module.types) {
|
||||
crate::TypeInner::Image {
|
||||
dim,
|
||||
arrayed,
|
||||
|
@ -912,9 +912,8 @@ impl<'a, W: Write> super::Writer<'a, W> {
|
|||
// Write `WrappedConstructor` for structs that are loaded from `AddressSpace::Storage`
|
||||
// since they will later be used by the fn `write_storage_load`
|
||||
crate::Expression::Load { pointer } => {
|
||||
let pointer_space = func_ctx.info[pointer]
|
||||
.ty
|
||||
.inner_with(&module.types)
|
||||
let pointer_space = func_ctx
|
||||
.resolve_type(pointer, &module.types)
|
||||
.pointer_space();
|
||||
|
||||
if let Some(crate::AddressSpace::Storage { .. }) = pointer_space {
|
||||
|
@ -1016,7 +1015,7 @@ impl<'a, W: Write> super::Writer<'a, W> {
|
|||
if extra == 0 {
|
||||
self.write_expr(module, coordinate, func_ctx)?;
|
||||
} else {
|
||||
let num_coords = match *func_ctx.info[coordinate].ty.inner_with(&module.types) {
|
||||
let num_coords = match *func_ctx.resolve_type(coordinate, &module.types) {
|
||||
crate::TypeInner::Scalar { .. } => 1,
|
||||
crate::TypeInner::Vector { size, .. } => size as usize,
|
||||
_ => unreachable!(),
|
||||
|
|
|
@ -466,7 +466,7 @@ impl<W: fmt::Write> super::Writer<'_, W> {
|
|||
}
|
||||
};
|
||||
|
||||
let parent = match *func_ctx.info[next_expr].ty.inner_with(&module.types) {
|
||||
let parent = match *func_ctx.resolve_type(next_expr, &module.types) {
|
||||
crate::TypeInner::Pointer { base, .. } => match module.types[base].inner {
|
||||
crate::TypeInner::Struct { ref members, .. } => Parent::Struct(members),
|
||||
crate::TypeInner::Array { stride, .. } => Parent::Array { stride },
|
||||
|
|
|
@ -1320,8 +1320,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
match *stmt {
|
||||
Statement::Emit(ref range) => {
|
||||
for handle in range.clone() {
|
||||
let info = &func_ctx.info[handle];
|
||||
let ptr_class = info.ty.inner_with(&module.types).pointer_space();
|
||||
let ptr_class = func_ctx.resolve_type(handle, &module.types).pointer_space();
|
||||
let expr_name = if ptr_class.is_some() {
|
||||
// HLSL can't save a pointer-valued expression in a variable,
|
||||
// but we shouldn't ever need to: they should never be named expressions,
|
||||
|
@ -1441,7 +1440,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
}
|
||||
}
|
||||
Statement::Store { pointer, value } => {
|
||||
let ty_inner = func_ctx.info[pointer].ty.inner_with(&module.types);
|
||||
let ty_inner = func_ctx.resolve_type(pointer, &module.types);
|
||||
if let Some(crate::AddressSpace::Storage { .. }) = ty_inner.pointer_space() {
|
||||
let var_handle = self.fill_access_chain(module, pointer, func_ctx)?;
|
||||
self.write_storage_store(
|
||||
|
@ -1467,8 +1466,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
}
|
||||
|
||||
let get_members = |expr: Handle<crate::Expression>| {
|
||||
let base_ty_res = &func_ctx.info[expr].ty;
|
||||
let resolved = base_ty_res.inner_with(&module.types);
|
||||
let resolved = func_ctx.resolve_type(expr, &module.types);
|
||||
match *resolved {
|
||||
TypeInner::Pointer { base, .. } => match module.types[base].inner {
|
||||
TypeInner::Struct { ref members, .. } => Some(members),
|
||||
|
@ -1484,7 +1482,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
|
||||
let mut current_expr = pointer;
|
||||
for _ in 0..3 {
|
||||
let resolved = func_ctx.info[current_expr].ty.inner_with(&module.types);
|
||||
let resolved = func_ctx.resolve_type(current_expr, &module.types);
|
||||
|
||||
match (resolved, &func_ctx.expressions[current_expr]) {
|
||||
(
|
||||
|
@ -1634,7 +1632,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
|
||||
let mut current_expr = pointer;
|
||||
for _ in 0..3 {
|
||||
let resolved = func_ctx.info[current_expr].ty.inner_with(&module.types);
|
||||
let resolved = func_ctx.resolve_type(current_expr, &module.types);
|
||||
match (resolved, &func_ctx.expressions[current_expr]) {
|
||||
(
|
||||
&TypeInner::ValuePointer {
|
||||
|
@ -1726,8 +1724,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
}) = get_inner_matrix_of_struct_array_member(
|
||||
module, pointer, func_ctx, false,
|
||||
) {
|
||||
let mut resolved =
|
||||
func_ctx.info[pointer].ty.inner_with(&module.types);
|
||||
let mut resolved = func_ctx.resolve_type(pointer, &module.types);
|
||||
if let TypeInner::Pointer { base, .. } = *resolved {
|
||||
resolved = &module.types[base].inner;
|
||||
}
|
||||
|
@ -1854,9 +1851,8 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
};
|
||||
|
||||
// Validation ensures that `pointer` has a `Pointer` type.
|
||||
let pointer_space = func_ctx.info[pointer]
|
||||
.ty
|
||||
.inner_with(&module.types)
|
||||
let pointer_space = func_ctx
|
||||
.resolve_type(pointer, &module.types)
|
||||
.pointer_space()
|
||||
.unwrap();
|
||||
|
||||
|
@ -2163,11 +2159,8 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
op: crate::BinaryOperator::Multiply,
|
||||
left,
|
||||
right,
|
||||
} if func_ctx.info[left].ty.inner_with(&module.types).is_matrix()
|
||||
|| func_ctx.info[right]
|
||||
.ty
|
||||
.inner_with(&module.types)
|
||||
.is_matrix() =>
|
||||
} if func_ctx.resolve_type(left, &module.types).is_matrix()
|
||||
|| func_ctx.resolve_type(right, &module.types).is_matrix() =>
|
||||
{
|
||||
// We intentionally flip the order of multiplication as our matrices are implicitly transposed.
|
||||
write!(self.out, "mul(")?;
|
||||
|
@ -2196,10 +2189,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
op: crate::BinaryOperator::Modulo,
|
||||
left,
|
||||
right,
|
||||
} if func_ctx.info[left]
|
||||
.ty
|
||||
.inner_with(&module.types)
|
||||
.scalar_kind()
|
||||
} if func_ctx.resolve_type(left, &module.types).scalar_kind()
|
||||
== Some(crate::ScalarKind::Float) =>
|
||||
{
|
||||
write!(self.out, "fmod(")?;
|
||||
|
@ -2216,10 +2206,8 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
write!(self.out, ")")?;
|
||||
}
|
||||
Expression::Access { base, index } => {
|
||||
if let Some(crate::AddressSpace::Storage { .. }) = func_ctx.info[expr]
|
||||
.ty
|
||||
.inner_with(&module.types)
|
||||
.pointer_space()
|
||||
if let Some(crate::AddressSpace::Storage { .. }) =
|
||||
func_ctx.resolve_type(expr, &module.types).pointer_space()
|
||||
{
|
||||
// do nothing, the chain is written on `Load`/`Store`
|
||||
} else {
|
||||
|
@ -2243,8 +2231,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
let base_ty_res = &func_ctx.info[base].ty;
|
||||
let resolved = base_ty_res.inner_with(&module.types);
|
||||
let resolved = func_ctx.resolve_type(base, &module.types);
|
||||
|
||||
let non_uniform_qualifier = match *resolved {
|
||||
TypeInner::BindingArray { .. } => {
|
||||
|
@ -2268,10 +2255,8 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
}
|
||||
}
|
||||
Expression::AccessIndex { base, index } => {
|
||||
if let Some(crate::AddressSpace::Storage { .. }) = func_ctx.info[expr]
|
||||
.ty
|
||||
.inner_with(&module.types)
|
||||
.pointer_space()
|
||||
if let Some(crate::AddressSpace::Storage { .. }) =
|
||||
func_ctx.resolve_type(expr, &module.types).pointer_space()
|
||||
{
|
||||
// do nothing, the chain is written on `Load`/`Store`
|
||||
} else {
|
||||
|
@ -2450,7 +2435,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
dim,
|
||||
arrayed,
|
||||
class,
|
||||
} = *func_ctx.info[image].ty.inner_with(&module.types)
|
||||
} = *func_ctx.resolve_type(image, &module.types)
|
||||
{
|
||||
let wrapped_image_query = WrappedImageQuery {
|
||||
dim,
|
||||
|
@ -2499,8 +2484,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
write!(self.out, ")")?;
|
||||
|
||||
// return x component if return type is scalar
|
||||
if let TypeInner::Scalar { .. } = *func_ctx.info[expr].ty.inner_with(&module.types)
|
||||
{
|
||||
if let TypeInner::Scalar { .. } = *func_ctx.resolve_type(expr, &module.types) {
|
||||
write!(self.out, ".x")?;
|
||||
}
|
||||
}
|
||||
|
@ -2515,9 +2499,8 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
write!(self.out, "{}", self.names[&func_ctx.name_key(handle)])?
|
||||
}
|
||||
Expression::Load { pointer } => {
|
||||
match func_ctx.info[pointer]
|
||||
.ty
|
||||
.inner_with(&module.types)
|
||||
match func_ctx
|
||||
.resolve_type(pointer, &module.types)
|
||||
.pointer_space()
|
||||
{
|
||||
Some(crate::AddressSpace::Storage { .. }) => {
|
||||
|
@ -2541,7 +2524,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
)
|
||||
.or_else(|| get_inner_matrix_of_global_uniform(module, pointer, func_ctx))
|
||||
{
|
||||
let mut resolved = func_ctx.info[pointer].ty.inner_with(&module.types);
|
||||
let mut resolved = func_ctx.resolve_type(pointer, &module.types);
|
||||
if let TypeInner::Pointer { base, .. } = *resolved {
|
||||
resolved = &module.types[base].inner;
|
||||
}
|
||||
|
@ -2581,7 +2564,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
kind,
|
||||
convert,
|
||||
} => {
|
||||
let inner = func_ctx.info[expr].ty.inner_with(&module.types);
|
||||
let inner = func_ctx.resolve_type(expr, &module.types);
|
||||
match convert {
|
||||
Some(dst_width) => {
|
||||
match *inner {
|
||||
|
@ -2956,11 +2939,8 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
write!(self.out, ")")?
|
||||
}
|
||||
Function::MissingIntOverload(fun_name) => {
|
||||
let scalar_kind = &func_ctx.info[arg]
|
||||
.ty
|
||||
.inner_with(&module.types)
|
||||
.scalar_kind();
|
||||
if let Some(ScalarKind::Sint) = *scalar_kind {
|
||||
let scalar_kind = func_ctx.resolve_type(arg, &module.types).scalar_kind();
|
||||
if let Some(ScalarKind::Sint) = scalar_kind {
|
||||
write!(self.out, "asint({fun_name}(asuint(")?;
|
||||
self.write_expr(module, arg, func_ctx)?;
|
||||
write!(self.out, ")))")?;
|
||||
|
@ -2971,11 +2951,8 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
}
|
||||
}
|
||||
Function::MissingIntReturnType(fun_name) => {
|
||||
let scalar_kind = &func_ctx.info[arg]
|
||||
.ty
|
||||
.inner_with(&module.types)
|
||||
.scalar_kind();
|
||||
if let Some(ScalarKind::Sint) = *scalar_kind {
|
||||
let scalar_kind = func_ctx.resolve_type(arg, &module.types).scalar_kind();
|
||||
if let Some(ScalarKind::Sint) = scalar_kind {
|
||||
write!(self.out, "asint({fun_name}(")?;
|
||||
self.write_expr(module, arg, func_ctx)?;
|
||||
write!(self.out, "))")?;
|
||||
|
@ -2986,7 +2963,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
}
|
||||
}
|
||||
Function::CountTrailingZeros => {
|
||||
match *func_ctx.info[arg].ty.inner_with(&module.types) {
|
||||
match *func_ctx.resolve_type(arg, &module.types) {
|
||||
TypeInner::Vector { size, kind, .. } => {
|
||||
let s = match size {
|
||||
crate::VectorSize::Bi => ".xx",
|
||||
|
@ -3021,7 +2998,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
return Ok(());
|
||||
}
|
||||
Function::CountLeadingZeros => {
|
||||
match *func_ctx.info[arg].ty.inner_with(&module.types) {
|
||||
match *func_ctx.resolve_type(arg, &module.types) {
|
||||
TypeInner::Vector { size, kind, .. } => {
|
||||
let s = match size {
|
||||
crate::VectorSize::Bi => ".xx",
|
||||
|
@ -3209,8 +3186,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
}
|
||||
}
|
||||
|
||||
let base_ty_res = &ctx.info[named].ty;
|
||||
let resolved = base_ty_res.inner_with(&module.types);
|
||||
let resolved = ctx.resolve_type(named, &module.types);
|
||||
|
||||
write!(self.out, " {name}")?;
|
||||
// If rhs is a array type, we should write array size
|
||||
|
@ -3287,7 +3263,7 @@ pub(super) fn get_inner_matrix_of_struct_array_member(
|
|||
|
||||
let mut current_base = base;
|
||||
loop {
|
||||
let mut resolved = func_ctx.info[current_base].ty.inner_with(&module.types);
|
||||
let mut resolved = func_ctx.resolve_type(current_base, &module.types);
|
||||
if let TypeInner::Pointer { base, .. } = *resolved {
|
||||
resolved = &module.types[base].inner;
|
||||
};
|
||||
|
@ -3344,7 +3320,7 @@ fn get_inner_matrix_of_global_uniform(
|
|||
|
||||
let mut current_base = base;
|
||||
loop {
|
||||
let mut resolved = func_ctx.info[current_base].ty.inner_with(&module.types);
|
||||
let mut resolved = func_ctx.resolve_type(current_base, &module.types);
|
||||
if let TypeInner::Pointer { base, .. } = *resolved {
|
||||
resolved = &module.types[base].inner;
|
||||
};
|
||||
|
|
|
@ -135,7 +135,7 @@ impl FunctionCtx<'_> {
|
|||
};
|
||||
}
|
||||
crate::Expression::AccessIndex { base, index } => {
|
||||
match *self.info[base].ty.inner_with(&module.types) {
|
||||
match *self.resolve_type(base, &module.types) {
|
||||
crate::TypeInner::Struct { ref members, .. } => {
|
||||
if let Some(crate::Binding::BuiltIn(bi)) =
|
||||
members[index as usize].binding
|
||||
|
|
|
@ -2624,11 +2624,7 @@ impl<W: Write> Writer<W> {
|
|||
)?;
|
||||
}
|
||||
|
||||
let info = &context.expression.info[handle];
|
||||
let ptr_class = info
|
||||
.ty
|
||||
.inner_with(&context.expression.module.types)
|
||||
.pointer_space();
|
||||
let ptr_class = context.expression.resolve_type(handle).pointer_space();
|
||||
let expr_name = if ptr_class.is_some() {
|
||||
None // don't bake pointer expressions (just yet)
|
||||
} else if let Some(name) =
|
||||
|
|
|
@ -177,7 +177,11 @@ pub enum Error<'a> {
|
|||
InconsistentBinding(Span),
|
||||
TypeNotConstructible(Span),
|
||||
TypeNotInferrable(Span),
|
||||
InitializationTypeMismatch(Span, String, String),
|
||||
InitializationTypeMismatch {
|
||||
name: Span,
|
||||
expected: String,
|
||||
got: String,
|
||||
},
|
||||
MissingType(Span),
|
||||
MissingAttribute(&'static str, Span),
|
||||
InvalidAtomicPointer(Span),
|
||||
|
@ -233,7 +237,7 @@ pub enum Error<'a> {
|
|||
},
|
||||
FunctionReturnsVoid(Span),
|
||||
InvalidWorkGroupUniformLoad(Span),
|
||||
Other,
|
||||
Internal(&'static str),
|
||||
ExpectedConstExprConcreteIntegerScalar(Span),
|
||||
ExpectedNonNegative(Span),
|
||||
ExpectedPositiveArrayLength(Span),
|
||||
|
@ -475,15 +479,15 @@ impl<'a> Error<'a> {
|
|||
labels: vec![(span, "type can't be inferred".into())],
|
||||
notes: vec![],
|
||||
},
|
||||
Error::InitializationTypeMismatch(name_span, ref expected_ty, ref got_ty) => {
|
||||
Error::InitializationTypeMismatch { name, ref expected, ref got } => {
|
||||
ParseError {
|
||||
message: format!(
|
||||
"the type of `{}` is expected to be `{}`, but got `{}`",
|
||||
&source[name_span], expected_ty, got_ty,
|
||||
&source[name], expected, got,
|
||||
),
|
||||
labels: vec![(
|
||||
name_span,
|
||||
format!("definition of `{}`", &source[name_span]).into(),
|
||||
name,
|
||||
format!("definition of `{}`", &source[name]).into(),
|
||||
)],
|
||||
notes: vec![],
|
||||
}
|
||||
|
@ -667,10 +671,10 @@ impl<'a> Error<'a> {
|
|||
labels: vec![(span, "".into())],
|
||||
notes: vec!["passed type must be a workgroup pointer".into()],
|
||||
},
|
||||
Error::Other => ParseError {
|
||||
message: "other error".to_string(),
|
||||
Error::Internal(message) => ParseError {
|
||||
message: "internal WGSL front end error".to_string(),
|
||||
labels: vec![],
|
||||
notes: vec![],
|
||||
notes: vec![message.into()],
|
||||
},
|
||||
Error::ExpectedConstExprConcreteIntegerScalar(span) => ParseError {
|
||||
message: "must be a const-expression that resolves to a concrete integer scalar (u32 or i32)".to_string(),
|
||||
|
|
|
@ -5,47 +5,58 @@ use crate::{Handle, Span};
|
|||
|
||||
use crate::front::wgsl::error::Error;
|
||||
use crate::front::wgsl::lower::{ExpressionContext, Lowerer};
|
||||
use crate::proc::TypeResolution;
|
||||
|
||||
enum ConcreteConstructorHandle {
|
||||
PartialVector {
|
||||
size: crate::VectorSize,
|
||||
},
|
||||
/// A cooked form of `ast::ConstructorType` that uses Naga types whenever
|
||||
/// possible.
|
||||
enum Constructor<T> {
|
||||
/// A vector construction whose component type is inferred from the
|
||||
/// argument: `vec3(1.0)`.
|
||||
PartialVector { size: crate::VectorSize },
|
||||
|
||||
/// A matrix construction whose component type is inferred from the
|
||||
/// argument: `mat2x2(1,2,3,4)`.
|
||||
PartialMatrix {
|
||||
columns: crate::VectorSize,
|
||||
rows: crate::VectorSize,
|
||||
},
|
||||
|
||||
/// An array whose component type and size are inferred from the arguments:
|
||||
/// `array(3,4,5)`.
|
||||
PartialArray,
|
||||
Type(Handle<crate::Type>),
|
||||
|
||||
/// A known Naga type.
|
||||
///
|
||||
/// When we match on this type, we need to see the `TypeInner` here, but at
|
||||
/// the point that we build this value we'll still need mutable access to
|
||||
/// the module later. To avoid borrowing from the module, the type parameter
|
||||
/// `T` is `Handle<Type>` initially. Then we use `borrow_inner` to produce a
|
||||
/// version holding a tuple `(Handle<Type>, &TypeInner)`.
|
||||
Type(T),
|
||||
}
|
||||
|
||||
impl ConcreteConstructorHandle {
|
||||
fn borrow<'a>(&self, module: &'a crate::Module) -> ConcreteConstructor<'a> {
|
||||
match *self {
|
||||
Self::PartialVector { size } => ConcreteConstructor::PartialVector { size },
|
||||
Self::PartialMatrix { columns, rows } => {
|
||||
ConcreteConstructor::PartialMatrix { columns, rows }
|
||||
impl Constructor<Handle<crate::Type>> {
|
||||
/// Return an equivalent `Constructor` value that includes borrowed
|
||||
/// `TypeInner` values alongside any type handles.
|
||||
///
|
||||
/// The returned form is more convenient to match on, since the patterns
|
||||
/// can actually see what the handle refers to.
|
||||
fn borrow_inner(
|
||||
self,
|
||||
module: &crate::Module,
|
||||
) -> Constructor<(Handle<crate::Type>, &crate::TypeInner)> {
|
||||
match self {
|
||||
Constructor::PartialVector { size } => Constructor::PartialVector { size },
|
||||
Constructor::PartialMatrix { columns, rows } => {
|
||||
Constructor::PartialMatrix { columns, rows }
|
||||
}
|
||||
Self::PartialArray => ConcreteConstructor::PartialArray,
|
||||
Self::Type(handle) => ConcreteConstructor::Type(handle, &module.types[handle].inner),
|
||||
Constructor::PartialArray => Constructor::PartialArray,
|
||||
Constructor::Type(handle) => Constructor::Type((handle, &module.types[handle].inner)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum ConcreteConstructor<'a> {
|
||||
PartialVector {
|
||||
size: crate::VectorSize,
|
||||
},
|
||||
PartialMatrix {
|
||||
columns: crate::VectorSize,
|
||||
rows: crate::VectorSize,
|
||||
},
|
||||
PartialArray,
|
||||
Type(Handle<crate::Type>, &'a crate::TypeInner),
|
||||
}
|
||||
|
||||
impl ConcreteConstructorHandle {
|
||||
fn to_error_string(&self, ctx: ExpressionContext) -> String {
|
||||
impl Constructor<(Handle<crate::Type>, &crate::TypeInner)> {
|
||||
fn to_error_string(&self, ctx: &ExpressionContext) -> String {
|
||||
match *self {
|
||||
Self::PartialVector { size } => {
|
||||
format!("vec{}<?>", size as u32,)
|
||||
|
@ -54,47 +65,7 @@ impl ConcreteConstructorHandle {
|
|||
format!("mat{}x{}<?>", columns as u32, rows as u32,)
|
||||
}
|
||||
Self::PartialArray => "array<?, ?>".to_string(),
|
||||
Self::Type(ty) => ctx.format_type(ty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum ComponentsHandle<'a> {
|
||||
None,
|
||||
One {
|
||||
component: Handle<crate::Expression>,
|
||||
span: Span,
|
||||
ty: &'a TypeResolution,
|
||||
},
|
||||
Many {
|
||||
components: Vec<Handle<crate::Expression>>,
|
||||
spans: Vec<Span>,
|
||||
first_component_ty: &'a TypeResolution,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'a> ComponentsHandle<'a> {
|
||||
fn borrow(self, module: &'a crate::Module) -> Components<'a> {
|
||||
match self {
|
||||
Self::None => Components::None,
|
||||
Self::One {
|
||||
component,
|
||||
span,
|
||||
ty,
|
||||
} => Components::One {
|
||||
component,
|
||||
span,
|
||||
ty_inner: ty.inner_with(&module.types),
|
||||
},
|
||||
Self::Many {
|
||||
components,
|
||||
spans,
|
||||
first_component_ty,
|
||||
} => Components::Many {
|
||||
components,
|
||||
spans,
|
||||
first_component_ty_inner: first_component_ty.inner_with(&module.types),
|
||||
},
|
||||
Self::Type((handle, _inner)) => ctx.format_type(handle),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -143,32 +114,31 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||
constructor: &ast::ConstructorType<'source>,
|
||||
ty_span: Span,
|
||||
components: &[Handle<ast::Expression<'source>>],
|
||||
mut ctx: ExpressionContext<'source, '_, '_>,
|
||||
ctx: &mut ExpressionContext<'source, '_, '_>,
|
||||
) -> Result<Handle<crate::Expression>, Error<'source>> {
|
||||
let constructor_h = self.constructor(constructor, ctx.reborrow())?;
|
||||
let constructor_h = self.constructor(constructor, ctx)?;
|
||||
|
||||
let components_h = match *components {
|
||||
[] => ComponentsHandle::None,
|
||||
let components = match *components {
|
||||
[] => Components::None,
|
||||
[component] => {
|
||||
let span = ctx.ast_expressions.get_span(component);
|
||||
let component = self.expression(component, ctx.reborrow())?;
|
||||
ctx.grow_types(component)?;
|
||||
let ty = &ctx.typifier()[component];
|
||||
let component = self.expression(component, ctx)?;
|
||||
let ty_inner = super::resolve_inner!(ctx, component);
|
||||
|
||||
ComponentsHandle::One {
|
||||
Components::One {
|
||||
component,
|
||||
span,
|
||||
ty,
|
||||
ty_inner,
|
||||
}
|
||||
}
|
||||
[component, ref rest @ ..] => {
|
||||
let span = ctx.ast_expressions.get_span(component);
|
||||
let component = self.expression(component, ctx.reborrow())?;
|
||||
let component = self.expression(component, ctx)?;
|
||||
|
||||
let components = std::iter::once(Ok(component))
|
||||
.chain(
|
||||
rest.iter()
|
||||
.map(|&component| self.expression(component, ctx.reborrow())),
|
||||
.map(|&component| self.expression(component, ctx)),
|
||||
)
|
||||
.collect::<Result<_, _>>()?;
|
||||
let spans = std::iter::once(span)
|
||||
|
@ -178,28 +148,34 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||
)
|
||||
.collect();
|
||||
|
||||
ctx.grow_types(component)?;
|
||||
let ty = &ctx.typifier()[component];
|
||||
let first_component_ty_inner = super::resolve_inner!(ctx, component);
|
||||
|
||||
ComponentsHandle::Many {
|
||||
Components::Many {
|
||||
components,
|
||||
spans,
|
||||
first_component_ty: ty,
|
||||
first_component_ty_inner,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let (components, constructor) = (
|
||||
components_h.borrow(ctx.module),
|
||||
constructor_h.borrow(ctx.module),
|
||||
);
|
||||
// Even though we computed `constructor` above, wait until now to borrow
|
||||
// a reference to the `TypeInner`, so that the component-handling code
|
||||
// above can have mutable access to the type arena.
|
||||
let constructor = constructor_h.borrow_inner(ctx.module);
|
||||
|
||||
let expr = match (components, constructor) {
|
||||
// Empty constructor
|
||||
(Components::None, dst_ty) => match dst_ty {
|
||||
ConcreteConstructor::Type(ty, _) => {
|
||||
return ctx.append_expression(crate::Expression::ZeroValue(ty), span)
|
||||
Constructor::Type((result_ty, _)) => {
|
||||
return ctx.append_expression(crate::Expression::ZeroValue(result_ty), span)
|
||||
}
|
||||
Constructor::PartialVector { .. }
|
||||
| Constructor::PartialMatrix { .. }
|
||||
| Constructor::PartialArray => {
|
||||
// We have no arguments from which to infer the result type, so
|
||||
// partial constructors aren't acceptable here.
|
||||
return Err(Error::TypeNotInferrable(ty_span));
|
||||
}
|
||||
_ => return Err(Error::TypeNotInferrable(ty_span)),
|
||||
},
|
||||
|
||||
// Scalar constructor & conversion (scalar -> scalar)
|
||||
|
@ -209,7 +185,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||
ty_inner: &crate::TypeInner::Scalar { .. },
|
||||
..
|
||||
},
|
||||
ConcreteConstructor::Type(_, &crate::TypeInner::Scalar { kind, width }),
|
||||
Constructor::Type((_, &crate::TypeInner::Scalar { kind, width })),
|
||||
) => crate::Expression::As {
|
||||
expr: component,
|
||||
kind,
|
||||
|
@ -223,14 +199,14 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||
ty_inner: &crate::TypeInner::Vector { size: src_size, .. },
|
||||
..
|
||||
},
|
||||
ConcreteConstructor::Type(
|
||||
Constructor::Type((
|
||||
_,
|
||||
&crate::TypeInner::Vector {
|
||||
size: dst_size,
|
||||
kind: dst_kind,
|
||||
width: dst_width,
|
||||
},
|
||||
),
|
||||
)),
|
||||
) if dst_size == src_size => crate::Expression::As {
|
||||
expr: component,
|
||||
kind: dst_kind,
|
||||
|
@ -241,20 +217,16 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||
(
|
||||
Components::One {
|
||||
component,
|
||||
ty_inner:
|
||||
&crate::TypeInner::Vector {
|
||||
size: src_size,
|
||||
kind: src_kind,
|
||||
ty_inner: &crate::TypeInner::Vector { size: src_size, .. },
|
||||
..
|
||||
},
|
||||
..
|
||||
},
|
||||
ConcreteConstructor::PartialVector { size: dst_size },
|
||||
) if dst_size == src_size => crate::Expression::As {
|
||||
expr: component,
|
||||
kind: src_kind,
|
||||
convert: None,
|
||||
},
|
||||
Constructor::PartialVector { size: dst_size },
|
||||
) if dst_size == src_size => {
|
||||
// This is a trivial conversion: the sizes match, and a Partial
|
||||
// constructor doesn't specify a scalar type, so nothing can
|
||||
// possibly happen.
|
||||
return Ok(component);
|
||||
}
|
||||
|
||||
// Matrix conversion (matrix -> matrix)
|
||||
(
|
||||
|
@ -268,14 +240,14 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||
},
|
||||
..
|
||||
},
|
||||
ConcreteConstructor::Type(
|
||||
Constructor::Type((
|
||||
_,
|
||||
&crate::TypeInner::Matrix {
|
||||
columns: dst_columns,
|
||||
rows: dst_rows,
|
||||
width: dst_width,
|
||||
},
|
||||
),
|
||||
)),
|
||||
) if dst_columns == src_columns && dst_rows == src_rows => crate::Expression::As {
|
||||
expr: component,
|
||||
kind: crate::ScalarKind::Float,
|
||||
|
@ -294,15 +266,16 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||
},
|
||||
..
|
||||
},
|
||||
ConcreteConstructor::PartialMatrix {
|
||||
Constructor::PartialMatrix {
|
||||
columns: dst_columns,
|
||||
rows: dst_rows,
|
||||
},
|
||||
) if dst_columns == src_columns && dst_rows == src_rows => crate::Expression::As {
|
||||
expr: component,
|
||||
kind: crate::ScalarKind::Float,
|
||||
convert: None,
|
||||
},
|
||||
) if dst_columns == src_columns && dst_rows == src_rows => {
|
||||
// This is a trivial conversion: the sizes match, and a Partial
|
||||
// constructor doesn't specify a scalar type, so nothing can
|
||||
// possibly happen.
|
||||
return Ok(component);
|
||||
}
|
||||
|
||||
// Vector constructor (splat) - infer type
|
||||
(
|
||||
|
@ -311,7 +284,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||
ty_inner: &crate::TypeInner::Scalar { .. },
|
||||
..
|
||||
},
|
||||
ConcreteConstructor::PartialVector { size },
|
||||
Constructor::PartialVector { size },
|
||||
) => crate::Expression::Splat {
|
||||
size,
|
||||
value: component,
|
||||
|
@ -329,14 +302,14 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||
},
|
||||
..
|
||||
},
|
||||
ConcreteConstructor::Type(
|
||||
Constructor::Type((
|
||||
_,
|
||||
&crate::TypeInner::Vector {
|
||||
size,
|
||||
kind: dst_kind,
|
||||
width: dst_width,
|
||||
},
|
||||
),
|
||||
)),
|
||||
) if dst_kind == src_kind || dst_width == src_width => crate::Expression::Splat {
|
||||
size,
|
||||
value: component,
|
||||
|
@ -351,7 +324,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||
| &crate::TypeInner::Vector { kind, width, .. },
|
||||
..
|
||||
},
|
||||
ConcreteConstructor::PartialVector { size },
|
||||
Constructor::PartialVector { size },
|
||||
)
|
||||
| (
|
||||
Components::Many {
|
||||
|
@ -360,7 +333,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||
&crate::TypeInner::Scalar { .. } | &crate::TypeInner::Vector { .. },
|
||||
..
|
||||
},
|
||||
ConcreteConstructor::Type(_, &crate::TypeInner::Vector { size, width, kind }),
|
||||
Constructor::Type((_, &crate::TypeInner::Vector { size, width, kind })),
|
||||
) => {
|
||||
let inner = crate::TypeInner::Vector { size, kind, width };
|
||||
let ty = ctx.ensure_type_exists(inner);
|
||||
|
@ -374,7 +347,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||
first_component_ty_inner: &crate::TypeInner::Scalar { width, .. },
|
||||
..
|
||||
},
|
||||
ConcreteConstructor::PartialMatrix { columns, rows },
|
||||
Constructor::PartialMatrix { columns, rows },
|
||||
)
|
||||
| (
|
||||
Components::Many {
|
||||
|
@ -382,14 +355,14 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||
first_component_ty_inner: &crate::TypeInner::Scalar { .. },
|
||||
..
|
||||
},
|
||||
ConcreteConstructor::Type(
|
||||
Constructor::Type((
|
||||
_,
|
||||
&crate::TypeInner::Matrix {
|
||||
columns,
|
||||
rows,
|
||||
width,
|
||||
},
|
||||
),
|
||||
)),
|
||||
) => {
|
||||
let vec_ty = ctx.ensure_type_exists(crate::TypeInner::Vector {
|
||||
width,
|
||||
|
@ -425,7 +398,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||
first_component_ty_inner: &crate::TypeInner::Vector { width, .. },
|
||||
..
|
||||
},
|
||||
ConcreteConstructor::PartialMatrix { columns, rows },
|
||||
Constructor::PartialMatrix { columns, rows },
|
||||
)
|
||||
| (
|
||||
Components::Many {
|
||||
|
@ -433,14 +406,14 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||
first_component_ty_inner: &crate::TypeInner::Vector { .. },
|
||||
..
|
||||
},
|
||||
ConcreteConstructor::Type(
|
||||
Constructor::Type((
|
||||
_,
|
||||
&crate::TypeInner::Matrix {
|
||||
columns,
|
||||
rows,
|
||||
width,
|
||||
},
|
||||
),
|
||||
)),
|
||||
) => {
|
||||
let ty = ctx.ensure_type_exists(crate::TypeInner::Matrix {
|
||||
columns,
|
||||
|
@ -451,7 +424,7 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||
}
|
||||
|
||||
// Array constructor - infer type
|
||||
(components, ConcreteConstructor::PartialArray) => {
|
||||
(components, Constructor::PartialArray) => {
|
||||
let components = components.into_components_vec();
|
||||
|
||||
let base = ctx.register_type(components[0])?;
|
||||
|
@ -471,36 +444,34 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||
crate::Expression::Compose { ty, components }
|
||||
}
|
||||
|
||||
// Array constructor
|
||||
(components, ConcreteConstructor::Type(ty, &crate::TypeInner::Array { .. })) => {
|
||||
// Array or Struct constructor
|
||||
(
|
||||
components,
|
||||
Constructor::Type((
|
||||
ty,
|
||||
&crate::TypeInner::Array { .. } | &crate::TypeInner::Struct { .. },
|
||||
)),
|
||||
) => {
|
||||
let components = components.into_components_vec();
|
||||
crate::Expression::Compose { ty, components }
|
||||
}
|
||||
|
||||
// Struct constructor
|
||||
(components, ConcreteConstructor::Type(ty, &crate::TypeInner::Struct { .. })) => {
|
||||
crate::Expression::Compose {
|
||||
ty,
|
||||
components: components.into_components_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
// ERRORS
|
||||
|
||||
// Bad conversion (type cast)
|
||||
(Components::One { span, ty_inner, .. }, _) => {
|
||||
(Components::One { span, ty_inner, .. }, constructor) => {
|
||||
let from_type = ctx.format_typeinner(ty_inner);
|
||||
return Err(Error::BadTypeCast {
|
||||
span,
|
||||
from_type,
|
||||
to_type: constructor_h.to_error_string(ctx.reborrow()),
|
||||
to_type: constructor.to_error_string(ctx),
|
||||
});
|
||||
}
|
||||
|
||||
// Too many parameters for scalar constructor
|
||||
(
|
||||
Components::Many { spans, .. },
|
||||
ConcreteConstructor::Type(_, &crate::TypeInner::Scalar { .. }),
|
||||
Constructor::Type((_, &crate::TypeInner::Scalar { .. })),
|
||||
) => {
|
||||
let span = spans[1].until(spans.last().unwrap());
|
||||
return Err(Error::UnexpectedComponents(span));
|
||||
|
@ -509,12 +480,12 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||
// Parameters are of the wrong type for vector or matrix constructor
|
||||
(
|
||||
Components::Many { spans, .. },
|
||||
ConcreteConstructor::Type(
|
||||
Constructor::Type((
|
||||
_,
|
||||
&crate::TypeInner::Vector { .. } | &crate::TypeInner::Matrix { .. },
|
||||
)
|
||||
| ConcreteConstructor::PartialVector { .. }
|
||||
| ConcreteConstructor::PartialMatrix { .. },
|
||||
))
|
||||
| Constructor::PartialVector { .. }
|
||||
| Constructor::PartialMatrix { .. },
|
||||
) => {
|
||||
return Err(Error::InvalidConstructorComponentType(spans[0], 0));
|
||||
}
|
||||
|
@ -527,45 +498,35 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||
Ok(expr)
|
||||
}
|
||||
|
||||
/// Build a Naga IR [`Type`] for `constructor` if there is enough
|
||||
/// information to do so.
|
||||
/// Build a [`Constructor`] for a WGSL construction expression.
|
||||
///
|
||||
/// For `Partial` variants of [`ast::ConstructorType`], we don't know the
|
||||
/// component type, so in that case we return the appropriate `Partial`
|
||||
/// variant of [`ConcreteConstructorHandle`].
|
||||
/// If `constructor` conveys enough information to determine which Naga [`Type`]
|
||||
/// we're actually building (i.e., it's not a partial constructor), then
|
||||
/// ensure the `Type` exists in [`ctx.module`], and return
|
||||
/// [`Constructor::Type`].
|
||||
///
|
||||
/// But for the other `ConstructorType` variants, we have everything we need
|
||||
/// to know to actually produce a Naga IR type. In this case we add to/find
|
||||
/// in [`ctx.module`] a suitable Naga `Type` and return a
|
||||
/// [`ConcreteConstructorHandle::Type`] value holding its handle.
|
||||
///
|
||||
/// Note that constructing an [`Array`] type may require inserting
|
||||
/// [`Constant`]s as well as `Type`s into `ctx.module`, to represent the
|
||||
/// array's length.
|
||||
/// Otherwise, return the [`Constructor`] partial variant corresponding to
|
||||
/// `constructor`.
|
||||
///
|
||||
/// [`Type`]: crate::Type
|
||||
/// [`ctx.module`]: ExpressionContext::module
|
||||
/// [`Array`]: crate::TypeInner::Array
|
||||
/// [`Constant`]: crate::Constant
|
||||
fn constructor<'out>(
|
||||
&mut self,
|
||||
constructor: &ast::ConstructorType<'source>,
|
||||
mut ctx: ExpressionContext<'source, '_, 'out>,
|
||||
) -> Result<ConcreteConstructorHandle, Error<'source>> {
|
||||
let c = match *constructor {
|
||||
ctx: &mut ExpressionContext<'source, '_, 'out>,
|
||||
) -> Result<Constructor<Handle<crate::Type>>, Error<'source>> {
|
||||
let handle = match *constructor {
|
||||
ast::ConstructorType::Scalar { width, kind } => {
|
||||
let ty = ctx.ensure_type_exists(crate::TypeInner::Scalar { width, kind });
|
||||
ConcreteConstructorHandle::Type(ty)
|
||||
}
|
||||
ast::ConstructorType::PartialVector { size } => {
|
||||
ConcreteConstructorHandle::PartialVector { size }
|
||||
Constructor::Type(ty)
|
||||
}
|
||||
ast::ConstructorType::PartialVector { size } => Constructor::PartialVector { size },
|
||||
ast::ConstructorType::Vector { size, kind, width } => {
|
||||
let ty = ctx.ensure_type_exists(crate::TypeInner::Vector { size, kind, width });
|
||||
ConcreteConstructorHandle::Type(ty)
|
||||
Constructor::Type(ty)
|
||||
}
|
||||
ast::ConstructorType::PartialMatrix { rows, columns } => {
|
||||
ConcreteConstructorHandle::PartialMatrix { rows, columns }
|
||||
ast::ConstructorType::PartialMatrix { columns, rows } => {
|
||||
Constructor::PartialMatrix { columns, rows }
|
||||
}
|
||||
ast::ConstructorType::Matrix {
|
||||
rows,
|
||||
|
@ -577,22 +538,22 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
|
|||
rows,
|
||||
width,
|
||||
});
|
||||
ConcreteConstructorHandle::Type(ty)
|
||||
Constructor::Type(ty)
|
||||
}
|
||||
ast::ConstructorType::PartialArray => ConcreteConstructorHandle::PartialArray,
|
||||
ast::ConstructorType::PartialArray => Constructor::PartialArray,
|
||||
ast::ConstructorType::Array { base, size } => {
|
||||
let base = self.resolve_ast_type(base, ctx.as_global())?;
|
||||
let size = self.array_size(size, ctx.as_global())?;
|
||||
let base = self.resolve_ast_type(base, &mut ctx.as_global())?;
|
||||
let size = self.array_size(size, &mut ctx.as_global())?;
|
||||
|
||||
self.layouter.update(ctx.module.to_ctx()).unwrap();
|
||||
let stride = self.layouter[base].to_stride();
|
||||
|
||||
let ty = ctx.ensure_type_exists(crate::TypeInner::Array { base, size, stride });
|
||||
ConcreteConstructorHandle::Type(ty)
|
||||
Constructor::Type(ty)
|
||||
}
|
||||
ast::ConstructorType::Type(ty) => ConcreteConstructorHandle::Type(ty),
|
||||
ast::ConstructorType::Type(ty) => Constructor::Type(ty),
|
||||
};
|
||||
|
||||
Ok(c)
|
||||
Ok(handle)
|
||||
}
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -350,9 +350,7 @@ impl<'a> Lexer<'a> {
|
|||
&mut self,
|
||||
) -> Result<(&'a str, Span), Error<'a>> {
|
||||
match self.next() {
|
||||
(Token::Word(word), span) if word == "_" => {
|
||||
Err(Error::InvalidIdentifierUnderscore(span))
|
||||
}
|
||||
(Token::Word("_"), span) => Err(Error::InvalidIdentifierUnderscore(span)),
|
||||
(Token::Word(word), span) if word.starts_with("__") => {
|
||||
Err(Error::ReservedIdentifierPrefix(span))
|
||||
}
|
||||
|
|
|
@ -55,31 +55,21 @@ struct ExpressionContext<'input, 'temp, 'out> {
|
|||
}
|
||||
|
||||
impl<'a> ExpressionContext<'a, '_, '_> {
|
||||
fn reborrow(&mut self) -> ExpressionContext<'a, '_, '_> {
|
||||
ExpressionContext {
|
||||
expressions: self.expressions,
|
||||
types: self.types,
|
||||
local_table: self.local_table,
|
||||
locals: self.locals,
|
||||
unresolved: self.unresolved,
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_binary_op(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
classifier: impl Fn(Token<'a>) -> Option<crate::BinaryOperator>,
|
||||
mut parser: impl FnMut(
|
||||
&mut Lexer<'a>,
|
||||
ExpressionContext<'a, '_, '_>,
|
||||
&mut Self,
|
||||
) -> Result<Handle<ast::Expression<'a>>, Error<'a>>,
|
||||
) -> Result<Handle<ast::Expression<'a>>, Error<'a>> {
|
||||
let start = lexer.start_byte_offset();
|
||||
let mut accumulator = parser(lexer, self.reborrow())?;
|
||||
let mut accumulator = parser(lexer, self)?;
|
||||
while let Some(op) = classifier(lexer.peek().0) {
|
||||
let _ = lexer.next();
|
||||
let left = accumulator;
|
||||
let right = parser(lexer, self.reborrow())?;
|
||||
let right = parser(lexer, self)?;
|
||||
accumulator = self.expressions.append(
|
||||
ast::Expression::Binary { op, left, right },
|
||||
lexer.span_from(start),
|
||||
|
@ -157,13 +147,13 @@ impl<'a> BindingParser<'a> {
|
|||
lexer: &mut Lexer<'a>,
|
||||
name: &'a str,
|
||||
name_span: Span,
|
||||
mut ctx: ExpressionContext<'a, '_, '_>,
|
||||
ctx: &mut ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<(), Error<'a>> {
|
||||
match name {
|
||||
"location" => {
|
||||
lexer.expect(Token::Paren('('))?;
|
||||
self.location
|
||||
.set(parser.general_expression(lexer, ctx.reborrow())?, name_span)?;
|
||||
.set(parser.general_expression(lexer, ctx)?, name_span)?;
|
||||
lexer.expect(Token::Paren(')'))?;
|
||||
}
|
||||
"builtin" => {
|
||||
|
@ -258,14 +248,14 @@ impl Parser {
|
|||
fn switch_value<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut ctx: ExpressionContext<'a, '_, '_>,
|
||||
ctx: &mut ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<ast::SwitchValue<'a>, Error<'a>> {
|
||||
if let Token::Word("default") = lexer.peek().0 {
|
||||
let _ = lexer.next();
|
||||
return Ok(ast::SwitchValue::Default);
|
||||
}
|
||||
|
||||
let expr = self.general_expression(lexer, ctx.reborrow())?;
|
||||
let expr = self.general_expression(lexer, ctx)?;
|
||||
Ok(ast::SwitchValue::Expr(expr))
|
||||
}
|
||||
|
||||
|
@ -285,7 +275,7 @@ impl Parser {
|
|||
lexer: &mut Lexer<'a>,
|
||||
word: &'a str,
|
||||
span: Span,
|
||||
mut ctx: ExpressionContext<'a, '_, '_>,
|
||||
ctx: &mut ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<Option<ast::ConstructorType<'a>>, Error<'a>> {
|
||||
if let Some((kind, width)) = conv::get_scalar_type(word) {
|
||||
return Ok(Some(ast::ConstructorType::Scalar { kind, width }));
|
||||
|
@ -509,9 +499,9 @@ impl Parser {
|
|||
}
|
||||
(Token::Paren('<'), ast::ConstructorType::PartialArray) => {
|
||||
lexer.expect_generic_paren('<')?;
|
||||
let base = self.type_decl(lexer, ctx.reborrow())?;
|
||||
let base = self.type_decl(lexer, ctx)?;
|
||||
let size = if lexer.skip(Token::Separator(',')) {
|
||||
let expr = self.unary_expression(lexer, ctx.reborrow())?;
|
||||
let expr = self.unary_expression(lexer, ctx)?;
|
||||
ast::ArraySize::Constant(expr)
|
||||
} else {
|
||||
ast::ArraySize::Dynamic
|
||||
|
@ -528,7 +518,7 @@ impl Parser {
|
|||
fn arguments<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut ctx: ExpressionContext<'a, '_, '_>,
|
||||
ctx: &mut ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<Vec<Handle<ast::Expression<'a>>>, Error<'a>> {
|
||||
lexer.open_arguments()?;
|
||||
let mut arguments = Vec::new();
|
||||
|
@ -540,7 +530,7 @@ impl Parser {
|
|||
} else if lexer.skip(Token::Paren(')')) {
|
||||
break;
|
||||
}
|
||||
let arg = self.general_expression(lexer, ctx.reborrow())?;
|
||||
let arg = self.general_expression(lexer, ctx)?;
|
||||
arguments.push(arg);
|
||||
}
|
||||
|
||||
|
@ -554,7 +544,7 @@ impl Parser {
|
|||
lexer: &mut Lexer<'a>,
|
||||
name: &'a str,
|
||||
name_span: Span,
|
||||
mut ctx: ExpressionContext<'a, '_, '_>,
|
||||
ctx: &mut ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<Handle<ast::Expression<'a>>, Error<'a>> {
|
||||
assert!(self.rules.last().is_some());
|
||||
|
||||
|
@ -563,12 +553,12 @@ impl Parser {
|
|||
"bitcast" => {
|
||||
lexer.expect_generic_paren('<')?;
|
||||
let start = lexer.start_byte_offset();
|
||||
let to = self.type_decl(lexer, ctx.reborrow())?;
|
||||
let to = self.type_decl(lexer, ctx)?;
|
||||
let span = lexer.span_from(start);
|
||||
lexer.expect_generic_paren('>')?;
|
||||
|
||||
lexer.open_arguments()?;
|
||||
let expr = self.general_expression(lexer, ctx.reborrow())?;
|
||||
let expr = self.general_expression(lexer, ctx)?;
|
||||
lexer.close_arguments()?;
|
||||
|
||||
ast::Expression::Bitcast {
|
||||
|
@ -579,7 +569,7 @@ impl Parser {
|
|||
}
|
||||
// everything else must be handled later, since they can be hidden by user-defined functions.
|
||||
_ => {
|
||||
let arguments = self.arguments(lexer, ctx.reborrow())?;
|
||||
let arguments = self.arguments(lexer, ctx)?;
|
||||
ctx.unresolved.insert(ast::Dependency {
|
||||
ident: name,
|
||||
usage: name_span,
|
||||
|
@ -603,7 +593,7 @@ impl Parser {
|
|||
&mut self,
|
||||
name: &'a str,
|
||||
name_span: Span,
|
||||
ctx: ExpressionContext<'a, '_, '_>,
|
||||
ctx: &mut ExpressionContext<'a, '_, '_>,
|
||||
) -> ast::IdentExpr<'a> {
|
||||
match ctx.local_table.lookup(name) {
|
||||
Some(&local) => ast::IdentExpr::Local(local),
|
||||
|
@ -620,14 +610,14 @@ impl Parser {
|
|||
fn primary_expression<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut ctx: ExpressionContext<'a, '_, '_>,
|
||||
ctx: &mut ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<Handle<ast::Expression<'a>>, Error<'a>> {
|
||||
self.push_rule_span(Rule::PrimaryExpr, lexer);
|
||||
|
||||
let expr = match lexer.peek() {
|
||||
(Token::Paren('('), _) => {
|
||||
let _ = lexer.next();
|
||||
let expr = self.general_expression(lexer, ctx.reborrow())?;
|
||||
let expr = self.general_expression(lexer, ctx)?;
|
||||
lexer.expect(Token::Paren(')'))?;
|
||||
self.pop_rule_span(lexer);
|
||||
return Ok(expr);
|
||||
|
@ -661,9 +651,9 @@ impl Parser {
|
|||
let start = lexer.start_byte_offset();
|
||||
let _ = lexer.next();
|
||||
|
||||
if let Some(ty) = self.constructor_type(lexer, word, span, ctx.reborrow())? {
|
||||
if let Some(ty) = self.constructor_type(lexer, word, span, ctx)? {
|
||||
let ty_span = lexer.span_from(start);
|
||||
let components = self.arguments(lexer, ctx.reborrow())?;
|
||||
let components = self.arguments(lexer, ctx)?;
|
||||
ast::Expression::Construct {
|
||||
ty,
|
||||
ty_span,
|
||||
|
@ -676,7 +666,7 @@ impl Parser {
|
|||
self.pop_rule_span(lexer);
|
||||
return self.function_call(lexer, word, span, ctx);
|
||||
} else {
|
||||
let ident = self.ident_expr(word, span, ctx.reborrow());
|
||||
let ident = self.ident_expr(word, span, ctx);
|
||||
ast::Expression::Ident(ident)
|
||||
}
|
||||
}
|
||||
|
@ -692,7 +682,7 @@ impl Parser {
|
|||
&mut self,
|
||||
span_start: usize,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut ctx: ExpressionContext<'a, '_, '_>,
|
||||
ctx: &mut ExpressionContext<'a, '_, '_>,
|
||||
expr: Handle<ast::Expression<'a>>,
|
||||
) -> Result<Handle<ast::Expression<'a>>, Error<'a>> {
|
||||
let mut expr = expr;
|
||||
|
@ -707,7 +697,7 @@ impl Parser {
|
|||
}
|
||||
Token::Paren('[') => {
|
||||
let _ = lexer.next();
|
||||
let index = self.general_expression(lexer, ctx.reborrow())?;
|
||||
let index = self.general_expression(lexer, ctx)?;
|
||||
lexer.expect(Token::Paren(']'))?;
|
||||
|
||||
ast::Expression::Index { base: expr, index }
|
||||
|
@ -726,14 +716,14 @@ impl Parser {
|
|||
fn unary_expression<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut ctx: ExpressionContext<'a, '_, '_>,
|
||||
ctx: &mut ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<Handle<ast::Expression<'a>>, Error<'a>> {
|
||||
self.push_rule_span(Rule::UnaryExpr, lexer);
|
||||
//TODO: refactor this to avoid backing up
|
||||
let expr = match lexer.peek().0 {
|
||||
Token::Operation('-') => {
|
||||
let _ = lexer.next();
|
||||
let expr = self.unary_expression(lexer, ctx.reborrow())?;
|
||||
let expr = self.unary_expression(lexer, ctx)?;
|
||||
let expr = ast::Expression::Unary {
|
||||
op: crate::UnaryOperator::Negate,
|
||||
expr,
|
||||
|
@ -743,7 +733,7 @@ impl Parser {
|
|||
}
|
||||
Token::Operation('!') => {
|
||||
let _ = lexer.next();
|
||||
let expr = self.unary_expression(lexer, ctx.reborrow())?;
|
||||
let expr = self.unary_expression(lexer, ctx)?;
|
||||
let expr = ast::Expression::Unary {
|
||||
op: crate::UnaryOperator::LogicalNot,
|
||||
expr,
|
||||
|
@ -753,7 +743,7 @@ impl Parser {
|
|||
}
|
||||
Token::Operation('~') => {
|
||||
let _ = lexer.next();
|
||||
let expr = self.unary_expression(lexer, ctx.reborrow())?;
|
||||
let expr = self.unary_expression(lexer, ctx)?;
|
||||
let expr = ast::Expression::Unary {
|
||||
op: crate::UnaryOperator::BitwiseNot,
|
||||
expr,
|
||||
|
@ -763,19 +753,19 @@ impl Parser {
|
|||
}
|
||||
Token::Operation('*') => {
|
||||
let _ = lexer.next();
|
||||
let expr = self.unary_expression(lexer, ctx.reborrow())?;
|
||||
let expr = self.unary_expression(lexer, ctx)?;
|
||||
let expr = ast::Expression::Deref(expr);
|
||||
let span = self.peek_rule_span(lexer);
|
||||
ctx.expressions.append(expr, span)
|
||||
}
|
||||
Token::Operation('&') => {
|
||||
let _ = lexer.next();
|
||||
let expr = self.unary_expression(lexer, ctx.reborrow())?;
|
||||
let expr = self.unary_expression(lexer, ctx)?;
|
||||
let expr = ast::Expression::AddrOf(expr);
|
||||
let span = self.peek_rule_span(lexer);
|
||||
ctx.expressions.append(expr, span)
|
||||
}
|
||||
_ => self.singular_expression(lexer, ctx.reborrow())?,
|
||||
_ => self.singular_expression(lexer, ctx)?,
|
||||
};
|
||||
|
||||
self.pop_rule_span(lexer);
|
||||
|
@ -786,12 +776,12 @@ impl Parser {
|
|||
fn singular_expression<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut ctx: ExpressionContext<'a, '_, '_>,
|
||||
ctx: &mut ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<Handle<ast::Expression<'a>>, Error<'a>> {
|
||||
let start = lexer.start_byte_offset();
|
||||
self.push_rule_span(Rule::SingularExpr, lexer);
|
||||
let primary_expr = self.primary_expression(lexer, ctx.reborrow())?;
|
||||
let singular_expr = self.postfix(start, lexer, ctx.reborrow(), primary_expr)?;
|
||||
let primary_expr = self.primary_expression(lexer, ctx)?;
|
||||
let singular_expr = self.postfix(start, lexer, ctx, primary_expr)?;
|
||||
self.pop_rule_span(lexer);
|
||||
|
||||
Ok(singular_expr)
|
||||
|
@ -800,7 +790,7 @@ impl Parser {
|
|||
fn equality_expression<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut context: ExpressionContext<'a, '_, '_>,
|
||||
context: &mut ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<Handle<ast::Expression<'a>>, Error<'a>> {
|
||||
// equality_expression
|
||||
context.parse_binary_op(
|
||||
|
@ -811,7 +801,7 @@ impl Parser {
|
|||
_ => None,
|
||||
},
|
||||
// relational_expression
|
||||
|lexer, mut context| {
|
||||
|lexer, context| {
|
||||
context.parse_binary_op(
|
||||
lexer,
|
||||
|token| match token {
|
||||
|
@ -822,7 +812,7 @@ impl Parser {
|
|||
_ => None,
|
||||
},
|
||||
// shift_expression
|
||||
|lexer, mut context| {
|
||||
|lexer, context| {
|
||||
context.parse_binary_op(
|
||||
lexer,
|
||||
|token| match token {
|
||||
|
@ -835,7 +825,7 @@ impl Parser {
|
|||
_ => None,
|
||||
},
|
||||
// additive_expression
|
||||
|lexer, mut context| {
|
||||
|lexer, context| {
|
||||
context.parse_binary_op(
|
||||
lexer,
|
||||
|token| match token {
|
||||
|
@ -846,7 +836,7 @@ impl Parser {
|
|||
_ => None,
|
||||
},
|
||||
// multiplicative_expression
|
||||
|lexer, mut context| {
|
||||
|lexer, context| {
|
||||
context.parse_binary_op(
|
||||
lexer,
|
||||
|token| match token {
|
||||
|
@ -876,16 +866,16 @@ impl Parser {
|
|||
fn general_expression<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut ctx: ExpressionContext<'a, '_, '_>,
|
||||
ctx: &mut ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<Handle<ast::Expression<'a>>, Error<'a>> {
|
||||
self.general_expression_with_span(lexer, ctx.reborrow())
|
||||
self.general_expression_with_span(lexer, ctx)
|
||||
.map(|(expr, _)| expr)
|
||||
}
|
||||
|
||||
fn general_expression_with_span<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut context: ExpressionContext<'a, '_, '_>,
|
||||
context: &mut ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<(Handle<ast::Expression<'a>>, Span), Error<'a>> {
|
||||
self.push_rule_span(Rule::GeneralExpr, lexer);
|
||||
// logical_or_expression
|
||||
|
@ -896,7 +886,7 @@ impl Parser {
|
|||
_ => None,
|
||||
},
|
||||
// logical_and_expression
|
||||
|lexer, mut context| {
|
||||
|lexer, context| {
|
||||
context.parse_binary_op(
|
||||
lexer,
|
||||
|token| match token {
|
||||
|
@ -904,7 +894,7 @@ impl Parser {
|
|||
_ => None,
|
||||
},
|
||||
// inclusive_or_expression
|
||||
|lexer, mut context| {
|
||||
|lexer, context| {
|
||||
context.parse_binary_op(
|
||||
lexer,
|
||||
|token| match token {
|
||||
|
@ -912,7 +902,7 @@ impl Parser {
|
|||
_ => None,
|
||||
},
|
||||
// exclusive_or_expression
|
||||
|lexer, mut context| {
|
||||
|lexer, context| {
|
||||
context.parse_binary_op(
|
||||
lexer,
|
||||
|token| match token {
|
||||
|
@ -922,7 +912,7 @@ impl Parser {
|
|||
_ => None,
|
||||
},
|
||||
// and_expression
|
||||
|lexer, mut context| {
|
||||
|lexer, context| {
|
||||
context.parse_binary_op(
|
||||
lexer,
|
||||
|token| match token {
|
||||
|
@ -949,7 +939,7 @@ impl Parser {
|
|||
fn variable_decl<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut ctx: ExpressionContext<'a, '_, '_>,
|
||||
ctx: &mut ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<ast::GlobalVariable<'a>, Error<'a>> {
|
||||
self.push_rule_span(Rule::VariableDecl, lexer);
|
||||
let mut space = crate::AddressSpace::Handle;
|
||||
|
@ -972,10 +962,10 @@ impl Parser {
|
|||
}
|
||||
let name = lexer.next_ident()?;
|
||||
lexer.expect(Token::Separator(':'))?;
|
||||
let ty = self.type_decl(lexer, ctx.reborrow())?;
|
||||
let ty = self.type_decl(lexer, ctx)?;
|
||||
|
||||
let init = if lexer.skip(Token::Operation('=')) {
|
||||
let handle = self.general_expression(lexer, ctx.reborrow())?;
|
||||
let handle = self.general_expression(lexer, ctx)?;
|
||||
Some(handle)
|
||||
} else {
|
||||
None
|
||||
|
@ -995,7 +985,7 @@ impl Parser {
|
|||
fn struct_body<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut ctx: ExpressionContext<'a, '_, '_>,
|
||||
ctx: &mut ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<Vec<ast::StructMember<'a>>, Error<'a>> {
|
||||
let mut members = Vec::new();
|
||||
|
||||
|
@ -1015,19 +1005,17 @@ impl Parser {
|
|||
match lexer.next_ident_with_span()? {
|
||||
("size", name_span) => {
|
||||
lexer.expect(Token::Paren('('))?;
|
||||
let expr = self.general_expression(lexer, ctx.reborrow())?;
|
||||
let expr = self.general_expression(lexer, ctx)?;
|
||||
lexer.expect(Token::Paren(')'))?;
|
||||
size.set(expr, name_span)?;
|
||||
}
|
||||
("align", name_span) => {
|
||||
lexer.expect(Token::Paren('('))?;
|
||||
let expr = self.general_expression(lexer, ctx.reborrow())?;
|
||||
let expr = self.general_expression(lexer, ctx)?;
|
||||
lexer.expect(Token::Paren(')'))?;
|
||||
align.set(expr, name_span)?;
|
||||
}
|
||||
(word, word_span) => {
|
||||
bind_parser.parse(self, lexer, word, word_span, ctx.reborrow())?
|
||||
}
|
||||
(word, word_span) => bind_parser.parse(self, lexer, word, word_span, ctx)?,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1036,7 +1024,7 @@ impl Parser {
|
|||
|
||||
let name = lexer.next_ident()?;
|
||||
lexer.expect(Token::Separator(':'))?;
|
||||
let ty = self.type_decl(lexer, ctx.reborrow())?;
|
||||
let ty = self.type_decl(lexer, ctx)?;
|
||||
ready = lexer.skip(Token::Separator(','));
|
||||
|
||||
members.push(ast::StructMember {
|
||||
|
@ -1072,7 +1060,7 @@ impl Parser {
|
|||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
word: &'a str,
|
||||
mut ctx: ExpressionContext<'a, '_, '_>,
|
||||
ctx: &mut ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<Option<ast::Type<'a>>, Error<'a>> {
|
||||
if let Some((kind, width)) = conv::get_scalar_type(word) {
|
||||
return Ok(Some(ast::Type::Scalar { kind, width }));
|
||||
|
@ -1242,9 +1230,9 @@ impl Parser {
|
|||
}
|
||||
"array" => {
|
||||
lexer.expect_generic_paren('<')?;
|
||||
let base = self.type_decl(lexer, ctx.reborrow())?;
|
||||
let base = self.type_decl(lexer, ctx)?;
|
||||
let size = if lexer.skip(Token::Separator(',')) {
|
||||
let size = self.unary_expression(lexer, ctx.reborrow())?;
|
||||
let size = self.unary_expression(lexer, ctx)?;
|
||||
ast::ArraySize::Constant(size)
|
||||
} else {
|
||||
ast::ArraySize::Dynamic
|
||||
|
@ -1255,9 +1243,9 @@ impl Parser {
|
|||
}
|
||||
"binding_array" => {
|
||||
lexer.expect_generic_paren('<')?;
|
||||
let base = self.type_decl(lexer, ctx.reborrow())?;
|
||||
let base = self.type_decl(lexer, ctx)?;
|
||||
let size = if lexer.skip(Token::Separator(',')) {
|
||||
let size = self.unary_expression(lexer, ctx.reborrow())?;
|
||||
let size = self.unary_expression(lexer, ctx)?;
|
||||
ast::ArraySize::Constant(size)
|
||||
} else {
|
||||
ast::ArraySize::Dynamic
|
||||
|
@ -1439,13 +1427,13 @@ impl Parser {
|
|||
fn type_decl<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut ctx: ExpressionContext<'a, '_, '_>,
|
||||
ctx: &mut ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<Handle<ast::Type<'a>>, Error<'a>> {
|
||||
self.push_rule_span(Rule::TypeDecl, lexer);
|
||||
|
||||
let (name, span) = lexer.next_ident_with_span()?;
|
||||
|
||||
let ty = match self.type_decl_impl(lexer, name, ctx.reborrow())? {
|
||||
let ty = match self.type_decl_impl(lexer, name, ctx)? {
|
||||
Some(ty) => ty,
|
||||
None => {
|
||||
ctx.unresolved.insert(ast::Dependency {
|
||||
|
@ -1462,11 +1450,11 @@ impl Parser {
|
|||
Ok(handle)
|
||||
}
|
||||
|
||||
fn assignment_op_and_rhs<'a, 'out>(
|
||||
fn assignment_op_and_rhs<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut ctx: ExpressionContext<'a, '_, 'out>,
|
||||
block: &'out mut ast::Block<'a>,
|
||||
ctx: &mut ExpressionContext<'a, '_, '_>,
|
||||
block: &mut ast::Block<'a>,
|
||||
target: Handle<ast::Expression<'a>>,
|
||||
span_start: usize,
|
||||
) -> Result<(), Error<'a>> {
|
||||
|
@ -1475,7 +1463,7 @@ impl Parser {
|
|||
let op = lexer.next();
|
||||
let (op, value) = match op {
|
||||
(Token::Operation('='), _) => {
|
||||
let value = self.general_expression(lexer, ctx.reborrow())?;
|
||||
let value = self.general_expression(lexer, ctx)?;
|
||||
(None, value)
|
||||
}
|
||||
(Token::AssignmentOperation(c), _) => {
|
||||
|
@ -1494,7 +1482,7 @@ impl Parser {
|
|||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let value = self.general_expression(lexer, ctx.reborrow())?;
|
||||
let value = self.general_expression(lexer, ctx)?;
|
||||
(Some(op), value)
|
||||
}
|
||||
token @ (Token::IncrementOperation | Token::DecrementOperation, _) => {
|
||||
|
@ -1523,27 +1511,27 @@ impl Parser {
|
|||
}
|
||||
|
||||
/// Parse an assignment statement (will also parse increment and decrement statements)
|
||||
fn assignment_statement<'a, 'out>(
|
||||
fn assignment_statement<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut ctx: ExpressionContext<'a, '_, 'out>,
|
||||
block: &'out mut ast::Block<'a>,
|
||||
ctx: &mut ExpressionContext<'a, '_, '_>,
|
||||
block: &mut ast::Block<'a>,
|
||||
) -> Result<(), Error<'a>> {
|
||||
let span_start = lexer.start_byte_offset();
|
||||
let target = self.general_expression(lexer, ctx.reborrow())?;
|
||||
let target = self.general_expression(lexer, ctx)?;
|
||||
self.assignment_op_and_rhs(lexer, ctx, block, target, span_start)
|
||||
}
|
||||
|
||||
/// Parse a function call statement.
|
||||
/// Expects `ident` to be consumed (not in the lexer).
|
||||
fn function_statement<'a, 'out>(
|
||||
fn function_statement<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
ident: &'a str,
|
||||
ident_span: Span,
|
||||
span_start: usize,
|
||||
mut context: ExpressionContext<'a, '_, 'out>,
|
||||
block: &'out mut ast::Block<'a>,
|
||||
context: &mut ExpressionContext<'a, '_, '_>,
|
||||
block: &mut ast::Block<'a>,
|
||||
) -> Result<(), Error<'a>> {
|
||||
self.push_rule_span(Rule::SingularExpr, lexer);
|
||||
|
||||
|
@ -1551,7 +1539,7 @@ impl Parser {
|
|||
ident,
|
||||
usage: ident_span,
|
||||
});
|
||||
let arguments = self.arguments(lexer, context.reborrow())?;
|
||||
let arguments = self.arguments(lexer, context)?;
|
||||
let span = lexer.span_from(span_start);
|
||||
|
||||
block.stmts.push(ast::Statement {
|
||||
|
@ -1570,11 +1558,11 @@ impl Parser {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn function_call_or_assignment_statement<'a, 'out>(
|
||||
fn function_call_or_assignment_statement<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut context: ExpressionContext<'a, '_, 'out>,
|
||||
block: &'out mut ast::Block<'a>,
|
||||
context: &mut ExpressionContext<'a, '_, '_>,
|
||||
block: &mut ast::Block<'a>,
|
||||
) -> Result<(), Error<'a>> {
|
||||
let span_start = lexer.start_byte_offset();
|
||||
match lexer.peek() {
|
||||
|
@ -1583,29 +1571,24 @@ impl Parser {
|
|||
let cloned = lexer.clone();
|
||||
let _ = lexer.next();
|
||||
match lexer.peek() {
|
||||
(Token::Paren('('), _) => self.function_statement(
|
||||
lexer,
|
||||
name,
|
||||
span,
|
||||
span_start,
|
||||
context.reborrow(),
|
||||
block,
|
||||
),
|
||||
(Token::Paren('('), _) => {
|
||||
self.function_statement(lexer, name, span, span_start, context, block)
|
||||
}
|
||||
_ => {
|
||||
*lexer = cloned;
|
||||
self.assignment_statement(lexer, context.reborrow(), block)
|
||||
self.assignment_statement(lexer, context, block)
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => self.assignment_statement(lexer, context.reborrow(), block),
|
||||
_ => self.assignment_statement(lexer, context, block),
|
||||
}
|
||||
}
|
||||
|
||||
fn statement<'a, 'out>(
|
||||
fn statement<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut ctx: ExpressionContext<'a, '_, 'out>,
|
||||
block: &'out mut ast::Block<'a>,
|
||||
ctx: &mut ExpressionContext<'a, '_, '_>,
|
||||
block: &mut ast::Block<'a>,
|
||||
) -> Result<(), Error<'a>> {
|
||||
self.push_rule_span(Rule::Statement, lexer);
|
||||
match lexer.peek() {
|
||||
|
@ -1615,7 +1598,7 @@ impl Parser {
|
|||
return Ok(());
|
||||
}
|
||||
(Token::Paren('{'), _) => {
|
||||
let (inner, span) = self.block(lexer, ctx.reborrow())?;
|
||||
let (inner, span) = self.block(lexer, ctx)?;
|
||||
block.stmts.push(ast::Statement {
|
||||
kind: ast::StatementKind::Block(inner),
|
||||
span,
|
||||
|
@ -1628,7 +1611,7 @@ impl Parser {
|
|||
"_" => {
|
||||
let _ = lexer.next();
|
||||
lexer.expect(Token::Operation('='))?;
|
||||
let expr = self.general_expression(lexer, ctx.reborrow())?;
|
||||
let expr = self.general_expression(lexer, ctx)?;
|
||||
lexer.expect(Token::Separator(';'))?;
|
||||
|
||||
ast::StatementKind::Ignore(expr)
|
||||
|
@ -1638,13 +1621,13 @@ impl Parser {
|
|||
let name = lexer.next_ident()?;
|
||||
|
||||
let given_ty = if lexer.skip(Token::Separator(':')) {
|
||||
let ty = self.type_decl(lexer, ctx.reborrow())?;
|
||||
let ty = self.type_decl(lexer, ctx)?;
|
||||
Some(ty)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
lexer.expect(Token::Operation('='))?;
|
||||
let expr_id = self.general_expression(lexer, ctx.reborrow())?;
|
||||
let expr_id = self.general_expression(lexer, ctx)?;
|
||||
lexer.expect(Token::Separator(';'))?;
|
||||
|
||||
let handle = ctx.declare_local(name)?;
|
||||
|
@ -1660,14 +1643,14 @@ impl Parser {
|
|||
|
||||
let name = lexer.next_ident()?;
|
||||
let ty = if lexer.skip(Token::Separator(':')) {
|
||||
let ty = self.type_decl(lexer, ctx.reborrow())?;
|
||||
let ty = self.type_decl(lexer, ctx)?;
|
||||
Some(ty)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let init = if lexer.skip(Token::Operation('=')) {
|
||||
let init = self.general_expression(lexer, ctx.reborrow())?;
|
||||
let init = self.general_expression(lexer, ctx)?;
|
||||
Some(init)
|
||||
} else {
|
||||
None
|
||||
|
@ -1686,7 +1669,7 @@ impl Parser {
|
|||
"return" => {
|
||||
let _ = lexer.next();
|
||||
let value = if lexer.peek().0 != Token::Separator(';') {
|
||||
let handle = self.general_expression(lexer, ctx.reborrow())?;
|
||||
let handle = self.general_expression(lexer, ctx)?;
|
||||
Some(handle)
|
||||
} else {
|
||||
None
|
||||
|
@ -1696,9 +1679,9 @@ impl Parser {
|
|||
}
|
||||
"if" => {
|
||||
let _ = lexer.next();
|
||||
let condition = self.general_expression(lexer, ctx.reborrow())?;
|
||||
let condition = self.general_expression(lexer, ctx)?;
|
||||
|
||||
let accept = self.block(lexer, ctx.reborrow())?.0;
|
||||
let accept = self.block(lexer, ctx)?.0;
|
||||
|
||||
let mut elsif_stack = Vec::new();
|
||||
let mut elseif_span_start = lexer.start_byte_offset();
|
||||
|
@ -1709,12 +1692,12 @@ impl Parser {
|
|||
|
||||
if !lexer.skip(Token::Word("if")) {
|
||||
// ... else { ... }
|
||||
break self.block(lexer, ctx.reborrow())?.0;
|
||||
break self.block(lexer, ctx)?.0;
|
||||
}
|
||||
|
||||
// ... else if (...) { ... }
|
||||
let other_condition = self.general_expression(lexer, ctx.reborrow())?;
|
||||
let other_block = self.block(lexer, ctx.reborrow())?;
|
||||
let other_condition = self.general_expression(lexer, ctx)?;
|
||||
let other_block = self.block(lexer, ctx)?;
|
||||
elsif_stack.push((elseif_span_start, other_condition, other_block));
|
||||
elseif_span_start = lexer.start_byte_offset();
|
||||
};
|
||||
|
@ -1745,7 +1728,7 @@ impl Parser {
|
|||
}
|
||||
"switch" => {
|
||||
let _ = lexer.next();
|
||||
let selector = self.general_expression(lexer, ctx.reborrow())?;
|
||||
let selector = self.general_expression(lexer, ctx)?;
|
||||
lexer.expect(Token::Paren('{'))?;
|
||||
let mut cases = Vec::new();
|
||||
|
||||
|
@ -1755,7 +1738,7 @@ impl Parser {
|
|||
(Token::Word("case"), _) => {
|
||||
// parse a list of values
|
||||
let value = loop {
|
||||
let value = self.switch_value(lexer, ctx.reborrow())?;
|
||||
let value = self.switch_value(lexer, ctx)?;
|
||||
if lexer.skip(Token::Separator(',')) {
|
||||
if lexer.skip(Token::Separator(':')) {
|
||||
break value;
|
||||
|
@ -1771,7 +1754,7 @@ impl Parser {
|
|||
});
|
||||
};
|
||||
|
||||
let body = self.block(lexer, ctx.reborrow())?.0;
|
||||
let body = self.block(lexer, ctx)?.0;
|
||||
|
||||
cases.push(ast::SwitchCase {
|
||||
value,
|
||||
|
@ -1781,7 +1764,7 @@ impl Parser {
|
|||
}
|
||||
(Token::Word("default"), _) => {
|
||||
lexer.skip(Token::Separator(':'));
|
||||
let body = self.block(lexer, ctx.reborrow())?.0;
|
||||
let body = self.block(lexer, ctx)?.0;
|
||||
cases.push(ast::SwitchCase {
|
||||
value: ast::SwitchValue::Default,
|
||||
body,
|
||||
|
@ -1797,13 +1780,13 @@ impl Parser {
|
|||
|
||||
ast::StatementKind::Switch { selector, cases }
|
||||
}
|
||||
"loop" => self.r#loop(lexer, ctx.reborrow())?,
|
||||
"loop" => self.r#loop(lexer, ctx)?,
|
||||
"while" => {
|
||||
let _ = lexer.next();
|
||||
let mut body = ast::Block::default();
|
||||
|
||||
let (condition, span) = lexer.capture_span(|lexer| {
|
||||
let condition = self.general_expression(lexer, ctx.reborrow())?;
|
||||
let condition = self.general_expression(lexer, ctx)?;
|
||||
Ok(condition)
|
||||
})?;
|
||||
let mut reject = ast::Block::default();
|
||||
|
@ -1821,7 +1804,7 @@ impl Parser {
|
|||
span,
|
||||
});
|
||||
|
||||
let (block, span) = self.block(lexer, ctx.reborrow())?;
|
||||
let (block, span) = self.block(lexer, ctx)?;
|
||||
body.stmts.push(ast::Statement {
|
||||
kind: ast::StatementKind::Block(block),
|
||||
span,
|
||||
|
@ -1841,9 +1824,11 @@ impl Parser {
|
|||
|
||||
if !lexer.skip(Token::Separator(';')) {
|
||||
let num_statements = block.stmts.len();
|
||||
let (_, span) = lexer.capture_span(|lexer| {
|
||||
self.statement(lexer, ctx.reborrow(), block)
|
||||
})?;
|
||||
let (_, span) = {
|
||||
let ctx = &mut *ctx;
|
||||
let block = &mut *block;
|
||||
lexer.capture_span(|lexer| self.statement(lexer, ctx, block))?
|
||||
};
|
||||
|
||||
if block.stmts.len() != num_statements {
|
||||
match block.stmts.last().unwrap().kind {
|
||||
|
@ -1858,7 +1843,7 @@ impl Parser {
|
|||
let mut body = ast::Block::default();
|
||||
if !lexer.skip(Token::Separator(';')) {
|
||||
let (condition, span) = lexer.capture_span(|lexer| {
|
||||
let condition = self.general_expression(lexer, ctx.reborrow())?;
|
||||
let condition = self.general_expression(lexer, ctx)?;
|
||||
lexer.expect(Token::Separator(';'))?;
|
||||
Ok(condition)
|
||||
})?;
|
||||
|
@ -1881,13 +1866,13 @@ impl Parser {
|
|||
if !lexer.skip(Token::Paren(')')) {
|
||||
self.function_call_or_assignment_statement(
|
||||
lexer,
|
||||
ctx.reborrow(),
|
||||
ctx,
|
||||
&mut continuing,
|
||||
)?;
|
||||
lexer.expect(Token::Paren(')'))?;
|
||||
}
|
||||
|
||||
let (block, span) = self.block(lexer, ctx.reborrow())?;
|
||||
let (block, span) = self.block(lexer, ctx)?;
|
||||
body.stmts.push(ast::Statement {
|
||||
kind: ast::StatementKind::Block(block),
|
||||
span,
|
||||
|
@ -1926,7 +1911,7 @@ impl Parser {
|
|||
}
|
||||
// assignment or a function call
|
||||
_ => {
|
||||
self.function_call_or_assignment_statement(lexer, ctx.reborrow(), block)?;
|
||||
self.function_call_or_assignment_statement(lexer, ctx, block)?;
|
||||
lexer.expect(Token::Separator(';'))?;
|
||||
self.pop_rule_span(lexer);
|
||||
return Ok(());
|
||||
|
@ -1937,7 +1922,7 @@ impl Parser {
|
|||
block.stmts.push(ast::Statement { kind, span });
|
||||
}
|
||||
_ => {
|
||||
self.assignment_statement(lexer, ctx.reborrow(), block)?;
|
||||
self.assignment_statement(lexer, ctx, block)?;
|
||||
lexer.expect(Token::Separator(';'))?;
|
||||
self.pop_rule_span(lexer);
|
||||
}
|
||||
|
@ -1948,7 +1933,7 @@ impl Parser {
|
|||
fn r#loop<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut ctx: ExpressionContext<'a, '_, '_>,
|
||||
ctx: &mut ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<ast::StatementKind<'a>, Error<'a>> {
|
||||
let _ = lexer.next();
|
||||
let mut body = ast::Block::default();
|
||||
|
@ -1976,7 +1961,7 @@ impl Parser {
|
|||
// the break if
|
||||
lexer.expect(Token::Word("if"))?;
|
||||
|
||||
let condition = self.general_expression(lexer, ctx.reborrow())?;
|
||||
let condition = self.general_expression(lexer, ctx)?;
|
||||
// Set the condition of the break if to the newly parsed
|
||||
// expression
|
||||
break_if = Some(condition);
|
||||
|
@ -1994,7 +1979,7 @@ impl Parser {
|
|||
break;
|
||||
} else {
|
||||
// Otherwise try to parse a statement
|
||||
self.statement(lexer, ctx.reborrow(), &mut continuing)?;
|
||||
self.statement(lexer, ctx, &mut continuing)?;
|
||||
}
|
||||
}
|
||||
// Since the continuing block must be the last part of the loop body,
|
||||
|
@ -2008,7 +1993,7 @@ impl Parser {
|
|||
break;
|
||||
}
|
||||
// Otherwise try to parse a statement
|
||||
self.statement(lexer, ctx.reborrow(), &mut body)?;
|
||||
self.statement(lexer, ctx, &mut body)?;
|
||||
}
|
||||
|
||||
ctx.local_table.pop_scope();
|
||||
|
@ -2024,7 +2009,7 @@ impl Parser {
|
|||
fn block<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut ctx: ExpressionContext<'a, '_, '_>,
|
||||
ctx: &mut ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<(ast::Block<'a>, Span), Error<'a>> {
|
||||
self.push_rule_span(Rule::Block, lexer);
|
||||
|
||||
|
@ -2033,7 +2018,7 @@ impl Parser {
|
|||
lexer.expect(Token::Paren('{'))?;
|
||||
let mut block = ast::Block::default();
|
||||
while !lexer.skip(Token::Paren('}')) {
|
||||
self.statement(lexer, ctx.reborrow(), &mut block)?;
|
||||
self.statement(lexer, ctx, &mut block)?;
|
||||
}
|
||||
|
||||
ctx.local_table.pop_scope();
|
||||
|
@ -2045,14 +2030,14 @@ impl Parser {
|
|||
fn varying_binding<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut ctx: ExpressionContext<'a, '_, '_>,
|
||||
ctx: &mut ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<Option<ast::Binding<'a>>, Error<'a>> {
|
||||
let mut bind_parser = BindingParser::default();
|
||||
self.push_rule_span(Rule::Attribute, lexer);
|
||||
|
||||
while lexer.skip(Token::Attribute) {
|
||||
let (word, span) = lexer.next_ident_with_span()?;
|
||||
bind_parser.parse(self, lexer, word, span, ctx.reborrow())?;
|
||||
bind_parser.parse(self, lexer, word, span, ctx)?;
|
||||
}
|
||||
|
||||
let span = self.pop_rule_span(lexer);
|
||||
|
@ -2093,12 +2078,12 @@ impl Parser {
|
|||
ExpectedToken::Token(Token::Separator(',')),
|
||||
));
|
||||
}
|
||||
let binding = self.varying_binding(lexer, ctx.reborrow())?;
|
||||
let binding = self.varying_binding(lexer, &mut ctx)?;
|
||||
|
||||
let param_name = lexer.next_ident()?;
|
||||
|
||||
lexer.expect(Token::Separator(':'))?;
|
||||
let param_type = self.type_decl(lexer, ctx.reborrow())?;
|
||||
let param_type = self.type_decl(lexer, &mut ctx)?;
|
||||
|
||||
let handle = ctx.declare_local(param_name)?;
|
||||
arguments.push(ast::FunctionArgument {
|
||||
|
@ -2111,8 +2096,8 @@ impl Parser {
|
|||
}
|
||||
// read return type
|
||||
let result = if lexer.skip(Token::Arrow) && !lexer.skip(Token::Word("void")) {
|
||||
let binding = self.varying_binding(lexer, ctx.reborrow())?;
|
||||
let ty = self.type_decl(lexer, ctx.reborrow())?;
|
||||
let binding = self.varying_binding(lexer, &mut ctx)?;
|
||||
let ty = self.type_decl(lexer, &mut ctx)?;
|
||||
Some(ast::FunctionResult { ty, binding })
|
||||
} else {
|
||||
None
|
||||
|
@ -2122,7 +2107,7 @@ impl Parser {
|
|||
lexer.expect(Token::Paren('{'))?;
|
||||
let mut body = ast::Block::default();
|
||||
while !lexer.skip(Token::Paren('}')) {
|
||||
self.statement(lexer, ctx.reborrow(), &mut body)?;
|
||||
self.statement(lexer, &mut ctx, &mut body)?;
|
||||
}
|
||||
|
||||
ctx.local_table.pop_scope();
|
||||
|
@ -2170,12 +2155,12 @@ impl Parser {
|
|||
match lexer.next_ident_with_span()? {
|
||||
("binding", name_span) => {
|
||||
lexer.expect(Token::Paren('('))?;
|
||||
bind_index.set(self.general_expression(lexer, ctx.reborrow())?, name_span)?;
|
||||
bind_index.set(self.general_expression(lexer, &mut ctx)?, name_span)?;
|
||||
lexer.expect(Token::Paren(')'))?;
|
||||
}
|
||||
("group", name_span) => {
|
||||
lexer.expect(Token::Paren('('))?;
|
||||
bind_group.set(self.general_expression(lexer, ctx.reborrow())?, name_span)?;
|
||||
bind_group.set(self.general_expression(lexer, &mut ctx)?, name_span)?;
|
||||
lexer.expect(Token::Paren(')'))?;
|
||||
}
|
||||
("vertex", name_span) => {
|
||||
|
@ -2192,7 +2177,7 @@ impl Parser {
|
|||
lexer.expect(Token::Paren('('))?;
|
||||
let mut new_workgroup_size = [None; 3];
|
||||
for (i, size) in new_workgroup_size.iter_mut().enumerate() {
|
||||
*size = Some(self.general_expression(lexer, ctx.reborrow())?);
|
||||
*size = Some(self.general_expression(lexer, &mut ctx)?);
|
||||
match lexer.next() {
|
||||
(Token::Paren(')'), _) => break,
|
||||
(Token::Separator(','), _) if i != 2 => (),
|
||||
|
@ -2241,14 +2226,14 @@ impl Parser {
|
|||
(Token::Word("struct"), _) => {
|
||||
let name = lexer.next_ident()?;
|
||||
|
||||
let members = self.struct_body(lexer, ctx)?;
|
||||
let members = self.struct_body(lexer, &mut ctx)?;
|
||||
Some(ast::GlobalDeclKind::Struct(ast::Struct { name, members }))
|
||||
}
|
||||
(Token::Word("alias"), _) => {
|
||||
let name = lexer.next_ident()?;
|
||||
|
||||
lexer.expect(Token::Operation('='))?;
|
||||
let ty = self.type_decl(lexer, ctx)?;
|
||||
let ty = self.type_decl(lexer, &mut ctx)?;
|
||||
lexer.expect(Token::Separator(';'))?;
|
||||
Some(ast::GlobalDeclKind::Type(ast::TypeAlias { name, ty }))
|
||||
}
|
||||
|
@ -2256,20 +2241,20 @@ impl Parser {
|
|||
let name = lexer.next_ident()?;
|
||||
|
||||
let ty = if lexer.skip(Token::Separator(':')) {
|
||||
let ty = self.type_decl(lexer, ctx.reborrow())?;
|
||||
let ty = self.type_decl(lexer, &mut ctx)?;
|
||||
Some(ty)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
lexer.expect(Token::Operation('='))?;
|
||||
let init = self.general_expression(lexer, ctx)?;
|
||||
let init = self.general_expression(lexer, &mut ctx)?;
|
||||
lexer.expect(Token::Separator(';'))?;
|
||||
|
||||
Some(ast::GlobalDeclKind::Const(ast::Const { name, ty, init }))
|
||||
}
|
||||
(Token::Word("var"), _) => {
|
||||
let mut var = self.variable_decl(lexer, ctx)?;
|
||||
let mut var = self.variable_decl(lexer, &mut ctx)?;
|
||||
var.binding = binding.take();
|
||||
Some(ast::GlobalDeclKind::Var(var))
|
||||
}
|
||||
|
@ -2305,13 +2290,12 @@ impl Parser {
|
|||
if !self.rules.is_empty() {
|
||||
log::error!("Reached the end of global decl, but rule stack is not empty");
|
||||
log::error!("Rules: {:?}", self.rules);
|
||||
return Err(Error::Other);
|
||||
return Err(Error::Internal("rule stack is not empty"));
|
||||
};
|
||||
|
||||
match binding {
|
||||
None => Ok(()),
|
||||
// we had the attribute but no var?
|
||||
Some(_) => Err(Error::Other),
|
||||
Some(_) => Err(Error::Internal("we had the attribute but no var?")),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1231,7 +1231,7 @@ impl<'a> ConstantEvaluator<'a> {
|
|||
// expression at a time, `Compose` expressions can only refer to other
|
||||
// expressions, and `ZeroValue` expressions are always okay.
|
||||
if let Expression::Literal(literal) = expr {
|
||||
crate::valid::validate_literal(literal)?;
|
||||
crate::valid::check_literal_value(literal)?;
|
||||
}
|
||||
|
||||
if let Some(FunctionLocalData {
|
||||
|
|
|
@ -140,6 +140,8 @@ pub enum ConstExpressionError {
|
|||
Type(#[from] ResolveError),
|
||||
#[error(transparent)]
|
||||
Literal(#[from] LiteralError),
|
||||
#[error(transparent)]
|
||||
Width(#[from] super::r#type::WidthError),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, thiserror::Error)]
|
||||
|
@ -149,6 +151,8 @@ pub enum LiteralError {
|
|||
NaN,
|
||||
#[error("Float literal is infinite")]
|
||||
Infinity,
|
||||
#[error(transparent)]
|
||||
Width(#[from] super::r#type::WidthError),
|
||||
}
|
||||
|
||||
#[cfg(feature = "validate")]
|
||||
|
@ -188,7 +192,7 @@ impl super::Validator {
|
|||
|
||||
match gctx.const_expressions[handle] {
|
||||
E::Literal(literal) => {
|
||||
validate_literal(literal)?;
|
||||
self.validate_literal(literal)?;
|
||||
}
|
||||
E::Constant(_) | E::ZeroValue(_) => {}
|
||||
E::Compose { ref components, ty } => {
|
||||
|
@ -343,7 +347,7 @@ impl super::Validator {
|
|||
ShaderStages::all()
|
||||
}
|
||||
E::Literal(literal) => {
|
||||
validate_literal(literal)?;
|
||||
self.validate_literal(literal)?;
|
||||
ShaderStages::all()
|
||||
}
|
||||
E::Constant(_) | E::ZeroValue(_) => ShaderStages::all(),
|
||||
|
@ -1563,9 +1567,18 @@ impl super::Validator {
|
|||
_ => Err(ExpressionError::ExpectedGlobalVariable),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn validate_literal(&self, literal: crate::Literal) -> Result<(), LiteralError> {
|
||||
let kind = literal.scalar_kind();
|
||||
let width = literal.width();
|
||||
self.check_width(kind, width)?;
|
||||
check_literal_value(literal)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn validate_literal(literal: crate::Literal) -> Result<(), LiteralError> {
|
||||
pub fn check_literal_value(literal: crate::Literal) -> Result<(), LiteralError> {
|
||||
let is_nan = match literal {
|
||||
crate::Literal::F64(v) => v.is_nan(),
|
||||
crate::Literal::F32(v) => v.is_nan(),
|
||||
|
|
|
@ -24,7 +24,7 @@ use std::ops;
|
|||
use crate::span::{AddSpan as _, WithSpan};
|
||||
pub use analyzer::{ExpressionInfo, FunctionInfo, GlobalUse, Uniformity, UniformityRequirements};
|
||||
pub use compose::ComposeError;
|
||||
pub use expression::{validate_literal, LiteralError};
|
||||
pub use expression::{check_literal_value, LiteralError};
|
||||
pub use expression::{ConstExpressionError, ExpressionError};
|
||||
pub use function::{CallError, FunctionError, LocalVariableError};
|
||||
pub use interface::{EntryPointError, GlobalVariableError, VaryingError};
|
||||
|
|
|
@ -90,8 +90,6 @@ pub enum Disalignment {
|
|||
pub enum TypeError {
|
||||
#[error("Capability {0:?} is required")]
|
||||
MissingCapability(Capabilities),
|
||||
#[error("The {0:?} scalar width {1} is not supported")]
|
||||
InvalidWidth(crate::ScalarKind, crate::Bytes),
|
||||
#[error("The {0:?} scalar width {1} is not supported for an atomic")]
|
||||
InvalidAtomicWidth(crate::ScalarKind, crate::Bytes),
|
||||
#[error("Invalid type for pointer target {0:?}")]
|
||||
|
@ -126,6 +124,23 @@ pub enum TypeError {
|
|||
},
|
||||
#[error("Structure types must have at least one member")]
|
||||
EmptyStruct,
|
||||
#[error(transparent)]
|
||||
WidthError(#[from] WidthError),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, thiserror::Error)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
pub enum WidthError {
|
||||
#[error("The {0:?} scalar width {1} is not supported")]
|
||||
Invalid(crate::ScalarKind, crate::Bytes),
|
||||
#[error("Using `{name}` values requires the `naga::valid::Capabilities::{flag}` flag")]
|
||||
MissingCapability {
|
||||
name: &'static str,
|
||||
flag: &'static str,
|
||||
},
|
||||
|
||||
#[error("64-bit integers are not yet supported")]
|
||||
Unsupported64Bit,
|
||||
}
|
||||
|
||||
// Only makes sense if `flags.contains(HOST_SHAREABLE)`
|
||||
|
@ -209,16 +224,21 @@ impl super::Validator {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn check_width(
|
||||
pub(super) const fn check_width(
|
||||
&self,
|
||||
kind: crate::ScalarKind,
|
||||
width: crate::Bytes,
|
||||
) -> Result<(), TypeError> {
|
||||
) -> Result<(), WidthError> {
|
||||
let good = match kind {
|
||||
crate::ScalarKind::Bool => width == crate::BOOL_WIDTH,
|
||||
crate::ScalarKind::Float => {
|
||||
if width == 8 {
|
||||
self.require_type_capability(Capabilities::FLOAT64)?;
|
||||
if !self.capabilities.contains(Capabilities::FLOAT64) {
|
||||
return Err(WidthError::MissingCapability {
|
||||
name: "f64",
|
||||
flag: "FLOAT64",
|
||||
});
|
||||
}
|
||||
true
|
||||
} else {
|
||||
width == 4
|
||||
|
@ -229,7 +249,7 @@ impl super::Validator {
|
|||
if good {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(TypeError::InvalidWidth(kind, width))
|
||||
Err(WidthError::Invalid(kind, width))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"2e8fc931efa9fbf6e5ea207527f5f9a88488bc4a2bcbb962dbfac1d2b28afec7","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","src/binding_model.rs":"f6d9b170a9328751b3109c81d6f1b555a6db1410f1b7e67c59cc596a1fd1d293","src/command/bind.rs":"67b8431a32f403e358b9c1593e6e0d64519f5f0b699059e6ea5374800d5c23d9","src/command/bundle.rs":"d5456be31f973fcae55ee01781da963f1c950aa5db7eae4d3c6166d4f1a132ca","src/command/clear.rs":"bf78a5eab40f67343054dc982c51f45caab36fb5bddaf065b7a4c1b7a0ada803","src/command/compute.rs":"8caa0f5fa1956a3747f0b845fdeec2572b9462a7e98fdb5cf7b562c472bd6c4c","src/command/draw.rs":"92facdd0e3fd553af590ecbc0de3491f212e237ea66494ff99f67dbf090d10df","src/command/memory_init.rs":"b50d3d20dbf659052f19da2e79469ba6435e06370f19d6ef45e1b1128d9900b7","src/command/mod.rs":"4eac2ac0283c0cfdcc3512af5439fe38e7004e5f406bf52a66d3017ad1ae7632","src/command/query.rs":"d39e1b8cb6a054fd31333a916da5d79a6671a724212c90c490c13e55043a1685","src/command/render.rs":"64d5ac0c00401520cb420b41ee9a7fc03a62a66f06b9434f48c7351dd6b0b11c","src/command/transfer.rs":"2b6f266ba1155ab42bed23b28abffc1008ce26d60b656f56012b896e63daa111","src/conv.rs":"da95b36b7680ae74ebf810ad8f1decf01bd3eeaff44b3c5af1d4b3c3f0e2059a","src/device/global.rs":"05febdc453628bf88e7d0fd40026d2ca243ec966094a7de96f0b4fd6b626511c","src/device/life.rs":"9ac0aab46de65fd2b493f3ee2c3527e37eaad9dbde1583752958eace71423cef","src/device/mod.rs":"702cd9c88015fb40d8ea838ed607afcfceb5bea809f508c49a70b49d5b9803fd","src/device/queue.rs":"e92840c4cf6af66947cd9b7189f1c539ead08f4610a7dddf9726a8c1294b6a36","src/device/resource.rs":"1ae0fe31d64b99e5cc8a473c48990e2920c8960577061e62b157bc5360de1df3","src/device/trace.rs":"21408dfd2c99e3ce36a77d08ba86cf52f32bb376ed82690bbbf74937bfd42cbe","src/error.rs":"ca37282283985e2b7d184b2ab7ca6f53f726432d920f8d8477bfff6fab9b34e2","src/global.rs":"cf551de97c3eb5acd0c2710da09ebd92cc863ad0bb0f53c0fd4911bf8cd3ad97","src/hal_api.rs":"92a2f0cb80f192693530ed61048919bbad446742c2370bf0944c44b1c5df8362","src/hub.rs":"b4207d0a450da9e1d9edb0abc3c99e495132793ebe26af78ea07397d2e5c0b85","src/id.rs":"ef7b3a77110277f4eb2fa1a2ae3d89318023b74d5671181684d2845ef7b7d87a","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":"c57b61e1b0ef20ece19c1d2ebc513e967ada42fbb53a14a73e9e651062af3535","src/lib.rs":"71d42899594be62c2e7074618e03f3639b5ef510b42d6dde660aaa4d5672691e","src/pipeline.rs":"212d469bc1a2256871f64b3f666f05995a92ce39391c32de3856ef2e11c08e16","src/present.rs":"a81f62ca967825f777a5f0d32defb2febb8793406c527d08c6ab0e129df5a81a","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":"815961f6a38cd0691aa8af85e739fd3668133c0ca8937c84bfe698070490d418"},"package":null}
|
||||
{"files":{"Cargo.toml":"92e907552b777ef0a66f4e0617eab6b1c36efbc61d438a2e7acede178c79b047","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","src/binding_model.rs":"f6d9b170a9328751b3109c81d6f1b555a6db1410f1b7e67c59cc596a1fd1d293","src/command/bind.rs":"67b8431a32f403e358b9c1593e6e0d64519f5f0b699059e6ea5374800d5c23d9","src/command/bundle.rs":"d5456be31f973fcae55ee01781da963f1c950aa5db7eae4d3c6166d4f1a132ca","src/command/clear.rs":"bf78a5eab40f67343054dc982c51f45caab36fb5bddaf065b7a4c1b7a0ada803","src/command/compute.rs":"8caa0f5fa1956a3747f0b845fdeec2572b9462a7e98fdb5cf7b562c472bd6c4c","src/command/draw.rs":"92facdd0e3fd553af590ecbc0de3491f212e237ea66494ff99f67dbf090d10df","src/command/memory_init.rs":"b50d3d20dbf659052f19da2e79469ba6435e06370f19d6ef45e1b1128d9900b7","src/command/mod.rs":"4eac2ac0283c0cfdcc3512af5439fe38e7004e5f406bf52a66d3017ad1ae7632","src/command/query.rs":"d39e1b8cb6a054fd31333a916da5d79a6671a724212c90c490c13e55043a1685","src/command/render.rs":"64d5ac0c00401520cb420b41ee9a7fc03a62a66f06b9434f48c7351dd6b0b11c","src/command/transfer.rs":"2b6f266ba1155ab42bed23b28abffc1008ce26d60b656f56012b896e63daa111","src/conv.rs":"da95b36b7680ae74ebf810ad8f1decf01bd3eeaff44b3c5af1d4b3c3f0e2059a","src/device/global.rs":"05febdc453628bf88e7d0fd40026d2ca243ec966094a7de96f0b4fd6b626511c","src/device/life.rs":"9ac0aab46de65fd2b493f3ee2c3527e37eaad9dbde1583752958eace71423cef","src/device/mod.rs":"702cd9c88015fb40d8ea838ed607afcfceb5bea809f508c49a70b49d5b9803fd","src/device/queue.rs":"e92840c4cf6af66947cd9b7189f1c539ead08f4610a7dddf9726a8c1294b6a36","src/device/resource.rs":"3f2726f9b64fad521dd6268023a2efe2a81cc9f524f03aad5c110b148ac0bd0d","src/device/trace.rs":"21408dfd2c99e3ce36a77d08ba86cf52f32bb376ed82690bbbf74937bfd42cbe","src/error.rs":"ca37282283985e2b7d184b2ab7ca6f53f726432d920f8d8477bfff6fab9b34e2","src/global.rs":"cf551de97c3eb5acd0c2710da09ebd92cc863ad0bb0f53c0fd4911bf8cd3ad97","src/hal_api.rs":"92a2f0cb80f192693530ed61048919bbad446742c2370bf0944c44b1c5df8362","src/hub.rs":"b4207d0a450da9e1d9edb0abc3c99e495132793ebe26af78ea07397d2e5c0b85","src/id.rs":"ef7b3a77110277f4eb2fa1a2ae3d89318023b74d5671181684d2845ef7b7d87a","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":"558d0abb437f1bf80c9d97c4b1d9dd17adefb752147c2a237334a5de5687242f","src/lib.rs":"71d42899594be62c2e7074618e03f3639b5ef510b42d6dde660aaa4d5672691e","src/pipeline.rs":"212d469bc1a2256871f64b3f666f05995a92ce39391c32de3856ef2e11c08e16","src/present.rs":"a81f62ca967825f777a5f0d32defb2febb8793406c527d08c6ab0e129df5a81a","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":"815961f6a38cd0691aa8af85e739fd3668133c0ca8937c84bfe698070490d418"},"package":null}
|
|
@ -13,7 +13,7 @@
|
|||
edition = "2021"
|
||||
rust-version = "1.65"
|
||||
name = "wgpu-core"
|
||||
version = "0.17.0"
|
||||
version = "0.18.0"
|
||||
authors = ["wgpu developers"]
|
||||
description = "WebGPU core logic on wgpu-hal"
|
||||
homepage = "https://wgpu.rs/"
|
||||
|
@ -48,15 +48,15 @@ smallvec = "1"
|
|||
thiserror = "1"
|
||||
|
||||
[dependencies.hal]
|
||||
version = "0.17"
|
||||
version = "0.18.0"
|
||||
path = "../wgpu-hal"
|
||||
default_features = false
|
||||
package = "wgpu-hal"
|
||||
|
||||
[dependencies.naga]
|
||||
version = "0.13.0"
|
||||
version = "0.14.0"
|
||||
git = "https://github.com/gfx-rs/naga"
|
||||
rev = "e25280df9316434ef7752970016d01a3aede3f17"
|
||||
rev = "92e41b43e437146b5d946eb238de963be1168016"
|
||||
features = [
|
||||
"clone",
|
||||
"span",
|
||||
|
@ -81,7 +81,7 @@ features = ["serde_derive"]
|
|||
optional = true
|
||||
|
||||
[dependencies.wgt]
|
||||
version = "0.17"
|
||||
version = "0.18.0"
|
||||
path = "../wgpu-types"
|
||||
package = "wgpu-types"
|
||||
|
||||
|
|
|
@ -1317,6 +1317,19 @@ impl<A: HalApi> Device<A> {
|
|||
.contains(wgt::DownlevelFlags::CUBE_ARRAY_TEXTURES),
|
||||
);
|
||||
|
||||
let debug_source = if self.instance_flags.contains(wgt::InstanceFlags::DEBUG) {
|
||||
Some(hal::DebugSource {
|
||||
file_name: Cow::Owned(
|
||||
desc.label
|
||||
.as_ref()
|
||||
.map_or("shader".to_string(), |l| l.to_string()),
|
||||
),
|
||||
source_code: Cow::Owned(source.clone()),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let info = naga::valid::Validator::new(naga::valid::ValidationFlags::all(), caps)
|
||||
.validate(&module)
|
||||
.map_err(|inner| {
|
||||
|
@ -1326,10 +1339,14 @@ impl<A: HalApi> Device<A> {
|
|||
inner: Box::new(inner),
|
||||
})
|
||||
})?;
|
||||
|
||||
let interface =
|
||||
validation::Interface::new(&module, &info, self.limits.clone(), self.features);
|
||||
let hal_shader = hal::ShaderInput::Naga(hal::NagaShader { module, info });
|
||||
|
||||
let hal_shader = hal::ShaderInput::Naga(hal::NagaShader {
|
||||
module,
|
||||
info,
|
||||
debug_source,
|
||||
});
|
||||
let hal_desc = hal::ShaderModuleDescriptor {
|
||||
label: desc.label.to_hal(self.instance_flags),
|
||||
runtime_checks: desc.shader_bound_checks.runtime_checks(),
|
||||
|
|
|
@ -615,9 +615,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
presentation: None,
|
||||
#[cfg(all(feature = "vulkan", not(target_arch = "wasm32")))]
|
||||
vulkan: None,
|
||||
#[cfg(all(feature = "dx12", windows))]
|
||||
dx12: self.instance.dx12.as_ref().map(|inst| HalSurface {
|
||||
raw: unsafe { inst.create_surface_from_visual(visual as _) },
|
||||
}),
|
||||
#[cfg(all(feature = "dx11", windows))]
|
||||
dx11: None,
|
||||
#[cfg(feature = "gles")]
|
||||
gl: None,
|
||||
|
@ -643,9 +645,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
presentation: None,
|
||||
#[cfg(all(feature = "vulkan", not(target_arch = "wasm32")))]
|
||||
vulkan: None,
|
||||
#[cfg(all(feature = "dx12", windows))]
|
||||
dx12: self.instance.dx12.as_ref().map(|inst| HalSurface {
|
||||
raw: unsafe { inst.create_surface_from_surface_handle(surface_handle) },
|
||||
}),
|
||||
#[cfg(all(feature = "dx11", windows))]
|
||||
dx11: None,
|
||||
#[cfg(feature = "gles")]
|
||||
gl: None,
|
||||
|
@ -671,9 +675,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
presentation: None,
|
||||
#[cfg(all(feature = "vulkan", not(target_arch = "wasm32")))]
|
||||
vulkan: None,
|
||||
#[cfg(all(feature = "dx12", windows))]
|
||||
dx12: self.instance.dx12.as_ref().map(|inst| HalSurface {
|
||||
raw: unsafe { inst.create_surface_from_swap_chain_panel(swap_chain_panel as _) },
|
||||
}),
|
||||
#[cfg(all(feature = "dx11", windows))]
|
||||
dx11: None,
|
||||
#[cfg(feature = "gles")]
|
||||
gl: None,
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -13,7 +13,7 @@
|
|||
edition = "2021"
|
||||
rust-version = "1.65"
|
||||
name = "wgpu-hal"
|
||||
version = "0.17.0"
|
||||
version = "0.18.0"
|
||||
authors = ["wgpu developers"]
|
||||
description = "WebGPU hardware abstraction layer"
|
||||
homepage = "https://wgpu.rs/"
|
||||
|
@ -59,13 +59,13 @@ rustc-hash = "1.1"
|
|||
thiserror = "1"
|
||||
|
||||
[dependencies.glow]
|
||||
version = "0.12.3"
|
||||
version = "0.13"
|
||||
optional = true
|
||||
|
||||
[dependencies.naga]
|
||||
version = "0.13.0"
|
||||
version = "0.14.0"
|
||||
git = "https://github.com/gfx-rs/naga"
|
||||
rev = "e25280df9316434ef7752970016d01a3aede3f17"
|
||||
rev = "92e41b43e437146b5d946eb238de963be1168016"
|
||||
features = ["clone"]
|
||||
|
||||
[dependencies.profiling]
|
||||
|
@ -73,7 +73,7 @@ version = "1"
|
|||
default-features = false
|
||||
|
||||
[dependencies.wgt]
|
||||
version = "0.17"
|
||||
version = "0.18.0"
|
||||
path = "../wgpu-types"
|
||||
package = "wgpu-types"
|
||||
|
||||
|
@ -82,9 +82,9 @@ cfg-if = "1"
|
|||
env_logger = "0.10"
|
||||
|
||||
[dev-dependencies.naga]
|
||||
version = "0.13.0"
|
||||
version = "0.14.0"
|
||||
git = "https://github.com/gfx-rs/naga"
|
||||
rev = "e25280df9316434ef7752970016d01a3aede3f17"
|
||||
rev = "92e41b43e437146b5d946eb238de963be1168016"
|
||||
features = ["wgsl-in"]
|
||||
|
||||
[dev-dependencies.winit]
|
||||
|
@ -160,16 +160,13 @@ features = [
|
|||
|
||||
[target."cfg(any(target_os=\"macos\", target_os=\"ios\"))".dependencies]
|
||||
core-graphics-types = "0.1"
|
||||
metal = "0.27.0"
|
||||
objc = "0.2.5"
|
||||
|
||||
[target."cfg(any(target_os=\"macos\", target_os=\"ios\"))".dependencies.block]
|
||||
version = "0.1"
|
||||
optional = true
|
||||
|
||||
[target."cfg(any(target_os=\"macos\", target_os=\"ios\"))".dependencies.metal]
|
||||
git = "https://github.com/gfx-rs/metal-rs/"
|
||||
rev = "d24f1a4"
|
||||
|
||||
[target."cfg(not(target_arch = \"wasm32\"))".dependencies.ash]
|
||||
version = "0.37.3"
|
||||
optional = true
|
||||
|
@ -230,7 +227,7 @@ features = ["libloading"]
|
|||
optional = true
|
||||
|
||||
[target."cfg(windows)".dependencies.glutin_wgl_sys]
|
||||
version = "0.4"
|
||||
version = "0.5"
|
||||
optional = true
|
||||
|
||||
[target."cfg(windows)".dependencies.gpu-allocator]
|
||||
|
|
|
@ -156,6 +156,7 @@ impl<A: hal::Api> Example<A> {
|
|||
hal::NagaShader {
|
||||
module: Cow::Owned(module),
|
||||
info,
|
||||
debug_source: None,
|
||||
}
|
||||
};
|
||||
let shader_desc = hal::ShaderModuleDescriptor {
|
||||
|
|
|
@ -210,16 +210,12 @@ impl super::Adapter {
|
|||
(glow::VENDOR, glow::RENDERER)
|
||||
};
|
||||
|
||||
let (vendor, renderer) = {
|
||||
let vendor = unsafe { gl.get_parameter_string(vendor_const) };
|
||||
let renderer = unsafe { gl.get_parameter_string(renderer_const) };
|
||||
|
||||
(vendor, renderer)
|
||||
};
|
||||
let version = unsafe { gl.get_parameter_string(glow::VERSION) };
|
||||
log::info!("Vendor: {}", vendor);
|
||||
log::info!("Renderer: {}", renderer);
|
||||
log::info!("Version: {}", version);
|
||||
log::trace!("Vendor: {}", vendor);
|
||||
log::trace!("Renderer: {}", renderer);
|
||||
log::trace!("Version: {}", version);
|
||||
|
||||
let full_ver = Self::parse_full_version(&version).ok();
|
||||
let es_ver = full_ver
|
||||
|
@ -254,27 +250,9 @@ impl super::Adapter {
|
|||
}
|
||||
}
|
||||
|
||||
let supported = |(req_es_major, req_es_minor), (req_full_major, req_full_minor)| {
|
||||
let es_supported = es_ver
|
||||
.map(|es_ver| es_ver >= (req_es_major, req_es_minor))
|
||||
.unwrap_or_default();
|
||||
|
||||
let full_supported = full_ver
|
||||
.map(|full_ver| full_ver >= (req_full_major, req_full_minor))
|
||||
.unwrap_or_default();
|
||||
|
||||
es_supported || full_supported
|
||||
};
|
||||
|
||||
let supports_storage =
|
||||
supported((3, 1), (4, 3)) || extensions.contains("GL_ARB_shader_storage_buffer_object");
|
||||
let supports_compute =
|
||||
supported((3, 1), (4, 3)) || extensions.contains("GL_ARB_compute_shader");
|
||||
let supports_work_group_params = supports_compute;
|
||||
|
||||
let shading_language_version = {
|
||||
let sl_version = unsafe { gl.get_parameter_string(glow::SHADING_LANGUAGE_VERSION) };
|
||||
log::info!("SL version: {}", &sl_version);
|
||||
log::trace!("SL version: {}", &sl_version);
|
||||
if full_ver.is_some() {
|
||||
let (sl_major, sl_minor) = Self::parse_full_version(&sl_version).ok()?;
|
||||
let mut value = sl_major as u16 * 100 + sl_minor as u16 * 10;
|
||||
|
@ -293,6 +271,26 @@ impl super::Adapter {
|
|||
}
|
||||
};
|
||||
|
||||
log::trace!("Supported GL Extensions: {:#?}", extensions);
|
||||
|
||||
let supported = |(req_es_major, req_es_minor), (req_full_major, req_full_minor)| {
|
||||
let es_supported = es_ver
|
||||
.map(|es_ver| es_ver >= (req_es_major, req_es_minor))
|
||||
.unwrap_or_default();
|
||||
|
||||
let full_supported = full_ver
|
||||
.map(|full_ver| full_ver >= (req_full_major, req_full_minor))
|
||||
.unwrap_or_default();
|
||||
|
||||
es_supported || full_supported
|
||||
};
|
||||
|
||||
let supports_storage =
|
||||
supported((3, 1), (4, 3)) || extensions.contains("GL_ARB_shader_storage_buffer_object");
|
||||
let supports_compute =
|
||||
supported((3, 1), (4, 3)) || extensions.contains("GL_ARB_compute_shader");
|
||||
let supports_work_group_params = supports_compute;
|
||||
|
||||
// ANGLE provides renderer strings like: "ANGLE (Apple, Apple M1 Pro, OpenGL 4.1)"
|
||||
let is_angle = renderer.contains("ANGLE");
|
||||
|
||||
|
@ -385,7 +383,9 @@ impl super::Adapter {
|
|||
&& (vertex_shader_storage_blocks != 0 || vertex_ssbo_false_zero),
|
||||
);
|
||||
downlevel_flags.set(wgt::DownlevelFlags::FRAGMENT_STORAGE, supports_storage);
|
||||
if extensions.contains("EXT_texture_filter_anisotropic") {
|
||||
if extensions.contains("EXT_texture_filter_anisotropic")
|
||||
|| extensions.contains("GL_EXT_texture_filter_anisotropic")
|
||||
{
|
||||
let max_aniso =
|
||||
unsafe { gl.get_parameter_i32(glow::MAX_TEXTURE_MAX_ANISOTROPY_EXT) } as u32;
|
||||
downlevel_flags.set(wgt::DownlevelFlags::ANISOTROPIC_FILTERING, max_aniso >= 16);
|
||||
|
@ -411,6 +411,11 @@ impl super::Adapter {
|
|||
wgt::DownlevelFlags::MULTISAMPLED_SHADING,
|
||||
supported((3, 2), (4, 0)) || extensions.contains("OES_sample_variables"),
|
||||
);
|
||||
let query_buffers = extensions.contains("GL_ARB_query_buffer_object")
|
||||
|| extensions.contains("GL_AMD_query_buffer_object");
|
||||
if query_buffers {
|
||||
downlevel_flags.set(wgt::DownlevelFlags::NONBLOCKING_QUERY_RESOLVE, true);
|
||||
}
|
||||
|
||||
let mut features = wgt::Features::empty()
|
||||
| wgt::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES
|
||||
|
@ -418,11 +423,12 @@ impl super::Adapter {
|
|||
| wgt::Features::PUSH_CONSTANTS;
|
||||
features.set(
|
||||
wgt::Features::ADDRESS_MODE_CLAMP_TO_BORDER | wgt::Features::ADDRESS_MODE_CLAMP_TO_ZERO,
|
||||
extensions.contains("GL_EXT_texture_border_clamp"),
|
||||
extensions.contains("GL_EXT_texture_border_clamp")
|
||||
|| extensions.contains("GL_ARB_texture_border_clamp"),
|
||||
);
|
||||
features.set(
|
||||
wgt::Features::DEPTH_CLIP_CONTROL,
|
||||
extensions.contains("GL_EXT_depth_clamp"),
|
||||
extensions.contains("GL_EXT_depth_clamp") || extensions.contains("GL_ARB_depth_clamp"),
|
||||
);
|
||||
features.set(
|
||||
wgt::Features::VERTEX_WRITABLE_STORAGE,
|
||||
|
@ -431,11 +437,12 @@ impl super::Adapter {
|
|||
);
|
||||
features.set(
|
||||
wgt::Features::MULTIVIEW,
|
||||
extensions.contains("OVR_multiview2"),
|
||||
extensions.contains("OVR_multiview2") || extensions.contains("GL_OVR_multiview2"),
|
||||
);
|
||||
features.set(
|
||||
wgt::Features::DUAL_SOURCE_BLENDING,
|
||||
extensions.contains("GL_EXT_blend_func_extended"),
|
||||
extensions.contains("GL_EXT_blend_func_extended")
|
||||
|| extensions.contains("GL_ARB_blend_func_extended"),
|
||||
);
|
||||
features.set(
|
||||
wgt::Features::SHADER_PRIMITIVE_INDEX,
|
||||
|
@ -448,6 +455,15 @@ impl super::Adapter {
|
|||
supported((3, 1), (4, 2)) || extensions.contains("GL_ARB_shader_image_load_store"),
|
||||
);
|
||||
features.set(wgt::Features::SHADER_UNUSED_VERTEX_OUTPUT, true);
|
||||
if extensions.contains("GL_ARB_timer_query") {
|
||||
features.set(wgt::Features::TIMESTAMP_QUERY, true);
|
||||
features.set(wgt::Features::TIMESTAMP_QUERY_INSIDE_PASSES, true);
|
||||
}
|
||||
let gl_bcn_exts = [
|
||||
"GL_EXT_texture_compression_s3tc",
|
||||
"GL_EXT_texture_compression_rgtc",
|
||||
"GL_ARB_texture_compression_bptc",
|
||||
];
|
||||
let gles_bcn_exts = [
|
||||
"GL_EXT_texture_compression_s3tc_srgb",
|
||||
"GL_EXT_texture_compression_rgtc",
|
||||
|
@ -461,18 +477,23 @@ impl super::Adapter {
|
|||
];
|
||||
let bcn_exts = if cfg!(target_arch = "wasm32") {
|
||||
&webgl_bcn_exts[..]
|
||||
} else {
|
||||
} else if es_ver.is_some() {
|
||||
&gles_bcn_exts[..]
|
||||
} else {
|
||||
&gl_bcn_exts[..]
|
||||
};
|
||||
features.set(
|
||||
wgt::Features::TEXTURE_COMPRESSION_BC,
|
||||
bcn_exts.iter().all(|&ext| extensions.contains(ext)),
|
||||
);
|
||||
features.set(
|
||||
wgt::Features::TEXTURE_COMPRESSION_ETC2,
|
||||
// This is a part of GLES-3 but not WebGL2 core
|
||||
!cfg!(target_arch = "wasm32") || extensions.contains("WEBGL_compressed_texture_etc"),
|
||||
);
|
||||
let has_etc = if cfg!(target_arch = "wasm32") {
|
||||
extensions.contains("WEBGL_compressed_texture_etc")
|
||||
} else {
|
||||
// This is a required part of GLES3, but not part of Desktop GL at all.
|
||||
es_ver.is_some()
|
||||
};
|
||||
features.set(wgt::Features::TEXTURE_COMPRESSION_ETC2, has_etc);
|
||||
|
||||
// `OES_texture_compression_astc` provides 2D + 3D, LDR + HDR support
|
||||
if extensions.contains("WEBGL_compressed_texture_astc")
|
||||
|| extensions.contains("GL_OES_texture_compression_astc")
|
||||
|
@ -514,7 +535,8 @@ impl super::Adapter {
|
|||
let mut private_caps = super::PrivateCapabilities::empty();
|
||||
private_caps.set(
|
||||
super::PrivateCapabilities::BUFFER_ALLOCATION,
|
||||
extensions.contains("GL_EXT_buffer_storage"),
|
||||
extensions.contains("GL_EXT_buffer_storage")
|
||||
|| extensions.contains("GL_ARB_buffer_storage"),
|
||||
);
|
||||
private_caps.set(
|
||||
super::PrivateCapabilities::SHADER_BINDING_LAYOUT,
|
||||
|
@ -538,11 +560,13 @@ impl super::Adapter {
|
|||
);
|
||||
private_caps.set(
|
||||
super::PrivateCapabilities::GET_BUFFER_SUB_DATA,
|
||||
cfg!(target_arch = "wasm32"),
|
||||
cfg!(target_arch = "wasm32") || full_ver.is_some(),
|
||||
);
|
||||
let color_buffer_float = extensions.contains("GL_EXT_color_buffer_float")
|
||||
|| extensions.contains("GL_ARB_color_buffer_float")
|
||||
|| extensions.contains("EXT_color_buffer_float");
|
||||
let color_buffer_half_float = extensions.contains("GL_EXT_color_buffer_half_float");
|
||||
let color_buffer_half_float = extensions.contains("GL_EXT_color_buffer_half_float")
|
||||
|| extensions.contains("GL_ARB_half_float_pixel");
|
||||
private_caps.set(
|
||||
super::PrivateCapabilities::COLOR_BUFFER_HALF_FLOAT,
|
||||
color_buffer_half_float || color_buffer_float,
|
||||
|
@ -553,8 +577,13 @@ impl super::Adapter {
|
|||
);
|
||||
private_caps.set(
|
||||
super::PrivateCapabilities::TEXTURE_FLOAT_LINEAR,
|
||||
extensions.contains("OES_texture_float_linear"),
|
||||
if full_ver.is_some() {
|
||||
color_buffer_float
|
||||
} else {
|
||||
extensions.contains("OES_texture_float_linear")
|
||||
},
|
||||
);
|
||||
private_caps.set(super::PrivateCapabilities::QUERY_BUFFERS, query_buffers);
|
||||
|
||||
let max_texture_size = unsafe { gl.get_parameter_i32(glow::MAX_TEXTURE_SIZE) } as u32;
|
||||
let max_texture_3d_size = unsafe { gl.get_parameter_i32(glow::MAX_3D_TEXTURE_SIZE) } as u32;
|
||||
|
|
|
@ -31,6 +31,7 @@ pub(super) struct State {
|
|||
dirty_vbuf_mask: usize,
|
||||
active_first_instance: u32,
|
||||
push_offset_to_uniform: ArrayVec<super::UniformDesc, { super::MAX_PUSH_CONSTANTS }>,
|
||||
end_of_pass_timestamp: Option<glow::Query>,
|
||||
}
|
||||
|
||||
impl super::CommandBuffer {
|
||||
|
@ -409,8 +410,9 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
|||
unsafe fn end_query(&mut self, set: &super::QuerySet, _index: u32) {
|
||||
self.cmd_buffer.commands.push(C::EndQuery(set.target));
|
||||
}
|
||||
unsafe fn write_timestamp(&mut self, _set: &super::QuerySet, _index: u32) {
|
||||
unimplemented!()
|
||||
unsafe fn write_timestamp(&mut self, set: &super::QuerySet, index: u32) {
|
||||
let query = set.queries[index as usize];
|
||||
self.cmd_buffer.commands.push(C::TimestampQuery(query));
|
||||
}
|
||||
unsafe fn reset_queries(&mut self, _set: &super::QuerySet, _range: Range<u32>) {
|
||||
//TODO: what do we do here?
|
||||
|
@ -439,6 +441,16 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
|||
// render
|
||||
|
||||
unsafe fn begin_render_pass(&mut self, desc: &crate::RenderPassDescriptor<super::Api>) {
|
||||
debug_assert!(self.state.end_of_pass_timestamp.is_none());
|
||||
if let Some(ref t) = desc.timestamp_writes {
|
||||
if let Some(index) = t.beginning_of_pass_write_index {
|
||||
unsafe { self.write_timestamp(t.query_set, index) }
|
||||
}
|
||||
self.state.end_of_pass_timestamp = t
|
||||
.end_of_pass_write_index
|
||||
.map(|index| t.query_set.queries[index as usize]);
|
||||
}
|
||||
|
||||
self.state.render_size = desc.extent;
|
||||
self.state.resolve_attachments.clear();
|
||||
self.state.invalidate_attachments.clear();
|
||||
|
@ -623,6 +635,10 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
|||
}
|
||||
self.state.vertex_attributes.clear();
|
||||
self.state.primitive = super::PrimitiveState::default();
|
||||
|
||||
if let Some(query) = self.state.end_of_pass_timestamp.take() {
|
||||
self.cmd_buffer.commands.push(C::TimestampQuery(query));
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn set_bind_group(
|
||||
|
@ -1030,6 +1046,16 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
|||
// compute
|
||||
|
||||
unsafe fn begin_compute_pass(&mut self, desc: &crate::ComputePassDescriptor<super::Api>) {
|
||||
debug_assert!(self.state.end_of_pass_timestamp.is_none());
|
||||
if let Some(ref t) = desc.timestamp_writes {
|
||||
if let Some(index) = t.beginning_of_pass_write_index {
|
||||
unsafe { self.write_timestamp(t.query_set, index) }
|
||||
}
|
||||
self.state.end_of_pass_timestamp = t
|
||||
.end_of_pass_write_index
|
||||
.map(|index| t.query_set.queries[index as usize]);
|
||||
}
|
||||
|
||||
if let Some(label) = desc.label {
|
||||
let range = self.cmd_buffer.add_marker(label);
|
||||
self.cmd_buffer.commands.push(C::PushDebugGroup(range));
|
||||
|
@ -1041,6 +1067,10 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
|
|||
self.cmd_buffer.commands.push(C::PopDebugGroup);
|
||||
self.state.has_pass_label = false;
|
||||
}
|
||||
|
||||
if let Some(query) = self.state.end_of_pass_timestamp.take() {
|
||||
self.cmd_buffer.commands.push(C::TimestampQuery(query));
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn set_compute_pipeline(&mut self, pipeline: &super::ComputePipeline) {
|
||||
|
|
|
@ -1224,6 +1224,14 @@ impl crate::Device<super::Api> for super::Device {
|
|||
if gl.supports_debug() {
|
||||
use std::fmt::Write;
|
||||
|
||||
// Initialize the query so we can label it
|
||||
match desc.ty {
|
||||
wgt::QueryType::Timestamp => unsafe {
|
||||
gl.query_counter(query, glow::TIMESTAMP)
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
|
||||
if let Some(label) = desc.label {
|
||||
temp_string.clear();
|
||||
let _ = write!(temp_string, "{label}[{i}]");
|
||||
|
@ -1238,6 +1246,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||
queries: queries.into_boxed_slice(),
|
||||
target: match desc.ty {
|
||||
wgt::QueryType::Occlusion => glow::ANY_SAMPLES_PASSED_CONSERVATIVE,
|
||||
wgt::QueryType::Timestamp => glow::TIMESTAMP,
|
||||
_ => unimplemented!(),
|
||||
},
|
||||
})
|
||||
|
|
|
@ -946,7 +946,7 @@ impl crate::Instance<super::Api> for Instance {
|
|||
let inner = self.inner.lock();
|
||||
inner.egl.make_current();
|
||||
|
||||
let gl = unsafe {
|
||||
let mut gl = unsafe {
|
||||
glow::Context::from_loader_function(|name| {
|
||||
inner
|
||||
.egl
|
||||
|
|
|
@ -161,6 +161,8 @@ bitflags::bitflags! {
|
|||
const COLOR_BUFFER_FLOAT = 1 << 9;
|
||||
/// Supports linear flitering `f32` textures.
|
||||
const TEXTURE_FLOAT_LINEAR = 1 << 10;
|
||||
/// Supports query buffer objects.
|
||||
const QUERY_BUFFERS = 1 << 11;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -775,6 +777,7 @@ enum Command {
|
|||
SetIndexBuffer(glow::Buffer),
|
||||
BeginQuery(glow::Query, BindTarget),
|
||||
EndQuery(BindTarget),
|
||||
TimestampQuery(glow::Query),
|
||||
CopyQueryResults {
|
||||
query_range: Range<u32>,
|
||||
dst: Buffer,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::{conv::is_layered_target, Command as C};
|
||||
use super::{conv::is_layered_target, Command as C, PrivateCapabilities};
|
||||
use arrayvec::ArrayVec;
|
||||
use glow::HasContext;
|
||||
use std::{mem, slice, sync::Arc};
|
||||
|
@ -808,16 +808,74 @@ impl super::Queue {
|
|||
C::EndQuery(target) => {
|
||||
unsafe { gl.end_query(target) };
|
||||
}
|
||||
C::TimestampQuery(query) => {
|
||||
unsafe { gl.query_counter(query, glow::TIMESTAMP) };
|
||||
}
|
||||
C::CopyQueryResults {
|
||||
ref query_range,
|
||||
ref dst,
|
||||
dst_target,
|
||||
dst_offset,
|
||||
} => {
|
||||
if self
|
||||
.shared
|
||||
.private_caps
|
||||
.contains(PrivateCapabilities::QUERY_BUFFERS)
|
||||
&& dst.raw.is_some()
|
||||
{
|
||||
unsafe {
|
||||
// We're assuming that the only relevant queries are 8 byte timestamps or
|
||||
// occlusion tests.
|
||||
let query_size = 8;
|
||||
|
||||
let query_range_size = query_size * query_range.len();
|
||||
|
||||
let buffer = gl.create_buffer().ok();
|
||||
gl.bind_buffer(glow::QUERY_BUFFER, buffer);
|
||||
gl.buffer_data_size(
|
||||
glow::QUERY_BUFFER,
|
||||
query_range_size as _,
|
||||
glow::STREAM_COPY,
|
||||
);
|
||||
|
||||
for (i, &query) in queries
|
||||
[query_range.start as usize..query_range.end as usize]
|
||||
.iter()
|
||||
.enumerate()
|
||||
{
|
||||
gl.get_query_parameter_u64_with_offset(
|
||||
query,
|
||||
glow::QUERY_RESULT,
|
||||
query_size * i,
|
||||
)
|
||||
}
|
||||
gl.bind_buffer(dst_target, dst.raw);
|
||||
gl.copy_buffer_sub_data(
|
||||
glow::QUERY_BUFFER,
|
||||
dst_target,
|
||||
0,
|
||||
dst_offset as _,
|
||||
query_range_size as _,
|
||||
);
|
||||
if let Some(buffer) = buffer {
|
||||
gl.delete_buffer(buffer)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.temp_query_results.clear();
|
||||
for &query in queries[query_range.start as usize..query_range.end as usize].iter() {
|
||||
let result = unsafe { gl.get_query_parameter_u32(query, glow::QUERY_RESULT) };
|
||||
self.temp_query_results.push(result as u64);
|
||||
for &query in
|
||||
queries[query_range.start as usize..query_range.end as usize].iter()
|
||||
{
|
||||
let mut result: u64 = 0;
|
||||
unsafe {
|
||||
let result: *mut u64 = &mut result;
|
||||
gl.get_query_parameter_u64_with_offset(
|
||||
query,
|
||||
glow::QUERY_RESULT,
|
||||
result as usize,
|
||||
)
|
||||
};
|
||||
self.temp_query_results.push(result);
|
||||
}
|
||||
let query_data = unsafe {
|
||||
slice::from_raw_parts(
|
||||
|
@ -829,7 +887,11 @@ impl super::Queue {
|
|||
Some(buffer) => {
|
||||
unsafe { gl.bind_buffer(dst_target, Some(buffer)) };
|
||||
unsafe {
|
||||
gl.buffer_sub_data_u8_slice(dst_target, dst_offset as i32, query_data)
|
||||
gl.buffer_sub_data_u8_slice(
|
||||
dst_target,
|
||||
dst_offset as i32,
|
||||
query_data,
|
||||
)
|
||||
};
|
||||
}
|
||||
None => {
|
||||
|
@ -839,6 +901,7 @@ impl super::Queue {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
C::ResetFramebuffer { is_default } => {
|
||||
if is_default {
|
||||
unsafe { gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, None) };
|
||||
|
|
|
@ -26,9 +26,9 @@ use winapi::{
|
|||
libloaderapi::{GetModuleHandleA, GetProcAddress, LoadLibraryA},
|
||||
wingdi::{
|
||||
wglCreateContext, wglDeleteContext, wglGetCurrentContext, wglGetProcAddress,
|
||||
wglMakeCurrent, wglShareLists, ChoosePixelFormat, DescribePixelFormat, GetPixelFormat,
|
||||
SetPixelFormat, SwapBuffers, PFD_DOUBLEBUFFER, PFD_DRAW_TO_WINDOW, PFD_SUPPORT_OPENGL,
|
||||
PFD_TYPE_RGBA, PIXELFORMATDESCRIPTOR,
|
||||
wglMakeCurrent, ChoosePixelFormat, DescribePixelFormat, GetPixelFormat, SetPixelFormat,
|
||||
SwapBuffers, PFD_DOUBLEBUFFER, PFD_DRAW_TO_WINDOW, PFD_SUPPORT_OPENGL, PFD_TYPE_RGBA,
|
||||
PIXELFORMATDESCRIPTOR,
|
||||
},
|
||||
winuser::{
|
||||
CreateWindowExA, DefWindowProcA, GetDC, RegisterClassExA, ReleaseDC, CS_OWNDC,
|
||||
|
@ -133,7 +133,6 @@ unsafe impl Send for WglContext {}
|
|||
unsafe impl Sync for WglContext {}
|
||||
|
||||
struct Inner {
|
||||
opengl_module: HMODULE,
|
||||
gl: glow::Context,
|
||||
device: HDC,
|
||||
context: WglContext,
|
||||
|
@ -388,7 +387,7 @@ impl crate::Instance<super::Api> for Instance {
|
|||
)
|
||||
})?;
|
||||
|
||||
let gl = unsafe {
|
||||
let mut gl = unsafe {
|
||||
glow::Context::from_loader_function(|name| load_gl_func(name, Some(opengl_module)))
|
||||
};
|
||||
|
||||
|
@ -406,7 +405,7 @@ impl crate::Instance<super::Api> for Instance {
|
|||
}
|
||||
|
||||
if desc.flags.contains(InstanceFlags::VALIDATION) && gl.supports_debug() {
|
||||
log::info!("Enabling GL debug output");
|
||||
log::debug!("Enabling GL debug output");
|
||||
unsafe { gl.enable(glow::DEBUG_OUTPUT) };
|
||||
unsafe { gl.debug_message_callback(super::gl_debug_message_callback) };
|
||||
}
|
||||
|
@ -421,7 +420,6 @@ impl crate::Instance<super::Api> for Instance {
|
|||
Ok(Instance {
|
||||
inner: Arc::new(Mutex::new(Inner {
|
||||
device: dc,
|
||||
opengl_module,
|
||||
gl,
|
||||
context,
|
||||
})),
|
||||
|
@ -476,12 +474,12 @@ impl Drop for DeviceContextHandle {
|
|||
}
|
||||
|
||||
pub struct Swapchain {
|
||||
surface_context: WglContext,
|
||||
surface_gl: glow::Context,
|
||||
framebuffer: glow::Framebuffer,
|
||||
renderbuffer: glow::Renderbuffer,
|
||||
|
||||
/// Extent because the window lies
|
||||
extent: wgt::Extent3d,
|
||||
|
||||
format: wgt::TextureFormat,
|
||||
format_desc: super::TextureFormatDesc,
|
||||
#[allow(unused)]
|
||||
|
@ -520,17 +518,25 @@ impl Surface {
|
|||
window: self.window,
|
||||
};
|
||||
|
||||
// Hold the lock for the shared context as we're using resources from there.
|
||||
let _inner = context.inner.lock();
|
||||
let inner = context.inner.lock();
|
||||
|
||||
if let Err(e) = sc.surface_context.make_current(dc.device) {
|
||||
log::error!("unable to make the surface OpenGL context current: {e}",);
|
||||
if let Err(e) = inner.context.make_current(dc.device) {
|
||||
log::error!("unable to make the OpenGL context current for surface: {e}",);
|
||||
return Err(crate::SurfaceError::Other(
|
||||
"unable to make the surface OpenGL context current",
|
||||
"unable to make the OpenGL context current for surface",
|
||||
));
|
||||
}
|
||||
|
||||
let gl = &sc.surface_gl;
|
||||
let gl = &inner.gl;
|
||||
|
||||
unsafe { gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, None) };
|
||||
unsafe { gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(sc.framebuffer)) };
|
||||
|
||||
if self.srgb_capable {
|
||||
// Disable sRGB conversions for `glBlitFramebuffer` as behavior does diverge between
|
||||
// drivers and formats otherwise and we want to ensure no sRGB conversions happen.
|
||||
unsafe { gl.disable(glow::FRAMEBUFFER_SRGB) };
|
||||
}
|
||||
|
||||
// Note the Y-flipping here. GL's presentation is not flipped,
|
||||
// but main rendering is. Therefore, we Y-flip the output positions
|
||||
|
@ -550,6 +556,13 @@ impl Surface {
|
|||
)
|
||||
};
|
||||
|
||||
if self.srgb_capable {
|
||||
unsafe { gl.enable(glow::FRAMEBUFFER_SRGB) };
|
||||
}
|
||||
|
||||
unsafe { gl.bind_renderbuffer(glow::RENDERBUFFER, None) };
|
||||
unsafe { gl.bind_framebuffer(glow::READ_FRAMEBUFFER, None) };
|
||||
|
||||
if unsafe { SwapBuffers(dc.device) } == FALSE {
|
||||
log::error!("unable to swap buffers: {}", Error::last_os_error());
|
||||
return Err(crate::SurfaceError::Other("unable to swap buffers"));
|
||||
|
@ -572,33 +585,6 @@ impl crate::Surface<super::Api> for Surface {
|
|||
// Remove the old configuration.
|
||||
unsafe { self.unconfigure(device) };
|
||||
|
||||
let format_desc = device.shared.describe_texture_format(config.format);
|
||||
let inner = &device.shared.context.inner.lock();
|
||||
|
||||
if let Err(e) = inner.context.make_current(inner.device) {
|
||||
log::error!("unable to make the shared OpenGL context current: {e}",);
|
||||
return Err(crate::SurfaceError::Other(
|
||||
"unable to make the shared OpenGL context current",
|
||||
));
|
||||
}
|
||||
|
||||
let gl = &inner.gl;
|
||||
let renderbuffer = unsafe { gl.create_renderbuffer() }.map_err(|error| {
|
||||
log::error!("Internal swapchain renderbuffer creation failed: {error}");
|
||||
crate::DeviceError::OutOfMemory
|
||||
})?;
|
||||
unsafe { gl.bind_renderbuffer(glow::RENDERBUFFER, Some(renderbuffer)) };
|
||||
unsafe {
|
||||
gl.renderbuffer_storage(
|
||||
glow::RENDERBUFFER,
|
||||
format_desc.internal,
|
||||
config.extent.width as _,
|
||||
config.extent.height as _,
|
||||
)
|
||||
};
|
||||
|
||||
// Create the swap chain OpenGL context
|
||||
|
||||
let dc = unsafe { GetDC(self.window) };
|
||||
if dc.is_null() {
|
||||
log::error!(
|
||||
|
@ -621,35 +607,48 @@ impl crate::Surface<super::Api> for Surface {
|
|||
));
|
||||
}
|
||||
|
||||
let context = unsafe { wglCreateContext(dc.device) };
|
||||
if context.is_null() {
|
||||
log::error!(
|
||||
"unable to create surface OpenGL context: {}",
|
||||
Error::last_os_error()
|
||||
);
|
||||
return Err(crate::SurfaceError::Other(
|
||||
"unable to create surface OpenGL context",
|
||||
));
|
||||
}
|
||||
let surface_context = WglContext { context };
|
||||
let format_desc = device.shared.describe_texture_format(config.format);
|
||||
let inner = &device.shared.context.inner.lock();
|
||||
|
||||
if unsafe { wglShareLists(inner.context.context, surface_context.context) } == FALSE {
|
||||
log::error!(
|
||||
"unable to share objects between OpenGL contexts: {}",
|
||||
Error::last_os_error()
|
||||
);
|
||||
if let Err(e) = inner.context.make_current(dc.device) {
|
||||
log::error!("unable to make the OpenGL context current for surface: {e}",);
|
||||
return Err(crate::SurfaceError::Other(
|
||||
"unable to share objects between OpenGL contexts",
|
||||
"unable to make the OpenGL context current for surface",
|
||||
));
|
||||
}
|
||||
|
||||
if let Err(e) = surface_context.make_current(dc.device) {
|
||||
log::error!("unable to make the surface OpengL context current: {e}",);
|
||||
return Err(crate::SurfaceError::Other(
|
||||
"unable to make the surface OpengL context current",
|
||||
));
|
||||
}
|
||||
let gl = &inner.gl;
|
||||
let renderbuffer = unsafe { gl.create_renderbuffer() }.map_err(|error| {
|
||||
log::error!("Internal swapchain renderbuffer creation failed: {error}");
|
||||
crate::DeviceError::OutOfMemory
|
||||
})?;
|
||||
unsafe { gl.bind_renderbuffer(glow::RENDERBUFFER, Some(renderbuffer)) };
|
||||
unsafe {
|
||||
gl.renderbuffer_storage(
|
||||
glow::RENDERBUFFER,
|
||||
format_desc.internal,
|
||||
config.extent.width as _,
|
||||
config.extent.height as _,
|
||||
)
|
||||
};
|
||||
|
||||
let framebuffer = unsafe { gl.create_framebuffer() }.map_err(|error| {
|
||||
log::error!("Internal swapchain framebuffer creation failed: {error}");
|
||||
crate::DeviceError::OutOfMemory
|
||||
})?;
|
||||
unsafe { gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(framebuffer)) };
|
||||
unsafe {
|
||||
gl.framebuffer_renderbuffer(
|
||||
glow::READ_FRAMEBUFFER,
|
||||
glow::COLOR_ATTACHMENT0,
|
||||
glow::RENDERBUFFER,
|
||||
Some(renderbuffer),
|
||||
)
|
||||
};
|
||||
unsafe { gl.bind_renderbuffer(glow::RENDERBUFFER, None) };
|
||||
unsafe { gl.bind_framebuffer(glow::READ_FRAMEBUFFER, None) };
|
||||
|
||||
// Setup presentation mode
|
||||
let extra = Wgl::load_with(|name| load_gl_func(name, None));
|
||||
let extentions = extensions(&extra, dc.device);
|
||||
if !(extentions.contains("WGL_EXT_swap_control") && extra.SwapIntervalEXT.is_loaded()) {
|
||||
|
@ -673,58 +672,7 @@ impl crate::Surface<super::Api> for Surface {
|
|||
return Err(crate::SurfaceError::Other("unable to set swap interval"));
|
||||
}
|
||||
|
||||
let surface_gl = unsafe {
|
||||
glow::Context::from_loader_function(|name| {
|
||||
load_gl_func(name, Some(inner.opengl_module))
|
||||
})
|
||||
};
|
||||
|
||||
// Check that the surface context OpenGL is new enough to support framebuffers.
|
||||
let version = unsafe { gl.get_parameter_string(glow::VERSION) };
|
||||
let version = super::Adapter::parse_full_version(&version);
|
||||
match version {
|
||||
Ok(version) => {
|
||||
if version < (3, 0) {
|
||||
log::error!(
|
||||
"surface context OpenGL version ({}.{}) too old",
|
||||
version.0,
|
||||
version.1
|
||||
);
|
||||
return Err(crate::SurfaceError::Other(
|
||||
"surface context OpenGL version too old",
|
||||
));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("unable to parse surface context OpenGL version: {e}",);
|
||||
return Err(crate::SurfaceError::Other(
|
||||
"unable to parse surface context OpenGL version",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let framebuffer = unsafe { surface_gl.create_framebuffer() }.map_err(|error| {
|
||||
log::error!("Internal swapchain framebuffer creation failed: {error}");
|
||||
crate::DeviceError::OutOfMemory
|
||||
})?;
|
||||
unsafe { surface_gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(framebuffer)) };
|
||||
unsafe {
|
||||
surface_gl.framebuffer_renderbuffer(
|
||||
glow::READ_FRAMEBUFFER,
|
||||
glow::COLOR_ATTACHMENT0,
|
||||
glow::RENDERBUFFER,
|
||||
Some(renderbuffer),
|
||||
)
|
||||
};
|
||||
unsafe { surface_gl.bind_renderbuffer(glow::RENDERBUFFER, None) };
|
||||
unsafe { surface_gl.bind_framebuffer(glow::READ_FRAMEBUFFER, None) };
|
||||
|
||||
unsafe { surface_gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, None) };
|
||||
unsafe { surface_gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(framebuffer)) };
|
||||
|
||||
self.swapchain = Some(Swapchain {
|
||||
surface_context,
|
||||
surface_gl,
|
||||
renderbuffer,
|
||||
framebuffer,
|
||||
extent: config.extent,
|
||||
|
|
|
@ -1097,6 +1097,8 @@ pub struct NagaShader {
|
|||
pub module: Cow<'static, naga::Module>,
|
||||
/// Analysis information of the module.
|
||||
pub info: naga::valid::ModuleInfo,
|
||||
/// Source codes for debug
|
||||
pub debug_source: Option<DebugSource>,
|
||||
}
|
||||
|
||||
// Custom implementation avoids the need to generate Debug impl code
|
||||
|
@ -1119,6 +1121,12 @@ pub struct ShaderModuleDescriptor<'a> {
|
|||
pub runtime_checks: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DebugSource {
|
||||
pub file_name: Cow<'static, str>,
|
||||
pub source_code: Cow<'static, str>,
|
||||
}
|
||||
|
||||
/// Describes a programmable pipeline stage.
|
||||
#[derive(Debug)]
|
||||
pub struct ProgrammableStage<'a, A: Api> {
|
||||
|
|
|
@ -80,7 +80,8 @@ impl Instance {
|
|||
|
||||
impl crate::Instance<Api> for Instance {
|
||||
unsafe fn init(_desc: &crate::InstanceDescriptor) -> Result<Self, crate::InstanceError> {
|
||||
//TODO: enable `METAL_DEVICE_WRAPPER_TYPE` environment based on the flags?
|
||||
// We do not enable metal validation based on the validation flags as it affects the entire
|
||||
// process. Instead, we enable the validation inside the test harness itself in tests/src/native.rs.
|
||||
Ok(Instance {
|
||||
managed_metal_layer_delegate: surface::HalManagedMetalLayerDelegate::new(),
|
||||
})
|
||||
|
|
|
@ -326,7 +326,8 @@ impl PhysicalDeviceFeatures {
|
|||
| Df::UNRESTRICTED_INDEX_BUFFER
|
||||
| Df::INDIRECT_EXECUTION
|
||||
| Df::VIEW_FORMATS
|
||||
| Df::UNRESTRICTED_EXTERNAL_TEXTURE_COPIES;
|
||||
| Df::UNRESTRICTED_EXTERNAL_TEXTURE_COPIES
|
||||
| Df::NONBLOCKING_QUERY_RESOLVE;
|
||||
|
||||
dl_flags.set(
|
||||
Df::SURFACE_VIEW_FORMATS,
|
||||
|
|
|
@ -723,7 +723,9 @@ impl super::Device {
|
|||
entry_point: stage.entry_point.to_string(),
|
||||
shader_stage: naga_stage,
|
||||
};
|
||||
let needs_temp_options = !runtime_checks || !binding_map.is_empty();
|
||||
let needs_temp_options = !runtime_checks
|
||||
|| !binding_map.is_empty()
|
||||
|| naga_shader.debug_source.is_some();
|
||||
let mut temp_options;
|
||||
let options = if needs_temp_options {
|
||||
temp_options = self.naga_options.clone();
|
||||
|
@ -739,6 +741,14 @@ impl super::Device {
|
|||
if !binding_map.is_empty() {
|
||||
temp_options.binding_map = binding_map.clone();
|
||||
}
|
||||
|
||||
if let Some(ref debug) = naga_shader.debug_source {
|
||||
temp_options.debug_info = Some(naga::back::spv::DebugInfo {
|
||||
source_code: &debug.source_code,
|
||||
file_name: debug.file_name.as_ref().as_ref(),
|
||||
})
|
||||
}
|
||||
|
||||
&temp_options
|
||||
} else {
|
||||
&self.naga_options
|
||||
|
@ -1513,6 +1523,14 @@ impl crate::Device<super::Api> for super::Device {
|
|||
});
|
||||
}
|
||||
let mut naga_options = self.naga_options.clone();
|
||||
naga_options.debug_info =
|
||||
naga_shader
|
||||
.debug_source
|
||||
.as_ref()
|
||||
.map(|d| naga::back::spv::DebugInfo {
|
||||
source_code: d.source_code.as_ref(),
|
||||
file_name: d.file_name.as_ref().as_ref(),
|
||||
});
|
||||
if !desc.runtime_checks {
|
||||
naga_options.bounds_check_policies = naga::proc::BoundsCheckPolicies {
|
||||
index: naga::proc::BoundsCheckPolicy::Unchecked,
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"60d11013451ea3e3d460b7548e2cc0e3d72ec0fa4d9961d4d4eda3f089bda729","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","src/assertions.rs":"3fe98027aa73970c8ab7874a3e13dbfd6faa87df2081beb5c83aeec4c60f372f","src/lib.rs":"b874a635584930085c801ccf8b6d6c157298d3e1df55b039d3919cfc0d2cd85b","src/math.rs":"4d03039736dd6926feb139bc68734cb59df34ede310427bbf059e5c925e0af3b"},"package":null}
|
||||
{"files":{"Cargo.toml":"5740ba85d83eadf690d7571d1b3268c364eaacb311569758b8ea5ed5eeb70580","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","src/assertions.rs":"3fe98027aa73970c8ab7874a3e13dbfd6faa87df2081beb5c83aeec4c60f372f","src/lib.rs":"58eb04d8a2387fd87f3623f7004fb0353020aa9ff6c02aa19166788ab6b7c772","src/math.rs":"4d03039736dd6926feb139bc68734cb59df34ede310427bbf059e5c925e0af3b"},"package":null}
|
|
@ -13,7 +13,7 @@
|
|||
edition = "2021"
|
||||
rust-version = "1.65"
|
||||
name = "wgpu-types"
|
||||
version = "0.17.0"
|
||||
version = "0.18.0"
|
||||
authors = ["wgpu developers"]
|
||||
description = "WebGPU types"
|
||||
homepage = "https://wgpu.rs/"
|
||||
|
|
|
@ -1463,6 +1463,23 @@ bitflags::bitflags! {
|
|||
///
|
||||
/// The GLES/WebGL and Vulkan on Android doesn't support this.
|
||||
const SURFACE_VIEW_FORMATS = 1 << 21;
|
||||
|
||||
/// If this is true, calls to `CommandEncoder::resolve_query_set` will be performed on the queue timeline.
|
||||
///
|
||||
/// If this is false, calls to `CommandEncoder::resolve_query_set` will be performed on the device (i.e. cpu) timeline
|
||||
/// and will block that timeline until the query has data. You may work around this limitation by waiting until the submit
|
||||
/// whose queries you are resolving is fully finished (through use of `queue.on_submitted_work_done`) and only
|
||||
/// then submitting the resolve_query_set command. The queries will be guarenteed finished, so will not block.
|
||||
///
|
||||
/// Supported by:
|
||||
/// - Vulkan,
|
||||
/// - DX12
|
||||
/// - Metal
|
||||
/// - OpenGL 4.4+
|
||||
///
|
||||
/// Not Supported by:
|
||||
/// - GL ES / WebGL
|
||||
const NONBLOCKING_QUERY_RESOLVE = 1 << 22;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче