зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 2 changesets (bug 1769633) for causing build bustages in jimb/rust/wgpu/wgpu-core. CLOSED TREE
Backed out changeset d7b9bac2ace5 (bug 1769633) Backed out changeset 82d7d8a51cdd (bug 1769633)
This commit is contained in:
Родитель
2fd8458561
Коммит
f4c40b82c0
|
@ -85,12 +85,12 @@ rev = "3484d3e3ebdc8931493aa5df4d7ee9360a90e76b"
|
|||
[source."https://github.com/gfx-rs/wgpu"]
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
replace-with = "vendored-sources"
|
||||
rev = "b51fd851"
|
||||
rev = "0b61a191"
|
||||
|
||||
[source."https://github.com/gfx-rs/naga"]
|
||||
git = "https://github.com/gfx-rs/naga"
|
||||
replace-with = "vendored-sources"
|
||||
rev = "1aa91549"
|
||||
rev = "85056524"
|
||||
|
||||
[source."https://github.com/gfx-rs/metal-rs"]
|
||||
git = "https://github.com/gfx-rs/metal-rs"
|
||||
|
|
|
@ -332,7 +332,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
version = "1.0.1"
|
||||
|
||||
[[package]]
|
||||
name = "baldrdash"
|
||||
|
@ -3432,7 +3432,7 @@ checksum = "a2983372caf4480544083767bf2d27defafe32af49ab4df3a0b7fc90793a3664"
|
|||
[[package]]
|
||||
name = "naga"
|
||||
version = "0.8.0"
|
||||
source = "git+https://github.com/gfx-rs/naga?rev=1aa91549#1aa9154964238af8c692cf521ff90e1f2395e147"
|
||||
source = "git+https://github.com/gfx-rs/naga?rev=85056524#850565243d1d0d03215f13246c94d63e1d4c51cd"
|
||||
dependencies = [
|
||||
"bit-set",
|
||||
"bitflags",
|
||||
|
@ -5876,7 +5876,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "wgpu-core"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=b51fd851#b51fd851be51cfe40c937ef789a44244e7dc2971"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=0b61a191#0b61a191244da0f0d987d53614a6698097a7622f"
|
||||
dependencies = [
|
||||
"arrayvec 0.7.2",
|
||||
"bitflags",
|
||||
|
@ -5899,7 +5899,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "wgpu-hal"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=b51fd851#b51fd851be51cfe40c937ef789a44244e7dc2971"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=0b61a191#0b61a191244da0f0d987d53614a6698097a7622f"
|
||||
dependencies = [
|
||||
"arrayvec 0.7.2",
|
||||
"ash",
|
||||
|
@ -5936,7 +5936,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "wgpu-types"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=b51fd851#b51fd851be51cfe40c937ef789a44244e7dc2971"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=0b61a191#0b61a191244da0f0d987d53614a6698097a7622f"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags_serde_shim",
|
||||
|
|
|
@ -63,15 +63,15 @@ void ComputePassEncoder::SetPipeline(const ComputePipeline& aPipeline) {
|
|||
void ComputePassEncoder::DispatchWorkgroups(uint32_t x, uint32_t y,
|
||||
uint32_t z) {
|
||||
if (mValid) {
|
||||
ffi::wgpu_compute_pass_dispatch_workgroups(mPass, x, y, z);
|
||||
ffi::wgpu_compute_pass_dispatch(mPass, x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
void ComputePassEncoder::DispatchWorkgroupsIndirect(
|
||||
const Buffer& aIndirectBuffer, uint64_t aIndirectOffset) {
|
||||
if (mValid) {
|
||||
ffi::wgpu_compute_pass_dispatch_workgroups_indirect(
|
||||
mPass, aIndirectBuffer.mId, aIndirectOffset);
|
||||
ffi::wgpu_compute_pass_dispatch_indirect(mPass, aIndirectBuffer.mId,
|
||||
aIndirectOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ default = []
|
|||
[dependencies.wgc]
|
||||
package = "wgpu-core"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "b51fd851"
|
||||
rev = "0b61a191"
|
||||
#Note: "replay" shouldn't ideally be needed,
|
||||
# but it allows us to serialize everything across IPC.
|
||||
features = ["replay", "trace", "serial-pass"]
|
||||
|
@ -25,12 +25,12 @@ features = ["replay", "trace", "serial-pass"]
|
|||
[dependencies.wgt]
|
||||
package = "wgpu-types"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "b51fd851"
|
||||
rev = "0b61a191"
|
||||
|
||||
[dependencies.wgh]
|
||||
package = "wgpu-hal"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "b51fd851"
|
||||
rev = "0b61a191"
|
||||
|
||||
[dependencies]
|
||||
bincode = "1"
|
||||
|
|
|
@ -18,8 +18,8 @@ if CONFIG["COMPILE_ENVIRONMENT"]:
|
|||
"wgpu_ffi_generated.h",
|
||||
inputs=[
|
||||
"/gfx/wgpu_bindings",
|
||||
"%/home/jimb/rust/wgpu/wgpu-core",
|
||||
"%/home/jimb/rust/wgpu/wgpu-types",
|
||||
"/third_party/rust/wgpu-core",
|
||||
"/third_party/rust/wgpu-types",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -1092,6 +1092,28 @@ pub unsafe extern "C" fn wgpu_command_encoder_insert_debug_marker(
|
|||
*bb = make_byte_buf(&action);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wgpu_render_pass_set_index_buffer(
|
||||
pass: &mut wgc::command::RenderPass,
|
||||
buffer: wgc::id::BufferId,
|
||||
index_format: wgt::IndexFormat,
|
||||
offset: wgt::BufferAddress,
|
||||
size: Option<wgt::BufferSize>,
|
||||
) {
|
||||
pass.set_index_buffer(buffer, index_format, offset, size);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wgpu_render_bundle_set_index_buffer(
|
||||
encoder: &mut wgc::command::RenderBundleEncoder,
|
||||
buffer: wgc::id::BufferId,
|
||||
index_format: wgt::IndexFormat,
|
||||
offset: wgt::BufferAddress,
|
||||
size: Option<wgt::BufferSize>,
|
||||
) {
|
||||
encoder.set_index_buffer(buffer, index_format, offset, size);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn wgpu_queue_write_buffer(
|
||||
dst: id::BufferId,
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.lock":"3d91565ed13de572a9ebde408a0c98e33f931d6ab52f212b0830a60b4ab26b77","Cargo.toml":"39f627122dceaad42146634719fde802fca3baa1b3908753af723074ae2a6d69","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"27995d58ad5c1145c1a8cd86244ce844886958a35eb2b78c6b772748669999ac","README.md":"4c8f9b5016f2a0c3dbeca5bc41241f57db5568f803e58c1fa480ae2b3638d0a9","examples/integers.rs":"589ff4271566dfa322becddf3e2c7b592e6e0bc97b02892ce75619b7e452e930","examples/paths.rs":"1b30e466b824ce8df7ad0a55334424131d9d2573d6cf9f7d5d50c09c8901d526","examples/traits.rs":"cbee6a3e1f7db60b02ae25b714926517144a77cb492021f492774cf0e1865a9e","examples/versions.rs":"38535e6d9f5bfae0de474a3db79a40e8f5da8ba9334c5ff4c363de9bc99d4d12","src/error.rs":"12de7dafea4a35d1dc2f0fa79bfa038386bbbea72bf083979f4ddf227999eeda","src/lib.rs":"6fa01458e8f9258d84f83ead24fdb0cdf9aec10838b0262f1dfbdf79c530c537","src/tests.rs":"f0e6dc1ad9223c0336c02e215ea3940acb2af6c3bc8fd791e16cd4e786e6a608","src/version.rs":"175727d5f02f2fe2271ddc9b041db2a5b9c6fe0f95afd17c73a4d982612764a3","tests/rustflags.rs":"5c8169b88216055019db61b5d7baf4abdf675e3b14b54f5037bb1e3acd0a5d3f"},"package":"d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"}
|
||||
{"files":{"Cargo.lock":"d658acfaa27a2b30de98cf004d4d3f4ec0f1757b136610289cbbd1c847ae2e6c","Cargo.toml":"e2176be78c2989884eba4a20a58a672277b3a8a99a72b0ba7347f48eb827ae0e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"27995d58ad5c1145c1a8cd86244ce844886958a35eb2b78c6b772748669999ac","README.md":"2d8b6f07819ad7adfab1d153216bfdcde154ffd4a870d98794125c910b0f4593","examples/integers.rs":"589ff4271566dfa322becddf3e2c7b592e6e0bc97b02892ce75619b7e452e930","examples/paths.rs":"1b30e466b824ce8df7ad0a55334424131d9d2573d6cf9f7d5d50c09c8901d526","examples/traits.rs":"cbee6a3e1f7db60b02ae25b714926517144a77cb492021f492774cf0e1865a9e","examples/versions.rs":"38535e6d9f5bfae0de474a3db79a40e8f5da8ba9334c5ff4c363de9bc99d4d12","src/error.rs":"12de7dafea4a35d1dc2f0fa79bfa038386bbbea72bf083979f4ddf227999eeda","src/lib.rs":"9b450d90730624807979045ea7ff48374355314cd894345e1b9651485ba1b2ff","src/tests.rs":"a902fbd42b0f0b81a2830f2368fab733041b02fcb902c8e2520d07b3bff10713","src/version.rs":"175727d5f02f2fe2271ddc9b041db2a5b9c6fe0f95afd17c73a4d982612764a3","tests/rustflags.rs":"441fb0c6606e243c31d3817a5ae2240b65fcae0ea8ab583f80f8f6d6c267e614"},"package":"cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"}
|
|
@ -1,7 +1,6 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
version = "1.0.1"
|
||||
|
||||
|
|
|
@ -3,15 +3,16 @@
|
|||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
# to registry (e.g., crates.io) dependencies
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
# If you believe there's an error in this file please file an
|
||||
# issue against the rust-lang/cargo repository. If you're
|
||||
# editing this file be aware that the upstream Cargo.toml
|
||||
# will likely look very different (and much more reasonable)
|
||||
|
||||
[package]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
version = "1.0.1"
|
||||
authors = ["Josh Stone <cuviper@gmail.com>"]
|
||||
exclude = ["/.github/**", "/bors.toml"]
|
||||
description = "Automatic cfg for Rust compiler features"
|
||||
|
|
|
@ -43,9 +43,6 @@ should only be used when the compiler supports it.
|
|||
|
||||
## Release Notes
|
||||
|
||||
- 1.1.0 (2022-02-07)
|
||||
- Use `CARGO_ENCODED_RUSTFLAGS` when it is set.
|
||||
|
||||
- 1.0.1 (2020-08-20)
|
||||
- Apply `RUSTFLAGS` for more `--target` scenarios, by @adamreichold.
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ use std::env;
|
|||
use std::ffi::OsString;
|
||||
use std::fs;
|
||||
use std::io::{stderr, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::PathBuf;
|
||||
use std::process::{Command, Stdio};
|
||||
#[allow(deprecated)]
|
||||
use std::sync::atomic::ATOMIC_USIZE_INIT;
|
||||
|
@ -86,7 +86,7 @@ pub struct AutoCfg {
|
|||
rustc_version: Version,
|
||||
target: Option<OsString>,
|
||||
no_std: bool,
|
||||
rustflags: Vec<String>,
|
||||
rustflags: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
/// Writes a config flag for rustc on standard out.
|
||||
|
@ -166,13 +166,37 @@ impl AutoCfg {
|
|||
return Err(error::from_str("output path is not a writable directory"));
|
||||
}
|
||||
|
||||
// Cargo only applies RUSTFLAGS for building TARGET artifact in
|
||||
// cross-compilation environment. Sadly, we don't have a way to detect
|
||||
// when we're building HOST artifact in a cross-compilation environment,
|
||||
// so for now we only apply RUSTFLAGS when cross-compiling an artifact.
|
||||
//
|
||||
// See https://github.com/cuviper/autocfg/pull/10#issuecomment-527575030.
|
||||
let rustflags = if target != env::var_os("HOST")
|
||||
|| dir_contains_target(&target, &dir, env::var_os("CARGO_TARGET_DIR"))
|
||||
{
|
||||
env::var("RUSTFLAGS").ok().map(|rustflags| {
|
||||
// This is meant to match how cargo handles the RUSTFLAG environment
|
||||
// variable.
|
||||
// See https://github.com/rust-lang/cargo/blob/69aea5b6f69add7c51cca939a79644080c0b0ba0/src/cargo/core/compiler/build_context/target_info.rs#L434-L441
|
||||
rustflags
|
||||
.split(' ')
|
||||
.map(str::trim)
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(str::to_string)
|
||||
.collect::<Vec<String>>()
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut ac = AutoCfg {
|
||||
rustflags: rustflags(&target, &dir),
|
||||
out_dir: dir,
|
||||
rustc: rustc,
|
||||
rustc_version: rustc_version,
|
||||
target: target,
|
||||
no_std: false,
|
||||
rustflags: rustflags,
|
||||
};
|
||||
|
||||
// Sanity check with and without `std`.
|
||||
|
@ -216,23 +240,14 @@ impl AutoCfg {
|
|||
.arg(&self.out_dir)
|
||||
.arg("--emit=llvm-ir");
|
||||
|
||||
if let &Some(ref rustflags) = &self.rustflags {
|
||||
command.args(rustflags);
|
||||
}
|
||||
|
||||
if let Some(target) = self.target.as_ref() {
|
||||
command.arg("--target").arg(target);
|
||||
}
|
||||
|
||||
command.args(&self.rustflags);
|
||||
|
||||
// Mozilla-local change: throw away stderr output.
|
||||
//
|
||||
// Mozilla's build system runs cargo with `-v -v` to help diagnose rustc
|
||||
// selection problems. Without the change below, that causes error
|
||||
// messages from autocfg compiler invocations (which simply indicate
|
||||
// that the feature autocfg was checking for isn't available, and are
|
||||
// not actual build errors) to show up in the build output stream, where
|
||||
// they confuse other parts of Mozilla's build system that try to
|
||||
// highlight and track errors.
|
||||
//
|
||||
// See: https://github.com/cuviper/autocfg/issues/30
|
||||
command.arg("-").stdin(Stdio::piped()).stderr(Stdio::null());
|
||||
let mut child = try!(command.spawn().map_err(error::from_io));
|
||||
let mut stdin = child.stdin.take().expect("rustc stdin");
|
||||
|
@ -402,7 +417,7 @@ fn mangle(s: &str) -> String {
|
|||
|
||||
fn dir_contains_target(
|
||||
target: &Option<OsString>,
|
||||
dir: &Path,
|
||||
dir: &PathBuf,
|
||||
cargo_target_dir: Option<OsString>,
|
||||
) -> bool {
|
||||
target
|
||||
|
@ -421,44 +436,3 @@ fn dir_contains_target(
|
|||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
fn rustflags(target: &Option<OsString>, dir: &Path) -> Vec<String> {
|
||||
// Starting with rust-lang/cargo#9601, shipped in Rust 1.55, Cargo always sets
|
||||
// CARGO_ENCODED_RUSTFLAGS for any host/target build script invocation. This
|
||||
// includes any source of flags, whether from the environment, toml config, or
|
||||
// whatever may come in the future. The value is either an empty string, or a
|
||||
// list of arguments separated by the ASCII unit separator (US), 0x1f.
|
||||
if let Ok(a) = env::var("CARGO_ENCODED_RUSTFLAGS") {
|
||||
return if a.is_empty() {
|
||||
Vec::new()
|
||||
} else {
|
||||
a.split('\x1f').map(str::to_string).collect()
|
||||
};
|
||||
}
|
||||
|
||||
// Otherwise, we have to take a more heuristic approach, and we don't
|
||||
// support values from toml config at all.
|
||||
//
|
||||
// Cargo only applies RUSTFLAGS for building TARGET artifact in
|
||||
// cross-compilation environment. Sadly, we don't have a way to detect
|
||||
// when we're building HOST artifact in a cross-compilation environment,
|
||||
// so for now we only apply RUSTFLAGS when cross-compiling an artifact.
|
||||
//
|
||||
// See https://github.com/cuviper/autocfg/pull/10#issuecomment-527575030.
|
||||
if *target != env::var_os("HOST")
|
||||
|| dir_contains_target(target, dir, env::var_os("CARGO_TARGET_DIR"))
|
||||
{
|
||||
if let Ok(rustflags) = env::var("RUSTFLAGS") {
|
||||
// This is meant to match how cargo handles the RUSTFLAGS environment variable.
|
||||
// See https://github.com/rust-lang/cargo/blob/69aea5b6f69add7c51cca939a79644080c0b0ba0/src/cargo/core/compiler/build_context/target_info.rs#L434-L441
|
||||
return rustflags
|
||||
.split(' ')
|
||||
.map(str::trim)
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(str::to_string)
|
||||
.collect();
|
||||
}
|
||||
}
|
||||
|
||||
Vec::new()
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use super::AutoCfg;
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
|
||||
impl AutoCfg {
|
||||
fn core_std(&self, path: &str) -> String {
|
||||
|
@ -137,7 +136,7 @@ fn probe_constant() {
|
|||
fn dir_does_not_contain_target() {
|
||||
assert!(!super::dir_contains_target(
|
||||
&Some("x86_64-unknown-linux-gnu".into()),
|
||||
Path::new("/project/target/debug/build/project-ea75983148559682/out"),
|
||||
&"/project/target/debug/build/project-ea75983148559682/out".into(),
|
||||
None,
|
||||
));
|
||||
}
|
||||
|
@ -146,9 +145,7 @@ fn dir_does_not_contain_target() {
|
|||
fn dir_does_contain_target() {
|
||||
assert!(super::dir_contains_target(
|
||||
&Some("x86_64-unknown-linux-gnu".into()),
|
||||
Path::new(
|
||||
"/project/target/x86_64-unknown-linux-gnu/debug/build/project-0147aca016480b9d/out"
|
||||
),
|
||||
&"/project/target/x86_64-unknown-linux-gnu/debug/build/project-0147aca016480b9d/out".into(),
|
||||
None,
|
||||
));
|
||||
}
|
||||
|
@ -157,7 +154,7 @@ fn dir_does_contain_target() {
|
|||
fn dir_does_not_contain_target_with_custom_target_dir() {
|
||||
assert!(!super::dir_contains_target(
|
||||
&Some("x86_64-unknown-linux-gnu".into()),
|
||||
Path::new("/project/custom/debug/build/project-ea75983148559682/out"),
|
||||
&"/project/custom/debug/build/project-ea75983148559682/out".into(),
|
||||
Some("custom".into()),
|
||||
));
|
||||
}
|
||||
|
@ -166,9 +163,7 @@ fn dir_does_not_contain_target_with_custom_target_dir() {
|
|||
fn dir_does_contain_target_with_custom_target_dir() {
|
||||
assert!(super::dir_contains_target(
|
||||
&Some("x86_64-unknown-linux-gnu".into()),
|
||||
Path::new(
|
||||
"/project/custom/x86_64-unknown-linux-gnu/debug/build/project-0147aca016480b9d/out"
|
||||
),
|
||||
&"/project/custom/x86_64-unknown-linux-gnu/debug/build/project-0147aca016480b9d/out".into(),
|
||||
Some("custom".into()),
|
||||
));
|
||||
}
|
||||
|
|
|
@ -2,32 +2,18 @@ extern crate autocfg;
|
|||
|
||||
use std::env;
|
||||
|
||||
/// Tests that autocfg uses the RUSTFLAGS or CARGO_ENCODED_RUSTFLAGS
|
||||
/// environment variables when running rustc.
|
||||
/// Tests that autocfg uses the RUSTFLAGS environment variable when running
|
||||
/// rustc.
|
||||
#[test]
|
||||
fn test_with_sysroot() {
|
||||
// Use the same path as this test binary.
|
||||
let dir = env::current_exe().unwrap().parent().unwrap().to_path_buf();
|
||||
env::set_var("RUSTFLAGS", &format!("-L {}", dir.display()));
|
||||
env::set_var("OUT_DIR", &format!("{}", dir.display()));
|
||||
|
||||
// If we have encoded rustflags, they take precedence, even if empty.
|
||||
env::set_var("CARGO_ENCODED_RUSTFLAGS", "");
|
||||
env::set_var("RUSTFLAGS", &format!("-L {}", dir.display()));
|
||||
let ac = autocfg::AutoCfg::new().unwrap();
|
||||
assert!(ac.probe_sysroot_crate("std"));
|
||||
assert!(!ac.probe_sysroot_crate("autocfg"));
|
||||
|
||||
// Now try again with useful encoded args.
|
||||
env::set_var(
|
||||
"CARGO_ENCODED_RUSTFLAGS",
|
||||
&format!("-L\x1f{}", dir.display()),
|
||||
);
|
||||
let ac = autocfg::AutoCfg::new().unwrap();
|
||||
assert!(ac.probe_sysroot_crate("autocfg"));
|
||||
|
||||
// Try the old-style RUSTFLAGS, ensuring HOST != TARGET.
|
||||
env::remove_var("CARGO_ENCODED_RUSTFLAGS");
|
||||
// Ensure HOST != TARGET.
|
||||
env::set_var("HOST", "lol");
|
||||
|
||||
let ac = autocfg::AutoCfg::new().unwrap();
|
||||
assert!(ac.probe_sysroot_crate("autocfg"));
|
||||
}
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -785,8 +785,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
|||
TypeInner::Pointer { .. }
|
||||
| TypeInner::Struct { .. }
|
||||
| TypeInner::Image { .. }
|
||||
| TypeInner::Sampler { .. }
|
||||
| TypeInner::BindingArray { .. } => {
|
||||
| TypeInner::Sampler { .. } => {
|
||||
return Err(Error::Custom(format!("Unable to write type {:?}", inner)))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,8 +119,6 @@ use crate::proc;
|
|||
pub struct BindTarget {
|
||||
pub space: u8,
|
||||
pub register: u32,
|
||||
/// If the binding is an unsized binding array, this overrides the size.
|
||||
pub binding_array_size: Option<u32>,
|
||||
}
|
||||
|
||||
// Using `BTreeMap` instead of `HashMap` so that we can hash itself.
|
||||
|
@ -216,7 +214,6 @@ impl Options {
|
|||
None if self.fake_missing_bindings => Ok(BindTarget {
|
||||
space: res_binding.group as u8,
|
||||
register: res_binding.binding,
|
||||
binding_array_size: None,
|
||||
}),
|
||||
None => Err(EntryPointError::MissingBinding(res_binding.clone())),
|
||||
}
|
||||
|
|
|
@ -603,12 +603,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
register
|
||||
}
|
||||
crate::AddressSpace::Handle => {
|
||||
let handle_ty = match *inner {
|
||||
TypeInner::BindingArray { ref base, .. } => &module.types[*base].inner,
|
||||
_ => inner,
|
||||
};
|
||||
|
||||
let register = match *handle_ty {
|
||||
let register = match *inner {
|
||||
TypeInner::Sampler { .. } => "s",
|
||||
// all storage textures are UAV, unconditionally
|
||||
TypeInner::Image {
|
||||
|
@ -629,16 +624,6 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
if let Some(ref binding) = global.binding {
|
||||
// this was already resolved earlier when we started evaluating an entry point.
|
||||
let bt = self.options.resolve_resource_binding(binding).unwrap();
|
||||
|
||||
// need to write the binding array size if the type was emitted with `write_type`
|
||||
if let TypeInner::BindingArray { base, size, .. } = module.types[global.ty].inner {
|
||||
if let Some(overridden_size) = bt.binding_array_size {
|
||||
write!(self.out, "[{}]", overridden_size)?;
|
||||
} else {
|
||||
self.write_array_size(module, base, size)?;
|
||||
}
|
||||
}
|
||||
|
||||
write!(self.out, " : register({}{}", register_ty, bt.register)?;
|
||||
if bt.space != 0 {
|
||||
write!(self.out, ", space{}", bt.space)?;
|
||||
|
@ -747,7 +732,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
let size = module.constants[const_handle].to_array_length().unwrap();
|
||||
write!(self.out, "{}", size)?;
|
||||
}
|
||||
crate::ArraySize::Dynamic => {}
|
||||
crate::ArraySize::Dynamic => unreachable!(),
|
||||
}
|
||||
|
||||
write!(self.out, "]")?;
|
||||
|
@ -889,9 +874,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
match *inner {
|
||||
TypeInner::Struct { .. } => write!(self.out, "{}", self.names[&NameKey::Type(ty)])?,
|
||||
// hlsl array has the size separated from the base type
|
||||
TypeInner::Array { base, .. } | TypeInner::BindingArray { base, .. } => {
|
||||
self.write_type(module, base)?
|
||||
}
|
||||
TypeInner::Array { base, .. } => self.write_type(module, base)?,
|
||||
ref other => self.write_value_type(module, other)?,
|
||||
}
|
||||
|
||||
|
@ -950,7 +933,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
// HLSL arrays are written as `type name[size]`
|
||||
// Current code is written arrays only as `[size]`
|
||||
// Base `type` and `name` should be written outside
|
||||
TypeInner::Array { base, size, .. } | TypeInner::BindingArray { base, size } => {
|
||||
TypeInner::Array { base, size, .. } => {
|
||||
self.write_array_size(module, base, size)?;
|
||||
}
|
||||
_ => {
|
||||
|
@ -1810,27 +1793,9 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
{
|
||||
// do nothing, the chain is written on `Load`/`Store`
|
||||
} else {
|
||||
let base_ty_res = &func_ctx.info[base].ty;
|
||||
let resolved = base_ty_res.inner_with(&module.types);
|
||||
|
||||
let non_uniform_qualifier = match *resolved {
|
||||
TypeInner::BindingArray { .. } => {
|
||||
let uniformity = &func_ctx.info[index].uniformity;
|
||||
|
||||
uniformity.non_uniform_result.is_some()
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
|
||||
self.write_expr(module, base, func_ctx)?;
|
||||
write!(self.out, "[")?;
|
||||
if non_uniform_qualifier {
|
||||
write!(self.out, "NonUniformResourceIndex(")?;
|
||||
}
|
||||
self.write_expr(module, index, func_ctx)?;
|
||||
if non_uniform_qualifier {
|
||||
write!(self.out, ")")?;
|
||||
}
|
||||
write!(self.out, "]")?;
|
||||
}
|
||||
}
|
||||
|
@ -1887,7 +1852,6 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
|||
}
|
||||
TypeInner::Matrix { .. }
|
||||
| TypeInner::Array { .. }
|
||||
| TypeInner::BindingArray { .. }
|
||||
| TypeInner::ValuePointer { .. } => write!(self.out, "[{}]", index)?,
|
||||
TypeInner::Struct { .. } => {
|
||||
// This will never panic in case the type is a `Struct`, this is not true
|
||||
|
|
|
@ -57,8 +57,6 @@ pub struct BindTarget {
|
|||
pub buffer: Option<Slot>,
|
||||
pub texture: Option<Slot>,
|
||||
pub sampler: Option<BindSamplerTarget>,
|
||||
/// If the binding is an unsized binding array, this overrides the size.
|
||||
pub binding_array_size: Option<u32>,
|
||||
pub mutable: bool,
|
||||
}
|
||||
|
||||
|
@ -321,7 +319,6 @@ impl Options {
|
|||
buffer: Some(slot),
|
||||
texture: None,
|
||||
sampler: None,
|
||||
binding_array_size: None,
|
||||
mutable: false,
|
||||
})),
|
||||
None if self.fake_missing_bindings => Ok(ResolvedBinding::User {
|
||||
|
@ -343,7 +340,6 @@ impl Options {
|
|||
buffer: Some(slot),
|
||||
texture: None,
|
||||
sampler: None,
|
||||
binding_array_size: None,
|
||||
mutable: false,
|
||||
})),
|
||||
None if self.fake_missing_bindings => Ok(ResolvedBinding::User {
|
||||
|
@ -367,13 +363,6 @@ impl ResolvedBinding {
|
|||
}
|
||||
}
|
||||
|
||||
const fn as_bind_target(&self) -> Option<&BindTarget> {
|
||||
match *self {
|
||||
Self::Resource(ref target) => Some(target),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn try_fmt<W: Write>(&self, out: &mut W) -> Result<(), Error> {
|
||||
write!(out, " [[")?;
|
||||
match *self {
|
||||
|
|
|
@ -70,16 +70,15 @@ const CLAMPED_LOD_LOAD_PREFIX: &str = "clamped_lod_e";
|
|||
|
||||
struct TypeContext<'a> {
|
||||
handle: Handle<crate::Type>,
|
||||
module: &'a crate::Module,
|
||||
arena: &'a crate::UniqueArena<crate::Type>,
|
||||
names: &'a FastHashMap<NameKey, String>,
|
||||
access: crate::StorageAccess,
|
||||
binding: Option<&'a super::ResolvedBinding>,
|
||||
first_time: bool,
|
||||
}
|
||||
|
||||
impl<'a> Display for TypeContext<'a> {
|
||||
fn fmt(&self, out: &mut Formatter<'_>) -> Result<(), FmtError> {
|
||||
let ty = &self.module.types[self.handle];
|
||||
let ty = &self.arena[self.handle];
|
||||
if ty.needs_alias() && !self.first_time {
|
||||
let name = &self.names[&NameKey::Type(self.handle)];
|
||||
return write!(out, "{}", name);
|
||||
|
@ -202,39 +201,6 @@ impl<'a> Display for TypeContext<'a> {
|
|||
crate::TypeInner::Sampler { comparison: _ } => {
|
||||
write!(out, "{}::sampler", NAMESPACE)
|
||||
}
|
||||
crate::TypeInner::BindingArray { base, size } => {
|
||||
let base_tyname = Self {
|
||||
handle: base,
|
||||
first_time: false,
|
||||
..*self
|
||||
};
|
||||
|
||||
if let Some(&super::ResolvedBinding::Resource(super::BindTarget {
|
||||
binding_array_size: Some(override_size),
|
||||
..
|
||||
})) = self.binding
|
||||
{
|
||||
write!(
|
||||
out,
|
||||
"{}::array<{}, {}>",
|
||||
NAMESPACE, base_tyname, override_size
|
||||
)
|
||||
} else if let crate::ArraySize::Constant(size) = size {
|
||||
let constant_ctx = ConstantContext {
|
||||
handle: size,
|
||||
arena: &self.module.constants,
|
||||
names: self.names,
|
||||
first_time: false,
|
||||
};
|
||||
write!(
|
||||
out,
|
||||
"{}::array<{}, {}>",
|
||||
NAMESPACE, base_tyname, constant_ctx
|
||||
)
|
||||
} else {
|
||||
unreachable!("metal requires all arrays be constant sized");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -244,7 +210,6 @@ struct TypedGlobalVariable<'a> {
|
|||
names: &'a FastHashMap<NameKey, String>,
|
||||
handle: Handle<crate::GlobalVariable>,
|
||||
usage: valid::GlobalUse,
|
||||
binding: Option<&'a super::ResolvedBinding>,
|
||||
reference: bool,
|
||||
}
|
||||
|
||||
|
@ -260,24 +225,14 @@ impl<'a> TypedGlobalVariable<'a> {
|
|||
class: crate::ImageClass::Storage { access, .. },
|
||||
..
|
||||
} => access,
|
||||
crate::TypeInner::BindingArray { base, .. } => {
|
||||
match self.module.types[base].inner {
|
||||
crate::TypeInner::Image {
|
||||
class: crate::ImageClass::Storage { access, .. },
|
||||
..
|
||||
} => access,
|
||||
_ => crate::StorageAccess::default(),
|
||||
}
|
||||
}
|
||||
_ => crate::StorageAccess::default(),
|
||||
},
|
||||
};
|
||||
let ty_name = TypeContext {
|
||||
handle: var.ty,
|
||||
module: self.module,
|
||||
arena: &self.module.types,
|
||||
names: self.names,
|
||||
access: storage_access,
|
||||
binding: self.binding,
|
||||
first_time: false,
|
||||
};
|
||||
|
||||
|
@ -497,7 +452,7 @@ impl crate::Type {
|
|||
// composite types are better to be aliased, regardless of the name
|
||||
Ti::Struct { .. } | Ti::Array { .. } => true,
|
||||
// handle types may be different, depending on the global var access, so we always inline them
|
||||
Ti::Image { .. } | Ti::Sampler { .. } | Ti::BindingArray { .. } => false,
|
||||
Ti::Image { .. } | Ti::Sampler { .. } => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1270,14 +1225,13 @@ impl<W: Write> Writer<W> {
|
|||
let expression = &context.function.expressions[expr_handle];
|
||||
log::trace!("expression {:?} = {:?}", expr_handle, expression);
|
||||
match *expression {
|
||||
crate::Expression::Access { base, .. }
|
||||
| crate::Expression::AccessIndex { base, .. } => {
|
||||
crate::Expression::Access { .. } | crate::Expression::AccessIndex { .. } => {
|
||||
// This is an acceptable place to generate a `ReadZeroSkipWrite` check.
|
||||
// Since `put_bounds_checks` and `put_access_chain` handle an entire
|
||||
// access chain at a time, recursing back through `put_expression` only
|
||||
// for index expressions and the base object, we will never see intermediate
|
||||
// `Access` or `AccessIndex` expressions here.
|
||||
let policy = context.choose_bounds_check_policy(base);
|
||||
let policy = context.choose_bounds_check_policy(expr_handle);
|
||||
if policy == index::BoundsCheckPolicy::ReadZeroSkipWrite
|
||||
&& self.put_bounds_checks(
|
||||
expr_handle,
|
||||
|
@ -2315,10 +2269,9 @@ impl<W: Write> Writer<W> {
|
|||
TypeResolution::Handle(ty_handle) => {
|
||||
let ty_name = TypeContext {
|
||||
handle: ty_handle,
|
||||
module: context.module,
|
||||
arena: &context.module.types,
|
||||
names: &self.names,
|
||||
access: crate::StorageAccess::empty(),
|
||||
binding: None,
|
||||
first_time: false,
|
||||
};
|
||||
write!(self.out, "{}", ty_name)?;
|
||||
|
@ -2910,10 +2863,9 @@ impl<W: Write> Writer<W> {
|
|||
} => {
|
||||
let base_name = TypeContext {
|
||||
handle: base,
|
||||
module,
|
||||
arena: &module.types,
|
||||
names: &self.names,
|
||||
access: crate::StorageAccess::empty(),
|
||||
binding: None,
|
||||
first_time: false,
|
||||
};
|
||||
|
||||
|
@ -2974,10 +2926,9 @@ impl<W: Write> Writer<W> {
|
|||
None => {
|
||||
let base_name = TypeContext {
|
||||
handle: member.ty,
|
||||
module,
|
||||
arena: &module.types,
|
||||
names: &self.names,
|
||||
access: crate::StorageAccess::empty(),
|
||||
binding: None,
|
||||
first_time: false,
|
||||
};
|
||||
writeln!(
|
||||
|
@ -3005,10 +2956,9 @@ impl<W: Write> Writer<W> {
|
|||
_ => {
|
||||
let ty_name = TypeContext {
|
||||
handle,
|
||||
module,
|
||||
arena: &module.types,
|
||||
names: &self.names,
|
||||
access: crate::StorageAccess::empty(),
|
||||
binding: None,
|
||||
first_time: true,
|
||||
};
|
||||
writeln!(self.out, "typedef {} {};", ty_name, name)?;
|
||||
|
@ -3065,10 +3015,9 @@ impl<W: Write> Writer<W> {
|
|||
let name = &self.names[&NameKey::Constant(handle)];
|
||||
let ty_name = TypeContext {
|
||||
handle: ty,
|
||||
module,
|
||||
arena: &module.types,
|
||||
names: &self.names,
|
||||
access: crate::StorageAccess::empty(),
|
||||
binding: None,
|
||||
first_time: false,
|
||||
};
|
||||
write!(self.out, "constant {} {} = {{", ty_name, name,)?;
|
||||
|
@ -3201,10 +3150,9 @@ impl<W: Write> Writer<W> {
|
|||
Some(ref result) => {
|
||||
let ty_name = TypeContext {
|
||||
handle: result.ty,
|
||||
module,
|
||||
arena: &module.types,
|
||||
names: &self.names,
|
||||
access: crate::StorageAccess::empty(),
|
||||
binding: None,
|
||||
first_time: false,
|
||||
};
|
||||
write!(self.out, "{}", ty_name)?;
|
||||
|
@ -3219,10 +3167,9 @@ impl<W: Write> Writer<W> {
|
|||
let name = &self.names[&NameKey::FunctionArgument(fun_handle, index as u32)];
|
||||
let param_type_name = TypeContext {
|
||||
handle: arg.ty,
|
||||
module,
|
||||
arena: &module.types,
|
||||
names: &self.names,
|
||||
access: crate::StorageAccess::empty(),
|
||||
binding: None,
|
||||
first_time: false,
|
||||
};
|
||||
let separator = separate(
|
||||
|
@ -3245,7 +3192,6 @@ impl<W: Write> Writer<W> {
|
|||
names: &self.names,
|
||||
handle,
|
||||
usage: fun_info[handle],
|
||||
binding: None,
|
||||
reference: true,
|
||||
};
|
||||
let separator =
|
||||
|
@ -3268,10 +3214,9 @@ impl<W: Write> Writer<W> {
|
|||
for (local_handle, local) in fun.local_variables.iter() {
|
||||
let ty_name = TypeContext {
|
||||
handle: local.ty,
|
||||
module,
|
||||
arena: &module.types,
|
||||
names: &self.names,
|
||||
access: crate::StorageAccess::empty(),
|
||||
binding: None,
|
||||
first_time: false,
|
||||
};
|
||||
let local_name = &self.names[&NameKey::FunctionLocal(fun_handle, local_handle)];
|
||||
|
@ -3340,19 +3285,11 @@ impl<W: Write> Writer<W> {
|
|||
}
|
||||
if let Some(ref br) = var.binding {
|
||||
let good = match options.per_stage_map[ep.stage].resources.get(br) {
|
||||
Some(target) => {
|
||||
let binding_ty = match module.types[var.ty].inner {
|
||||
crate::TypeInner::BindingArray { base, .. } => {
|
||||
&module.types[base].inner
|
||||
}
|
||||
ref ty => ty,
|
||||
};
|
||||
match *binding_ty {
|
||||
crate::TypeInner::Image { .. } => target.texture.is_some(),
|
||||
crate::TypeInner::Sampler { .. } => target.sampler.is_some(),
|
||||
_ => target.buffer.is_some(),
|
||||
}
|
||||
}
|
||||
Some(target) => match module.types[var.ty].inner {
|
||||
crate::TypeInner::Image { .. } => target.texture.is_some(),
|
||||
crate::TypeInner::Sampler { .. } => target.sampler.is_some(),
|
||||
_ => target.buffer.is_some(),
|
||||
},
|
||||
None => false,
|
||||
};
|
||||
if !good {
|
||||
|
@ -3440,10 +3377,9 @@ impl<W: Write> Writer<W> {
|
|||
let name = &self.names[name_key];
|
||||
let ty_name = TypeContext {
|
||||
handle: ty,
|
||||
module,
|
||||
arena: &module.types,
|
||||
names: &self.names,
|
||||
access: crate::StorageAccess::empty(),
|
||||
binding: None,
|
||||
first_time: false,
|
||||
};
|
||||
let resolved = options.resolve_local_binding(binding, in_mode)?;
|
||||
|
@ -3484,10 +3420,9 @@ impl<W: Write> Writer<W> {
|
|||
for (name, ty, binding) in result_members {
|
||||
let ty_name = TypeContext {
|
||||
handle: ty,
|
||||
module,
|
||||
arena: &module.types,
|
||||
names: &self.names,
|
||||
access: crate::StorageAccess::empty(),
|
||||
binding: None,
|
||||
first_time: true,
|
||||
};
|
||||
let binding = binding.ok_or(Error::Validation)?;
|
||||
|
@ -3586,10 +3521,9 @@ impl<W: Write> Writer<W> {
|
|||
};
|
||||
let ty_name = TypeContext {
|
||||
handle: ty,
|
||||
module,
|
||||
arena: &module.types,
|
||||
names: &self.names,
|
||||
access: crate::StorageAccess::empty(),
|
||||
binding: None,
|
||||
first_time: false,
|
||||
};
|
||||
let resolved = options.resolve_local_binding(binding, in_mode)?;
|
||||
|
@ -3638,7 +3572,6 @@ impl<W: Write> Writer<W> {
|
|||
names: &self.names,
|
||||
handle,
|
||||
usage,
|
||||
binding: resolved.as_ref(),
|
||||
reference: true,
|
||||
};
|
||||
let separator = if is_first_argument {
|
||||
|
@ -3699,7 +3632,6 @@ impl<W: Write> Writer<W> {
|
|||
names: &self.names,
|
||||
handle,
|
||||
usage,
|
||||
binding: None,
|
||||
reference: false,
|
||||
};
|
||||
write!(self.out, "{}", back::INDENT)?;
|
||||
|
@ -3801,10 +3733,9 @@ impl<W: Write> Writer<W> {
|
|||
let name = &self.names[&NameKey::EntryPointLocal(ep_index as _, local_handle)];
|
||||
let ty_name = TypeContext {
|
||||
handle: local.ty,
|
||||
module,
|
||||
arena: &module.types,
|
||||
names: &self.names,
|
||||
access: crate::StorageAccess::empty(),
|
||||
binding: None,
|
||||
first_time: false,
|
||||
};
|
||||
write!(self.out, "{}{} {}", back::INDENT, ty_name, name)?;
|
||||
|
@ -3924,7 +3855,7 @@ fn test_stack_size() {
|
|||
let stack_size = addresses.end - addresses.start;
|
||||
// check the size (in debug only)
|
||||
// last observed macOS value: 19152 (CI)
|
||||
if !(9500..=20000).contains(&stack_size) {
|
||||
if !(11000..=20000).contains(&stack_size) {
|
||||
panic!("`put_block` stack size {} has changed!", stack_size);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -173,14 +173,7 @@ impl<'w> BlockContext<'w> {
|
|||
/// thing in one fell swoop.
|
||||
fn is_intermediate(&self, expr_handle: Handle<crate::Expression>) -> bool {
|
||||
match self.ir_function.expressions[expr_handle] {
|
||||
crate::Expression::GlobalVariable(handle) => {
|
||||
let ty = self.ir_module.global_variables[handle].ty;
|
||||
match self.ir_module.types[ty].inner {
|
||||
crate::TypeInner::BindingArray { .. } => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
crate::Expression::LocalVariable(_) => true,
|
||||
crate::Expression::GlobalVariable(_) | crate::Expression::LocalVariable(_) => true,
|
||||
crate::Expression::FunctionArgument(index) => {
|
||||
let arg = &self.ir_function.arguments[index as usize];
|
||||
self.ir_module.types[arg.ty].inner.pointer_space().is_some()
|
||||
|
@ -207,53 +200,9 @@ impl<'w> BlockContext<'w> {
|
|||
0
|
||||
}
|
||||
crate::Expression::Access { base, index } => {
|
||||
let base_ty_inner = self.fun_info[base].ty.inner_with(&self.ir_module.types);
|
||||
match *base_ty_inner {
|
||||
crate::TypeInner::Vector { .. } => {
|
||||
self.write_vector_access(expr_handle, base, index, block)?
|
||||
}
|
||||
crate::TypeInner::BindingArray {
|
||||
base: binding_type, ..
|
||||
} => {
|
||||
let binding_array_false_pointer = LookupType::Local(LocalType::Pointer {
|
||||
base: binding_type,
|
||||
class: spirv::StorageClass::UniformConstant,
|
||||
});
|
||||
|
||||
let result_id = match self.write_expression_pointer(
|
||||
expr_handle,
|
||||
block,
|
||||
Some(binding_array_false_pointer),
|
||||
)? {
|
||||
ExpressionPointer::Ready { pointer_id } => pointer_id,
|
||||
ExpressionPointer::Conditional { .. } => {
|
||||
return Err(Error::FeatureNotImplemented(
|
||||
"Texture array out-of-bounds handling",
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let binding_type_id = self.get_type_id(LookupType::Handle(binding_type));
|
||||
|
||||
let load_id = self.gen_id();
|
||||
block.body.push(Instruction::load(
|
||||
binding_type_id,
|
||||
load_id,
|
||||
result_id,
|
||||
None,
|
||||
));
|
||||
|
||||
if self.fun_info[index].uniformity.non_uniform_result.is_some() {
|
||||
self.writer.require_any(
|
||||
"NonUniformEXT",
|
||||
&[spirv::Capability::ShaderNonUniform],
|
||||
)?;
|
||||
self.writer.use_extension("SPV_EXT_descriptor_indexing");
|
||||
self.writer
|
||||
.decorate(load_id, spirv::Decoration::NonUniform, &[]);
|
||||
}
|
||||
load_id
|
||||
}
|
||||
let base_ty = self.fun_info[base].ty.inner_with(&self.ir_module.types);
|
||||
match *base_ty {
|
||||
crate::TypeInner::Vector { .. } => (),
|
||||
ref other => {
|
||||
log::error!(
|
||||
"Unable to access base {:?} of type {:?}",
|
||||
|
@ -264,7 +213,9 @@ impl<'w> BlockContext<'w> {
|
|||
"only vectors may be dynamically indexed by value",
|
||||
));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.write_vector_access(expr_handle, base, index, block)?
|
||||
}
|
||||
crate::Expression::AccessIndex { base, index: _ } if self.is_intermediate(base) => {
|
||||
// See `is_intermediate`; we'll handle this later in
|
||||
|
@ -291,39 +242,6 @@ impl<'w> BlockContext<'w> {
|
|||
));
|
||||
id
|
||||
}
|
||||
crate::TypeInner::BindingArray {
|
||||
base: binding_type, ..
|
||||
} => {
|
||||
let binding_array_false_pointer = LookupType::Local(LocalType::Pointer {
|
||||
base: binding_type,
|
||||
class: spirv::StorageClass::UniformConstant,
|
||||
});
|
||||
|
||||
let result_id = match self.write_expression_pointer(
|
||||
expr_handle,
|
||||
block,
|
||||
Some(binding_array_false_pointer),
|
||||
)? {
|
||||
ExpressionPointer::Ready { pointer_id } => pointer_id,
|
||||
ExpressionPointer::Conditional { .. } => {
|
||||
return Err(Error::FeatureNotImplemented(
|
||||
"Texture array out-of-bounds handling",
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let binding_type_id = self.get_type_id(LookupType::Handle(binding_type));
|
||||
|
||||
let load_id = self.gen_id();
|
||||
block.body.push(Instruction::load(
|
||||
binding_type_id,
|
||||
load_id,
|
||||
result_id,
|
||||
None,
|
||||
));
|
||||
|
||||
load_id
|
||||
}
|
||||
ref other => {
|
||||
log::error!("Unable to access index of {:?}", other);
|
||||
return Err(Error::FeatureNotImplemented("access index for type"));
|
||||
|
@ -858,7 +776,7 @@ impl<'w> BlockContext<'w> {
|
|||
}
|
||||
crate::Expression::LocalVariable(variable) => self.function.variables[&variable].id,
|
||||
crate::Expression::Load { pointer } => {
|
||||
match self.write_expression_pointer(pointer, block, None)? {
|
||||
match self.write_expression_pointer(pointer, block)? {
|
||||
ExpressionPointer::Ready { pointer_id } => {
|
||||
let id = self.gen_id();
|
||||
let atomic_space =
|
||||
|
@ -1182,26 +1100,15 @@ impl<'w> BlockContext<'w> {
|
|||
///
|
||||
/// Emit any needed bounds-checking expressions to `block`.
|
||||
///
|
||||
/// Some cases we need to generate a different return type than what the IR gives us.
|
||||
/// This is because pointers to binding arrays don't exist in the IR, but we need to
|
||||
/// create them to create an access chain in SPIRV.
|
||||
///
|
||||
/// On success, the return value is an [`ExpressionPointer`] value; see the
|
||||
/// documentation for that type.
|
||||
fn write_expression_pointer(
|
||||
&mut self,
|
||||
mut expr_handle: Handle<crate::Expression>,
|
||||
block: &mut Block,
|
||||
return_type_override: Option<LookupType>,
|
||||
) -> Result<ExpressionPointer, Error> {
|
||||
let result_lookup_ty = match self.fun_info[expr_handle].ty {
|
||||
TypeResolution::Handle(ty_handle) => match return_type_override {
|
||||
// We use the return type override as a special case for binding arrays as the OpAccessChain
|
||||
// needs to return a pointer, but indexing into a binding array just gives you the type of
|
||||
// the binding in the IR.
|
||||
Some(ty) => ty,
|
||||
None => LookupType::Handle(ty_handle),
|
||||
},
|
||||
TypeResolution::Handle(ty_handle) => LookupType::Handle(ty_handle),
|
||||
TypeResolution::Value(ref inner) => LookupType::Local(make_local(inner).unwrap()),
|
||||
};
|
||||
let result_type_id = self.get_type_id(result_lookup_ty);
|
||||
|
@ -1705,7 +1612,7 @@ impl<'w> BlockContext<'w> {
|
|||
}
|
||||
crate::Statement::Store { pointer, value } => {
|
||||
let value_id = self.cached[value];
|
||||
match self.write_expression_pointer(pointer, &mut block, None)? {
|
||||
match self.write_expression_pointer(pointer, &mut block)? {
|
||||
ExpressionPointer::Ready { pointer_id } => {
|
||||
let atomic_space = match *self.fun_info[pointer]
|
||||
.ty
|
||||
|
@ -1795,15 +1702,14 @@ impl<'w> BlockContext<'w> {
|
|||
|
||||
self.cached[result] = id;
|
||||
|
||||
let pointer_id =
|
||||
match self.write_expression_pointer(pointer, &mut block, None)? {
|
||||
ExpressionPointer::Ready { pointer_id } => pointer_id,
|
||||
ExpressionPointer::Conditional { .. } => {
|
||||
return Err(Error::FeatureNotImplemented(
|
||||
"Atomics out-of-bounds handling",
|
||||
));
|
||||
}
|
||||
};
|
||||
let pointer_id = match self.write_expression_pointer(pointer, &mut block)? {
|
||||
ExpressionPointer::Ready { pointer_id } => pointer_id,
|
||||
ExpressionPointer::Conditional { .. } => {
|
||||
return Err(Error::FeatureNotImplemented(
|
||||
"Atomics out-of-bounds handling",
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let space = self.fun_info[pointer]
|
||||
.ty
|
||||
|
|
|
@ -365,9 +365,6 @@ impl<'w> BlockContext<'w> {
|
|||
crate::Expression::FunctionArgument(i) => {
|
||||
self.function.parameters[i as usize].handle_id
|
||||
}
|
||||
crate::Expression::Access { .. } | crate::Expression::AccessIndex { .. } => {
|
||||
self.cached[expr_handle]
|
||||
}
|
||||
ref other => unreachable!("Unexpected image expression {:?}", other),
|
||||
};
|
||||
|
||||
|
|
|
@ -287,14 +287,6 @@ enum LocalType {
|
|||
image_type_id: Word,
|
||||
},
|
||||
Sampler,
|
||||
PointerToBindingArray {
|
||||
base: Handle<crate::Type>,
|
||||
size: u64,
|
||||
},
|
||||
BindingArray {
|
||||
base: Handle<crate::Type>,
|
||||
size: u64,
|
||||
},
|
||||
}
|
||||
|
||||
/// A type encountered during SPIR-V generation.
|
||||
|
@ -575,9 +567,6 @@ pub struct Writer {
|
|||
/// that.
|
||||
capabilities_used: crate::FastHashSet<Capability>,
|
||||
|
||||
/// The set of spirv extensions used.
|
||||
extensions_used: crate::FastHashSet<&'static str>,
|
||||
|
||||
debugs: Vec<Instruction>,
|
||||
annotations: Vec<Instruction>,
|
||||
flags: WriterFlags,
|
||||
|
@ -590,7 +579,6 @@ pub struct Writer {
|
|||
constant_ids: Vec<Word>,
|
||||
cached_constants: crate::FastHashMap<(crate::ScalarValue, crate::Bytes), Word>,
|
||||
global_variables: Vec<GlobalVariable>,
|
||||
binding_map: BindingMap,
|
||||
|
||||
// Cached expressions are only meaningful within a BlockContext, but we
|
||||
// retain the table here between functions to save heap allocations.
|
||||
|
@ -619,17 +607,6 @@ bitflags::bitflags! {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
|
||||
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
|
||||
pub struct BindingInfo {
|
||||
/// If the binding is an unsized binding array, this overrides the size.
|
||||
pub binding_array_size: Option<u32>,
|
||||
}
|
||||
|
||||
// Using `BTreeMap` instead of `HashMap` so that we can hash itself.
|
||||
pub type BindingMap = std::collections::BTreeMap<crate::ResourceBinding, BindingInfo>;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Options {
|
||||
/// (Major, Minor) target version of the SPIR-V.
|
||||
|
@ -638,9 +615,6 @@ pub struct Options {
|
|||
/// Configuration flags for the writer.
|
||||
pub flags: WriterFlags,
|
||||
|
||||
/// Map of resources to information about the binding.
|
||||
pub binding_map: BindingMap,
|
||||
|
||||
/// If given, the set of capabilities modules are allowed to use. Code that
|
||||
/// requires capabilities beyond these is rejected with an error.
|
||||
///
|
||||
|
@ -663,7 +637,6 @@ impl Default for Options {
|
|||
Options {
|
||||
lang_version: (1, 0),
|
||||
flags,
|
||||
binding_map: BindingMap::default(),
|
||||
capabilities: None,
|
||||
bounds_check_policies: crate::proc::BoundsCheckPolicies::default(),
|
||||
}
|
||||
|
|
|
@ -51,10 +51,3 @@ impl<K, S: Clone> Recyclable for std::collections::HashSet<K, S> {
|
|||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ord, V> Recyclable for std::collections::BTreeMap<K, V> {
|
||||
fn recycle(mut self) -> Self {
|
||||
self.clear();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ use super::{
|
|||
};
|
||||
use crate::{
|
||||
arena::{Handle, UniqueArena},
|
||||
back::spv::BindingInfo,
|
||||
proc::TypeResolution,
|
||||
valid::{FunctionInfo, ModuleInfo},
|
||||
};
|
||||
|
@ -60,7 +59,6 @@ impl Writer {
|
|||
id_gen,
|
||||
capabilities_available: options.capabilities.clone(),
|
||||
capabilities_used,
|
||||
extensions_used: crate::FastHashSet::default(),
|
||||
debugs: vec![],
|
||||
annotations: vec![],
|
||||
flags: options.flags,
|
||||
|
@ -72,7 +70,6 @@ impl Writer {
|
|||
constant_ids: Vec::new(),
|
||||
cached_constants: crate::FastHashMap::default(),
|
||||
global_variables: Vec::new(),
|
||||
binding_map: options.binding_map.clone(),
|
||||
saved_cached: CachedExpressions::default(),
|
||||
gl450_ext_inst_id,
|
||||
temp_list: Vec::new(),
|
||||
|
@ -103,7 +100,6 @@ impl Writer {
|
|||
flags: self.flags,
|
||||
bounds_check_policies: self.bounds_check_policies,
|
||||
capabilities_available: take(&mut self.capabilities_available),
|
||||
binding_map: take(&mut self.binding_map),
|
||||
|
||||
// Initialized afresh:
|
||||
id_gen,
|
||||
|
@ -112,7 +108,6 @@ impl Writer {
|
|||
|
||||
// Recycled:
|
||||
capabilities_used: take(&mut self.capabilities_used).recycle(),
|
||||
extensions_used: take(&mut self.extensions_used).recycle(),
|
||||
physical_layout: self.physical_layout.clone().recycle(),
|
||||
logical_layout: take(&mut self.logical_layout).recycle(),
|
||||
debugs: take(&mut self.debugs).recycle(),
|
||||
|
@ -173,11 +168,6 @@ impl Writer {
|
|||
}
|
||||
}
|
||||
|
||||
/// Indicate that the code uses the given extension.
|
||||
pub(super) fn use_extension(&mut self, extension: &'static str) {
|
||||
self.extensions_used.insert(extension);
|
||||
}
|
||||
|
||||
pub(super) fn get_type_id(&mut self, lookup_ty: LookupType) -> Word {
|
||||
match self.lookup_type.entry(lookup_ty) {
|
||||
Entry::Occupied(e) => *e.get(),
|
||||
|
@ -277,7 +267,7 @@ impl Writer {
|
|||
self.get_type_id(local_type.into())
|
||||
}
|
||||
|
||||
pub(super) fn decorate(&mut self, id: Word, decoration: spirv::Decoration, operands: &[Word]) {
|
||||
fn decorate(&mut self, id: Word, decoration: spirv::Decoration, operands: &[Word]) {
|
||||
self.annotations
|
||||
.push(Instruction::decorate(id, decoration, operands));
|
||||
}
|
||||
|
@ -507,14 +497,7 @@ impl Writer {
|
|||
let mut gv = self.global_variables[handle.index()].clone();
|
||||
|
||||
// Handle globals are pre-emitted and should be loaded automatically.
|
||||
//
|
||||
// Any that are binding arrays we skip as we cannot load the array, we must load the result after indexing.
|
||||
let is_binding_array = match ir_module.types[var.ty].inner {
|
||||
crate::TypeInner::BindingArray { .. } => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if var.space == crate::AddressSpace::Handle && !is_binding_array {
|
||||
if var.space == crate::AddressSpace::Handle {
|
||||
let var_type_id = self.get_type_id(LookupType::Handle(var.ty));
|
||||
let id = self.id_gen.next();
|
||||
prelude
|
||||
|
@ -805,16 +788,6 @@ impl Writer {
|
|||
LocalType::SampledImage { image_type_id } => {
|
||||
Instruction::type_sampled_image(id, image_type_id)
|
||||
}
|
||||
LocalType::BindingArray { base, size } => {
|
||||
let inner_ty = self.get_type_id(LookupType::Handle(base));
|
||||
let scalar_id = self.get_constant_scalar(crate::ScalarValue::Uint(size), 4);
|
||||
Instruction::type_array(id, inner_ty, scalar_id)
|
||||
}
|
||||
LocalType::PointerToBindingArray { base, size } => {
|
||||
let inner_ty =
|
||||
self.get_type_id(LookupType::Local(LocalType::BindingArray { base, size }));
|
||||
Instruction::type_pointer(id, spirv::StorageClass::UniformConstant, inner_ty)
|
||||
}
|
||||
};
|
||||
|
||||
instruction.to_words(&mut self.logical_layout.declarations);
|
||||
|
@ -865,16 +838,6 @@ impl Writer {
|
|||
crate::ArraySize::Dynamic => Instruction::type_runtime_array(id, type_id),
|
||||
}
|
||||
}
|
||||
crate::TypeInner::BindingArray { base, size } => {
|
||||
let type_id = self.get_type_id(LookupType::Handle(base));
|
||||
match size {
|
||||
crate::ArraySize::Constant(const_handle) => {
|
||||
let length_id = self.constant_ids[const_handle.index()];
|
||||
Instruction::type_array(id, type_id, length_id)
|
||||
}
|
||||
crate::ArraySize::Dynamic => Instruction::type_runtime_array(id, type_id),
|
||||
}
|
||||
}
|
||||
crate::TypeInner::Struct {
|
||||
ref members,
|
||||
span: _,
|
||||
|
@ -1260,34 +1223,15 @@ impl Writer {
|
|||
}
|
||||
}
|
||||
|
||||
let mut substitute_inner_type_lookup = None;
|
||||
if let Some(ref res_binding) = global_variable.binding {
|
||||
self.decorate(id, Decoration::DescriptorSet, &[res_binding.group]);
|
||||
self.decorate(id, Decoration::Binding, &[res_binding.binding]);
|
||||
|
||||
if let Some(&BindingInfo {
|
||||
binding_array_size: Some(remapped_binding_array_size),
|
||||
}) = self.binding_map.get(res_binding)
|
||||
{
|
||||
if let crate::TypeInner::BindingArray { base, .. } =
|
||||
ir_module.types[global_variable.ty].inner
|
||||
{
|
||||
substitute_inner_type_lookup =
|
||||
Some(LookupType::Local(LocalType::PointerToBindingArray {
|
||||
base,
|
||||
size: remapped_binding_array_size as u64,
|
||||
}))
|
||||
}
|
||||
} else {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let init_word = global_variable
|
||||
.init
|
||||
.map(|constant| self.constant_ids[constant.index()]);
|
||||
let inner_type_id = self.get_type_id(
|
||||
substitute_inner_type_lookup.unwrap_or(LookupType::Handle(global_variable.ty)),
|
||||
);
|
||||
let inner_type_id = self.get_type_id(LookupType::Handle(global_variable.ty));
|
||||
|
||||
// generate the wrapping structure if needed
|
||||
let pointer_type_id = if global_needs_wrapper(ir_module, global_variable) {
|
||||
|
@ -1318,11 +1262,7 @@ impl Writer {
|
|||
if let crate::AddressSpace::Storage { .. } = global_variable.space {
|
||||
self.decorate(inner_type_id, Decoration::Block, &[]);
|
||||
}
|
||||
if substitute_inner_type_lookup.is_some() {
|
||||
inner_type_id
|
||||
} else {
|
||||
self.get_pointer_id(&ir_module.types, global_variable.ty, class)?
|
||||
}
|
||||
self.get_pointer_id(&ir_module.types, global_variable.ty, class)?
|
||||
};
|
||||
|
||||
Instruction::variable(pointer_type_id, id, class, init_word)
|
||||
|
@ -1553,9 +1493,6 @@ impl Writer {
|
|||
for capability in self.capabilities_used.iter() {
|
||||
Instruction::capability(*capability).to_words(&mut self.logical_layout.capabilities);
|
||||
}
|
||||
for extension in self.extensions_used.iter() {
|
||||
Instruction::extension(extension).to_words(&mut self.logical_layout.extensions);
|
||||
}
|
||||
if ir_module.entry_points.is_empty() {
|
||||
// SPIR-V doesn't like modules without entry points
|
||||
Instruction::capability(spirv::Capability::Linkage)
|
||||
|
|
|
@ -535,21 +535,6 @@ impl<W: Write> Writer<W> {
|
|||
}
|
||||
write!(self.out, ">")?;
|
||||
}
|
||||
TypeInner::BindingArray { base, size } => {
|
||||
// More info https://github.com/gpuweb/gpuweb/issues/2105
|
||||
write!(self.out, "binding_array<")?;
|
||||
match size {
|
||||
crate::ArraySize::Constant(handle) => {
|
||||
self.write_type(module, base)?;
|
||||
write!(self.out, ",")?;
|
||||
self.write_constant(module, handle)?;
|
||||
}
|
||||
crate::ArraySize::Dynamic => {
|
||||
self.write_type(module, base)?;
|
||||
}
|
||||
}
|
||||
write!(self.out, ">")?;
|
||||
}
|
||||
TypeInner::Matrix {
|
||||
columns,
|
||||
rows,
|
||||
|
@ -1196,7 +1181,6 @@ impl<W: Write> Writer<W> {
|
|||
}
|
||||
TypeInner::Matrix { .. }
|
||||
| TypeInner::Array { .. }
|
||||
| TypeInner::BindingArray { .. }
|
||||
| TypeInner::ValuePointer { .. } => write!(self.out, "[{}]", index)?,
|
||||
TypeInner::Struct { .. } => {
|
||||
// This will never panic in case the type is a `Struct`, this is not true
|
||||
|
|
|
@ -580,9 +580,9 @@ impl crate::TypeInner {
|
|||
match size {
|
||||
crate::ArraySize::Constant(size) => {
|
||||
let size = constants[size].name.as_deref().unwrap_or("unknown");
|
||||
format!("array<{}, {}>", base, size)
|
||||
format!("{}[{}]", base, size)
|
||||
}
|
||||
crate::ArraySize::Dynamic => format!("array<{}>", base),
|
||||
crate::ArraySize::Dynamic => format!("{}[]", base),
|
||||
}
|
||||
}
|
||||
Ti::Struct { .. } => {
|
||||
|
@ -634,17 +634,6 @@ impl crate::TypeInner {
|
|||
)
|
||||
}
|
||||
Ti::Sampler { .. } => "sampler".to_string(),
|
||||
Ti::BindingArray { base, size, .. } => {
|
||||
let member_type = &types[base];
|
||||
let base = member_type.name.as_deref().unwrap_or("unknown");
|
||||
match size {
|
||||
crate::ArraySize::Constant(size) => {
|
||||
let size = constants[size].name.as_deref().unwrap_or("unknown");
|
||||
format!("binding_array<{}, {}>", base, size)
|
||||
}
|
||||
crate::ArraySize::Dynamic => format!("binding_array<{}>", base),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -692,7 +681,7 @@ mod type_inner_tests {
|
|||
stride: 4,
|
||||
size: crate::ArraySize::Constant(c),
|
||||
};
|
||||
assert_eq!(array.to_wgsl(&types, &constants), "array<MyType1, C>");
|
||||
assert_eq!(array.to_wgsl(&types, &constants), "MyType1[C]");
|
||||
|
||||
let mat = crate::TypeInner::Matrix {
|
||||
rows: crate::VectorSize::Quad,
|
||||
|
@ -738,15 +727,6 @@ mod type_inner_tests {
|
|||
img3.to_wgsl(&types, &constants),
|
||||
"texture_depth_multisampled_2d"
|
||||
);
|
||||
|
||||
let array = crate::TypeInner::BindingArray {
|
||||
base: mytype1,
|
||||
size: crate::ArraySize::Constant(c),
|
||||
};
|
||||
assert_eq!(
|
||||
array.to_wgsl(&types, &constants),
|
||||
"binding_array<MyType1, C>"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -885,9 +865,10 @@ impl<'a> ExpressionContext<'a, '_, '_> {
|
|||
|
||||
fn prepare_sampling(
|
||||
&mut self,
|
||||
image: Handle<crate::Expression>,
|
||||
image_name: &'a str,
|
||||
span: Span,
|
||||
) -> Result<SamplingContext, Error<'a>> {
|
||||
let image = self.lookup_ident.lookup(image_name, span.clone())?.handle;
|
||||
Ok(SamplingContext {
|
||||
image,
|
||||
arrayed: match *self.resolve_type(image)? {
|
||||
|
@ -1781,13 +1762,12 @@ impl Parser {
|
|||
"textureSample" => {
|
||||
let _ = lexer.next();
|
||||
lexer.open_arguments()?;
|
||||
let (image, image_span) =
|
||||
self.parse_general_expression_with_span(lexer, ctx.reborrow())?;
|
||||
let (image_name, image_span) = lexer.next_ident_with_span()?;
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
let sampler_expr = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
let (sampler_name, sampler_span) = lexer.next_ident_with_span()?;
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
let sc = ctx.prepare_sampling(image, image_span)?;
|
||||
let sc = ctx.prepare_sampling(image_name, image_span)?;
|
||||
let array_index = if sc.arrayed {
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
Some(self.parse_general_expression(lexer, ctx.reborrow())?)
|
||||
|
@ -1802,7 +1782,7 @@ impl Parser {
|
|||
lexer.close_arguments()?;
|
||||
crate::Expression::ImageSample {
|
||||
image: sc.image,
|
||||
sampler: sampler_expr,
|
||||
sampler: ctx.lookup_ident.lookup(sampler_name, sampler_span)?.handle,
|
||||
gather: None,
|
||||
coordinate,
|
||||
array_index,
|
||||
|
@ -1814,13 +1794,12 @@ impl Parser {
|
|||
"textureSampleLevel" => {
|
||||
let _ = lexer.next();
|
||||
lexer.open_arguments()?;
|
||||
let (image, image_span) =
|
||||
self.parse_general_expression_with_span(lexer, ctx.reborrow())?;
|
||||
let (image_name, image_span) = lexer.next_ident_with_span()?;
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
let sampler_expr = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
let (sampler_name, sampler_span) = lexer.next_ident_with_span()?;
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
let sc = ctx.prepare_sampling(image, image_span)?;
|
||||
let sc = ctx.prepare_sampling(image_name, image_span)?;
|
||||
let array_index = if sc.arrayed {
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
Some(self.parse_general_expression(lexer, ctx.reborrow())?)
|
||||
|
@ -1837,7 +1816,7 @@ impl Parser {
|
|||
lexer.close_arguments()?;
|
||||
crate::Expression::ImageSample {
|
||||
image: sc.image,
|
||||
sampler: sampler_expr,
|
||||
sampler: ctx.lookup_ident.lookup(sampler_name, sampler_span)?.handle,
|
||||
gather: None,
|
||||
coordinate,
|
||||
array_index,
|
||||
|
@ -1849,13 +1828,12 @@ impl Parser {
|
|||
"textureSampleBias" => {
|
||||
let _ = lexer.next();
|
||||
lexer.open_arguments()?;
|
||||
let (image, image_span) =
|
||||
self.parse_general_expression_with_span(lexer, ctx.reborrow())?;
|
||||
let (image_name, image_span) = lexer.next_ident_with_span()?;
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
let sampler_expr = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
let (sampler_name, sampler_span) = lexer.next_ident_with_span()?;
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
let sc = ctx.prepare_sampling(image, image_span)?;
|
||||
let sc = ctx.prepare_sampling(image_name, image_span)?;
|
||||
let array_index = if sc.arrayed {
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
Some(self.parse_general_expression(lexer, ctx.reborrow())?)
|
||||
|
@ -1872,7 +1850,7 @@ impl Parser {
|
|||
lexer.close_arguments()?;
|
||||
crate::Expression::ImageSample {
|
||||
image: sc.image,
|
||||
sampler: sampler_expr,
|
||||
sampler: ctx.lookup_ident.lookup(sampler_name, sampler_span)?.handle,
|
||||
gather: None,
|
||||
coordinate,
|
||||
array_index,
|
||||
|
@ -1884,13 +1862,12 @@ impl Parser {
|
|||
"textureSampleGrad" => {
|
||||
let _ = lexer.next();
|
||||
lexer.open_arguments()?;
|
||||
let (image, image_span) =
|
||||
self.parse_general_expression_with_span(lexer, ctx.reborrow())?;
|
||||
let (image_name, image_span) = lexer.next_ident_with_span()?;
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
let sampler_expr = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
let (sampler_name, sampler_span) = lexer.next_ident_with_span()?;
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
let sc = ctx.prepare_sampling(image, image_span)?;
|
||||
let sc = ctx.prepare_sampling(image_name, image_span)?;
|
||||
let array_index = if sc.arrayed {
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
Some(self.parse_general_expression(lexer, ctx.reborrow())?)
|
||||
|
@ -1909,7 +1886,7 @@ impl Parser {
|
|||
lexer.close_arguments()?;
|
||||
crate::Expression::ImageSample {
|
||||
image: sc.image,
|
||||
sampler: sampler_expr,
|
||||
sampler: ctx.lookup_ident.lookup(sampler_name, sampler_span)?.handle,
|
||||
gather: None,
|
||||
coordinate,
|
||||
array_index,
|
||||
|
@ -1921,13 +1898,12 @@ impl Parser {
|
|||
"textureSampleCompare" => {
|
||||
let _ = lexer.next();
|
||||
lexer.open_arguments()?;
|
||||
let (image, image_span) =
|
||||
self.parse_general_expression_with_span(lexer, ctx.reborrow())?;
|
||||
let (image_name, image_span) = lexer.next_ident_with_span()?;
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
let sampler_expr = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
let (sampler_name, sampler_span) = lexer.next_ident_with_span()?;
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
let sc = ctx.prepare_sampling(image, image_span)?;
|
||||
let sc = ctx.prepare_sampling(image_name, image_span)?;
|
||||
let array_index = if sc.arrayed {
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
Some(self.parse_general_expression(lexer, ctx.reborrow())?)
|
||||
|
@ -1944,7 +1920,7 @@ impl Parser {
|
|||
lexer.close_arguments()?;
|
||||
crate::Expression::ImageSample {
|
||||
image: sc.image,
|
||||
sampler: sampler_expr,
|
||||
sampler: ctx.lookup_ident.lookup(sampler_name, sampler_span)?.handle,
|
||||
gather: None,
|
||||
coordinate,
|
||||
array_index,
|
||||
|
@ -1956,13 +1932,12 @@ impl Parser {
|
|||
"textureSampleCompareLevel" => {
|
||||
let _ = lexer.next();
|
||||
lexer.open_arguments()?;
|
||||
let (image, image_span) =
|
||||
self.parse_general_expression_with_span(lexer, ctx.reborrow())?;
|
||||
let (image_name, image_span) = lexer.next_ident_with_span()?;
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
let sampler_expr = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
let (sampler_name, sampler_span) = lexer.next_ident_with_span()?;
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
let sc = ctx.prepare_sampling(image, image_span)?;
|
||||
let sc = ctx.prepare_sampling(image_name, image_span)?;
|
||||
let array_index = if sc.arrayed {
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
Some(self.parse_general_expression(lexer, ctx.reborrow())?)
|
||||
|
@ -1979,7 +1954,7 @@ impl Parser {
|
|||
lexer.close_arguments()?;
|
||||
crate::Expression::ImageSample {
|
||||
image: sc.image,
|
||||
sampler: sampler_expr,
|
||||
sampler: ctx.lookup_ident.lookup(sampler_name, sampler_span)?.handle,
|
||||
gather: None,
|
||||
coordinate,
|
||||
array_index,
|
||||
|
@ -2008,13 +1983,12 @@ impl Parser {
|
|||
} else {
|
||||
crate::SwizzleComponent::X
|
||||
};
|
||||
let (image, image_span) =
|
||||
self.parse_general_expression_with_span(lexer, ctx.reborrow())?;
|
||||
let (image_name, image_span) = lexer.next_ident_with_span()?;
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
let sampler_expr = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
let (sampler_name, sampler_span) = lexer.next_ident_with_span()?;
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
let sc = ctx.prepare_sampling(image, image_span)?;
|
||||
let sc = ctx.prepare_sampling(image_name, image_span)?;
|
||||
let array_index = if sc.arrayed {
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
Some(self.parse_general_expression(lexer, ctx.reborrow())?)
|
||||
|
@ -2029,7 +2003,7 @@ impl Parser {
|
|||
lexer.close_arguments()?;
|
||||
crate::Expression::ImageSample {
|
||||
image: sc.image,
|
||||
sampler: sampler_expr,
|
||||
sampler: ctx.lookup_ident.lookup(sampler_name, sampler_span)?.handle,
|
||||
gather: Some(component),
|
||||
coordinate,
|
||||
array_index,
|
||||
|
@ -2041,13 +2015,12 @@ impl Parser {
|
|||
"textureGatherCompare" => {
|
||||
let _ = lexer.next();
|
||||
lexer.open_arguments()?;
|
||||
let (image, image_span) =
|
||||
self.parse_general_expression_with_span(lexer, ctx.reborrow())?;
|
||||
let (image_name, image_span) = lexer.next_ident_with_span()?;
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
let sampler_expr = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
let (sampler_name, sampler_span) = lexer.next_ident_with_span()?;
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
let sc = ctx.prepare_sampling(image, image_span)?;
|
||||
let sc = ctx.prepare_sampling(image_name, image_span)?;
|
||||
let array_index = if sc.arrayed {
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
Some(self.parse_general_expression(lexer, ctx.reborrow())?)
|
||||
|
@ -2064,7 +2037,7 @@ impl Parser {
|
|||
lexer.close_arguments()?;
|
||||
crate::Expression::ImageSample {
|
||||
image: sc.image,
|
||||
sampler: sampler_expr,
|
||||
sampler: ctx.lookup_ident.lookup(sampler_name, sampler_span)?.handle,
|
||||
gather: Some(crate::SwizzleComponent::X),
|
||||
coordinate,
|
||||
array_index,
|
||||
|
@ -2076,8 +2049,11 @@ impl Parser {
|
|||
"textureLoad" => {
|
||||
let _ = lexer.next();
|
||||
lexer.open_arguments()?;
|
||||
let (image, image_span) =
|
||||
self.parse_general_expression_with_span(lexer, ctx.reborrow())?;
|
||||
let (image_name, image_span) = lexer.next_ident_with_span()?;
|
||||
let image = ctx
|
||||
.lookup_ident
|
||||
.lookup(image_name, image_span.clone())?
|
||||
.handle;
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
let coordinate = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
let (class, arrayed) = match *ctx.resolve_type(image)? {
|
||||
|
@ -2114,7 +2090,8 @@ impl Parser {
|
|||
"textureDimensions" => {
|
||||
let _ = lexer.next();
|
||||
lexer.open_arguments()?;
|
||||
let image = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
let (image_name, image_span) = lexer.next_ident_with_span()?;
|
||||
let image = ctx.lookup_ident.lookup(image_name, image_span)?.handle;
|
||||
let level = if lexer.skip(Token::Separator(',')) {
|
||||
let expr = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
Some(expr)
|
||||
|
@ -2130,7 +2107,8 @@ impl Parser {
|
|||
"textureNumLevels" => {
|
||||
let _ = lexer.next();
|
||||
lexer.open_arguments()?;
|
||||
let image = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
let (image_name, image_span) = lexer.next_ident_with_span()?;
|
||||
let image = ctx.lookup_ident.lookup(image_name, image_span)?.handle;
|
||||
lexer.close_arguments()?;
|
||||
crate::Expression::ImageQuery {
|
||||
image,
|
||||
|
@ -2140,7 +2118,8 @@ impl Parser {
|
|||
"textureNumLayers" => {
|
||||
let _ = lexer.next();
|
||||
lexer.open_arguments()?;
|
||||
let image = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
let (image_name, image_span) = lexer.next_ident_with_span()?;
|
||||
let image = ctx.lookup_ident.lookup(image_name, image_span)?.handle;
|
||||
lexer.close_arguments()?;
|
||||
crate::Expression::ImageQuery {
|
||||
image,
|
||||
|
@ -2150,7 +2129,8 @@ impl Parser {
|
|||
"textureNumSamples" => {
|
||||
let _ = lexer.next();
|
||||
lexer.open_arguments()?;
|
||||
let image = self.parse_general_expression(lexer, ctx.reborrow())?;
|
||||
let (image_name, image_span) = lexer.next_ident_with_span()?;
|
||||
let image = ctx.lookup_ident.lookup(image_name, image_span)?.handle;
|
||||
lexer.close_arguments()?;
|
||||
crate::Expression::ImageQuery {
|
||||
image,
|
||||
|
@ -2291,8 +2271,7 @@ impl Parser {
|
|||
let expr = match lexer.peek() {
|
||||
(Token::Paren('('), _) => {
|
||||
let _ = lexer.next();
|
||||
let (expr, _span) =
|
||||
self.parse_general_expression_for_reference(lexer, ctx.reborrow())?;
|
||||
let expr = self.parse_general_expression_for_reference(lexer, ctx.reborrow())?;
|
||||
lexer.expect(Token::Paren(')'))?;
|
||||
self.pop_scope(lexer);
|
||||
expr
|
||||
|
@ -2679,21 +2658,12 @@ impl Parser {
|
|||
)
|
||||
}
|
||||
|
||||
fn parse_general_expression_with_span<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut ctx: ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<(Handle<crate::Expression>, Span), Error<'a>> {
|
||||
let (expr, span) = self.parse_general_expression_for_reference(lexer, ctx.reborrow())?;
|
||||
Ok((ctx.apply_load_rule(expr), span))
|
||||
}
|
||||
|
||||
fn parse_general_expression<'a>(
|
||||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut ctx: ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<Handle<crate::Expression>, Error<'a>> {
|
||||
let (expr, _span) = self.parse_general_expression_for_reference(lexer, ctx.reborrow())?;
|
||||
let expr = self.parse_general_expression_for_reference(lexer, ctx.reborrow())?;
|
||||
Ok(ctx.apply_load_rule(expr))
|
||||
}
|
||||
|
||||
|
@ -2701,7 +2671,7 @@ impl Parser {
|
|||
&mut self,
|
||||
lexer: &mut Lexer<'a>,
|
||||
mut context: ExpressionContext<'a, '_, '_>,
|
||||
) -> Result<(TypedExpression, Span), Error<'a>> {
|
||||
) -> Result<TypedExpression, Error<'a>> {
|
||||
self.push_scope(Scope::GeneralExpr, lexer);
|
||||
// logical_or_expression
|
||||
let handle = context.parse_binary_op(
|
||||
|
@ -2758,7 +2728,8 @@ impl Parser {
|
|||
)
|
||||
},
|
||||
)?;
|
||||
Ok((handle, self.pop_scope(lexer)))
|
||||
self.pop_scope(lexer);
|
||||
Ok(handle)
|
||||
}
|
||||
|
||||
fn parse_variable_ident_decl<'a>(
|
||||
|
@ -3041,20 +3012,6 @@ impl Parser {
|
|||
};
|
||||
crate::TypeInner::Array { base, size, stride }
|
||||
}
|
||||
"binding_array" => {
|
||||
lexer.expect_generic_paren('<')?;
|
||||
let (base, _access) = self.parse_type_decl(lexer, None, type_arena, const_arena)?;
|
||||
let size = if lexer.skip(Token::Separator(',')) {
|
||||
let const_handle =
|
||||
self.parse_const_expression(lexer, type_arena, const_arena)?;
|
||||
crate::ArraySize::Constant(const_handle)
|
||||
} else {
|
||||
crate::ArraySize::Dynamic
|
||||
};
|
||||
lexer.expect_generic_paren('>')?;
|
||||
|
||||
crate::TypeInner::BindingArray { base, size }
|
||||
}
|
||||
"sampler" => crate::TypeInner::Sampler { comparison: false },
|
||||
"sampler_comparison" => crate::TypeInner::Sampler { comparison: true },
|
||||
"texture_1d" => {
|
||||
|
@ -3979,10 +3936,13 @@ impl Parser {
|
|||
let _ = lexer.next();
|
||||
emitter.start(context.expressions);
|
||||
lexer.open_arguments()?;
|
||||
let mut expr_context = context.as_expression(block, &mut emitter);
|
||||
let (image, image_span) = self
|
||||
.parse_general_expression_with_span(lexer, expr_context.reborrow())?;
|
||||
let (image_name, image_span) = lexer.next_ident_with_span()?;
|
||||
let image = context
|
||||
.lookup_ident
|
||||
.lookup(image_name, image_span.clone())?
|
||||
.handle;
|
||||
lexer.expect(Token::Separator(','))?;
|
||||
let mut expr_context = context.as_expression(block, &mut emitter);
|
||||
let arrayed = match *expr_context.resolve_type(image)? {
|
||||
crate::TypeInner::Image { arrayed, .. } => arrayed,
|
||||
_ => return Err(Error::BadTexture(image_span)),
|
||||
|
|
|
@ -698,8 +698,6 @@ pub enum TypeInner {
|
|||
},
|
||||
/// Can be used to sample values from images.
|
||||
Sampler { comparison: bool },
|
||||
/// Array of bindings
|
||||
BindingArray { base: Handle<Type>, size: ArraySize },
|
||||
}
|
||||
|
||||
/// Constant value.
|
||||
|
|
|
@ -117,10 +117,6 @@ pub struct BoundsCheckPolicies {
|
|||
/// [`ImageStore`]: crate::Statement::ImageStore
|
||||
#[cfg_attr(feature = "deserialize", serde(default))]
|
||||
pub image: BoundsCheckPolicy,
|
||||
|
||||
/// How should the generated code handle binding array indexes that are out of bounds.
|
||||
#[cfg_attr(feature = "deserialize", serde(default))]
|
||||
pub binding_array: BoundsCheckPolicy,
|
||||
}
|
||||
|
||||
/// The default `BoundsCheckPolicy` is `Unchecked`.
|
||||
|
@ -131,27 +127,20 @@ impl Default for BoundsCheckPolicy {
|
|||
}
|
||||
|
||||
impl BoundsCheckPolicies {
|
||||
/// Determine which policy applies to `base`.
|
||||
/// Determine which policy applies to `access`.
|
||||
///
|
||||
/// `base` is the "base" expression (the expression being indexed) of a `Access`
|
||||
/// and `AccessIndex` expression. This is either a pointer, a value, being directly
|
||||
/// indexed, or a binding array.
|
||||
/// `access` is a subtree of `Access` and `AccessIndex` expressions,
|
||||
/// operating either on a pointer to a value, or on a value directly.
|
||||
///
|
||||
/// See the documentation for [`BoundsCheckPolicy`] for details about
|
||||
/// when each policy applies.
|
||||
pub fn choose_policy(
|
||||
&self,
|
||||
base: Handle<crate::Expression>,
|
||||
access: Handle<crate::Expression>,
|
||||
types: &UniqueArena<crate::Type>,
|
||||
info: &valid::FunctionInfo,
|
||||
) -> BoundsCheckPolicy {
|
||||
let ty = info[base].ty.inner_with(types);
|
||||
|
||||
if let crate::TypeInner::BindingArray { .. } = *ty {
|
||||
return self.binding_array;
|
||||
}
|
||||
|
||||
match ty.pointer_space() {
|
||||
match info[access].ty.inner_with(types).pointer_space() {
|
||||
Some(crate::AddressSpace::Storage { access: _ } | crate::AddressSpace::Uniform) => {
|
||||
self.buffer
|
||||
}
|
||||
|
@ -376,7 +365,7 @@ impl crate::TypeInner {
|
|||
let known_length = match *self {
|
||||
Ti::Vector { size, .. } => size as _,
|
||||
Ti::Matrix { columns, .. } => columns as _,
|
||||
Ti::Array { size, .. } | Ti::BindingArray { size, .. } => {
|
||||
Ti::Array { size, .. } => {
|
||||
return size.to_indexable_length(module);
|
||||
}
|
||||
Ti::ValuePointer {
|
||||
|
|
|
@ -202,7 +202,7 @@ impl Layouter {
|
|||
alignment,
|
||||
}
|
||||
}
|
||||
Ti::Image { .. } | Ti::Sampler { .. } | Ti::BindingArray { .. } => TypeLayout {
|
||||
Ti::Image { .. } | Ti::Sampler { .. } => TypeLayout {
|
||||
size,
|
||||
alignment: Alignment::new(1).unwrap(),
|
||||
},
|
||||
|
|
|
@ -125,7 +125,7 @@ impl super::TypeInner {
|
|||
count * stride
|
||||
}
|
||||
Self::Struct { span, .. } => span,
|
||||
Self::Image { .. } | Self::Sampler { .. } | Self::BindingArray { .. } => 0,
|
||||
Self::Image { .. } | Self::Sampler { .. } => 0,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ impl Namer {
|
|||
*count += 1;
|
||||
// Add the suffix. This may fit in base's existing allocation.
|
||||
let mut suffixed = base.into_owned();
|
||||
write!(suffixed, "{}{}", SEPARATOR, *count).unwrap();
|
||||
write!(&mut suffixed, "{}{}", SEPARATOR, *count).unwrap();
|
||||
suffixed
|
||||
}
|
||||
None => {
|
||||
|
|
|
@ -291,7 +291,6 @@ impl<'a> ResolveContext<'a> {
|
|||
}
|
||||
})
|
||||
}
|
||||
Ti::BindingArray { base, .. } => TypeResolution::Handle(base),
|
||||
ref other => {
|
||||
log::error!("Access type {:?}", other);
|
||||
return Err(ResolveError::InvalidAccess {
|
||||
|
@ -393,7 +392,6 @@ impl<'a> ResolveContext<'a> {
|
|||
});
|
||||
}
|
||||
}),
|
||||
Ti::BindingArray { base, .. } => TypeResolution::Handle(base),
|
||||
ref other => {
|
||||
log::error!("Access index type {:?}", other);
|
||||
return Err(ResolveError::InvalidAccess {
|
||||
|
|
|
@ -168,19 +168,11 @@ enum GlobalOrArgument {
|
|||
Argument(u32),
|
||||
}
|
||||
|
||||
impl GlobalOrArgument {
|
||||
fn from_expression(
|
||||
expression_arena: &Arena<crate::Expression>,
|
||||
expression: Handle<crate::Expression>,
|
||||
) -> Result<GlobalOrArgument, ExpressionError> {
|
||||
Ok(match expression_arena[expression] {
|
||||
impl crate::Expression {
|
||||
const fn to_global_or_argument(&self) -> Result<GlobalOrArgument, ExpressionError> {
|
||||
Ok(match *self {
|
||||
crate::Expression::GlobalVariable(var) => GlobalOrArgument::Global(var),
|
||||
crate::Expression::FunctionArgument(i) => GlobalOrArgument::Argument(i),
|
||||
crate::Expression::Access { base, .. }
|
||||
| crate::Expression::AccessIndex { base, .. } => match expression_arena[base] {
|
||||
crate::Expression::GlobalVariable(var) => GlobalOrArgument::Global(var),
|
||||
_ => return Err(ExpressionError::ExpectedGlobalOrArgument),
|
||||
},
|
||||
_ => return Err(ExpressionError::ExpectedGlobalOrArgument),
|
||||
})
|
||||
}
|
||||
|
@ -364,12 +356,12 @@ impl FunctionInfo {
|
|||
GlobalOrArgument::Global(var) => GlobalOrArgument::Global(var),
|
||||
GlobalOrArgument::Argument(i) => {
|
||||
let handle = arguments[i as usize];
|
||||
GlobalOrArgument::from_expression(expression_arena, handle).map_err(
|
||||
|error| {
|
||||
expression_arena[handle]
|
||||
.to_global_or_argument()
|
||||
.map_err(|error| {
|
||||
FunctionError::Expression { handle, error }
|
||||
.with_span_handle(handle, expression_arena)
|
||||
},
|
||||
)?
|
||||
})?
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -377,12 +369,12 @@ impl FunctionInfo {
|
|||
GlobalOrArgument::Global(var) => GlobalOrArgument::Global(var),
|
||||
GlobalOrArgument::Argument(i) => {
|
||||
let handle = arguments[i as usize];
|
||||
GlobalOrArgument::from_expression(expression_arena, handle).map_err(
|
||||
|error| {
|
||||
expression_arena[handle]
|
||||
.to_global_or_argument()
|
||||
.map_err(|error| {
|
||||
FunctionError::Expression { handle, error }
|
||||
.with_span_handle(handle, expression_arena)
|
||||
},
|
||||
)?
|
||||
})?
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -425,73 +417,17 @@ impl FunctionInfo {
|
|||
expression_arena: &Arena<crate::Expression>,
|
||||
other_functions: &[FunctionInfo],
|
||||
resolve_context: &ResolveContext,
|
||||
capabilities: super::Capabilities,
|
||||
) -> Result<(), ExpressionError> {
|
||||
use crate::{Expression as E, SampleLevel as Sl};
|
||||
|
||||
let mut assignable_global = None;
|
||||
let uniformity = match *expression {
|
||||
E::Access { base, index } => {
|
||||
let base_ty = self[base].ty.inner_with(resolve_context.types);
|
||||
|
||||
// build up the caps needed if this is indexed non-uniformly
|
||||
let mut needed_caps = super::Capabilities::empty();
|
||||
let is_binding_array = match *base_ty {
|
||||
crate::TypeInner::BindingArray {
|
||||
base: array_element_ty_handle,
|
||||
..
|
||||
} => {
|
||||
// these are nasty aliases, but these idents are too long and break rustfmt
|
||||
let ub_st = super::Capabilities::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING;
|
||||
let st_sb = super::Capabilities::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING;
|
||||
let sampler = super::Capabilities::SAMPLER_NON_UNIFORM_INDEXING;
|
||||
|
||||
// We're a binding array, so lets use the type of _what_ we are array of to determine if we can non-uniformly index it.
|
||||
let array_element_ty =
|
||||
&resolve_context.types[array_element_ty_handle].inner;
|
||||
|
||||
needed_caps |= match *array_element_ty {
|
||||
// If we're an image, use the appropriate limit.
|
||||
crate::TypeInner::Image { class, .. } => match class {
|
||||
crate::ImageClass::Storage { .. } => ub_st,
|
||||
_ => st_sb,
|
||||
},
|
||||
crate::TypeInner::Sampler { .. } => sampler,
|
||||
// If we're anything but an image, assume we're a buffer and use the address space.
|
||||
_ => {
|
||||
if let E::GlobalVariable(global_handle) = expression_arena[base] {
|
||||
let global = &resolve_context.global_vars[global_handle];
|
||||
match global.space {
|
||||
crate::AddressSpace::Uniform => ub_st,
|
||||
crate::AddressSpace::Storage { .. } => st_sb,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if self[index].uniformity.non_uniform_result.is_some()
|
||||
&& !capabilities.contains(needed_caps)
|
||||
&& is_binding_array
|
||||
{
|
||||
return Err(ExpressionError::MissingCapabilities(needed_caps));
|
||||
}
|
||||
|
||||
let _ = ();
|
||||
Uniformity {
|
||||
non_uniform_result: self
|
||||
.add_assignable_ref(base, &mut assignable_global)
|
||||
.or(self.add_ref(index)),
|
||||
requirements: UniformityRequirements::empty(),
|
||||
}
|
||||
}
|
||||
E::Access { base, index } => Uniformity {
|
||||
non_uniform_result: self
|
||||
.add_assignable_ref(base, &mut assignable_global)
|
||||
.or(self.add_ref(index)),
|
||||
requirements: UniformityRequirements::empty(),
|
||||
},
|
||||
E::AccessIndex { base, .. } => Uniformity {
|
||||
non_uniform_result: self.add_assignable_ref(base, &mut assignable_global),
|
||||
requirements: UniformityRequirements::empty(),
|
||||
|
@ -579,8 +515,8 @@ impl FunctionInfo {
|
|||
level,
|
||||
depth_ref,
|
||||
} => {
|
||||
let image_storage = GlobalOrArgument::from_expression(expression_arena, image)?;
|
||||
let sampler_storage = GlobalOrArgument::from_expression(expression_arena, sampler)?;
|
||||
let image_storage = expression_arena[image].to_global_or_argument()?;
|
||||
let sampler_storage = expression_arena[sampler].to_global_or_argument()?;
|
||||
|
||||
match (image_storage, sampler_storage) {
|
||||
(GlobalOrArgument::Global(image), GlobalOrArgument::Global(sampler)) => {
|
||||
|
@ -934,7 +870,6 @@ impl ModuleInfo {
|
|||
fun: &crate::Function,
|
||||
module: &crate::Module,
|
||||
flags: ValidationFlags,
|
||||
capabilities: super::Capabilities,
|
||||
) -> Result<FunctionInfo, WithSpan<FunctionError>> {
|
||||
let mut info = FunctionInfo {
|
||||
flags,
|
||||
|
@ -962,7 +897,6 @@ impl ModuleInfo {
|
|||
&fun.expressions,
|
||||
&self.functions,
|
||||
&resolve_context,
|
||||
capabilities,
|
||||
) {
|
||||
return Err(FunctionError::Expression { handle, error }
|
||||
.with_span_handle(handle, &fun.expressions));
|
||||
|
@ -1081,15 +1015,8 @@ fn uniform_control_flow() {
|
|||
arguments: &[],
|
||||
};
|
||||
for (handle, expression) in expressions.iter() {
|
||||
info.process_expression(
|
||||
handle,
|
||||
expression,
|
||||
&expressions,
|
||||
&[],
|
||||
&resolve_context,
|
||||
super::Capabilities::empty(),
|
||||
)
|
||||
.unwrap();
|
||||
info.process_expression(handle, expression, &expressions, &[], &resolve_context)
|
||||
.unwrap();
|
||||
}
|
||||
assert_eq!(info[non_uniform_global_expr].ref_count, 1);
|
||||
assert_eq!(info[uniform_global_expr].ref_count, 1);
|
||||
|
|
|
@ -65,8 +65,6 @@ pub enum ExpressionError {
|
|||
ExpectedGlobalOrArgument,
|
||||
#[error("Calling an undeclared function {0:?}")]
|
||||
CallToUndeclaredFunction(Handle<crate::Function>),
|
||||
#[error("Needs to be an binding array instead of {0:?}")]
|
||||
ExpectedBindingArrayType(Handle<crate::Type>),
|
||||
#[error("Needs to be an image instead of {0:?}")]
|
||||
ExpectedImageType(Handle<crate::Type>),
|
||||
#[error("Needs to be an image instead of {0:?}")]
|
||||
|
@ -117,8 +115,6 @@ pub enum ExpressionError {
|
|||
InvalidArgumentType(crate::MathFunction, u32, Handle<crate::Expression>),
|
||||
#[error("Atomic result type can't be {0:?} of {1} bytes")]
|
||||
InvalidAtomicResultType(crate::ScalarKind, crate::Bytes),
|
||||
#[error("Shader requires capability {0:?}")]
|
||||
MissingCapabilities(super::Capabilities),
|
||||
}
|
||||
|
||||
#[cfg(feature = "validate")]
|
||||
|
@ -168,9 +164,7 @@ impl super::Validator {
|
|||
let dynamic_indexing_restricted = match *base_type {
|
||||
Ti::Vector { .. } => false,
|
||||
Ti::Matrix { .. } | Ti::Array { .. } => true,
|
||||
Ti::Pointer { .. }
|
||||
| Ti::ValuePointer { size: Some(_), .. }
|
||||
| Ti::BindingArray { .. } => false,
|
||||
Ti::Pointer { .. } | Ti::ValuePointer { size: Some(_), .. } => false,
|
||||
ref other => {
|
||||
log::error!("Indexing of {:?}", other);
|
||||
return Err(ExpressionError::InvalidBaseType(base));
|
||||
|
@ -241,7 +235,7 @@ impl super::Validator {
|
|||
size: crate::ArraySize::Constant(handle),
|
||||
..
|
||||
} => module.constants[handle].to_array_length().unwrap(),
|
||||
Ti::Array { .. } | Ti::BindingArray { .. } => !0, // can't statically know, but need run-time checks
|
||||
Ti::Array { .. } => !0, // can't statically know, but need run-time checks
|
||||
Ti::Pointer { base, .. } if top_level => {
|
||||
resolve_index_limit(module, top, &module.types[base].inner, false)?
|
||||
}
|
||||
|
@ -351,50 +345,13 @@ impl super::Validator {
|
|||
module.global_variables[var_handle].ty
|
||||
}
|
||||
crate::Expression::FunctionArgument(i) => function.arguments[i as usize].ty,
|
||||
crate::Expression::Access { base, .. }
|
||||
| crate::Expression::AccessIndex { base, .. } => {
|
||||
match function.expressions[base] {
|
||||
crate::Expression::GlobalVariable(var_handle) => {
|
||||
let array_ty = module.global_variables[var_handle].ty;
|
||||
|
||||
match module.types[array_ty].inner {
|
||||
Ti::BindingArray { base, .. } => base,
|
||||
_ => {
|
||||
return Err(ExpressionError::ExpectedBindingArrayType(
|
||||
array_ty,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => return Err(ExpressionError::ExpectedGlobalVariable),
|
||||
}
|
||||
}
|
||||
_ => return Err(ExpressionError::ExpectedGlobalVariable),
|
||||
};
|
||||
|
||||
let sampler_ty = match function.expressions[sampler] {
|
||||
crate::Expression::GlobalVariable(var_handle) => {
|
||||
module.global_variables[var_handle].ty
|
||||
}
|
||||
crate::Expression::FunctionArgument(i) => function.arguments[i as usize].ty,
|
||||
crate::Expression::Access { base, .. }
|
||||
| crate::Expression::AccessIndex { base, .. } => {
|
||||
match function.expressions[base] {
|
||||
crate::Expression::GlobalVariable(var_handle) => {
|
||||
let array_ty = module.global_variables[var_handle].ty;
|
||||
|
||||
match module.types[array_ty].inner {
|
||||
Ti::BindingArray { base, .. } => base,
|
||||
_ => {
|
||||
return Err(ExpressionError::ExpectedBindingArrayType(
|
||||
array_ty,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => return Err(ExpressionError::ExpectedGlobalVariable),
|
||||
}
|
||||
}
|
||||
_ => return Err(ExpressionError::ExpectedGlobalVariable),
|
||||
};
|
||||
let comparison = match module.types[sampler_ty].inner {
|
||||
|
@ -584,24 +541,6 @@ impl super::Validator {
|
|||
module.global_variables[var_handle].ty
|
||||
}
|
||||
crate::Expression::FunctionArgument(i) => function.arguments[i as usize].ty,
|
||||
crate::Expression::Access { base, .. }
|
||||
| crate::Expression::AccessIndex { base, .. } => {
|
||||
match function.expressions[base] {
|
||||
crate::Expression::GlobalVariable(var_handle) => {
|
||||
let array_ty = module.global_variables[var_handle].ty;
|
||||
|
||||
match module.types[array_ty].inner {
|
||||
Ti::BindingArray { base, .. } => base,
|
||||
_ => {
|
||||
return Err(ExpressionError::ExpectedBindingArrayType(
|
||||
array_ty,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => return Err(ExpressionError::ExpectedGlobalVariable),
|
||||
}
|
||||
}
|
||||
_ => return Err(ExpressionError::ExpectedGlobalVariable),
|
||||
};
|
||||
match module.types[ty].inner {
|
||||
|
@ -667,24 +606,6 @@ impl super::Validator {
|
|||
module.global_variables[var_handle].ty
|
||||
}
|
||||
crate::Expression::FunctionArgument(i) => function.arguments[i as usize].ty,
|
||||
crate::Expression::Access { base, .. }
|
||||
| crate::Expression::AccessIndex { base, .. } => {
|
||||
match function.expressions[base] {
|
||||
crate::Expression::GlobalVariable(var_handle) => {
|
||||
let array_ty = module.global_variables[var_handle].ty;
|
||||
|
||||
match module.types[array_ty].inner {
|
||||
Ti::BindingArray { base, .. } => base,
|
||||
_ => {
|
||||
return Err(ExpressionError::ExpectedBindingArrayType(
|
||||
array_ty,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => return Err(ExpressionError::ExpectedGlobalVariable),
|
||||
}
|
||||
}
|
||||
_ => return Err(ExpressionError::ExpectedGlobalVariable),
|
||||
};
|
||||
match module.types[ty].inner {
|
||||
|
|
|
@ -657,21 +657,6 @@ impl super::Validator {
|
|||
crate::Expression::GlobalVariable(var_handle) => {
|
||||
&context.global_vars[var_handle]
|
||||
}
|
||||
// We're looking at a binding index situation, so punch through the index and look at the global behind it.
|
||||
crate::Expression::Access { base, .. }
|
||||
| crate::Expression::AccessIndex { base, .. } => {
|
||||
match *context.get_expression(base).map_err(|e| e.with_span())? {
|
||||
crate::Expression::GlobalVariable(var_handle) => {
|
||||
&context.global_vars[var_handle]
|
||||
}
|
||||
_ => {
|
||||
return Err(FunctionError::InvalidImageStore(
|
||||
ExpressionError::ExpectedGlobalVariable,
|
||||
)
|
||||
.with_span_handle(image, context.expressions))
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(FunctionError::InvalidImageStore(
|
||||
ExpressionError::ExpectedGlobalVariable,
|
||||
|
@ -680,13 +665,7 @@ impl super::Validator {
|
|||
}
|
||||
};
|
||||
|
||||
// Punch through a binding array to get the underlying type
|
||||
let global_ty = match context.types[var.ty].inner {
|
||||
Ti::BindingArray { base, .. } => &context.types[base].inner,
|
||||
ref inner => inner,
|
||||
};
|
||||
|
||||
let value_ty = match *global_ty {
|
||||
let value_ty = match context.types[var.ty].inner {
|
||||
Ti::Image {
|
||||
class,
|
||||
arrayed,
|
||||
|
@ -844,7 +823,7 @@ impl super::Validator {
|
|||
mod_info: &ModuleInfo,
|
||||
) -> Result<FunctionInfo, WithSpan<FunctionError>> {
|
||||
#[cfg_attr(not(feature = "validate"), allow(unused_mut))]
|
||||
let mut info = mod_info.process_function(fun, module, self.flags, self.capabilities)?;
|
||||
let mut info = mod_info.process_function(fun, module, self.flags)?;
|
||||
|
||||
#[cfg(feature = "validate")]
|
||||
for (var_handle, var) in fun.local_variables.iter() {
|
||||
|
|
|
@ -383,9 +383,7 @@ impl super::Validator {
|
|||
}
|
||||
crate::AddressSpace::Handle => {
|
||||
match types[var.ty].inner {
|
||||
crate::TypeInner::Image { .. }
|
||||
| crate::TypeInner::Sampler { .. }
|
||||
| crate::TypeInner::BindingArray { .. } => {}
|
||||
crate::TypeInner::Image { .. } | crate::TypeInner::Sampler { .. } => {}
|
||||
_ => {
|
||||
return Err(GlobalVariableError::InvalidType(var.space));
|
||||
}
|
||||
|
@ -514,13 +512,6 @@ impl super::Validator {
|
|||
crate::AddressSpace::Uniform => GlobalUse::READ | GlobalUse::QUERY,
|
||||
crate::AddressSpace::Storage { access } => storage_usage(access),
|
||||
crate::AddressSpace::Handle => match module.types[var.ty].inner {
|
||||
crate::TypeInner::BindingArray { base, .. } => match module.types[base].inner {
|
||||
crate::TypeInner::Image {
|
||||
class: crate::ImageClass::Storage { access, .. },
|
||||
..
|
||||
} => storage_usage(access),
|
||||
_ => GlobalUse::READ | GlobalUse::QUERY,
|
||||
},
|
||||
crate::TypeInner::Image {
|
||||
class: crate::ImageClass::Storage { access, .. },
|
||||
..
|
||||
|
|
|
@ -88,12 +88,6 @@ bitflags::bitflags! {
|
|||
const FLOAT64 = 0x2;
|
||||
/// Support for `Builtin:PrimitiveIndex`.
|
||||
const PRIMITIVE_INDEX = 0x4;
|
||||
/// Support for non-uniform indexing of sampled textures and storage buffer arrays.
|
||||
const SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING = 0x8;
|
||||
/// Support for non-uniform indexing of uniform buffers and storage texture arrays.
|
||||
const UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING = 0x10;
|
||||
/// Support for non-uniform indexing of samplers.
|
||||
const SAMPLER_NON_UNIFORM_INDEXING = 0x11;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,10 +203,7 @@ impl crate::TypeInner {
|
|||
| Self::Pointer { .. }
|
||||
| Self::ValuePointer { .. }
|
||||
| Self::Struct { .. } => true,
|
||||
Self::Array { .. }
|
||||
| Self::Image { .. }
|
||||
| Self::Sampler { .. }
|
||||
| Self::BindingArray { .. } => false,
|
||||
Self::Array { .. } | Self::Image { .. } | Self::Sampler { .. } => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -580,7 +580,6 @@ impl super::Validator {
|
|||
ti
|
||||
}
|
||||
Ti::Image { .. } | Ti::Sampler { .. } => TypeInfo::new(TypeFlags::ARGUMENT, 0),
|
||||
Ti::BindingArray { .. } => TypeInfo::new(TypeFlags::empty(), 0),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"f4dcb8db1e3276bfa485eac69d7906030719cd93787a44acc4cfd3598969ba8e","build.rs":"fedccfe06a4d75ba68233f0756de4161213c5d25851963f5b0521d8b7292b395","src/binding_model.rs":"218bfaa87b291be693c27ea496111c4a66edcbc585ce2661c060d5996822334b","src/command/bind.rs":"309f3f1b1719d25115d385368cff0a2c85e94da825b2930141db78235901c673","src/command/bundle.rs":"f015e176b7d7f67cd17dfef9ca67f46fd2c2edcc33286fc250929b9f00c9b18c","src/command/clear.rs":"03f624521571c46080051baa95b60230aca5698e2ddc6c83100a4c1162de4e1a","src/command/compute.rs":"05f405bba84c411f300eb635a7b77bbb557bc94fb91253b5578c49f62e1530d1","src/command/draw.rs":"c04bdbcdabfdf5e3b4524bf155089b20185e283847ecfd628acc983101b2cbba","src/command/memory_init.rs":"f7c73879b9fa728039a45d78f1f865e4eca863c860b3775a4542c973dfdb68c5","src/command/mod.rs":"6bee42ee62915d9ef6afe7c17fc3da04b22574b63ed9e38067ff2d92e51fe3bd","src/command/query.rs":"18659df22356493697ce1c5b56fe2ca0e2f3f1ef29bdf00d65f064eeecba5130","src/command/render.rs":"155aaf90898dade6ee54754824a151f3b3ddc1387767f35ca8cc991c61ac0156","src/command/transfer.rs":"6277878f4d99516bd7db5612aaf4fac280a46d48c44575a7c5f501d6fbae5c61","src/conv.rs":"15d87cd2a91cb9514273e86441940b86380861ec146796e5f214e95e4124d975","src/device/life.rs":"72ae33cc066ca1537c89ba1c7b12dab89957ea0449a4348e007a73aad471f4a5","src/device/mod.rs":"79dec24662a61af89ceeddef19c5fd101c6d97ae505f2a7f95d5699777b876e6","src/device/queue.rs":"5d070ff1f94f0796ece9359548806e41ed7c8f466828328f04fc7616644796e5","src/device/trace.rs":"de575a8213c8ae9df711e4b6afe5736d71ac65bf141375fe044d3b6c4375e039","src/error.rs":"34a4adbb6ec669d8de22b932363506eeef1b1115c422bcc8daa3b26f62378518","src/hub.rs":"e12f3ac5cbb126d37ca81c736ead67c65484b61f6f9433fc2b6ac2f904112490","src/id.rs":"420ef1442ce4663b4f8c011117bdc20682aaea4ad7bfa08c526ea3022a7b6d27","src/init_tracker/buffer.rs":"ccdddaace101f921463bf6c62ed5aca01a6520717a850b5d4442c3551e9f1875","src/init_tracker/mod.rs":"273c6ee67a927784a617899c6fe5560e47108248ab67cabdc2eebcba53133364","src/init_tracker/texture.rs":"75cf8753d850792ebc11da8ed7936836a23e12cbcdd52213a5e85ea3ff1412c1","src/instance.rs":"82d91ad4d7a98ee6fd87c05e93576e8351ccc6fa0f43fb880e1fddc5d54ca319","src/lib.rs":"f7101b4e0476e90d1ab7be5575d26855e074afb868a2f6f8dbcff04040e56689","src/pipeline.rs":"ffabdc74656717276241b1ca2ed043fabf18795662a523828193aea99d7a9ef5","src/present.rs":"50759b10537bf8bd52b1bb4cc48671fa860b325bd67d7f4d5057f8dc88794fdd","src/resource.rs":"2eb571779b9e1f3adaa67861a8d982ab58ade510023e6910936a0a1a952fd9e8","src/track/buffer.rs":"58828fa4bb6d9ca0f4c2549fd271b1ada738598675cc13714db99ef676c9332a","src/track/mod.rs":"753e8041bc4d10da311b95544e768f5f6dab235763305708632d8ad5a3f7984c","src/track/range.rs":"d24340a235103fd18e740236ebfe59b434023bc07abaeebc11c4d7b44057e267","src/track/texture.rs":"f64028e06c215d7dc9d1ac293acbcc40e88b9dbf7eb0e010214f0327d4569794","src/validation.rs":"254e9fbdd24949c3786ad300e1ca90a724ea022f1698f84f059b6fb298a2094c"},"package":null}
|
||||
{"files":{"Cargo.toml":"8843330929d66b09e5eb1ee5ebc5aa0991d777187d69a9fd58e719d20bf9c02a","build.rs":"fedccfe06a4d75ba68233f0756de4161213c5d25851963f5b0521d8b7292b395","src/binding_model.rs":"218bfaa87b291be693c27ea496111c4a66edcbc585ce2661c060d5996822334b","src/command/bind.rs":"309f3f1b1719d25115d385368cff0a2c85e94da825b2930141db78235901c673","src/command/bundle.rs":"4519a28c5acc4a70de274ad7e577073beb85c5b273d7e6081b7e78e87154ae93","src/command/clear.rs":"03f624521571c46080051baa95b60230aca5698e2ddc6c83100a4c1162de4e1a","src/command/compute.rs":"775d08b85c27cadfe7123b6312386099a165a72e1ff8fbdb25e9e84e23ca5623","src/command/draw.rs":"c04bdbcdabfdf5e3b4524bf155089b20185e283847ecfd628acc983101b2cbba","src/command/memory_init.rs":"f7c73879b9fa728039a45d78f1f865e4eca863c860b3775a4542c973dfdb68c5","src/command/mod.rs":"993b8a9806fa55f6d24eb6d49db353ab1ae1fc16cac5f4fb2557f6a3286df758","src/command/query.rs":"18659df22356493697ce1c5b56fe2ca0e2f3f1ef29bdf00d65f064eeecba5130","src/command/render.rs":"db903e1e659eb01ed521ffa7e07afd626026e8086e206eb699783ff15fc03cf8","src/command/transfer.rs":"6277878f4d99516bd7db5612aaf4fac280a46d48c44575a7c5f501d6fbae5c61","src/conv.rs":"15d87cd2a91cb9514273e86441940b86380861ec146796e5f214e95e4124d975","src/device/life.rs":"72ae33cc066ca1537c89ba1c7b12dab89957ea0449a4348e007a73aad471f4a5","src/device/mod.rs":"74c8f6bb462a65fe89115e77e5908df295e4582d5db50095b2817d0168c5bd7b","src/device/queue.rs":"5d070ff1f94f0796ece9359548806e41ed7c8f466828328f04fc7616644796e5","src/device/trace.rs":"de575a8213c8ae9df711e4b6afe5736d71ac65bf141375fe044d3b6c4375e039","src/error.rs":"34a4adbb6ec669d8de22b932363506eeef1b1115c422bcc8daa3b26f62378518","src/hub.rs":"5b6094b56b02c1a799e64ca6121f87dbb446e9e5bf1f7f3f2792a34b68c5d109","src/id.rs":"420ef1442ce4663b4f8c011117bdc20682aaea4ad7bfa08c526ea3022a7b6d27","src/init_tracker/buffer.rs":"ccdddaace101f921463bf6c62ed5aca01a6520717a850b5d4442c3551e9f1875","src/init_tracker/mod.rs":"273c6ee67a927784a617899c6fe5560e47108248ab67cabdc2eebcba53133364","src/init_tracker/texture.rs":"75cf8753d850792ebc11da8ed7936836a23e12cbcdd52213a5e85ea3ff1412c1","src/instance.rs":"30890e69af605c18c0402134cd7475ee504694e69d2ae1a50432053d3e90448c","src/lib.rs":"f7101b4e0476e90d1ab7be5575d26855e074afb868a2f6f8dbcff04040e56689","src/pipeline.rs":"ffabdc74656717276241b1ca2ed043fabf18795662a523828193aea99d7a9ef5","src/present.rs":"50759b10537bf8bd52b1bb4cc48671fa860b325bd67d7f4d5057f8dc88794fdd","src/resource.rs":"2eb571779b9e1f3adaa67861a8d982ab58ade510023e6910936a0a1a952fd9e8","src/track/buffer.rs":"58828fa4bb6d9ca0f4c2549fd271b1ada738598675cc13714db99ef676c9332a","src/track/mod.rs":"753e8041bc4d10da311b95544e768f5f6dab235763305708632d8ad5a3f7984c","src/track/range.rs":"d24340a235103fd18e740236ebfe59b434023bc07abaeebc11c4d7b44057e267","src/track/texture.rs":"f64028e06c215d7dc9d1ac293acbcc40e88b9dbf7eb0e010214f0327d4569794","src/validation.rs":"068c8a3560abac8e7f811cceb2386441ad88dc380c4e6ca7007f09b4e2a39321"},"package":null}
|
|
@ -30,8 +30,7 @@ codespan-reporting = "0.11"
|
|||
copyless = "0.1"
|
||||
fxhash = "0.2"
|
||||
log = "0.4"
|
||||
# parking_lot 0.12 switches from `winapi` to `windows`; permit either
|
||||
parking_lot = ">=0.11,<0.13"
|
||||
parking_lot = "0.11"
|
||||
profiling = { version = "1", default-features = false }
|
||||
raw-window-handle = { version = "0.4", optional = true }
|
||||
ron = { version = "0.7", optional = true }
|
||||
|
@ -41,7 +40,7 @@ thiserror = "1"
|
|||
|
||||
[dependencies.naga]
|
||||
git = "https://github.com/gfx-rs/naga"
|
||||
rev = "1aa91549"
|
||||
rev = "85056524"
|
||||
#version = "0.8"
|
||||
features = ["span", "validate", "wgsl-in"]
|
||||
|
||||
|
|
|
@ -36,8 +36,8 @@ invalidations or index format changes.
|
|||
use crate::{
|
||||
binding_model::buffer_binding_type_alignment,
|
||||
command::{
|
||||
BasePass, BindGroupStateChange, DrawError, MapPassErr, PassErrorScope, RenderCommand,
|
||||
RenderCommandError, StateChange,
|
||||
BasePass, DrawError, MapPassErr, PassErrorScope, RenderCommand, RenderCommandError,
|
||||
StateChange,
|
||||
},
|
||||
conv,
|
||||
device::{
|
||||
|
@ -86,12 +86,6 @@ pub struct RenderBundleEncoder {
|
|||
parent_id: id::DeviceId,
|
||||
pub(crate) context: RenderPassContext,
|
||||
pub(crate) is_ds_read_only: bool,
|
||||
|
||||
// Resource binding dedupe state.
|
||||
#[cfg_attr(feature = "serial-pass", serde(skip))]
|
||||
current_bind_groups: BindGroupStateChange,
|
||||
#[cfg_attr(feature = "serial-pass", serde(skip))]
|
||||
current_pipeline: StateChange<id::RenderPipelineId>,
|
||||
}
|
||||
|
||||
impl RenderBundleEncoder {
|
||||
|
@ -132,9 +126,6 @@ impl RenderBundleEncoder {
|
|||
}
|
||||
None => false,
|
||||
},
|
||||
|
||||
current_bind_groups: BindGroupStateChange::new(),
|
||||
current_pipeline: StateChange::new(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -152,9 +143,6 @@ impl RenderBundleEncoder {
|
|||
multiview: None,
|
||||
},
|
||||
is_ds_read_only: false,
|
||||
|
||||
current_bind_groups: BindGroupStateChange::new(),
|
||||
current_pipeline: StateChange::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,7 +180,7 @@ impl RenderBundleEncoder {
|
|||
raw_dynamic_offsets: Vec::new(),
|
||||
flat_dynamic_offsets: Vec::new(),
|
||||
used_bind_groups: 0,
|
||||
pipeline: None,
|
||||
pipeline: StateChange::new(),
|
||||
};
|
||||
let mut commands = Vec::new();
|
||||
let mut base = self.base.as_ref();
|
||||
|
@ -264,15 +252,15 @@ impl RenderBundleEncoder {
|
|||
}
|
||||
RenderCommand::SetPipeline(pipeline_id) => {
|
||||
let scope = PassErrorScope::SetPipelineRender(pipeline_id);
|
||||
|
||||
state.pipeline = Some(pipeline_id);
|
||||
if state.pipeline.set_and_check_redundant(pipeline_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let pipeline = state
|
||||
.trackers
|
||||
.render_pipes
|
||||
.use_extend(&*pipeline_guard, pipeline_id, (), ())
|
||||
.map_err(|_| RenderCommandError::InvalidPipeline(pipeline_id))
|
||||
.map_pass_err(scope)?;
|
||||
.unwrap();
|
||||
|
||||
self.context
|
||||
.check_compatible(&pipeline.pass_context)
|
||||
|
@ -382,7 +370,7 @@ impl RenderBundleEncoder {
|
|||
let scope = PassErrorScope::Draw {
|
||||
indexed: false,
|
||||
indirect: false,
|
||||
pipeline: state.pipeline,
|
||||
pipeline: state.pipeline.last_state,
|
||||
};
|
||||
let vertex_limits = state.vertex_limits();
|
||||
let last_vertex = first_vertex + vertex_count;
|
||||
|
@ -417,7 +405,7 @@ impl RenderBundleEncoder {
|
|||
let scope = PassErrorScope::Draw {
|
||||
indexed: true,
|
||||
indirect: false,
|
||||
pipeline: state.pipeline,
|
||||
pipeline: state.pipeline.last_state,
|
||||
};
|
||||
//TODO: validate that base_vertex + max_index() is within the provided range
|
||||
let vertex_limits = state.vertex_limits();
|
||||
|
@ -453,7 +441,7 @@ impl RenderBundleEncoder {
|
|||
let scope = PassErrorScope::Draw {
|
||||
indexed: false,
|
||||
indirect: true,
|
||||
pipeline: state.pipeline,
|
||||
pipeline: state.pipeline.last_state,
|
||||
};
|
||||
device
|
||||
.require_downlevel_flags(wgt::DownlevelFlags::INDIRECT_EXECUTION)
|
||||
|
@ -486,7 +474,7 @@ impl RenderBundleEncoder {
|
|||
let scope = PassErrorScope::Draw {
|
||||
indexed: true,
|
||||
indirect: true,
|
||||
pipeline: state.pipeline,
|
||||
pipeline: state.pipeline.last_state,
|
||||
};
|
||||
device
|
||||
.require_downlevel_flags(wgt::DownlevelFlags::INDIRECT_EXECUTION)
|
||||
|
@ -1002,7 +990,7 @@ struct State {
|
|||
raw_dynamic_offsets: Vec<wgt::DynamicOffset>,
|
||||
flat_dynamic_offsets: Vec<wgt::DynamicOffset>,
|
||||
used_bind_groups: usize,
|
||||
pipeline: Option<id::RenderPipelineId>,
|
||||
pipeline: StateChange<id::RenderPipelineId>,
|
||||
}
|
||||
|
||||
impl State {
|
||||
|
@ -1220,7 +1208,7 @@ pub mod bundle_ffi {
|
|||
use super::{RenderBundleEncoder, RenderCommand};
|
||||
use crate::{id, RawString};
|
||||
use std::{convert::TryInto, slice};
|
||||
use wgt::{BufferAddress, BufferSize, DynamicOffset, IndexFormat};
|
||||
use wgt::{BufferAddress, BufferSize, DynamicOffset};
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
|
@ -1234,23 +1222,17 @@ pub mod bundle_ffi {
|
|||
offsets: *const DynamicOffset,
|
||||
offset_length: usize,
|
||||
) {
|
||||
let redundant = bundle.current_bind_groups.set_and_check_redundant(
|
||||
bind_group_id,
|
||||
index,
|
||||
&mut bundle.base.dynamic_offsets,
|
||||
offsets,
|
||||
offset_length,
|
||||
);
|
||||
|
||||
if redundant {
|
||||
return;
|
||||
}
|
||||
|
||||
bundle.base.commands.push(RenderCommand::SetBindGroup {
|
||||
index: index.try_into().unwrap(),
|
||||
num_dynamic_offsets: offset_length.try_into().unwrap(),
|
||||
bind_group_id,
|
||||
});
|
||||
if offset_length != 0 {
|
||||
bundle
|
||||
.base
|
||||
.dynamic_offsets
|
||||
.extend_from_slice(slice::from_raw_parts(offsets, offset_length));
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -1258,10 +1240,6 @@ pub mod bundle_ffi {
|
|||
bundle: &mut RenderBundleEncoder,
|
||||
pipeline_id: id::RenderPipelineId,
|
||||
) {
|
||||
if bundle.current_pipeline.set_and_check_redundant(pipeline_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
bundle
|
||||
.base
|
||||
.commands
|
||||
|
@ -1284,17 +1262,6 @@ pub mod bundle_ffi {
|
|||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wgpu_render_bundle_set_index_buffer(
|
||||
encoder: &mut RenderBundleEncoder,
|
||||
buffer: id::BufferId,
|
||||
index_format: IndexFormat,
|
||||
offset: BufferAddress,
|
||||
size: Option<BufferSize>,
|
||||
) {
|
||||
encoder.set_index_buffer(buffer, index_format, offset, size);
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe as there is no guarantee that the given pointer is
|
||||
|
|
|
@ -6,8 +6,8 @@ use crate::{
|
|||
bind::Binder,
|
||||
end_pipeline_statistics_query,
|
||||
memory_init::{fixup_discarded_surfaces, SurfacesInDiscardState},
|
||||
BasePass, BasePassRef, BindGroupStateChange, CommandBuffer, CommandEncoderError,
|
||||
CommandEncoderStatus, MapPassErr, PassErrorScope, QueryUseError, StateChange,
|
||||
BasePass, BasePassRef, CommandBuffer, CommandEncoderError, CommandEncoderStatus,
|
||||
MapPassErr, PassErrorScope, QueryUseError, StateChange,
|
||||
},
|
||||
device::MissingDownlevelFlags,
|
||||
error::{ErrorFormatter, PrettyError},
|
||||
|
@ -76,12 +76,6 @@ pub enum ComputeCommand {
|
|||
pub struct ComputePass {
|
||||
base: BasePass<ComputeCommand>,
|
||||
parent_id: id::CommandEncoderId,
|
||||
|
||||
// Resource binding dedupe state.
|
||||
#[cfg_attr(feature = "serial-pass", serde(skip))]
|
||||
current_bind_groups: BindGroupStateChange,
|
||||
#[cfg_attr(feature = "serial-pass", serde(skip))]
|
||||
current_pipeline: StateChange<id::ComputePipelineId>,
|
||||
}
|
||||
|
||||
impl ComputePass {
|
||||
|
@ -89,9 +83,6 @@ impl ComputePass {
|
|||
Self {
|
||||
base: BasePass::new(&desc.label),
|
||||
parent_id,
|
||||
|
||||
current_bind_groups: BindGroupStateChange::new(),
|
||||
current_pipeline: StateChange::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,7 +222,7 @@ where
|
|||
#[derive(Debug)]
|
||||
struct State {
|
||||
binder: Binder,
|
||||
pipeline: Option<id::ComputePipelineId>,
|
||||
pipeline: StateChange<id::ComputePipelineId>,
|
||||
trackers: StatefulTrackerSubset,
|
||||
debug_scope_depth: u32,
|
||||
}
|
||||
|
@ -245,7 +236,7 @@ impl State {
|
|||
index: bind_mask.trailing_zeros(),
|
||||
});
|
||||
}
|
||||
if self.pipeline.is_none() {
|
||||
if self.pipeline.is_unset() {
|
||||
return Err(DispatchError::MissingPipeline);
|
||||
}
|
||||
self.binder.check_late_buffer_bindings()?;
|
||||
|
@ -309,11 +300,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
let (device_guard, mut token) = hub.devices.read(&mut token);
|
||||
|
||||
let (mut cmd_buf_guard, mut token) = hub.command_buffers.write(&mut token);
|
||||
// Spell out the type, to placate rust-analyzer.
|
||||
// https://github.com/rust-lang/rust-analyzer/issues/12247
|
||||
let cmd_buf: &mut CommandBuffer<A> =
|
||||
CommandBuffer::get_encoder_mut(&mut *cmd_buf_guard, encoder_id)
|
||||
.map_pass_err(init_scope)?;
|
||||
let cmd_buf = CommandBuffer::get_encoder_mut(&mut *cmd_buf_guard, encoder_id)
|
||||
.map_pass_err(init_scope)?;
|
||||
// will be reset to true if recording is done without errors
|
||||
cmd_buf.status = CommandEncoderStatus::Error;
|
||||
let raw = cmd_buf.encoder.open();
|
||||
|
@ -337,7 +325,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
|
||||
let mut state = State {
|
||||
binder: Binder::new(),
|
||||
pipeline: None,
|
||||
pipeline: StateChange::new(),
|
||||
trackers: StatefulTrackerSubset::new(A::VARIANT),
|
||||
debug_scope_depth: 0,
|
||||
};
|
||||
|
@ -432,7 +420,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
ComputeCommand::SetPipeline(pipeline_id) => {
|
||||
let scope = PassErrorScope::SetPipelineCompute(pipeline_id);
|
||||
|
||||
state.pipeline = Some(pipeline_id);
|
||||
if state.pipeline.set_and_check_redundant(pipeline_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let pipeline = cmd_buf
|
||||
.trackers
|
||||
|
@ -534,7 +524,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
ComputeCommand::Dispatch(groups) => {
|
||||
let scope = PassErrorScope::Dispatch {
|
||||
indirect: false,
|
||||
pipeline: state.pipeline,
|
||||
pipeline: state.pipeline.last_state,
|
||||
};
|
||||
|
||||
fixup_discarded_surfaces(
|
||||
|
@ -578,7 +568,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
ComputeCommand::DispatchIndirect { buffer_id, offset } => {
|
||||
let scope = PassErrorScope::Dispatch {
|
||||
indirect: true,
|
||||
pipeline: state.pipeline,
|
||||
pipeline: state.pipeline.last_state,
|
||||
};
|
||||
|
||||
state.is_ready().map_pass_err(scope)?;
|
||||
|
@ -760,23 +750,16 @@ pub mod compute_ffi {
|
|||
offsets: *const DynamicOffset,
|
||||
offset_length: usize,
|
||||
) {
|
||||
let redundant = pass.current_bind_groups.set_and_check_redundant(
|
||||
bind_group_id,
|
||||
index,
|
||||
&mut pass.base.dynamic_offsets,
|
||||
offsets,
|
||||
offset_length,
|
||||
);
|
||||
|
||||
if redundant {
|
||||
return;
|
||||
}
|
||||
|
||||
pass.base.commands.push(ComputeCommand::SetBindGroup {
|
||||
index: index.try_into().unwrap(),
|
||||
num_dynamic_offsets: offset_length.try_into().unwrap(),
|
||||
bind_group_id,
|
||||
});
|
||||
if offset_length != 0 {
|
||||
pass.base
|
||||
.dynamic_offsets
|
||||
.extend_from_slice(slice::from_raw_parts(offsets, offset_length));
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -784,10 +767,6 @@ pub mod compute_ffi {
|
|||
pass: &mut ComputePass,
|
||||
pipeline_id: id::ComputePipelineId,
|
||||
) {
|
||||
if pass.current_pipeline.set_and_check_redundant(pipeline_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
pass.base
|
||||
.commands
|
||||
.push(ComputeCommand::SetPipeline(pipeline_id));
|
||||
|
@ -833,7 +812,7 @@ pub mod compute_ffi {
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wgpu_compute_pass_dispatch_workgroups(
|
||||
pub extern "C" fn wgpu_compute_pass_dispatch(
|
||||
pass: &mut ComputePass,
|
||||
groups_x: u32,
|
||||
groups_y: u32,
|
||||
|
@ -845,7 +824,7 @@ pub mod compute_ffi {
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wgpu_compute_pass_dispatch_workgroups_indirect(
|
||||
pub extern "C" fn wgpu_compute_pass_dispatch_indirect(
|
||||
pass: &mut ComputePass,
|
||||
buffer_id: id::BufferId,
|
||||
offset: BufferAddress,
|
||||
|
|
|
@ -8,8 +8,6 @@ mod query;
|
|||
mod render;
|
||||
mod transfer;
|
||||
|
||||
use std::slice;
|
||||
|
||||
pub(crate) use self::clear::clear_texture_no_device;
|
||||
pub use self::{
|
||||
bundle::*, clear::ClearError, compute::*, draw::*, query::*, render::*, transfer::*,
|
||||
|
@ -407,7 +405,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[derive(Debug)]
|
||||
struct StateChange<T> {
|
||||
last_state: Option<T>,
|
||||
}
|
||||
|
@ -421,65 +419,14 @@ impl<T: Copy + PartialEq> StateChange<T> {
|
|||
self.last_state = Some(new_state);
|
||||
already_set
|
||||
}
|
||||
fn is_unset(&self) -> bool {
|
||||
self.last_state.is_none()
|
||||
}
|
||||
fn reset(&mut self) {
|
||||
self.last_state = None;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + PartialEq> Default for StateChange<T> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct BindGroupStateChange {
|
||||
last_states: [StateChange<id::BindGroupId>; hal::MAX_BIND_GROUPS],
|
||||
}
|
||||
|
||||
impl BindGroupStateChange {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
last_states: [StateChange::new(); hal::MAX_BIND_GROUPS],
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn set_and_check_redundant(
|
||||
&mut self,
|
||||
bind_group_id: id::BindGroupId,
|
||||
index: u32,
|
||||
dynamic_offsets: &mut Vec<u32>,
|
||||
offsets: *const wgt::DynamicOffset,
|
||||
offset_length: usize,
|
||||
) -> bool {
|
||||
// For now never deduplicate bind groups with dynamic offsets.
|
||||
if offset_length == 0 {
|
||||
// If this get returns None, that means we're well over the limit, so let the call through to get a proper error
|
||||
if let Some(current_bind_group) = self.last_states.get_mut(index as usize) {
|
||||
// Bail out if we're binding the same bind group.
|
||||
if current_bind_group.set_and_check_redundant(bind_group_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// We intentionally remove the memory of this bind group if we have dynamic offsets,
|
||||
// such that if you try to bind this bind group later with _no_ dynamic offsets it
|
||||
// tries to bind it again and gives a proper validation error.
|
||||
if let Some(current_bind_group) = self.last_states.get_mut(index as usize) {
|
||||
current_bind_group.reset();
|
||||
}
|
||||
dynamic_offsets.extend_from_slice(slice::from_raw_parts(offsets, offset_length));
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for BindGroupStateChange {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
trait MapPassErr<T, O> {
|
||||
fn map_pass_err(self, scope: PassErrorScope) -> Result<T, O>;
|
||||
}
|
||||
|
|
|
@ -4,9 +4,9 @@ use crate::{
|
|||
bind::Binder,
|
||||
end_pipeline_statistics_query,
|
||||
memory_init::{fixup_discarded_surfaces, SurfacesInDiscardState},
|
||||
BasePass, BasePassRef, BindGroupStateChange, CommandBuffer, CommandEncoderError,
|
||||
CommandEncoderStatus, DrawError, ExecutionError, MapPassErr, PassErrorScope, QueryResetMap,
|
||||
QueryUseError, RenderCommand, RenderCommandError, StateChange,
|
||||
BasePass, BasePassRef, CommandBuffer, CommandEncoderError, CommandEncoderStatus, DrawError,
|
||||
ExecutionError, MapPassErr, PassErrorScope, QueryResetMap, QueryUseError, RenderCommand,
|
||||
RenderCommandError, StateChange,
|
||||
},
|
||||
device::{
|
||||
AttachmentData, Device, MissingDownlevelFlags, MissingFeatures,
|
||||
|
@ -164,12 +164,6 @@ pub struct RenderPass {
|
|||
parent_id: id::CommandEncoderId,
|
||||
color_targets: ArrayVec<RenderPassColorAttachment, { hal::MAX_COLOR_TARGETS }>,
|
||||
depth_stencil_target: Option<RenderPassDepthStencilAttachment>,
|
||||
|
||||
// Resource binding dedupe state.
|
||||
#[cfg_attr(feature = "serial-pass", serde(skip))]
|
||||
current_bind_groups: BindGroupStateChange,
|
||||
#[cfg_attr(feature = "serial-pass", serde(skip))]
|
||||
current_pipeline: StateChange<id::RenderPipelineId>,
|
||||
}
|
||||
|
||||
impl RenderPass {
|
||||
|
@ -179,9 +173,6 @@ impl RenderPass {
|
|||
parent_id,
|
||||
color_targets: desc.color_attachments.iter().cloned().collect(),
|
||||
depth_stencil_target: desc.depth_stencil_attachment.cloned(),
|
||||
|
||||
current_bind_groups: BindGroupStateChange::new(),
|
||||
current_pipeline: StateChange::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -346,7 +337,7 @@ struct State {
|
|||
binder: Binder,
|
||||
blend_constant: OptionalState,
|
||||
stencil_reference: u32,
|
||||
pipeline: Option<id::RenderPipelineId>,
|
||||
pipeline: StateChange<id::RenderPipelineId>,
|
||||
index: IndexState,
|
||||
vertex: VertexState,
|
||||
debug_scope_depth: u32,
|
||||
|
@ -370,7 +361,7 @@ impl State {
|
|||
index: bind_mask.trailing_zeros(),
|
||||
});
|
||||
}
|
||||
if self.pipeline.is_none() {
|
||||
if self.pipeline.is_unset() {
|
||||
return Err(DrawError::MissingPipeline);
|
||||
}
|
||||
if self.blend_constant == OptionalState::Required {
|
||||
|
@ -401,7 +392,7 @@ impl State {
|
|||
/// Reset the `RenderBundle`-related states.
|
||||
fn reset_bundle(&mut self) {
|
||||
self.binder.reset();
|
||||
self.pipeline = None;
|
||||
self.pipeline.reset();
|
||||
self.index.reset();
|
||||
self.vertex.reset();
|
||||
}
|
||||
|
@ -1050,11 +1041,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
let (trackers, query_reset_state, pending_discard_init_fixups) = {
|
||||
let (mut cmb_guard, mut token) = hub.command_buffers.write(&mut token);
|
||||
|
||||
// Spell out the type, to placate rust-analyzer.
|
||||
// https://github.com/rust-lang/rust-analyzer/issues/12247
|
||||
let cmd_buf: &mut CommandBuffer<A> =
|
||||
CommandBuffer::get_encoder_mut(&mut *cmb_guard, encoder_id)
|
||||
.map_pass_err(init_scope)?;
|
||||
let cmd_buf = CommandBuffer::get_encoder_mut(&mut *cmb_guard, encoder_id)
|
||||
.map_pass_err(init_scope)?;
|
||||
// close everything while the new command encoder is filled
|
||||
cmd_buf.encoder.close();
|
||||
// will be reset to true if recording is done without errors
|
||||
|
@ -1104,7 +1092,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
binder: Binder::new(),
|
||||
blend_constant: OptionalState::Unused,
|
||||
stencil_reference: 0,
|
||||
pipeline: None,
|
||||
pipeline: StateChange::new(),
|
||||
index: IndexState::default(),
|
||||
vertex: VertexState::default(),
|
||||
debug_scope_depth: 0,
|
||||
|
@ -1199,7 +1187,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
}
|
||||
RenderCommand::SetPipeline(pipeline_id) => {
|
||||
let scope = PassErrorScope::SetPipelineRender(pipeline_id);
|
||||
state.pipeline = Some(pipeline_id);
|
||||
if state.pipeline.set_and_check_redundant(pipeline_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let pipeline = cmd_buf
|
||||
.trackers
|
||||
|
@ -1515,7 +1505,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
let scope = PassErrorScope::Draw {
|
||||
indexed,
|
||||
indirect: false,
|
||||
pipeline: state.pipeline,
|
||||
pipeline: state.pipeline.last_state,
|
||||
};
|
||||
state.is_ready(indexed).map_pass_err(scope)?;
|
||||
|
||||
|
@ -1555,7 +1545,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
let scope = PassErrorScope::Draw {
|
||||
indexed,
|
||||
indirect: false,
|
||||
pipeline: state.pipeline,
|
||||
pipeline: state.pipeline.last_state,
|
||||
};
|
||||
state.is_ready(indexed).map_pass_err(scope)?;
|
||||
|
||||
|
@ -1599,7 +1589,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
let scope = PassErrorScope::Draw {
|
||||
indexed,
|
||||
indirect: true,
|
||||
pipeline: state.pipeline,
|
||||
pipeline: state.pipeline.last_state,
|
||||
};
|
||||
state.is_ready(indexed).map_pass_err(scope)?;
|
||||
|
||||
|
@ -1672,7 +1662,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
let scope = PassErrorScope::Draw {
|
||||
indexed,
|
||||
indirect: true,
|
||||
pipeline: state.pipeline,
|
||||
pipeline: state.pipeline.last_state,
|
||||
};
|
||||
state.is_ready(indexed).map_pass_err(scope)?;
|
||||
|
||||
|
@ -2008,7 +1998,7 @@ pub mod render_ffi {
|
|||
};
|
||||
use crate::{id, RawString};
|
||||
use std::{convert::TryInto, ffi, num::NonZeroU32, slice};
|
||||
use wgt::{BufferAddress, BufferSize, Color, DynamicOffset, IndexFormat};
|
||||
use wgt::{BufferAddress, BufferSize, Color, DynamicOffset};
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
|
@ -2022,23 +2012,16 @@ pub mod render_ffi {
|
|||
offsets: *const DynamicOffset,
|
||||
offset_length: usize,
|
||||
) {
|
||||
let redundant = pass.current_bind_groups.set_and_check_redundant(
|
||||
bind_group_id,
|
||||
index,
|
||||
&mut pass.base.dynamic_offsets,
|
||||
offsets,
|
||||
offset_length,
|
||||
);
|
||||
|
||||
if redundant {
|
||||
return;
|
||||
}
|
||||
|
||||
pass.base.commands.push(RenderCommand::SetBindGroup {
|
||||
index: index.try_into().unwrap(),
|
||||
num_dynamic_offsets: offset_length.try_into().unwrap(),
|
||||
bind_group_id,
|
||||
});
|
||||
if offset_length != 0 {
|
||||
pass.base
|
||||
.dynamic_offsets
|
||||
.extend_from_slice(slice::from_raw_parts(offsets, offset_length));
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -2046,10 +2029,6 @@ pub mod render_ffi {
|
|||
pass: &mut RenderPass,
|
||||
pipeline_id: id::RenderPipelineId,
|
||||
) {
|
||||
if pass.current_pipeline.set_and_check_redundant(pipeline_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
pass.base
|
||||
.commands
|
||||
.push(RenderCommand::SetPipeline(pipeline_id));
|
||||
|
@ -2071,17 +2050,6 @@ pub mod render_ffi {
|
|||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wgpu_render_pass_set_index_buffer(
|
||||
pass: &mut RenderPass,
|
||||
buffer: id::BufferId,
|
||||
index_format: IndexFormat,
|
||||
offset: BufferAddress,
|
||||
size: Option<BufferSize>,
|
||||
) {
|
||||
pass.set_index_buffer(buffer, index_format, offset, size);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wgpu_render_pass_set_blend_constant(pass: &mut RenderPass, color: &Color) {
|
||||
pass.base
|
||||
|
|
|
@ -856,7 +856,10 @@ impl<A: HalApi> Device<A> {
|
|||
}
|
||||
None => match texture.desc.dimension {
|
||||
wgt::TextureDimension::D1 => wgt::TextureViewDimension::D1,
|
||||
wgt::TextureDimension::D2 if texture.desc.size.depth_or_array_layers > 1 => {
|
||||
wgt::TextureDimension::D2
|
||||
if texture.desc.size.depth_or_array_layers > 1
|
||||
&& desc.range.array_layer_count.is_none() =>
|
||||
{
|
||||
wgt::TextureViewDimension::D2Array
|
||||
}
|
||||
wgt::TextureDimension::D2 => wgt::TextureViewDimension::D2,
|
||||
|
@ -868,13 +871,7 @@ impl<A: HalApi> Device<A> {
|
|||
desc.range.base_mip_level + desc.range.mip_level_count.map_or(1, |count| count.get());
|
||||
let required_layer_count = match desc.range.array_layer_count {
|
||||
Some(count) => desc.range.base_array_layer + count.get(),
|
||||
None => match view_dim {
|
||||
wgt::TextureViewDimension::D1
|
||||
| wgt::TextureViewDimension::D2
|
||||
| wgt::TextureViewDimension::D3 => 1,
|
||||
wgt::TextureViewDimension::Cube => 6,
|
||||
_ => texture.desc.array_layer_count(),
|
||||
},
|
||||
None => texture.desc.array_layer_count(),
|
||||
};
|
||||
let level_end = texture.full_range.levels.end;
|
||||
let layer_end = texture.full_range.layers.end;
|
||||
|
@ -1145,25 +1142,6 @@ impl<A: HalApi> Device<A> {
|
|||
self.features
|
||||
.contains(wgt::Features::SHADER_PRIMITIVE_INDEX),
|
||||
);
|
||||
caps.set(
|
||||
Caps::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
|
||||
self.features.contains(
|
||||
wgt::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
|
||||
),
|
||||
);
|
||||
caps.set(
|
||||
Caps::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING,
|
||||
self.features.contains(
|
||||
wgt::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING,
|
||||
),
|
||||
);
|
||||
// TODO: This needs a proper wgpu feature
|
||||
caps.set(
|
||||
Caps::SAMPLER_NON_UNIFORM_INDEXING,
|
||||
self.features.contains(
|
||||
wgt::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
|
||||
),
|
||||
);
|
||||
let info = naga::valid::Validator::new(naga::valid::ValidationFlags::all(), caps)
|
||||
.validate(&module)
|
||||
.map_err(|inner| {
|
||||
|
@ -4949,14 +4927,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
}
|
||||
|
||||
/// Check `device_id` for freeable resources and completed buffer mappings.
|
||||
///
|
||||
/// Return `queue_empty` indicating whether there are more queue submissions still in flight.
|
||||
pub fn device_poll<A: HalApi>(
|
||||
&self,
|
||||
device_id: id::DeviceId,
|
||||
force_wait: bool,
|
||||
) -> Result<bool, WaitIdleError> {
|
||||
let (closures, queue_empty) = {
|
||||
) -> Result<(), WaitIdleError> {
|
||||
let (closures, _) = {
|
||||
let hub = A::hub(self);
|
||||
let mut token = Token::root();
|
||||
let (device_guard, mut token) = hub.devices.read(&mut token);
|
||||
|
@ -4968,31 +4944,27 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
unsafe {
|
||||
closures.fire();
|
||||
}
|
||||
Ok(queue_empty)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Poll all devices belonging to the backend `A`.
|
||||
///
|
||||
/// If `force_wait` is true, block until all buffer mappings are done.
|
||||
///
|
||||
/// Return `all_queue_empty` indicating whether there are more queue submissions still in flight.
|
||||
fn poll_devices<A: HalApi>(
|
||||
&self,
|
||||
force_wait: bool,
|
||||
closures: &mut UserClosures,
|
||||
) -> Result<bool, WaitIdleError> {
|
||||
) -> Result<(), WaitIdleError> {
|
||||
profiling::scope!("poll_devices");
|
||||
|
||||
let hub = A::hub(self);
|
||||
let mut devices_to_drop = vec![];
|
||||
let mut all_queue_empty = true;
|
||||
{
|
||||
let mut token = Token::root();
|
||||
let (device_guard, mut token) = hub.devices.read(&mut token);
|
||||
|
||||
for (id, device) in device_guard.iter(A::VARIANT) {
|
||||
let (cbs, queue_empty) = device.maintain(hub, force_wait, &mut token)?;
|
||||
all_queue_empty = all_queue_empty && queue_empty;
|
||||
|
||||
// If the device's own `RefCount` clone is the only one left, and
|
||||
// its submission queue is empty, then it can be freed.
|
||||
|
@ -5007,49 +4979,41 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
self.exit_device::<A>(device_id);
|
||||
}
|
||||
|
||||
Ok(all_queue_empty)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Poll all devices on all backends.
|
||||
///
|
||||
/// This is the implementation of `wgpu::Instance::poll_all`.
|
||||
///
|
||||
/// Return `all_queue_empty` indicating whether there are more queue submissions still in flight.
|
||||
pub fn poll_all_devices(&self, force_wait: bool) -> Result<bool, WaitIdleError> {
|
||||
pub fn poll_all_devices(&self, force_wait: bool) -> Result<(), WaitIdleError> {
|
||||
let mut closures = UserClosures::default();
|
||||
let mut all_queue_empty = true;
|
||||
|
||||
#[cfg(vulkan)]
|
||||
{
|
||||
all_queue_empty = self.poll_devices::<hal::api::Vulkan>(force_wait, &mut closures)?
|
||||
&& all_queue_empty;
|
||||
self.poll_devices::<hal::api::Vulkan>(force_wait, &mut closures)?;
|
||||
}
|
||||
#[cfg(metal)]
|
||||
{
|
||||
all_queue_empty =
|
||||
self.poll_devices::<hal::api::Metal>(force_wait, &mut closures)? && all_queue_empty;
|
||||
self.poll_devices::<hal::api::Metal>(force_wait, &mut closures)?;
|
||||
}
|
||||
#[cfg(dx12)]
|
||||
{
|
||||
all_queue_empty =
|
||||
self.poll_devices::<hal::api::Dx12>(force_wait, &mut closures)? && all_queue_empty;
|
||||
self.poll_devices::<hal::api::Dx12>(force_wait, &mut closures)?;
|
||||
}
|
||||
#[cfg(dx11)]
|
||||
{
|
||||
all_queue_empty =
|
||||
self.poll_devices::<hal::api::Dx11>(force_wait, &mut closures)? && all_queue_empty;
|
||||
self.poll_devices::<hal::api::Dx11>(force_wait, &mut closures)?;
|
||||
}
|
||||
#[cfg(gl)]
|
||||
{
|
||||
all_queue_empty =
|
||||
self.poll_devices::<hal::api::Gles>(force_wait, &mut closures)? && all_queue_empty;
|
||||
self.poll_devices::<hal::api::Gles>(force_wait, &mut closures)?;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
closures.fire();
|
||||
}
|
||||
|
||||
Ok(all_queue_empty)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn device_label<A: HalApi>(&self, id: id::DeviceId) -> String {
|
||||
|
|
|
@ -149,12 +149,11 @@ impl<T, I: id::TypedId> ops::IndexMut<id::Valid<I>> for Storage<T, I> {
|
|||
impl<T, I: id::TypedId> Storage<T, I> {
|
||||
pub(crate) fn contains(&self, id: I) -> bool {
|
||||
let (index, epoch, _) = id.unzip();
|
||||
match self.map.get(index as usize) {
|
||||
Some(&Element::Vacant) => false,
|
||||
Some(&Element::Occupied(_, storage_epoch) | &Element::Error(storage_epoch, _)) => {
|
||||
storage_epoch == epoch
|
||||
match self.map[index as usize] {
|
||||
Element::Vacant => false,
|
||||
Element::Occupied(_, storage_epoch) | Element::Error(storage_epoch, ..) => {
|
||||
epoch == storage_epoch
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,11 +161,10 @@ impl<T, I: id::TypedId> Storage<T, I> {
|
|||
/// Panics if there is an epoch mismatch, or the entry is empty.
|
||||
pub(crate) fn get(&self, id: I) -> Result<&T, InvalidId> {
|
||||
let (index, epoch, _) = id.unzip();
|
||||
let (result, storage_epoch) = match self.map.get(index as usize) {
|
||||
Some(&Element::Occupied(ref v, epoch)) => (Ok(v), epoch),
|
||||
Some(&Element::Vacant) => panic!("{}[{}] does not exist", self.kind, index),
|
||||
Some(&Element::Error(epoch, ..)) => (Err(InvalidId), epoch),
|
||||
None => return Err(InvalidId),
|
||||
let (result, storage_epoch) = match self.map[index as usize] {
|
||||
Element::Occupied(ref v, epoch) => (Ok(v), epoch),
|
||||
Element::Vacant => panic!("{}[{}] does not exist", self.kind, index),
|
||||
Element::Error(epoch, ..) => (Err(InvalidId), epoch),
|
||||
};
|
||||
assert_eq!(
|
||||
epoch, storage_epoch,
|
||||
|
@ -180,11 +178,10 @@ impl<T, I: id::TypedId> Storage<T, I> {
|
|||
/// Panics if there is an epoch mismatch, or the entry is empty.
|
||||
pub(crate) fn get_mut(&mut self, id: I) -> Result<&mut T, InvalidId> {
|
||||
let (index, epoch, _) = id.unzip();
|
||||
let (result, storage_epoch) = match self.map.get_mut(index as usize) {
|
||||
Some(&mut Element::Occupied(ref mut v, epoch)) => (Ok(v), epoch),
|
||||
Some(&mut Element::Vacant) => panic!("{}[{}] does not exist", self.kind, index),
|
||||
Some(&mut Element::Error(epoch, ..)) => (Err(InvalidId), epoch),
|
||||
None => return Err(InvalidId),
|
||||
let (result, storage_epoch) = match self.map[index as usize] {
|
||||
Element::Occupied(ref mut v, epoch) => (Ok(v), epoch),
|
||||
Element::Vacant => panic!("{}[{}] does not exist", self.kind, index),
|
||||
Element::Error(epoch, ..) => (Err(InvalidId), epoch),
|
||||
};
|
||||
assert_eq!(
|
||||
epoch, storage_epoch,
|
||||
|
@ -196,8 +193,8 @@ impl<T, I: id::TypedId> Storage<T, I> {
|
|||
|
||||
pub(crate) fn label_for_invalid_id(&self, id: I) -> &str {
|
||||
let (index, _, _) = id.unzip();
|
||||
match self.map.get(index as usize) {
|
||||
Some(&Element::Error(_, ref label)) => label,
|
||||
match self.map[index as usize] {
|
||||
Element::Error(_, ref label) => label,
|
||||
_ => "",
|
||||
}
|
||||
}
|
||||
|
|
|
@ -735,7 +735,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
|||
|
||||
let preferred_gpu = match desc.power_preference {
|
||||
PowerPreference::LowPower => integrated.or(other).or(discrete).or(virt).or(cpu),
|
||||
PowerPreference::HighPerformance => discrete.or(integrated).or(other).or(virt).or(cpu),
|
||||
PowerPreference::HighPerformance => discrete.or(other).or(integrated).or(virt).or(cpu),
|
||||
};
|
||||
|
||||
let mut selected = preferred_gpu.unwrap_or(0);
|
||||
|
|
|
@ -867,14 +867,7 @@ impl Interface {
|
|||
Some(ref br) => br.clone(),
|
||||
_ => continue,
|
||||
};
|
||||
let naga_ty = &module.types[var.ty].inner;
|
||||
|
||||
let inner_ty = match *naga_ty {
|
||||
naga::TypeInner::BindingArray { base, .. } => &module.types[base].inner,
|
||||
ref ty => ty,
|
||||
};
|
||||
|
||||
let ty = match *inner_ty {
|
||||
let ty = match module.types[var.ty].inner {
|
||||
naga::TypeInner::Image {
|
||||
dim,
|
||||
arrayed,
|
||||
|
@ -906,7 +899,7 @@ impl Interface {
|
|||
|
||||
let mut entry_points = FastHashMap::default();
|
||||
entry_points.reserve(module.entry_points.len());
|
||||
for (index, entry_point) in module.entry_points.iter().enumerate() {
|
||||
for (index, entry_point) in (&module.entry_points).iter().enumerate() {
|
||||
let info = info.get_entry_point(index);
|
||||
let mut ep = EntryPoint::default();
|
||||
for arg in entry_point.function.arguments.iter() {
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"e747e47c2303651b01be2badaa5c1df53a973d3dd7aa3e5de50247599392b450","README.md":"78377f5876fafd77963eff7e3c2ba3a7e3ad5cf9201b09ed5612e49c2288eb18","examples/halmark/main.rs":"c745317191eab3159465f79f4a693f671e2f75877dc3b7215a6a90d70e88ec7f","examples/halmark/shader.wgsl":"59e3628abe34c66708bf0106658e791ef24357df3cae72194d34ff07b40e8007","examples/raw-gles.em.html":"70fbe68394a1a4522192de1dcfaf7d399f60d7bdf5de70b708f9bb0417427546","examples/raw-gles.rs":"d6db84b269b934409ef85fa31914b3f4bc7e7012e40269aad3eff5454eae2a09","src/auxil/dxgi/conv.rs":"cbdb037f2be37b3886f1449b4872a8f248390e185c3d32bf61d64aef76e2008e","src/auxil/dxgi/exception.rs":"f8d69d3d475e03c4d96d22778e5a6f322afd98fcfafb1414cd4a76239fa97a37","src/auxil/dxgi/factory.rs":"82451fcfcc1f73a570ae9e708c94efa9c125d269dfb7396de97da5b32f8a4090","src/auxil/dxgi/mod.rs":"63db737b48378d4843e2f7904f104790688029ff614bc80387cd9efe444f1e52","src/auxil/dxgi/result.rs":"20c8eb03d738062dff198feca6327addb9882ed0462be842c789eadf7dca0573","src/auxil/mod.rs":"f899555124ad6d44f5326ef935f4911702539fd933ec2ab07c6009badb3ea22c","src/auxil/renderdoc.rs":"3a4da908ebd6230177ca55c541c8278639e83d78badb4595a941aea30dd7f80f","src/dx11/adapter.rs":"bf123464ef748d021f2e0c40d27b3f6bdd50222c6f91cce6d25686a912eef093","src/dx11/command.rs":"cdad8dcdb800acba56c931f1726ddada652af18db0f066465af643f82a034492","src/dx11/device.rs":"76ac52095c639482adc2058509cd3acafd49cebc0694fcd64f8d9f53abc823de","src/dx11/instance.rs":"3bbf2730956472cb8023bd8fbd2d53e49f93c5e4ce3d14664112a293a165d191","src/dx11/library.rs":"0da08a780eefa7ff50f2e0998117202f26e5dd3d3a433c58b585801cff9863d2","src/dx11/mod.rs":"e4f7c6100e1bec479b41f3e3af96e01d53e6597c1c3a8fcde6f14cc9eb8537f8","src/dx12/adapter.rs":"1bc8807a28a961df304b44314500ff2239bc53cc72c9308fab28504a6f00c54b","src/dx12/command.rs":"f9969744663c1f01fca3892b93fc516363fa8725739d270a5f633db78f7902da","src/dx12/conv.rs":"c27336e5b576a7e05a576548fa0e6588ff77be4208f08aac0bea7e649ed1301b","src/dx12/descriptor.rs":"7145d3dc6be13fae4cf6bb8bf34a1ea1749ad87e5f429b84f3cbbea7bf63c148","src/dx12/device.rs":"27f47868a77c77a74e63de7f2d152ac22da34559286f13add17568b83d9f7e1e","src/dx12/instance.rs":"ccc36443cb1df8ab8ed8366cf8599ec3d75fb5fefa5f9bb0f0f0b5e6fc1c5102","src/dx12/mod.rs":"e88f7396dca4aba859a6e28d3f9de64a57a0df85acd53cecd6ada3d96386062c","src/dx12/view.rs":"b7a5cb8933f30517a97b4bd767e10b4c09f686dbf493d53b9b265d2d0b16f1a6","src/empty.rs":"6bf65e405f63eff49b25d079af644b352b95a9c7edcf3a57be2e96a50307b66b","src/gles/adapter.rs":"1e246de20cdbbb5d1727955c618486ac967c2e9f326886feb609f8b321114d74","src/gles/command.rs":"3bef8a822b59c7e986c2c6dd084a2c537a96de77e2b48522f86210093daad3d0","src/gles/conv.rs":"c5d6ba4afd2b3245b1a36a84e4c392c640e6170a1e81df3741bf5323c57bdc51","src/gles/device.rs":"66c30c4010f410bf3b8a03ee9d8e14753832fa2b6e17b518481281f06e3d7cd9","src/gles/egl.rs":"38dc851eede42b6be2ff02f15fef3a4a116cd1b5803974fada89ac86d42a5df4","src/gles/mod.rs":"8686d9bcfb8a7be6f3b8ff7d96e7538e71c3d37b2b09762b06aa304518165dfd","src/gles/queue.rs":"c57f634c983dca6bd657d2f6150f699d9648e6b5726ead9bb4310dd975171cdd","src/gles/shaders/clear.frag":"aac702eed9ece5482db5ba6783a678b119a5e7802b1ecf93f4975dee8acab0b3","src/gles/shaders/clear.vert":"8f636168e1da2cac48091c466a543c3b09fb4a0dd8c60c1c9bf34cc890766740","src/gles/shaders/present.frag":"dd9a43c339a2fa4ccf7f6a1854c6f400cabf271a7d5e9230768e9f39d47f3ff5","src/gles/shaders/present.vert":"6e85d489403d80b81cc94790730bb53b309dfc5eeede8f1ea3412a660f31d357","src/gles/web.rs":"083500c0b36d079a82754895d06b993ea8ed4393690b226c85f07cbec373a730","src/lib.rs":"bebe5582d5e9563aebb0d44e6f267dc1eeb556557761bb1afc5f4191634a8588","src/metal/adapter.rs":"83ef6668160178fcce7820d3036c25aa35d02932577e45577832f19b93c8a12d","src/metal/command.rs":"b06983d7e11cdde526b7c9f5f0b86f1ea8faef02b7666367cb231211a8301570","src/metal/conv.rs":"517c491a87ba57f275f4a2f130ef1fc2c17528176ebc4813772f9bcd86ffd8e5","src/metal/device.rs":"dd823c8e12ba3ed69ef7cdcb543e8d995d0056d1f838516b0901068c83d8ffe2","src/metal/mod.rs":"c4f3959732f5f506fa881aa5812205a6452d6a946d661d7f81d1c7785359a10c","src/metal/surface.rs":"82836cadc751d94fb016bd590cdfec5649cbfae2f44d14599ed074dfb0a004dc","src/vulkan/adapter.rs":"6dc8f42fce7ea939134860944495fe687f2bffd47a97dc8dfd14ff34c11cd5b5","src/vulkan/command.rs":"60d1867acd0e46c34dabecea708cd776a1f435721b6673a506b5bb8aee87ff80","src/vulkan/conv.rs":"0d7b706a854ff3fdcea0e66f0d8563d9c2aa1f82b2e84692c16f4bfcc3872ed5","src/vulkan/device.rs":"472e915c73e69be8559e460061d720a32f7e8b5d3601982bc2bc588cc2b80a5d","src/vulkan/instance.rs":"49bb57b65c886c14f258e8a7fc183138765310ac7efd2fe3b26115e7942aa1fe","src/vulkan/mod.rs":"95347a82e2a276c1953e542c838f2ae07acc18d4187025fb22c264e61684860d"},"package":null}
|
||||
{"files":{"Cargo.toml":"e7dc9c948392b41eaaa81f730d2371e4cc94c9e49acb30edc9318bb0e0031a13","README.md":"78377f5876fafd77963eff7e3c2ba3a7e3ad5cf9201b09ed5612e49c2288eb18","examples/halmark/main.rs":"c745317191eab3159465f79f4a693f671e2f75877dc3b7215a6a90d70e88ec7f","examples/halmark/shader.wgsl":"59e3628abe34c66708bf0106658e791ef24357df3cae72194d34ff07b40e8007","examples/raw-gles.em.html":"70fbe68394a1a4522192de1dcfaf7d399f60d7bdf5de70b708f9bb0417427546","examples/raw-gles.rs":"d6db84b269b934409ef85fa31914b3f4bc7e7012e40269aad3eff5454eae2a09","src/auxil/dxgi/conv.rs":"cbdb037f2be37b3886f1449b4872a8f248390e185c3d32bf61d64aef76e2008e","src/auxil/dxgi/exception.rs":"f8d69d3d475e03c4d96d22778e5a6f322afd98fcfafb1414cd4a76239fa97a37","src/auxil/dxgi/factory.rs":"82451fcfcc1f73a570ae9e708c94efa9c125d269dfb7396de97da5b32f8a4090","src/auxil/dxgi/mod.rs":"63db737b48378d4843e2f7904f104790688029ff614bc80387cd9efe444f1e52","src/auxil/dxgi/result.rs":"20c8eb03d738062dff198feca6327addb9882ed0462be842c789eadf7dca0573","src/auxil/mod.rs":"f899555124ad6d44f5326ef935f4911702539fd933ec2ab07c6009badb3ea22c","src/auxil/renderdoc.rs":"3a4da908ebd6230177ca55c541c8278639e83d78badb4595a941aea30dd7f80f","src/dx11/adapter.rs":"dfd24df4d699772a02f8f1a9bb63e276d41ecb8ee899325d2818e01202b0845b","src/dx11/command.rs":"cdad8dcdb800acba56c931f1726ddada652af18db0f066465af643f82a034492","src/dx11/device.rs":"76ac52095c639482adc2058509cd3acafd49cebc0694fcd64f8d9f53abc823de","src/dx11/instance.rs":"3bbf2730956472cb8023bd8fbd2d53e49f93c5e4ce3d14664112a293a165d191","src/dx11/library.rs":"0da08a780eefa7ff50f2e0998117202f26e5dd3d3a433c58b585801cff9863d2","src/dx11/mod.rs":"e4f7c6100e1bec479b41f3e3af96e01d53e6597c1c3a8fcde6f14cc9eb8537f8","src/dx12/adapter.rs":"5b6f4110b558a3f5a35eca803b8253bae0f00156e9f99c486a0f20fb66a494da","src/dx12/command.rs":"f9969744663c1f01fca3892b93fc516363fa8725739d270a5f633db78f7902da","src/dx12/conv.rs":"c27336e5b576a7e05a576548fa0e6588ff77be4208f08aac0bea7e649ed1301b","src/dx12/descriptor.rs":"7145d3dc6be13fae4cf6bb8bf34a1ea1749ad87e5f429b84f3cbbea7bf63c148","src/dx12/device.rs":"d7509b4ab3537b1a4925d3f1abcca16b3ce77465a0a5ec3dcfa7c436a0f46576","src/dx12/instance.rs":"ccc36443cb1df8ab8ed8366cf8599ec3d75fb5fefa5f9bb0f0f0b5e6fc1c5102","src/dx12/mod.rs":"2ff1c8f52acbd86fa31838119025c20abfcdd13a4224fa396074b7857759a9a5","src/dx12/view.rs":"b7a5cb8933f30517a97b4bd767e10b4c09f686dbf493d53b9b265d2d0b16f1a6","src/empty.rs":"6bf65e405f63eff49b25d079af644b352b95a9c7edcf3a57be2e96a50307b66b","src/gles/adapter.rs":"c5b405d405c820cf7c2540125f1b3fed72983c9e4cabda1ef949b949a92c5915","src/gles/command.rs":"3bef8a822b59c7e986c2c6dd084a2c537a96de77e2b48522f86210093daad3d0","src/gles/conv.rs":"c5d6ba4afd2b3245b1a36a84e4c392c640e6170a1e81df3741bf5323c57bdc51","src/gles/device.rs":"95a9ab1d029ff25711e009c8d5fb4fe1454575b862e1c1eb699a67a660cfcccc","src/gles/egl.rs":"38dc851eede42b6be2ff02f15fef3a4a116cd1b5803974fada89ac86d42a5df4","src/gles/mod.rs":"8686d9bcfb8a7be6f3b8ff7d96e7538e71c3d37b2b09762b06aa304518165dfd","src/gles/queue.rs":"21543baba720fbd68aa679334c82f05ed4e138304c485cb4a9748c588cda67a6","src/gles/shaders/clear.frag":"aac702eed9ece5482db5ba6783a678b119a5e7802b1ecf93f4975dee8acab0b3","src/gles/shaders/clear.vert":"8f636168e1da2cac48091c466a543c3b09fb4a0dd8c60c1c9bf34cc890766740","src/gles/shaders/present.frag":"dd9a43c339a2fa4ccf7f6a1854c6f400cabf271a7d5e9230768e9f39d47f3ff5","src/gles/shaders/present.vert":"6e85d489403d80b81cc94790730bb53b309dfc5eeede8f1ea3412a660f31d357","src/gles/web.rs":"083500c0b36d079a82754895d06b993ea8ed4393690b226c85f07cbec373a730","src/lib.rs":"aff587532db234498bdf8e7282bb3100e378daf547feff4ffa88ea6e0d72da0d","src/metal/adapter.rs":"eb2c4969e20841115453dae06957741d317428c196e795f2fb1f64706bf09cd0","src/metal/command.rs":"de41fa5eaa2208abd9ff3d7daf929b17664c445cb26d43331aa84bcc7cfb67cd","src/metal/conv.rs":"517c491a87ba57f275f4a2f130ef1fc2c17528176ebc4813772f9bcd86ffd8e5","src/metal/device.rs":"839f39636c680098c3b9bec20770d2240775f0afeb0dc0111566feab92e9b93b","src/metal/mod.rs":"cb4ebc93b08fee670dc9b28115eb14b8e351a4e1b00bc8cc5384b6967c6ad614","src/metal/surface.rs":"82836cadc751d94fb016bd590cdfec5649cbfae2f44d14599ed074dfb0a004dc","src/vulkan/adapter.rs":"30943968799a96810e25ed79f304b331cafc85598180a6a407675ebdb595c0d0","src/vulkan/command.rs":"60d1867acd0e46c34dabecea708cd776a1f435721b6673a506b5bb8aee87ff80","src/vulkan/conv.rs":"0d7b706a854ff3fdcea0e66f0d8563d9c2aa1f82b2e84692c16f4bfcc3872ed5","src/vulkan/device.rs":"ed980a4cbad2a0aa9d2b6b2b3f28b71121f6773521664baf0bb66e225bbae376","src/vulkan/instance.rs":"49bb57b65c886c14f258e8a7fc183138765310ac7efd2fe3b26115e7942aa1fe","src/vulkan/mod.rs":"85e6a91864f36ec95517094a695b59a0dc0deb000b8772bb3c8656c2b2a4e9b4"},"package":null}
|
|
@ -31,8 +31,7 @@ required-features = ["gles"]
|
|||
|
||||
[dependencies]
|
||||
bitflags = "1.0"
|
||||
# parking_lot 0.12 switches from `winapi` to `windows`; permit either
|
||||
parking_lot = ">=0.11,<0.13"
|
||||
parking_lot = "0.11"
|
||||
profiling = { version = "1", default-features = false }
|
||||
raw-window-handle = "0.4"
|
||||
thiserror = "1"
|
||||
|
@ -92,14 +91,14 @@ js-sys = { version = "0.3" }
|
|||
|
||||
[dependencies.naga]
|
||||
git = "https://github.com/gfx-rs/naga"
|
||||
rev = "1aa91549"
|
||||
rev = "85056524"
|
||||
#version = "0.8"
|
||||
|
||||
# DEV dependencies
|
||||
|
||||
[dev-dependencies.naga]
|
||||
git = "https://github.com/gfx-rs/naga"
|
||||
rev = "1aa91549"
|
||||
rev = "85056524"
|
||||
#version = "0.8"
|
||||
features = ["wgsl-in"]
|
||||
|
||||
|
|
|
@ -193,8 +193,8 @@ impl super::Adapter {
|
|||
|
||||
let limits = wgt::Limits {
|
||||
max_texture_dimension_1d: max_texture_dimension_2d,
|
||||
max_texture_dimension_2d,
|
||||
max_texture_dimension_3d,
|
||||
max_texture_dimension_2d: max_texture_dimension_2d,
|
||||
max_texture_dimension_3d: max_texture_dimension_3d,
|
||||
max_texture_array_layers: max_texture_dimension_3d,
|
||||
max_bind_groups: u32::MAX,
|
||||
max_dynamic_uniform_buffers_per_pipeline_layout: max_constant_buffers,
|
||||
|
@ -206,7 +206,7 @@ impl super::Adapter {
|
|||
max_uniform_buffers_per_shader_stage: max_constant_buffers,
|
||||
max_uniform_buffer_binding_size: 1 << 16,
|
||||
max_storage_buffer_binding_size: u32::MAX,
|
||||
max_vertex_buffers,
|
||||
max_vertex_buffers: max_vertex_buffers,
|
||||
max_vertex_attributes: max_vertex_buffers,
|
||||
max_vertex_buffer_array_stride: u32::MAX,
|
||||
max_push_constant_size: 1 << 16,
|
||||
|
|
|
@ -91,18 +91,6 @@ impl super::Adapter {
|
|||
)
|
||||
});
|
||||
|
||||
let mut shader_model_support: d3d12::D3D12_FEATURE_DATA_SHADER_MODEL =
|
||||
d3d12::D3D12_FEATURE_DATA_SHADER_MODEL {
|
||||
HighestShaderModel: d3d12::D3D_SHADER_MODEL_6_0,
|
||||
};
|
||||
assert_eq!(0, unsafe {
|
||||
device.CheckFeatureSupport(
|
||||
d3d12::D3D12_FEATURE_SHADER_MODEL,
|
||||
&mut shader_model_support as *mut _ as *mut _,
|
||||
mem::size_of::<d3d12::D3D12_FEATURE_DATA_SHADER_MODEL>() as _,
|
||||
)
|
||||
});
|
||||
|
||||
let mut workarounds = super::Workarounds::default();
|
||||
|
||||
let info = wgt::AdapterInfo {
|
||||
|
@ -187,6 +175,11 @@ impl super::Adapter {
|
|||
| wgt::Features::DEPTH_CLIP_CONTROL
|
||||
| wgt::Features::INDIRECT_FIRST_INSTANCE
|
||||
| wgt::Features::MAPPABLE_PRIMARY_BUFFERS
|
||||
//TODO: Naga part
|
||||
//| wgt::Features::TEXTURE_BINDING_ARRAY
|
||||
//| wgt::Features::BUFFER_BINDING_ARRAY
|
||||
//| wgt::Features::STORAGE_RESOURCE_BINDING_ARRAY
|
||||
//| wgt::Features::UNSIZED_BINDING_ARRAY
|
||||
| wgt::Features::MULTI_DRAW_INDIRECT
|
||||
| wgt::Features::MULTI_DRAW_INDIRECT_COUNT
|
||||
| wgt::Features::ADDRESS_MODE_CLAMP_TO_BORDER
|
||||
|
@ -211,13 +204,6 @@ impl super::Adapter {
|
|||
!= d3d12::D3D12_CONSERVATIVE_RASTERIZATION_TIER_NOT_SUPPORTED,
|
||||
);
|
||||
|
||||
features.set(
|
||||
wgt::Features::TEXTURE_BINDING_ARRAY
|
||||
| wgt::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING
|
||||
| wgt::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING,
|
||||
shader_model_support.HighestShaderModel >= d3d12::D3D_SHADER_MODEL_5_1,
|
||||
);
|
||||
|
||||
let base = wgt::Limits::default();
|
||||
|
||||
Some(crate::ExposedAdapter {
|
||||
|
@ -296,7 +282,7 @@ impl super::Adapter {
|
|||
impl crate::Adapter<super::Api> for super::Adapter {
|
||||
unsafe fn open(
|
||||
&self,
|
||||
_features: wgt::Features,
|
||||
features: wgt::Features,
|
||||
_limits: &wgt::Limits,
|
||||
) -> Result<crate::OpenDevice<super::Api>, crate::DeviceError> {
|
||||
let queue = {
|
||||
|
@ -311,7 +297,13 @@ impl crate::Adapter<super::Api> for super::Adapter {
|
|||
.into_device_result("Queue creation")?
|
||||
};
|
||||
|
||||
let device = super::Device::new(self.device, queue, self.private_caps, &self.library)?;
|
||||
let device = super::Device::new(
|
||||
self.device,
|
||||
queue,
|
||||
features,
|
||||
self.private_caps,
|
||||
&self.library,
|
||||
)?;
|
||||
Ok(crate::OpenDevice {
|
||||
device,
|
||||
queue: super::Queue {
|
||||
|
|
|
@ -21,6 +21,7 @@ impl super::Device {
|
|||
pub(super) fn new(
|
||||
raw: native::Device,
|
||||
present_queue: native::CommandQueue,
|
||||
features: wgt::Features,
|
||||
private_caps: super::PrivateCapabilities,
|
||||
library: &Arc<native::D3D12Lib>,
|
||||
) -> Result<Self, crate::DeviceError> {
|
||||
|
@ -86,6 +87,7 @@ impl super::Device {
|
|||
let capacity_samplers = 2_048;
|
||||
|
||||
let shared = super::DeviceShared {
|
||||
features,
|
||||
zero_buffer,
|
||||
cmd_signatures: super::CommandSignatures {
|
||||
draw: raw
|
||||
|
@ -220,6 +222,13 @@ impl super::Device {
|
|||
compile_flags |=
|
||||
d3dcompiler::D3DCOMPILE_DEBUG | d3dcompiler::D3DCOMPILE_SKIP_OPTIMIZATION;
|
||||
}
|
||||
if self
|
||||
.shared
|
||||
.features
|
||||
.contains(wgt::Features::UNSIZED_BINDING_ARRAY)
|
||||
{
|
||||
compile_flags |= d3dcompiler::D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES;
|
||||
}
|
||||
|
||||
let source_name = match stage.module.raw_name {
|
||||
Some(ref cstr) => cstr.as_c_str().as_ptr(),
|
||||
|
@ -682,17 +691,16 @@ impl crate::Device<super::Api> for super::Device {
|
|||
) -> Result<super::BindGroupLayout, crate::DeviceError> {
|
||||
let (mut num_buffer_views, mut num_samplers, mut num_texture_views) = (0, 0, 0);
|
||||
for entry in desc.entries.iter() {
|
||||
let count = entry.count.map_or(1, NonZeroU32::get);
|
||||
match entry.ty {
|
||||
wgt::BindingType::Buffer {
|
||||
has_dynamic_offset: true,
|
||||
..
|
||||
} => {}
|
||||
wgt::BindingType::Buffer { .. } => num_buffer_views += count,
|
||||
wgt::BindingType::Buffer { .. } => num_buffer_views += 1,
|
||||
wgt::BindingType::Texture { .. } | wgt::BindingType::StorageTexture { .. } => {
|
||||
num_texture_views += count
|
||||
num_texture_views += 1
|
||||
}
|
||||
wgt::BindingType::Sampler { .. } => num_samplers += count,
|
||||
wgt::BindingType::Sampler { .. } => num_samplers += 1,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -850,10 +858,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||
group: index as u32,
|
||||
binding: entry.binding,
|
||||
},
|
||||
hlsl::BindTarget {
|
||||
binding_array_size: entry.count.map(NonZeroU32::get),
|
||||
..bt.clone()
|
||||
},
|
||||
bt.clone(),
|
||||
);
|
||||
ranges.push(native::DescriptorRange::new(
|
||||
range_ty,
|
||||
|
@ -861,7 +866,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||
native_binding(bt),
|
||||
d3d12::D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,
|
||||
));
|
||||
bt.register += entry.count.map(NonZeroU32::get).unwrap_or(1);
|
||||
bt.register += 1;
|
||||
}
|
||||
if ranges.len() > range_base {
|
||||
log::debug!(
|
||||
|
@ -889,10 +894,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||
group: index as u32,
|
||||
binding: entry.binding,
|
||||
},
|
||||
hlsl::BindTarget {
|
||||
binding_array_size: entry.count.map(NonZeroU32::get),
|
||||
..bind_sampler.clone()
|
||||
},
|
||||
bind_sampler.clone(),
|
||||
);
|
||||
ranges.push(native::DescriptorRange::new(
|
||||
range_ty,
|
||||
|
@ -900,7 +902,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||
native_binding(&bind_sampler),
|
||||
d3d12::D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,
|
||||
));
|
||||
bind_sampler.register += entry.count.map(NonZeroU32::get).unwrap_or(1);
|
||||
bind_sampler.register += 1;
|
||||
}
|
||||
if ranges.len() > range_base {
|
||||
log::debug!(
|
||||
|
@ -951,10 +953,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||
group: index as u32,
|
||||
binding: entry.binding,
|
||||
},
|
||||
hlsl::BindTarget {
|
||||
binding_array_size: entry.count.map(NonZeroU32::get),
|
||||
..bt.clone()
|
||||
},
|
||||
bt.clone(),
|
||||
);
|
||||
info.dynamic_buffers.push(kind);
|
||||
|
||||
|
@ -970,7 +969,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||
native_binding(bt),
|
||||
));
|
||||
|
||||
bt.register += entry.count.map_or(1, NonZeroU32::get);
|
||||
bt.register += 1;
|
||||
}
|
||||
|
||||
bind_group_infos.push(info);
|
||||
|
@ -1083,97 +1082,82 @@ impl crate::Device<super::Api> for super::Device {
|
|||
has_dynamic_offset: true,
|
||||
..
|
||||
} => {
|
||||
let start = entry.resource_index as usize;
|
||||
let end = start + entry.count as usize;
|
||||
for data in &desc.buffers[start..end] {
|
||||
dynamic_buffers.push(data.resolve_address());
|
||||
}
|
||||
let data = &desc.buffers[entry.resource_index as usize];
|
||||
dynamic_buffers.push(data.resolve_address());
|
||||
}
|
||||
wgt::BindingType::Buffer { ty, .. } => {
|
||||
let start = entry.resource_index as usize;
|
||||
let end = start + entry.count as usize;
|
||||
for data in &desc.buffers[start..end] {
|
||||
let gpu_address = data.resolve_address();
|
||||
let size = data.resolve_size() as u32;
|
||||
let inner = cpu_views.as_mut().unwrap();
|
||||
let cpu_index = inner.stage.len() as u32;
|
||||
let handle = desc.layout.cpu_heap_views.as_ref().unwrap().at(cpu_index);
|
||||
match ty {
|
||||
wgt::BufferBindingType::Uniform => {
|
||||
let size_mask =
|
||||
d3d12::D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1;
|
||||
let raw_desc = d3d12::D3D12_CONSTANT_BUFFER_VIEW_DESC {
|
||||
BufferLocation: gpu_address,
|
||||
SizeInBytes: ((size - 1) | size_mask) + 1,
|
||||
};
|
||||
self.raw.CreateConstantBufferView(&raw_desc, handle);
|
||||
}
|
||||
wgt::BufferBindingType::Storage { read_only: true } => {
|
||||
let mut raw_desc = d3d12::D3D12_SHADER_RESOURCE_VIEW_DESC {
|
||||
Format: dxgiformat::DXGI_FORMAT_R32_TYPELESS,
|
||||
Shader4ComponentMapping:
|
||||
view::D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
|
||||
ViewDimension: d3d12::D3D12_SRV_DIMENSION_BUFFER,
|
||||
u: mem::zeroed(),
|
||||
};
|
||||
*raw_desc.u.Buffer_mut() = d3d12::D3D12_BUFFER_SRV {
|
||||
FirstElement: data.offset / 4,
|
||||
NumElements: size / 4,
|
||||
StructureByteStride: 0,
|
||||
Flags: d3d12::D3D12_BUFFER_SRV_FLAG_RAW,
|
||||
};
|
||||
self.raw.CreateShaderResourceView(
|
||||
data.buffer.resource.as_mut_ptr(),
|
||||
&raw_desc,
|
||||
handle,
|
||||
);
|
||||
}
|
||||
wgt::BufferBindingType::Storage { read_only: false } => {
|
||||
let mut raw_desc = d3d12::D3D12_UNORDERED_ACCESS_VIEW_DESC {
|
||||
Format: dxgiformat::DXGI_FORMAT_R32_TYPELESS,
|
||||
ViewDimension: d3d12::D3D12_UAV_DIMENSION_BUFFER,
|
||||
u: mem::zeroed(),
|
||||
};
|
||||
*raw_desc.u.Buffer_mut() = d3d12::D3D12_BUFFER_UAV {
|
||||
FirstElement: data.offset / 4,
|
||||
NumElements: size / 4,
|
||||
StructureByteStride: 0,
|
||||
CounterOffsetInBytes: 0,
|
||||
Flags: d3d12::D3D12_BUFFER_UAV_FLAG_RAW,
|
||||
};
|
||||
self.raw.CreateUnorderedAccessView(
|
||||
data.buffer.resource.as_mut_ptr(),
|
||||
ptr::null_mut(),
|
||||
&raw_desc,
|
||||
handle,
|
||||
);
|
||||
}
|
||||
let data = &desc.buffers[entry.resource_index as usize];
|
||||
let gpu_address = data.resolve_address();
|
||||
let size = data.resolve_size() as u32;
|
||||
let inner = cpu_views.as_mut().unwrap();
|
||||
let cpu_index = inner.stage.len() as u32;
|
||||
let handle = desc.layout.cpu_heap_views.as_ref().unwrap().at(cpu_index);
|
||||
match ty {
|
||||
wgt::BufferBindingType::Uniform => {
|
||||
let size_mask =
|
||||
d3d12::D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT - 1;
|
||||
let raw_desc = d3d12::D3D12_CONSTANT_BUFFER_VIEW_DESC {
|
||||
BufferLocation: gpu_address,
|
||||
SizeInBytes: ((size - 1) | size_mask) + 1,
|
||||
};
|
||||
self.raw.CreateConstantBufferView(&raw_desc, handle);
|
||||
}
|
||||
wgt::BufferBindingType::Storage { read_only: true } => {
|
||||
let mut raw_desc = d3d12::D3D12_SHADER_RESOURCE_VIEW_DESC {
|
||||
Format: dxgiformat::DXGI_FORMAT_R32_TYPELESS,
|
||||
Shader4ComponentMapping:
|
||||
view::D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING,
|
||||
ViewDimension: d3d12::D3D12_SRV_DIMENSION_BUFFER,
|
||||
u: mem::zeroed(),
|
||||
};
|
||||
*raw_desc.u.Buffer_mut() = d3d12::D3D12_BUFFER_SRV {
|
||||
FirstElement: data.offset / 4,
|
||||
NumElements: size / 4,
|
||||
StructureByteStride: 0,
|
||||
Flags: d3d12::D3D12_BUFFER_SRV_FLAG_RAW,
|
||||
};
|
||||
self.raw.CreateShaderResourceView(
|
||||
data.buffer.resource.as_mut_ptr(),
|
||||
&raw_desc,
|
||||
handle,
|
||||
);
|
||||
}
|
||||
wgt::BufferBindingType::Storage { read_only: false } => {
|
||||
let mut raw_desc = d3d12::D3D12_UNORDERED_ACCESS_VIEW_DESC {
|
||||
Format: dxgiformat::DXGI_FORMAT_R32_TYPELESS,
|
||||
ViewDimension: d3d12::D3D12_UAV_DIMENSION_BUFFER,
|
||||
u: mem::zeroed(),
|
||||
};
|
||||
*raw_desc.u.Buffer_mut() = d3d12::D3D12_BUFFER_UAV {
|
||||
FirstElement: data.offset / 4,
|
||||
NumElements: size / 4,
|
||||
StructureByteStride: 0,
|
||||
CounterOffsetInBytes: 0,
|
||||
Flags: d3d12::D3D12_BUFFER_UAV_FLAG_RAW,
|
||||
};
|
||||
self.raw.CreateUnorderedAccessView(
|
||||
data.buffer.resource.as_mut_ptr(),
|
||||
ptr::null_mut(),
|
||||
&raw_desc,
|
||||
handle,
|
||||
);
|
||||
}
|
||||
inner.stage.push(handle);
|
||||
}
|
||||
inner.stage.push(handle);
|
||||
}
|
||||
wgt::BindingType::Texture { .. } => {
|
||||
let start = entry.resource_index as usize;
|
||||
let end = start + entry.count as usize;
|
||||
for data in &desc.textures[start..end] {
|
||||
let handle = data.view.handle_srv.unwrap();
|
||||
cpu_views.as_mut().unwrap().stage.push(handle.raw);
|
||||
}
|
||||
let data = &desc.textures[entry.resource_index as usize];
|
||||
let handle = data.view.handle_srv.unwrap();
|
||||
cpu_views.as_mut().unwrap().stage.push(handle.raw);
|
||||
}
|
||||
wgt::BindingType::StorageTexture { .. } => {
|
||||
let start = entry.resource_index as usize;
|
||||
let end = start + entry.count as usize;
|
||||
for data in &desc.textures[start..end] {
|
||||
let handle = data.view.handle_uav.unwrap();
|
||||
cpu_views.as_mut().unwrap().stage.push(handle.raw);
|
||||
}
|
||||
let data = &desc.textures[entry.resource_index as usize];
|
||||
let handle = data.view.handle_uav.unwrap();
|
||||
cpu_views.as_mut().unwrap().stage.push(handle.raw);
|
||||
}
|
||||
wgt::BindingType::Sampler { .. } => {
|
||||
let start = entry.resource_index as usize;
|
||||
let end = start + entry.count as usize;
|
||||
for data in &desc.samplers[start..end] {
|
||||
cpu_samplers.as_mut().unwrap().stage.push(data.handle.raw);
|
||||
}
|
||||
let data = &desc.samplers[entry.resource_index as usize];
|
||||
cpu_samplers.as_mut().unwrap().stage.push(data.handle.raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -199,6 +199,7 @@ impl CommandSignatures {
|
|||
}
|
||||
|
||||
struct DeviceShared {
|
||||
features: wgt::Features,
|
||||
zero_buffer: native::Resource,
|
||||
cmd_signatures: CommandSignatures,
|
||||
heap_views: descriptor::GeneralHeap,
|
||||
|
|
|
@ -98,7 +98,6 @@ impl super::Adapter {
|
|||
// opengl has no way to discern device_type, so we can try to infer it from the renderer string
|
||||
let strings_that_imply_integrated = [
|
||||
" xpress", // space here is on purpose so we don't match express
|
||||
"amd renoir",
|
||||
"radeon hd 4200",
|
||||
"radeon hd 4250",
|
||||
"radeon hd 4290",
|
||||
|
@ -135,7 +134,7 @@ impl super::Adapter {
|
|||
} else if strings_that_imply_cpu.iter().any(|&s| renderer.contains(s)) {
|
||||
wgt::DeviceType::Cpu
|
||||
} else {
|
||||
wgt::DeviceType::Other
|
||||
wgt::DeviceType::DiscreteGpu
|
||||
};
|
||||
|
||||
// source: Sascha Willems at Vulkan
|
||||
|
@ -285,10 +284,6 @@ impl super::Adapter {
|
|||
&& (vertex_shader_storage_blocks != 0 || vertex_ssbo_false_zero),
|
||||
);
|
||||
downlevel_flags.set(wgt::DownlevelFlags::FRAGMENT_STORAGE, supports_storage);
|
||||
downlevel_flags.set(
|
||||
wgt::DownlevelFlags::ANISOTROPIC_FILTERING,
|
||||
extensions.contains("EXT_texture_filter_anisotropic"),
|
||||
);
|
||||
|
||||
let mut features = wgt::Features::empty()
|
||||
| wgt::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES
|
||||
|
|
|
@ -740,9 +740,8 @@ impl crate::Device<super::Api> for super::Device {
|
|||
gl.sampler_parameter_f32(raw, glow::TEXTURE_MAX_LOD, range.end);
|
||||
}
|
||||
|
||||
if let Some(anisotropy) = desc.anisotropy_clamp {
|
||||
gl.sampler_parameter_i32(raw, glow::TEXTURE_MAX_ANISOTROPY, anisotropy.get() as i32);
|
||||
}
|
||||
//TODO: `desc.anisotropy_clamp` depends on the downlevel flag
|
||||
// gl.sampler_parameter_f32(rawow::TEXTURE_MAX_ANISOTROPY, aniso as f32);
|
||||
|
||||
//set_param_float(glow::TEXTURE_LOD_BIAS, info.lod_bias.0);
|
||||
|
||||
|
|
|
@ -493,7 +493,21 @@ impl super::Queue {
|
|||
glow::CompressedPixelUnpackData::Slice(src_data)
|
||||
}
|
||||
};
|
||||
|
||||
log::error!(
|
||||
"bytes_per_row: {}, \
|
||||
minimum_rows_per_image: {}, \
|
||||
rows_per_image: {}, \
|
||||
bytes_per_image: {}, \
|
||||
minimum_bytes_per_image: {}, \
|
||||
bytes_in_upload: {}\
|
||||
",
|
||||
bytes_per_row,
|
||||
minimum_rows_per_image,
|
||||
rows_per_image,
|
||||
bytes_per_image,
|
||||
minimum_bytes_per_image,
|
||||
bytes_in_upload
|
||||
);
|
||||
match dst_target {
|
||||
glow::TEXTURE_3D
|
||||
| glow::TEXTURE_CUBE_MAP_ARRAY
|
||||
|
|
|
@ -97,7 +97,7 @@ use thiserror::Error;
|
|||
pub const MAX_ANISOTROPY: u8 = 16;
|
||||
pub const MAX_BIND_GROUPS: usize = 8;
|
||||
pub const MAX_VERTEX_BUFFERS: usize = 16;
|
||||
pub const MAX_COLOR_TARGETS: usize = 8;
|
||||
pub const MAX_COLOR_TARGETS: usize = 4;
|
||||
pub const MAX_MIP_LEVELS: u32 = 16;
|
||||
/// Size of a single occlusion/timestamp query, when copied into a buffer, in bytes.
|
||||
pub const QUERY_SIZE: wgt::BufferAddress = 8;
|
||||
|
|
|
@ -202,7 +202,7 @@ impl crate::Adapter<super::Api> for super::Adapter {
|
|||
} else if pc.msaa_desktop {
|
||||
Tfc::SAMPLED_LINEAR
|
||||
} else {
|
||||
Tfc::SAMPLED_LINEAR
|
||||
Tfc::STORAGE
|
||||
| Tfc::COLOR_ATTACHMENT
|
||||
| Tfc::COLOR_ATTACHMENT_BLEND
|
||||
| Tfc::MULTISAMPLE
|
||||
|
@ -523,7 +523,10 @@ impl super::PrivateCapabilities {
|
|||
MUTABLE_COMPARISON_SAMPLER_SUPPORT,
|
||||
),
|
||||
sampler_clamp_to_border: Self::supports_any(device, SAMPLER_CLAMP_TO_BORDER_SUPPORT),
|
||||
sampler_lod_average: { version.at_least((11, 0), (9, 0)) },
|
||||
sampler_lod_average: {
|
||||
// TODO: Clarify minimum macOS version with Apple (43707452)
|
||||
version.at_least((10, 13), (9, 0))
|
||||
},
|
||||
base_instance: Self::supports_any(device, BASE_INSTANCE_SUPPORT),
|
||||
base_vertex_instance_drawing: Self::supports_any(device, BASE_VERTEX_INSTANCE_SUPPORT),
|
||||
dual_source_blending: Self::supports_any(device, DUAL_SOURCE_BLEND_SUPPORT),
|
||||
|
@ -748,8 +751,7 @@ impl super::PrivateCapabilities {
|
|||
| F::PUSH_CONSTANTS
|
||||
| F::POLYGON_MODE_LINE
|
||||
| F::CLEAR_TEXTURE
|
||||
| F::TEXTURE_FORMAT_16BIT_NORM
|
||||
| F::SHADER_FLOAT16;
|
||||
| F::TEXTURE_FORMAT_16BIT_NORM;
|
||||
|
||||
features.set(F::TEXTURE_COMPRESSION_ASTC_LDR, self.format_astc);
|
||||
features.set(F::TEXTURE_COMPRESSION_ASTC_HDR, self.format_astc_hdr);
|
||||
|
|
|
@ -74,21 +74,13 @@ impl super::CommandState {
|
|||
) -> Option<(u32, &'a [u32])> {
|
||||
let stage_info = &self.stage_infos[stage];
|
||||
let slot = stage_info.sizes_slot?;
|
||||
|
||||
result_sizes.clear();
|
||||
result_sizes.extend(
|
||||
stage_info
|
||||
.sized_bindings
|
||||
.iter()
|
||||
.filter_map(|br| self.storage_buffer_length_map.get(br))
|
||||
.map(|size| size.get().min(!0u32 as u64) as u32),
|
||||
);
|
||||
|
||||
if !result_sizes.is_empty() {
|
||||
Some((slot as _, result_sizes))
|
||||
} else {
|
||||
None
|
||||
for br in stage_info.sized_bindings.iter() {
|
||||
// If it's None, this isn't the right time to update the sizes
|
||||
let size = self.storage_buffer_length_map.get(br)?;
|
||||
result_sizes.push(size.get().min(!0u32 as u64) as u32);
|
||||
}
|
||||
Some((slot as _, result_sizes))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use parking_lot::Mutex;
|
||||
use std::{
|
||||
num::NonZeroU32,
|
||||
ptr,
|
||||
sync::{atomic, Arc},
|
||||
thread, time,
|
||||
|
@ -74,13 +73,6 @@ impl super::Device {
|
|||
)
|
||||
.map_err(|e| crate::PipelineError::Linkage(stage_bit, format!("MSL: {:?}", e)))?;
|
||||
|
||||
log::debug!(
|
||||
"Naga generated shader for entry point '{}' and stage {:?}\n{}",
|
||||
stage.entry_point,
|
||||
naga_stage,
|
||||
&source
|
||||
);
|
||||
|
||||
let options = mtl::CompileOptions::new();
|
||||
options.set_language_version(self.shared.private_caps.msl_version);
|
||||
|
||||
|
@ -566,12 +558,10 @@ impl crate::Device<super::Api> for super::Device {
|
|||
}
|
||||
|
||||
let mut target = naga::back::msl::BindTarget::default();
|
||||
let count = entry.count.map_or(1, NonZeroU32::get);
|
||||
target.binding_array_size = entry.count.map(NonZeroU32::get);
|
||||
match entry.ty {
|
||||
wgt::BindingType::Buffer { ty, .. } => {
|
||||
target.buffer = Some(info.counters.buffers as _);
|
||||
info.counters.buffers += count;
|
||||
info.counters.buffers += 1;
|
||||
if let wgt::BufferBindingType::Storage { read_only } = ty {
|
||||
target.mutable = !read_only;
|
||||
}
|
||||
|
@ -580,15 +570,15 @@ impl crate::Device<super::Api> for super::Device {
|
|||
target.sampler = Some(naga::back::msl::BindSamplerTarget::Resource(
|
||||
info.counters.samplers as _,
|
||||
));
|
||||
info.counters.samplers += count;
|
||||
info.counters.samplers += 1;
|
||||
}
|
||||
wgt::BindingType::Texture { .. } => {
|
||||
target.texture = Some(info.counters.textures as _);
|
||||
info.counters.textures += count;
|
||||
info.counters.textures += 1;
|
||||
}
|
||||
wgt::BindingType::StorageTexture { access, .. } => {
|
||||
target.texture = Some(info.counters.textures as _);
|
||||
info.counters.textures += count;
|
||||
info.counters.textures += 1;
|
||||
target.mutable = match access {
|
||||
wgt::StorageTextureAccess::ReadOnly => false,
|
||||
wgt::StorageTextureAccess::WriteOnly => true,
|
||||
|
@ -677,8 +667,6 @@ impl crate::Device<super::Api> for super::Device {
|
|||
index: naga::proc::BoundsCheckPolicy::ReadZeroSkipWrite,
|
||||
buffer: naga::proc::BoundsCheckPolicy::ReadZeroSkipWrite,
|
||||
image: naga::proc::BoundsCheckPolicy::ReadZeroSkipWrite,
|
||||
// TODO: support bounds checks on binding arrays
|
||||
binding_array: naga::proc::BoundsCheckPolicy::Unchecked,
|
||||
},
|
||||
},
|
||||
total_push_constants,
|
||||
|
@ -701,7 +689,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||
..
|
||||
} = layout.ty
|
||||
{
|
||||
dynamic_offsets_count += size;
|
||||
dynamic_offsets_count += 1;
|
||||
}
|
||||
if !layout.visibility.contains(stage_bit) {
|
||||
continue;
|
||||
|
@ -712,44 +700,39 @@ impl crate::Device<super::Api> for super::Device {
|
|||
has_dynamic_offset,
|
||||
..
|
||||
} => {
|
||||
let start = entry.resource_index as usize;
|
||||
let end = start + size as usize;
|
||||
bg.buffers
|
||||
.extend(desc.buffers[start..end].iter().map(|source| {
|
||||
let remaining_size =
|
||||
wgt::BufferSize::new(source.buffer.size - source.offset);
|
||||
let binding_size = match ty {
|
||||
wgt::BufferBindingType::Storage { .. } => {
|
||||
source.size.or(remaining_size)
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
super::BufferResource {
|
||||
ptr: source.buffer.as_raw(),
|
||||
offset: source.offset,
|
||||
dynamic_index: if has_dynamic_offset {
|
||||
Some(dynamic_offsets_count - 1)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
binding_size,
|
||||
binding_location: layout.binding,
|
||||
}
|
||||
}));
|
||||
debug_assert_eq!(size, 1);
|
||||
let source = &desc.buffers[entry.resource_index as usize];
|
||||
let remaining_size =
|
||||
wgt::BufferSize::new(source.buffer.size - source.offset);
|
||||
let binding_size = match ty {
|
||||
wgt::BufferBindingType::Storage { .. } => {
|
||||
source.size.or(remaining_size)
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
bg.buffers.push(super::BufferResource {
|
||||
ptr: source.buffer.as_raw(),
|
||||
offset: source.offset,
|
||||
dynamic_index: if has_dynamic_offset {
|
||||
Some(dynamic_offsets_count - 1)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
binding_size,
|
||||
binding_location: layout.binding,
|
||||
});
|
||||
counter.buffers += 1;
|
||||
}
|
||||
wgt::BindingType::Sampler { .. } => {
|
||||
let start = entry.resource_index as usize;
|
||||
let end = start + size as usize;
|
||||
bg.samplers
|
||||
.extend(desc.samplers[start..end].iter().map(|samp| samp.as_raw()));
|
||||
counter.samplers += size;
|
||||
let res = desc.samplers[entry.resource_index as usize].as_raw();
|
||||
bg.samplers.push(res);
|
||||
counter.samplers += 1;
|
||||
}
|
||||
wgt::BindingType::Texture { .. } | wgt::BindingType::StorageTexture { .. } => {
|
||||
let start = entry.resource_index as usize;
|
||||
let end = start + size as usize;
|
||||
let start = entry.resource_index;
|
||||
let end = start + size;
|
||||
bg.textures.extend(
|
||||
desc.textures[start..end]
|
||||
desc.textures[start as usize..end as usize]
|
||||
.iter()
|
||||
.map(|tex| tex.view.as_raw()),
|
||||
);
|
||||
|
|
|
@ -261,7 +261,7 @@ impl AdapterShared {
|
|||
|
||||
Self {
|
||||
disabilities: PrivateDisabilities::new(&device),
|
||||
private_caps,
|
||||
private_caps: PrivateCapabilities::new(&device),
|
||||
device: Mutex::new(device),
|
||||
settings: Settings::default(),
|
||||
}
|
||||
|
|
|
@ -3,12 +3,13 @@ use super::conv;
|
|||
use ash::{extensions::khr, vk};
|
||||
use parking_lot::Mutex;
|
||||
|
||||
use std::{collections::BTreeMap, ffi::CStr, sync::Arc};
|
||||
use std::{ffi::CStr, sync::Arc};
|
||||
|
||||
//TODO: const fn?
|
||||
fn indexing_features() -> wgt::Features {
|
||||
wgt::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING
|
||||
| wgt::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING
|
||||
| wgt::Features::UNSIZED_BINDING_ARRAY
|
||||
}
|
||||
|
||||
/// Aggregate of the `vk::PhysicalDevice*Features` structs used by `gfx`.
|
||||
|
@ -25,10 +26,6 @@ pub struct PhysicalDeviceFeatures {
|
|||
depth_clip_enable: Option<vk::PhysicalDeviceDepthClipEnableFeaturesEXT>,
|
||||
multiview: Option<vk::PhysicalDeviceMultiviewFeaturesKHR>,
|
||||
astc_hdr: Option<vk::PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT>,
|
||||
shader_float16: Option<(
|
||||
vk::PhysicalDeviceShaderFloat16Int8Features,
|
||||
vk::PhysicalDevice16BitStorageFeatures,
|
||||
)>,
|
||||
}
|
||||
|
||||
// This is safe because the structs have `p_next: *mut c_void`, which we null out/never read.
|
||||
|
@ -66,10 +63,6 @@ impl PhysicalDeviceFeatures {
|
|||
if let Some(ref mut feature) = self.astc_hdr {
|
||||
info = info.push_next(feature);
|
||||
}
|
||||
if let Some((ref mut f16_i8_feature, ref mut _16bit_feature)) = self.shader_float16 {
|
||||
info = info.push_next(f16_i8_feature);
|
||||
info = info.push_next(_16bit_feature);
|
||||
}
|
||||
info
|
||||
}
|
||||
|
||||
|
@ -219,6 +212,9 @@ impl PhysicalDeviceFeatures {
|
|||
uab_types.contains(super::UpdateAfterBindTypes::STORAGE_BUFFER),
|
||||
)
|
||||
.descriptor_binding_partially_bound(needs_partially_bound)
|
||||
.runtime_descriptor_array(
|
||||
requested_features.contains(wgt::Features::UNSIZED_BINDING_ARRAY),
|
||||
)
|
||||
//.sampler_filter_minmax(requested_features.contains(wgt::Features::SAMPLER_REDUCTION))
|
||||
.imageless_framebuffer(private_caps.imageless_framebuffers)
|
||||
.timeline_semaphore(private_caps.timeline_semaphores)
|
||||
|
@ -257,6 +253,9 @@ impl PhysicalDeviceFeatures {
|
|||
uab_types.contains(super::UpdateAfterBindTypes::STORAGE_BUFFER),
|
||||
)
|
||||
.descriptor_binding_partially_bound(needs_partially_bound)
|
||||
.runtime_descriptor_array(
|
||||
requested_features.contains(wgt::Features::UNSIZED_BINDING_ARRAY),
|
||||
)
|
||||
.build(),
|
||||
)
|
||||
} else {
|
||||
|
@ -334,19 +333,6 @@ impl PhysicalDeviceFeatures {
|
|||
} else {
|
||||
None
|
||||
},
|
||||
shader_float16: if requested_features.contains(wgt::Features::SHADER_FLOAT16) {
|
||||
Some((
|
||||
vk::PhysicalDeviceShaderFloat16Int8Features::builder()
|
||||
.shader_float16(true)
|
||||
.build(),
|
||||
vk::PhysicalDevice16BitStorageFeatures::builder()
|
||||
.storage_buffer16_bit_access(true)
|
||||
.uniform_and_storage_buffer16_bit_access(true)
|
||||
.build(),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -485,6 +471,9 @@ impl PhysicalDeviceFeatures {
|
|||
) {
|
||||
features.insert(F::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING);
|
||||
}
|
||||
if vulkan_1_2.runtime_descriptor_array != 0 {
|
||||
features |= F::UNSIZED_BINDING_ARRAY;
|
||||
}
|
||||
if vulkan_1_2.descriptor_binding_partially_bound != 0 && !intel_windows {
|
||||
features |= F::PARTIALLY_BOUND_BINDING_ARRAY;
|
||||
}
|
||||
|
@ -530,6 +519,9 @@ impl PhysicalDeviceFeatures {
|
|||
if descriptor_indexing.descriptor_binding_partially_bound != 0 && !intel_windows {
|
||||
features |= F::PARTIALLY_BOUND_BINDING_ARRAY;
|
||||
}
|
||||
if descriptor_indexing.runtime_descriptor_array != 0 {
|
||||
features |= F::UNSIZED_BINDING_ARRAY;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref feature) = self.depth_clip_enable {
|
||||
|
@ -552,15 +544,6 @@ impl PhysicalDeviceFeatures {
|
|||
);
|
||||
}
|
||||
|
||||
if let Some((ref f16_i8, ref bit16)) = self.shader_float16 {
|
||||
features.set(
|
||||
F::SHADER_FLOAT16,
|
||||
f16_i8.shader_float16 != 0
|
||||
&& bit16.storage_buffer16_bit_access != 0
|
||||
&& bit16.uniform_and_storage_buffer16_bit_access != 0,
|
||||
);
|
||||
}
|
||||
|
||||
(features, dl_flags)
|
||||
}
|
||||
|
||||
|
@ -672,12 +655,7 @@ impl PhysicalDeviceCapabilities {
|
|||
extensions.push(vk::KhrPortabilitySubsetFn::name());
|
||||
|
||||
if requested_features.contains(wgt::Features::TEXTURE_COMPRESSION_ASTC_HDR) {
|
||||
extensions.push(vk::ExtTextureCompressionAstcHdrFn::name());
|
||||
}
|
||||
|
||||
if requested_features.contains(wgt::Features::SHADER_FLOAT16) {
|
||||
extensions.push(vk::KhrShaderFloat16Int8Fn::name());
|
||||
extensions.push(vk::Khr16bitStorageFn::name());
|
||||
extensions.push(vk::ExtTextureCompressionAstcHdrFn::name())
|
||||
}
|
||||
|
||||
extensions
|
||||
|
@ -918,16 +896,6 @@ impl super::InstanceShared {
|
|||
.insert(vk::PhysicalDeviceTextureCompressionASTCHDRFeaturesEXT::default());
|
||||
builder = builder.push_next(next);
|
||||
}
|
||||
if capabilities.supports_extension(vk::KhrShaderFloat16Int8Fn::name())
|
||||
&& capabilities.supports_extension(vk::Khr16bitStorageFn::name())
|
||||
{
|
||||
let next = features.shader_float16.insert((
|
||||
vk::PhysicalDeviceShaderFloat16Int8FeaturesKHR::default(),
|
||||
vk::PhysicalDevice16BitStorageFeaturesKHR::default(),
|
||||
));
|
||||
builder = builder.push_next(&mut next.0);
|
||||
builder = builder.push_next(&mut next.1);
|
||||
}
|
||||
|
||||
let mut features2 = builder.build();
|
||||
unsafe {
|
||||
|
@ -1215,13 +1183,6 @@ impl super::Adapter {
|
|||
capabilities.push(spv::Capability::MultiView);
|
||||
}
|
||||
|
||||
if features.intersects(
|
||||
wgt::Features::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING
|
||||
| wgt::Features::UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING,
|
||||
) {
|
||||
capabilities.push(spv::Capability::ShaderNonUniform);
|
||||
}
|
||||
|
||||
let mut flags = spv::WriterFlags::empty();
|
||||
flags.set(
|
||||
spv::WriterFlags::DEBUG,
|
||||
|
@ -1254,11 +1215,7 @@ impl super::Adapter {
|
|||
} else {
|
||||
naga::proc::BoundsCheckPolicy::Restrict
|
||||
},
|
||||
// TODO: support bounds checks on binding arrays
|
||||
binding_array: naga::proc::BoundsCheckPolicy::Unchecked,
|
||||
},
|
||||
// We need to build this separately for each invocation, so just default it out here
|
||||
binding_map: BTreeMap::default(),
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -6,12 +6,7 @@ use inplace_it::inplace_or_alloc_from_iter;
|
|||
use parking_lot::Mutex;
|
||||
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
collections::{hash_map::Entry, BTreeMap},
|
||||
ffi::CString,
|
||||
num::NonZeroU32,
|
||||
ptr,
|
||||
sync::Arc,
|
||||
borrow::Cow, collections::hash_map::Entry, ffi::CString, num::NonZeroU32, ptr, sync::Arc,
|
||||
};
|
||||
|
||||
impl super::DeviceShared {
|
||||
|
@ -633,7 +628,6 @@ impl super::Device {
|
|||
&self,
|
||||
stage: &crate::ProgrammableStage<super::Api>,
|
||||
naga_stage: naga::ShaderStage,
|
||||
binding_map: &naga::back::spv::BindingMap,
|
||||
) -> Result<CompiledStage, crate::PipelineError> {
|
||||
let stage_flags = crate::auxil::map_naga_stage(naga_stage);
|
||||
let vk_module = match *stage.module {
|
||||
|
@ -646,21 +640,16 @@ 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 mut temp_options;
|
||||
let options = if needs_temp_options {
|
||||
temp_options = self.naga_options.clone();
|
||||
if !runtime_checks {
|
||||
temp_options.bounds_check_policies = naga::proc::BoundsCheckPolicies {
|
||||
let temp_options;
|
||||
let options = if !runtime_checks {
|
||||
temp_options = naga::back::spv::Options {
|
||||
bounds_check_policies: naga::proc::BoundsCheckPolicies {
|
||||
index: naga::proc::BoundsCheckPolicy::Unchecked,
|
||||
buffer: naga::proc::BoundsCheckPolicy::Unchecked,
|
||||
image: naga::proc::BoundsCheckPolicy::Unchecked,
|
||||
binding_array: naga::proc::BoundsCheckPolicy::Unchecked,
|
||||
};
|
||||
}
|
||||
if !binding_map.is_empty() {
|
||||
temp_options.binding_map = binding_map.clone();
|
||||
}
|
||||
},
|
||||
..self.naga_options.clone()
|
||||
};
|
||||
&temp_options
|
||||
} else {
|
||||
&self.naga_options
|
||||
|
@ -1111,13 +1100,6 @@ impl crate::Device<super::Api> for super::Device {
|
|||
|
||||
let vk_info = vk::DescriptorSetLayoutCreateInfo::builder().bindings(&vk_bindings);
|
||||
|
||||
let binding_arrays = desc
|
||||
.entries
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(idx, entry)| entry.count.map(|count| (idx as u32, count)))
|
||||
.collect();
|
||||
|
||||
let mut binding_flag_info;
|
||||
let binding_flag_vec;
|
||||
let mut requires_update_after_bind = false;
|
||||
|
@ -1194,7 +1176,6 @@ impl crate::Device<super::Api> for super::Device {
|
|||
raw,
|
||||
desc_count,
|
||||
types: types.into_boxed_slice(),
|
||||
binding_arrays,
|
||||
requires_update_after_bind,
|
||||
})
|
||||
}
|
||||
|
@ -1239,25 +1220,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||
.set_object_name(vk::ObjectType::PIPELINE_LAYOUT, raw, label);
|
||||
}
|
||||
|
||||
let mut binding_arrays = BTreeMap::new();
|
||||
for (group, &layout) in desc.bind_group_layouts.iter().enumerate() {
|
||||
for &(binding, binding_array_size) in &layout.binding_arrays {
|
||||
binding_arrays.insert(
|
||||
naga::ResourceBinding {
|
||||
group: group as u32,
|
||||
binding,
|
||||
},
|
||||
naga::back::spv::BindingInfo {
|
||||
binding_array_size: Some(binding_array_size.get()),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(super::PipelineLayout {
|
||||
raw,
|
||||
binding_arrays,
|
||||
})
|
||||
Ok(super::PipelineLayout { raw })
|
||||
}
|
||||
unsafe fn destroy_pipeline_layout(&self, pipeline_layout: super::PipelineLayout) {
|
||||
self.shared
|
||||
|
@ -1303,15 +1266,11 @@ impl crate::Device<super::Api> for super::Device {
|
|||
write = match ty {
|
||||
vk::DescriptorType::SAMPLER => {
|
||||
let index = sampler_infos.len();
|
||||
let start = entry.resource_index;
|
||||
let end = start + entry.count;
|
||||
sampler_infos.extend(desc.samplers[start as usize..end as usize].iter().map(
|
||||
|binding| {
|
||||
vk::DescriptorImageInfo::builder()
|
||||
.sampler(binding.raw)
|
||||
.build()
|
||||
},
|
||||
));
|
||||
let binding = desc.samplers[entry.resource_index as usize];
|
||||
let vk_info = vk::DescriptorImageInfo::builder()
|
||||
.sampler(binding.raw)
|
||||
.build();
|
||||
sampler_infos.push(vk_info);
|
||||
write.image_info(&sampler_infos[index..])
|
||||
}
|
||||
vk::DescriptorType::SAMPLED_IMAGE | vk::DescriptorType::STORAGE_IMAGE => {
|
||||
|
@ -1385,7 +1344,6 @@ impl crate::Device<super::Api> for super::Device {
|
|||
index: naga::proc::BoundsCheckPolicy::Unchecked,
|
||||
buffer: naga::proc::BoundsCheckPolicy::Unchecked,
|
||||
image: naga::proc::BoundsCheckPolicy::Unchecked,
|
||||
binding_array: naga::proc::BoundsCheckPolicy::Unchecked,
|
||||
};
|
||||
}
|
||||
Cow::Owned(
|
||||
|
@ -1467,19 +1425,11 @@ impl crate::Device<super::Api> for super::Device {
|
|||
.primitive_restart_enable(desc.primitive.strip_index_format.is_some())
|
||||
.build();
|
||||
|
||||
let compiled_vs = self.compile_stage(
|
||||
&desc.vertex_stage,
|
||||
naga::ShaderStage::Vertex,
|
||||
&desc.layout.binding_arrays,
|
||||
)?;
|
||||
let compiled_vs = self.compile_stage(&desc.vertex_stage, naga::ShaderStage::Vertex)?;
|
||||
stages.push(compiled_vs.create_info);
|
||||
let compiled_fs = match desc.fragment_stage {
|
||||
Some(ref stage) => {
|
||||
let compiled = self.compile_stage(
|
||||
stage,
|
||||
naga::ShaderStage::Fragment,
|
||||
&desc.layout.binding_arrays,
|
||||
)?;
|
||||
let compiled = self.compile_stage(stage, naga::ShaderStage::Fragment)?;
|
||||
stages.push(compiled.create_info);
|
||||
Some(compiled)
|
||||
}
|
||||
|
@ -1654,11 +1604,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||
&self,
|
||||
desc: &crate::ComputePipelineDescriptor<super::Api>,
|
||||
) -> Result<super::ComputePipeline, crate::PipelineError> {
|
||||
let compiled = self.compile_stage(
|
||||
&desc.stage,
|
||||
naga::ShaderStage::Compute,
|
||||
&desc.layout.binding_arrays,
|
||||
)?;
|
||||
let compiled = self.compile_stage(&desc.stage, naga::ShaderStage::Compute)?;
|
||||
|
||||
let vk_infos = [{
|
||||
vk::ComputePipelineCreateInfo::builder()
|
||||
|
@ -1777,7 +1723,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||
wait_value: crate::FenceValue,
|
||||
timeout_ms: u32,
|
||||
) -> Result<bool, crate::DeviceError> {
|
||||
let timeout_ns = timeout_ms as u64 * super::MILLIS_TO_NANOS;
|
||||
let timeout_us = timeout_ms as u64 * super::MILLIS_TO_NANOS;
|
||||
match *fence {
|
||||
super::Fence::TimelineSemaphore(raw) => {
|
||||
let semaphores = [raw];
|
||||
|
@ -1787,10 +1733,10 @@ impl crate::Device<super::Api> for super::Device {
|
|||
.values(&values);
|
||||
let result = match self.shared.extension_fns.timeline_semaphore {
|
||||
Some(super::ExtensionFn::Extension(ref ext)) => {
|
||||
ext.wait_semaphores(&vk_info, timeout_ns)
|
||||
ext.wait_semaphores(&vk_info, timeout_us)
|
||||
}
|
||||
Some(super::ExtensionFn::Promoted) => {
|
||||
self.shared.raw.wait_semaphores(&vk_info, timeout_ns)
|
||||
self.shared.raw.wait_semaphores(&vk_info, timeout_us)
|
||||
}
|
||||
None => unreachable!(),
|
||||
};
|
||||
|
@ -1810,7 +1756,7 @@ impl crate::Device<super::Api> for super::Device {
|
|||
} else {
|
||||
match active.iter().find(|&&(value, _)| value >= wait_value) {
|
||||
Some(&(_, raw)) => {
|
||||
match self.shared.raw.wait_for_fences(&[raw], true, timeout_ns) {
|
||||
match self.shared.raw.wait_for_fences(&[raw], true, timeout_us) {
|
||||
Ok(()) => Ok(true),
|
||||
Err(vk::Result::TIMEOUT) => Ok(false),
|
||||
Err(other) => Err(other.into()),
|
||||
|
|
|
@ -398,15 +398,12 @@ pub struct BindGroupLayout {
|
|||
raw: vk::DescriptorSetLayout,
|
||||
desc_count: gpu_descriptor::DescriptorTotalCount,
|
||||
types: Box<[(vk::DescriptorType, u32)]>,
|
||||
/// Map of binding index to size,
|
||||
binding_arrays: Vec<(u32, NonZeroU32)>,
|
||||
requires_update_after_bind: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PipelineLayout {
|
||||
raw: vk::PipelineLayout,
|
||||
binding_arrays: naga::back::spv::BindingMap,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"742abe387ad0a6b054a3e525040ff1e64f16072ae7cd305db0616beaa844e389","src/lib.rs":"f1262748d81d80812fadec75241a6128842db02dced79c5e6db54586f9b35002"},"package":null}
|
||||
{"files":{"Cargo.toml":"742abe387ad0a6b054a3e525040ff1e64f16072ae7cd305db0616beaa844e389","src/lib.rs":"291e4f8cf6b42c2d00484fa4b71454e543695eae03a999e28a96c5e4a49ff828"},"package":null}
|
|
@ -66,9 +66,6 @@ pub enum Backend {
|
|||
}
|
||||
|
||||
/// Power Preference when choosing a physical adapter.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUPowerPreference`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gpupowerpreference).
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -128,9 +125,6 @@ impl From<Backend> for Backends {
|
|||
}
|
||||
|
||||
/// Options for requesting adapter.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPURequestAdapterOptions`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpurequestadapteroptions).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -167,9 +161,6 @@ bitflags::bitflags! {
|
|||
/// If you want to use a feature, you need to first verify that the adapter supports
|
||||
/// the feature. If the adapter does not support the feature, requesting a device with it enabled
|
||||
/// will panic.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUFeatureName`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gpufeaturename).
|
||||
#[repr(transparent)]
|
||||
#[derive(Default)]
|
||||
pub struct Features: u64 {
|
||||
|
@ -241,16 +232,6 @@ bitflags::bitflags! {
|
|||
///
|
||||
/// This is a web and native feature.
|
||||
const PIPELINE_STATISTICS_QUERY = 1 << 4;
|
||||
/// Allows shaders to acquire the FP16 ability
|
||||
///
|
||||
/// Note: this is not supported in naga yet,only through spir-v passthrough right now.
|
||||
///
|
||||
/// Supported Platforms:
|
||||
/// - Vulkan
|
||||
/// - Metal
|
||||
///
|
||||
/// This is a web and native feature.
|
||||
const SHADER_FLOAT16 = 1 << 5;
|
||||
/// Webgpu only allows the MAP_READ and MAP_WRITE buffer usage to be matched with
|
||||
/// COPY_DST and COPY_SRC respectively. This removes this requirement.
|
||||
///
|
||||
|
@ -367,6 +348,16 @@ bitflags::bitflags! {
|
|||
///
|
||||
/// This is a native only feature.
|
||||
const PARTIALLY_BOUND_BINDING_ARRAY = 1 << 22;
|
||||
/// Allows the user to create unsized uniform arrays of bindings:
|
||||
///
|
||||
/// eg. `uniform texture2D textures[]`.
|
||||
///
|
||||
/// Supported platforms:
|
||||
/// - DX12
|
||||
/// - Vulkan 1.2+ (or VK_EXT_descriptor_indexing)'s runtimeDescriptorArray feature
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const UNSIZED_BINDING_ARRAY = 1 << 23;
|
||||
/// Allows the user to call [`RenderPass::multi_draw_indirect`] and [`RenderPass::multi_draw_indexed_indirect`].
|
||||
///
|
||||
/// Allows multiple indirect calls to be dispatched from a single buffer.
|
||||
|
@ -376,7 +367,7 @@ bitflags::bitflags! {
|
|||
/// - Vulkan
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const MULTI_DRAW_INDIRECT = 1 << 23;
|
||||
const MULTI_DRAW_INDIRECT = 1 << 24;
|
||||
/// Allows the user to call [`RenderPass::multi_draw_indirect_count`] and [`RenderPass::multi_draw_indexed_indirect_count`].
|
||||
///
|
||||
/// This allows the use of a buffer containing the actual number of draw calls.
|
||||
|
@ -386,7 +377,7 @@ bitflags::bitflags! {
|
|||
/// - Vulkan 1.2+ (or VK_KHR_draw_indirect_count)
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const MULTI_DRAW_INDIRECT_COUNT = 1 << 24;
|
||||
const MULTI_DRAW_INDIRECT_COUNT = 1 << 25;
|
||||
/// Allows the use of push constants: small, fast bits of memory that can be updated
|
||||
/// inside a [`RenderPass`].
|
||||
///
|
||||
|
@ -403,7 +394,7 @@ bitflags::bitflags! {
|
|||
/// - OpenGL (emulated with uniforms)
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const PUSH_CONSTANTS = 1 << 25;
|
||||
const PUSH_CONSTANTS = 1 << 26;
|
||||
/// Allows the use of [`AddressMode::ClampToBorder`] with a border color
|
||||
/// other than [`SamplerBorderColor::Zero`].
|
||||
///
|
||||
|
@ -415,7 +406,7 @@ bitflags::bitflags! {
|
|||
/// - OpenGL
|
||||
///
|
||||
/// This is a web and native feature.
|
||||
const ADDRESS_MODE_CLAMP_TO_BORDER = 1 << 26;
|
||||
const ADDRESS_MODE_CLAMP_TO_BORDER = 1 << 27;
|
||||
/// Allows the user to set [`PolygonMode::Line`] in [`PrimitiveState::polygon_mode`]
|
||||
///
|
||||
/// This allows drawing polygons/triangles as lines (wireframe) instead of filled
|
||||
|
@ -426,7 +417,7 @@ bitflags::bitflags! {
|
|||
/// - Metal
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const POLYGON_MODE_LINE = 1 << 27;
|
||||
const POLYGON_MODE_LINE = 1 << 28;
|
||||
/// Allows the user to set [`PolygonMode::Point`] in [`PrimitiveState::polygon_mode`]
|
||||
///
|
||||
/// This allows only drawing the vertices of polygons/triangles instead of filled
|
||||
|
@ -436,7 +427,7 @@ bitflags::bitflags! {
|
|||
/// - Vulkan
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const POLYGON_MODE_POINT = 1 << 28;
|
||||
const POLYGON_MODE_POINT = 1 << 29;
|
||||
/// Enables ETC family of compressed textures. All ETC textures use 4x4 pixel blocks.
|
||||
/// ETC2 RGB and RGBA1 are 8 bytes per block. RTC2 RGBA8 and EAC are 16 bytes per block.
|
||||
///
|
||||
|
@ -451,7 +442,7 @@ bitflags::bitflags! {
|
|||
/// - Mobile (some)
|
||||
///
|
||||
/// This is a native-only feature.
|
||||
const TEXTURE_COMPRESSION_ETC2 = 1 << 29;
|
||||
const TEXTURE_COMPRESSION_ETC2 = 1 << 30;
|
||||
/// Enables ASTC family of compressed textures. ASTC textures use pixel blocks varying from 4x4 to 12x12.
|
||||
/// Blocks are always 16 bytes.
|
||||
///
|
||||
|
@ -466,7 +457,7 @@ bitflags::bitflags! {
|
|||
/// - Mobile (some)
|
||||
///
|
||||
/// This is a native-only feature.
|
||||
const TEXTURE_COMPRESSION_ASTC_LDR = 1 << 30;
|
||||
const TEXTURE_COMPRESSION_ASTC_LDR = 1 << 31;
|
||||
/// Enables device specific texture format features.
|
||||
///
|
||||
/// See `TextureFormatFeatures` for a listing of the features in question.
|
||||
|
@ -478,7 +469,7 @@ bitflags::bitflags! {
|
|||
/// This extension does not enable additional formats.
|
||||
///
|
||||
/// This is a native-only feature.
|
||||
const TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES = 1 << 31;
|
||||
const TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES = 1 << 32;
|
||||
/// Enables 64-bit floating point types in SPIR-V shaders.
|
||||
///
|
||||
/// Note: even when supported by GPU hardware, 64-bit floating point operations are
|
||||
|
@ -488,7 +479,7 @@ bitflags::bitflags! {
|
|||
/// - Vulkan
|
||||
///
|
||||
/// This is a native-only feature.
|
||||
const SHADER_FLOAT64 = 1 << 32;
|
||||
const SHADER_FLOAT64 = 1 << 33;
|
||||
/// Enables using 64-bit types for vertex attributes.
|
||||
///
|
||||
/// Requires SHADER_FLOAT64.
|
||||
|
@ -496,7 +487,7 @@ bitflags::bitflags! {
|
|||
/// Supported Platforms: N/A
|
||||
///
|
||||
/// This is a native-only feature.
|
||||
const VERTEX_ATTRIBUTE_64BIT = 1 << 33;
|
||||
const VERTEX_ATTRIBUTE_64BIT = 1 << 34;
|
||||
/// Allows the user to set a overestimation-conservative-rasterization in [`PrimitiveState::conservative`]
|
||||
///
|
||||
/// Processing of degenerate triangles/lines is hardware specific.
|
||||
|
@ -506,7 +497,7 @@ bitflags::bitflags! {
|
|||
/// - Vulkan
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const CONSERVATIVE_RASTERIZATION = 1 << 34;
|
||||
const CONSERVATIVE_RASTERIZATION = 1 << 35;
|
||||
/// Enables bindings of writable storage buffers and textures visible to vertex shaders.
|
||||
///
|
||||
/// Note: some (tiled-based) platforms do not support vertex shaders with any side-effects.
|
||||
|
@ -515,14 +506,14 @@ bitflags::bitflags! {
|
|||
/// - All
|
||||
///
|
||||
/// This is a native-only feature.
|
||||
const VERTEX_WRITABLE_STORAGE = 1 << 35;
|
||||
const VERTEX_WRITABLE_STORAGE = 1 << 36;
|
||||
/// Enables clear to zero for textures.
|
||||
///
|
||||
/// Supported platforms:
|
||||
/// - All
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const CLEAR_TEXTURE = 1 << 36;
|
||||
const CLEAR_TEXTURE = 1 << 37;
|
||||
/// Enables creating shader modules from SPIR-V binary data (unsafe).
|
||||
///
|
||||
/// SPIR-V data is not parsed or interpreted in any way; you can use
|
||||
|
@ -534,7 +525,7 @@ bitflags::bitflags! {
|
|||
/// Vulkan implementation.
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const SPIRV_SHADER_PASSTHROUGH = 1 << 37;
|
||||
const SPIRV_SHADER_PASSTHROUGH = 1 << 38;
|
||||
/// Enables `builtin(primitive_index)` in fragment shaders.
|
||||
///
|
||||
/// Note: enables geometry processing for pipelines using the builtin.
|
||||
|
@ -545,14 +536,14 @@ bitflags::bitflags! {
|
|||
/// - Vulkan
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const SHADER_PRIMITIVE_INDEX = 1 << 38;
|
||||
const SHADER_PRIMITIVE_INDEX = 1 << 39;
|
||||
/// Enables multiview render passes and `builtin(view_index)` in vertex shaders.
|
||||
///
|
||||
/// Supported platforms:
|
||||
/// - Vulkan
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const MULTIVIEW = 1 << 39;
|
||||
const MULTIVIEW = 1 << 40;
|
||||
/// Enables normalized `16-bit` texture formats.
|
||||
///
|
||||
/// Supported platforms:
|
||||
|
@ -561,7 +552,7 @@ bitflags::bitflags! {
|
|||
/// - Metal
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const TEXTURE_FORMAT_16BIT_NORM = 1 << 40;
|
||||
const TEXTURE_FORMAT_16BIT_NORM = 1 << 41;
|
||||
/// Allows the use of [`AddressMode::ClampToBorder`] with a border color
|
||||
/// of [`SamplerBorderColor::Zero`].
|
||||
///
|
||||
|
@ -573,12 +564,12 @@ bitflags::bitflags! {
|
|||
/// - OpenGL
|
||||
///
|
||||
/// This is a native only feature.
|
||||
const ADDRESS_MODE_CLAMP_TO_ZERO = 1 << 41;
|
||||
const ADDRESS_MODE_CLAMP_TO_ZERO = 1 << 42;
|
||||
/// Supported Platforms:
|
||||
/// - Metal
|
||||
///
|
||||
/// This is a native-only feature.
|
||||
const TEXTURE_COMPRESSION_ASTC_HDR = 1 << 42;
|
||||
const TEXTURE_COMPRESSION_ASTC_HDR = 1 << 43;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -600,7 +591,7 @@ impl Features {
|
|||
/// Represents the sets of limits an adapter/device supports.
|
||||
///
|
||||
/// We provide three different defaults.
|
||||
/// - [`Limits::downlevel_defaults()`]. This is a set of limits that is guaranteed to work on almost
|
||||
/// - [`Limits::downlevel_defaults()`]. This is a set of limits that is guarenteed to work on almost
|
||||
/// all backends, including "downlevel" backends such as OpenGL and D3D11, other than WebGL. For
|
||||
/// most applications we recommend using these limits, assuming they are high enough for your
|
||||
/// application, and you do not intent to support WebGL.
|
||||
|
@ -625,8 +616,7 @@ impl Features {
|
|||
/// implementation needs to support more than is needed. You should ideally only request exactly
|
||||
/// what you need.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUSupportedLimits`](
|
||||
/// https://gpuweb.github.io/gpuweb/#gpusupportedlimits).
|
||||
/// See also: <https://gpuweb.github.io/gpuweb/#dictdef-gpulimits>
|
||||
///
|
||||
/// [`downlevel_defaults()`]: Limits::downlevel_defaults
|
||||
#[repr(C)]
|
||||
|
@ -1074,9 +1064,6 @@ pub struct AdapterInfo {
|
|||
}
|
||||
|
||||
/// Describes a [`Device`](../wgpu/struct.Device.html).
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUDeviceDescriptor`](
|
||||
/// https://gpuweb.github.io/gpuweb/#gpudevicedescriptor).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -1109,9 +1096,6 @@ bitflags::bitflags! {
|
|||
/// These can be combined so something that is visible from both vertex and fragment shaders can be defined as:
|
||||
///
|
||||
/// `ShaderStages::VERTEX | ShaderStages::FRAGMENT`
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUShaderStageFlags`](
|
||||
/// https://gpuweb.github.io/gpuweb/#typedefdef-gpushaderstageflags).
|
||||
#[repr(transparent)]
|
||||
pub struct ShaderStages: u32 {
|
||||
/// Binding is not visible from any shader stage.
|
||||
|
@ -1131,9 +1115,6 @@ bitflags::bitflags! {
|
|||
bitflags_serde_shim::impl_serde_for_bitflags!(ShaderStages);
|
||||
|
||||
/// Dimensions of a particular texture view.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUTextureViewDimension`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gputextureviewdimension).
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -1179,9 +1160,6 @@ impl TextureViewDimension {
|
|||
/// Alpha blend factor.
|
||||
///
|
||||
/// Alpha blending is very complicated: see the OpenGL or Vulkan spec for more information.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUBlendFactor`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gpublendfactor).
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -1219,9 +1197,6 @@ pub enum BlendFactor {
|
|||
/// Alpha blend operation.
|
||||
///
|
||||
/// Alpha blending is very complicated: see the OpenGL or Vulkan spec for more information.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUBlendOperation`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gpublendoperation).
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -1246,10 +1221,7 @@ impl Default for BlendOperation {
|
|||
}
|
||||
}
|
||||
|
||||
/// Describes a blend component of a [`BlendState`].
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUBlendComponent`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpublendcomponent).
|
||||
/// Describes the blend component of a pipeline.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -1299,13 +1271,9 @@ impl Default for BlendComponent {
|
|||
}
|
||||
}
|
||||
|
||||
/// Describe the blend state of a render pipeline,
|
||||
/// within [`ColorTargetState`].
|
||||
/// Describe the blend state of a render pipeline.
|
||||
///
|
||||
/// See the OpenGL or Vulkan spec for more information.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUBlendState`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpublendstate).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -1343,9 +1311,6 @@ impl BlendState {
|
|||
}
|
||||
|
||||
/// Describes the color state of a render pipeline.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUColorTargetState`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpucolortargetstate).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -1376,9 +1341,6 @@ impl From<TextureFormat> for ColorTargetState {
|
|||
}
|
||||
|
||||
/// Primitive type the input mesh is composed of.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUPrimitiveTopology`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gpuprimitivetopology).
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -1421,10 +1383,7 @@ impl PrimitiveTopology {
|
|||
}
|
||||
}
|
||||
|
||||
/// Vertex winding order which classifies the "front" face of a triangle.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUFrontFace`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gpufrontface).
|
||||
/// Winding order which classifies the "front" face.
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -1448,10 +1407,6 @@ impl Default for FrontFace {
|
|||
}
|
||||
|
||||
/// Face of a vertex.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUCullMode`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gpucullmode),
|
||||
/// except that the `"none"` value is represented using `Option<Face>` instead.
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -1486,9 +1441,6 @@ impl Default for PolygonMode {
|
|||
}
|
||||
|
||||
/// Describes the state of primitive assembly and rasterization in a render pipeline.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUPrimitiveState`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpuprimitivestate).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -1527,9 +1479,6 @@ pub struct PrimitiveState {
|
|||
}
|
||||
|
||||
/// Describes the multi-sampling state of a render pipeline.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUMultisampleState`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpumultisamplestate).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -1678,11 +1627,8 @@ pub enum AstcChannel {
|
|||
|
||||
/// Underlying texture data format.
|
||||
///
|
||||
/// If there is a conversion in the format (such as srgb -> linear), the conversion listed here is for
|
||||
/// If there is a conversion in the format (such as srgb -> linear), The conversion listed is for
|
||||
/// loading from texture in a shader. When writing to the texture, the opposite conversion takes place.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUTextureFormat`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gputextureformat).
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
||||
|
@ -2230,9 +2176,6 @@ impl TextureFormat {
|
|||
|
||||
bitflags::bitflags! {
|
||||
/// Color write mask. Disabled color channels will not be written to.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUColorWriteFlags`](
|
||||
/// https://gpuweb.github.io/gpuweb/#typedefdef-gpucolorwriteflags).
|
||||
#[repr(transparent)]
|
||||
pub struct ColorWrites: u32 {
|
||||
/// Enable red channel writes
|
||||
|
@ -2260,11 +2203,6 @@ impl Default for ColorWrites {
|
|||
}
|
||||
|
||||
/// State of the stencil operation (fixed-pipeline stage).
|
||||
///
|
||||
/// For use in [`DepthStencilState`].
|
||||
///
|
||||
/// Corresponds to a portion of [WebGPU `GPUDepthStencilState`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpudepthstencilstate).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -2297,11 +2235,6 @@ impl StencilState {
|
|||
}
|
||||
|
||||
/// Describes the biasing setting for the depth target.
|
||||
///
|
||||
/// For use in [`DepthStencilState`].
|
||||
///
|
||||
/// Corresponds to a portion of [WebGPU `GPUDepthStencilState`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpudepthstencilstate).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -2323,9 +2256,6 @@ impl DepthBiasState {
|
|||
}
|
||||
|
||||
/// Describes the depth/stencil state in a render pipeline.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUDepthStencilState`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpudepthstencilstate).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -2360,9 +2290,6 @@ impl DepthStencilState {
|
|||
}
|
||||
|
||||
/// Format of indices used with pipeline.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUIndexFormat`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gpuindexformat).
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
||||
|
@ -2381,9 +2308,6 @@ impl Default for IndexFormat {
|
|||
}
|
||||
|
||||
/// Operation to perform on the stencil value.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUStencilOperation`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gpustenciloperation).
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -2420,9 +2344,6 @@ impl Default for StencilOperation {
|
|||
/// Describes stencil state in a render pipeline.
|
||||
///
|
||||
/// If you are not using stencil state, set this to [`StencilFaceState::IGNORE`].
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUStencilFaceState`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpustencilfacestate).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -2464,9 +2385,6 @@ impl Default for StencilFaceState {
|
|||
}
|
||||
|
||||
/// Comparison function used for depth and stencil operations.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUCompareFunction`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gpucomparefunction).
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -2502,9 +2420,6 @@ impl CompareFunction {
|
|||
}
|
||||
|
||||
/// Rate that determines when vertex data is advanced.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUVertexStepMode`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gpuvertexstepmode).
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -2528,9 +2443,6 @@ impl Default for VertexStepMode {
|
|||
/// Arrays of these can be made with the [`vertex_attr_array`]
|
||||
/// macro. Vertex attributes are assumed to be tightly packed.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUVertexAttribute`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpuvertexattribute).
|
||||
///
|
||||
/// [`vertex_attr_array`]: ../wgpu/macro.vertex_attr_array.html
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
|
@ -2546,10 +2458,7 @@ pub struct VertexAttribute {
|
|||
pub shader_location: ShaderLocation,
|
||||
}
|
||||
|
||||
/// Vertex Format for a [`VertexAttribute`] (input).
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUVertexFormat`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gpuvertexformat).
|
||||
/// Vertex Format for a Vertex Attribute (input).
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -2665,9 +2574,6 @@ bitflags::bitflags! {
|
|||
///
|
||||
/// The usages determine what kind of memory the buffer is allocated from and what
|
||||
/// actions the buffer can partake in.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUBufferUsageFlags`](
|
||||
/// https://gpuweb.github.io/gpuweb/#typedefdef-gpubufferusageflags).
|
||||
#[repr(transparent)]
|
||||
pub struct BufferUsages: u32 {
|
||||
/// Allow a buffer to be mapped for reading using [`Buffer::map_async`] + [`Buffer::get_mapped_range`].
|
||||
|
@ -2705,9 +2611,6 @@ bitflags::bitflags! {
|
|||
bitflags_serde_shim::impl_serde_for_bitflags!(BufferUsages);
|
||||
|
||||
/// Describes a [`Buffer`](../wgpu/struct.Buffer.html).
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUBufferDescriptor`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpubufferdescriptor).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -2738,9 +2641,6 @@ impl<L> BufferDescriptor<L> {
|
|||
}
|
||||
|
||||
/// Describes a [`CommandEncoder`](../wgpu/struct.CommandEncoder.html).
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUCommandEncoderDescriptor`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpucommandencoderdescriptor).
|
||||
#[repr(C)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
|
@ -2792,9 +2692,6 @@ bitflags::bitflags! {
|
|||
///
|
||||
/// The usages determine what kind of memory the texture is allocated from and what
|
||||
/// actions the texture can partake in.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUTextureUsageFlags`](
|
||||
/// https://gpuweb.github.io/gpuweb/#typedefdef-gputextureusageflags).
|
||||
#[repr(transparent)]
|
||||
pub struct TextureUsages: u32 {
|
||||
/// Allows a texture to be the source in a [`CommandEncoder::copy_texture_to_buffer`] or
|
||||
|
@ -2913,9 +2810,6 @@ impl Color {
|
|||
}
|
||||
|
||||
/// Dimensionality of a texture.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUTextureDimension`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gputexturedimension).
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -2933,9 +2827,6 @@ pub enum TextureDimension {
|
|||
}
|
||||
|
||||
/// Origin of a copy to/from a texture.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUOrigin3D`](
|
||||
/// https://gpuweb.github.io/gpuweb/#typedefdef-gpuorigin3d).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -2962,9 +2853,6 @@ impl Default for Origin3d {
|
|||
}
|
||||
|
||||
/// Extent of a texture related operation.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUExtent3D`](
|
||||
/// https://gpuweb.github.io/gpuweb/#typedefdef-gpuextent3d).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -2996,13 +2884,12 @@ impl Default for Extent3d {
|
|||
}
|
||||
|
||||
impl Extent3d {
|
||||
/// Calculates the [physical size] backing a texture of the given
|
||||
/// format and extent. This includes padding to the block width
|
||||
/// and height of the format.
|
||||
/// Calculates the [physical size] is backing an texture of the given format and extent.
|
||||
/// This includes padding to the block width and height of the format.
|
||||
///
|
||||
/// This is the texture extent that you must upload at when uploading to _mipmaps_ of compressed textures.
|
||||
///
|
||||
/// [physical size]: https://gpuweb.github.io/gpuweb/#physical-miplevel-specific-texture-extent
|
||||
/// [physical size]: https://gpuweb.github.io/gpuweb/#physical-size
|
||||
pub fn physical_size(&self, format: TextureFormat) -> Self {
|
||||
let (block_width, block_height) = format.describe().block_dimensions;
|
||||
let block_width = block_width as u32;
|
||||
|
@ -3152,9 +3039,6 @@ fn test_max_mips() {
|
|||
}
|
||||
|
||||
/// Describes a [`Texture`](../wgpu/struct.Texture.html).
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUTextureDescriptor`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gputexturedescriptor).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -3234,16 +3118,13 @@ impl<L> TextureDescriptor<L> {
|
|||
/// Returns the number of array layers.
|
||||
pub fn array_layer_count(&self) -> u32 {
|
||||
match self.dimension {
|
||||
TextureDimension::D1 | TextureDimension::D3 => 1,
|
||||
TextureDimension::D2 => self.size.depth_or_array_layers,
|
||||
TextureDimension::D1 | TextureDimension::D2 => self.size.depth_or_array_layers,
|
||||
TextureDimension::D3 => 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Kind of data the texture holds.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUTextureAspect`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gputextureaspect).
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -3265,9 +3146,6 @@ impl Default for TextureAspect {
|
|||
}
|
||||
|
||||
/// How edges should be handled in texture addressing.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUAddressMode`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gpuaddressmode).
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -3304,9 +3182,6 @@ impl Default for AddressMode {
|
|||
}
|
||||
|
||||
/// Texel mixing mode when sampling between texels.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUFilterMode`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gpufiltermode).
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -3343,9 +3218,6 @@ pub struct PushConstantRange {
|
|||
}
|
||||
|
||||
/// Describes a [`CommandBuffer`](../wgpu/struct.CommandBuffer.html).
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUCommandBufferDescriptor`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpucommandbufferdescriptor).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -3365,9 +3237,6 @@ impl<L> CommandBufferDescriptor<L> {
|
|||
}
|
||||
|
||||
/// Describes the depth/stencil attachment for render bundles.
|
||||
///
|
||||
/// Corresponds to a portion of [WebGPU `GPURenderBundleEncoderDescriptor`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpurenderbundleencoderdescriptor).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
|
||||
|
@ -3382,9 +3251,6 @@ pub struct RenderBundleDepthStencil {
|
|||
}
|
||||
|
||||
/// Describes a [`RenderBundle`](../wgpu/struct.RenderBundle.html).
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPURenderBundleDescriptor`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpurenderbundledescriptor).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -3419,9 +3285,6 @@ impl<T> Default for RenderBundleDescriptor<Option<T>> {
|
|||
/// | 32x16x8 | RGBA8 | 4 | 1 * 1 * 1 | 32 * 4 = 128 padded to 256 = Some(256) | None |
|
||||
/// | 256x256 | BC3 | 16 | 4 * 4 * 1 | 16 * (256 / 4) = 1024 = Some(1024) | None |
|
||||
/// | 64x64x8 | BC3 | 16 | 4 * 4 * 1 | 16 * (64 / 4) = 256 = Some(256) | 64 / 4 = 16 = Some(16) |
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUImageDataLayout`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpuimagedatalayout).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
|
||||
|
@ -3462,8 +3325,7 @@ pub struct ImageDataLayout {
|
|||
|
||||
/// Specific type of a buffer binding.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUBufferBindingType`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gpubufferbindingtype).
|
||||
/// WebGPU spec: <https://gpuweb.github.io/gpuweb/#enumdef-gpubufferbindingtype>
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
|
@ -3509,8 +3371,7 @@ impl Default for BufferBindingType {
|
|||
|
||||
/// Specific type of a sample in a texture binding.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUTextureSampleType`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gputexturesampletype).
|
||||
/// WebGPU spec: <https://gpuweb.github.io/gpuweb/#enumdef-gputexturesampletype>
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
|
@ -3561,10 +3422,7 @@ impl Default for TextureSampleType {
|
|||
|
||||
/// Specific type of a sample in a texture binding.
|
||||
///
|
||||
/// For use in [`BindingType::StorageTexture`].
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUStorageTextureAccess`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gpustoragetextureaccess).
|
||||
/// WebGPU spec: <https://gpuweb.github.io/gpuweb/#enumdef-gpustoragetextureaccess>
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
|
@ -3597,10 +3455,7 @@ pub enum StorageTextureAccess {
|
|||
|
||||
/// Specific type of a sampler binding.
|
||||
///
|
||||
/// For use in [`BindingType::Sampler`].
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUSamplerBindingType`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gpusamplerbindingtype).
|
||||
/// WebGPU spec: <https://gpuweb.github.io/gpuweb/#enumdef-gpusamplerbindingtype>
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
|
@ -3619,18 +3474,16 @@ pub enum SamplerBindingType {
|
|||
|
||||
/// Specific type of a binding.
|
||||
///
|
||||
/// For use in [`BindGroupLayoutEntry`].
|
||||
///
|
||||
/// Corresponds to WebGPU's mutually exclusive fields within [`GPUBindGroupLayoutEntry`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpubindgrouplayoutentry).
|
||||
/// WebGPU spec: the enum of
|
||||
/// - <https://gpuweb.github.io/gpuweb/#dictdef-gpubufferbindinglayout>
|
||||
/// - <https://gpuweb.github.io/gpuweb/#dictdef-gpusamplerbindinglayout>
|
||||
/// - <https://gpuweb.github.io/gpuweb/#dictdef-gputexturebindinglayout>
|
||||
/// - <https://gpuweb.github.io/gpuweb/#dictdef-gpustoragetexturebindinglayout>
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub enum BindingType {
|
||||
/// A buffer binding.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUBufferBindingLayout`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpubufferbindinglayout).
|
||||
Buffer {
|
||||
/// Sub-type of the buffer binding.
|
||||
ty: BufferBindingType,
|
||||
|
@ -3656,9 +3509,6 @@ pub enum BindingType {
|
|||
/// layout(binding = 0)
|
||||
/// uniform sampler s;
|
||||
/// ```
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUSamplerBindingLayout`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpusamplerbindinglayout).
|
||||
Sampler(SamplerBindingType),
|
||||
/// A texture binding.
|
||||
///
|
||||
|
@ -3667,9 +3517,6 @@ pub enum BindingType {
|
|||
/// layout(binding = 0)
|
||||
/// uniform texture2D t;
|
||||
/// ```
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUTextureBindingLayout`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gputexturebindinglayout).
|
||||
Texture {
|
||||
/// Sample type of the texture binding.
|
||||
sample_type: TextureSampleType,
|
||||
|
@ -3688,9 +3535,6 @@ pub enum BindingType {
|
|||
/// ```
|
||||
/// Note that the texture format must be specified in the shader as well.
|
||||
/// A list of valid formats can be found in the specification here: <https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.60.html#layout-qualifiers>
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUStorageTextureBindingLayout`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpustoragetexturebindinglayout).
|
||||
StorageTexture {
|
||||
/// Allowed access to this texture.
|
||||
access: StorageTextureAccess,
|
||||
|
@ -3714,9 +3558,6 @@ impl BindingType {
|
|||
}
|
||||
|
||||
/// Describes a single binding inside a bind group.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUBindGroupLayoutEntry`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpubindgrouplayoutentry).
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "trace", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
|
@ -3738,9 +3579,6 @@ pub struct BindGroupLayoutEntry {
|
|||
}
|
||||
|
||||
/// View of a buffer which can be used to copy to/from a texture.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUImageCopyBuffer`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpuimagecopybuffer).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
|
||||
|
@ -3753,9 +3591,6 @@ pub struct ImageCopyBuffer<B> {
|
|||
}
|
||||
|
||||
/// View of a texture which can be used to copy to/from a buffer/texture.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUImageCopyTexture`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpuimagecopytexture).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
|
||||
|
@ -3843,9 +3678,6 @@ pub enum SamplerBorderColor {
|
|||
}
|
||||
|
||||
/// Describes how to create a QuerySet.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUQuerySetDescriptor`](
|
||||
/// https://gpuweb.github.io/gpuweb/#dictdef-gpuquerysetdescriptor).
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
|
||||
|
@ -3871,9 +3703,6 @@ impl<L> QuerySetDescriptor<L> {
|
|||
}
|
||||
|
||||
/// Type of query contained in a QuerySet.
|
||||
///
|
||||
/// Corresponds to [WebGPU `GPUQueryType`](
|
||||
/// https://gpuweb.github.io/gpuweb/#enumdef-gpuquerytype).
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
|
||||
|
|
Загрузка…
Ссылка в новой задаче