mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-10-29 21:42:20 +00:00
Merge branch 'main' into nanoserde
This commit is contained in:
commit
c78d7db769
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@ -1,3 +1,3 @@
|
||||
* @eddyb
|
||||
* @eddyb @oisyn
|
||||
|
||||
/examples/ @fu5ha @VZout
|
||||
|
11
.github/workflows/ci.yaml
vendored
11
.github/workflows/ci.yaml
vendored
@ -22,7 +22,7 @@ jobs:
|
||||
target: aarch64-linux-android
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
spirv_tools_version: "20210805"
|
||||
spirv_tools_version: "20220414" # get platform-specific download link from https://github.com/KhronosGroup/SPIRV-Tools/blob/master/docs/downloads.md
|
||||
RUSTUP_UNPACK_RAM: "26214400"
|
||||
RUSTUP_IO_THREADS: "1"
|
||||
steps:
|
||||
@ -33,8 +33,8 @@ jobs:
|
||||
name: Linux - Install native dependencies
|
||||
run: |
|
||||
sudo apt install libwayland-cursor0 libxkbcommon-dev libwayland-dev
|
||||
mkdir "${HOME}/spirv-tools"
|
||||
curl -fL https://storage.googleapis.com/spirv-tools/artifacts/prod/graphics_shader_compiler/spirv-tools/linux-clang-release/continuous/1530/20210805-040049/install.tgz | tar -xz -C "${HOME}/spirv-tools"
|
||||
mkdir "${HOME}/spirv-tools"
|
||||
curl -fL https://storage.googleapis.com/spirv-tools/artifacts/prod/graphics_shader_compiler/spirv-tools/linux-clang-release/continuous/1744/20220414-060821/install.tgz | tar -xz -C "${HOME}/spirv-tools"
|
||||
echo "${HOME}/spirv-tools/install/bin" >> $GITHUB_PATH
|
||||
- if: ${{ runner.os == 'macOS' }}
|
||||
name: Mac - Install spirv-tools
|
||||
@ -47,7 +47,7 @@ jobs:
|
||||
run: |
|
||||
tmparch=$(mktemp)
|
||||
mkdir "${HOME}/spirv-tools"
|
||||
curl -fL -o "$tmparch" https://storage.googleapis.com/spirv-tools/artifacts/prod/graphics_shader_compiler/spirv-tools/windows-msvc-2017-release/continuous/1517/20210805-040116/install.zip
|
||||
curl -fL -o "$tmparch" https://storage.googleapis.com/spirv-tools/artifacts/prod/graphics_shader_compiler/spirv-tools/windows-msvc-2017-release/continuous/1732/20220414-060824/install.zip
|
||||
unzip "$tmparch" -d "${HOME}/spirv-tools"
|
||||
- if: ${{ runner.os == 'Windows' }}
|
||||
# Runs separately to add spir-v tools to Powershell's Path.
|
||||
@ -94,7 +94,8 @@ jobs:
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Install cargo-apk"
|
||||
cargo install cargo-apk
|
||||
echo "FIXME(eddyb) working around libc 0.2.127 breakage by using stable Rust!"
|
||||
cargo +stable install cargo-apk
|
||||
echo "::endgroup::"
|
||||
|
||||
echo "::group::Add aarch64-linux-android target"
|
||||
|
58
Cargo.lock
generated
58
Cargo.lock
generated
@ -343,7 +343,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "compiletests"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"compiletest_rs",
|
||||
"rustc_codegen_spirv",
|
||||
@ -352,14 +352,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "compiletests-deps-helper"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"spirv-std",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "compute-shader"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rayon",
|
||||
"spirv-std",
|
||||
@ -518,12 +518,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.5"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
|
||||
checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"lazy_static",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -725,7 +725,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "example-runner-ash"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"ash",
|
||||
"ash-molten",
|
||||
@ -740,7 +740,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "example-runner-cpu"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"minifb",
|
||||
"rayon",
|
||||
@ -750,7 +750,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "example-runner-wgpu"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"cfg-if 1.0.0",
|
||||
@ -771,7 +771,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "example-runner-wgpu-builder"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"spirv-builder",
|
||||
]
|
||||
@ -1348,7 +1348,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mouse-shader"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"shared",
|
||||
"spirv-std",
|
||||
@ -1356,7 +1356,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "multibuilder"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"spirv-builder",
|
||||
]
|
||||
@ -1947,7 +1947,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "reduce"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"spirv-std",
|
||||
]
|
||||
@ -2009,7 +2009,7 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_codegen_spirv"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.4.0-alpha.14"
|
||||
dependencies = [
|
||||
"ar",
|
||||
"bimap",
|
||||
@ -2032,7 +2032,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustc_codegen_spirv-types"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.4.0-alpha.14"
|
||||
dependencies = [
|
||||
"nanoserde",
|
||||
"rspirv",
|
||||
@ -2079,9 +2079,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sanitize-filename"
|
||||
version = "0.3.0"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf18934a12018228c5b55a6dae9df5d0641e3566b3630cb46cc55564068e7c2f"
|
||||
checksum = "08c502bdb638f1396509467cb0580ef3b29aa2a45c5d43e5d84928241280296c"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"regex",
|
||||
@ -2160,7 +2160,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "shared"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"spirv-std",
|
||||
@ -2174,7 +2174,7 @@ checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
|
||||
|
||||
[[package]]
|
||||
name = "simplest-shader"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"shared",
|
||||
"spirv-std",
|
||||
@ -2182,7 +2182,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sky-shader"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"shared",
|
||||
"spirv-std",
|
||||
@ -2240,7 +2240,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "spirv-builder"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.4.0-alpha.14"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"nanoserde",
|
||||
@ -2252,25 +2252,29 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "spirv-std"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.4.0-alpha.14"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"glam",
|
||||
"num-traits",
|
||||
"spirv-std-macros",
|
||||
"spirv-types",
|
||||
"spirv-std-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spirv-std-macros"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.4.0-alpha.14"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"spirv-types",
|
||||
"spirv-std-types",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spirv-std-types"
|
||||
version = "0.4.0-alpha.14"
|
||||
|
||||
[[package]]
|
||||
name = "spirv-tools"
|
||||
version = "0.8.0"
|
||||
@ -2291,10 +2295,6 @@ dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spirv-types"
|
||||
version = "0.4.0-alpha.12"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.8.0"
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "rustc_codegen_spirv-types"
|
||||
description = "SPIR-V backend types shared between rustc_codegen_spirv and spirv-builder"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.4.0-alpha.14"
|
||||
authors = ["Embark <opensource@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
@ -1,10 +1,11 @@
|
||||
[package]
|
||||
name = "rustc_codegen_spirv"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.4.0-alpha.14"
|
||||
authors = ["Embark <opensource@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/EmbarkStudios/rust-gpu"
|
||||
description = "SPIR-V code generator backend for rustc"
|
||||
#keywords = []
|
||||
#categories = []
|
||||
#readme = "README.md"
|
||||
@ -40,11 +41,11 @@ bimap = "0.6"
|
||||
indexmap = "1.6.0"
|
||||
rspirv = "0.11"
|
||||
rustc-demangle = "0.1.21"
|
||||
sanitize-filename = "0.3"
|
||||
sanitize-filename = "0.4"
|
||||
nanoserde = "0.1.9"
|
||||
smallvec = "1.6.1"
|
||||
spirv-tools = { version = "0.8", default-features = false }
|
||||
rustc_codegen_spirv-types = { path = "../rustc_codegen_spirv-types", version = "0.4.0-alpha.12" }
|
||||
rustc_codegen_spirv-types = { path = "../rustc_codegen_spirv-types", version = "0.4.0-alpha.14" }
|
||||
|
||||
[dev-dependencies]
|
||||
pipe = "0.4"
|
||||
|
@ -412,6 +412,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
if field_ty_kind
|
||||
.sizeof(self)
|
||||
.map_or(true, |size| offset_in_field < size)
|
||||
// If the field is a zero sized type, check the type to
|
||||
// get the correct entry
|
||||
|| offset_in_field == Size::ZERO && leaf_ty == field_ty
|
||||
{
|
||||
Some((i, field_ty, field_ty_kind, offset_in_field))
|
||||
} else {
|
||||
|
@ -35,8 +35,12 @@ pub fn inline(sess: &Session, module: &mut Module) -> super::Result<()> {
|
||||
// Drop all the functions we'll be inlining. (This also means we won't waste time processing
|
||||
// inlines in functions that will get inlined)
|
||||
let mut dropped_ids = FxHashSet::default();
|
||||
let mut inlined_dont_inlines = Vec::new();
|
||||
module.functions.retain(|f| {
|
||||
if should_inline(&disallowed_argument_types, &disallowed_return_types, f) {
|
||||
if has_dont_inline(f) {
|
||||
inlined_dont_inlines.push(f.def_id().unwrap());
|
||||
}
|
||||
// TODO: We should insert all defined IDs in this function.
|
||||
dropped_ids.insert(f.def_id().unwrap());
|
||||
false
|
||||
@ -44,6 +48,17 @@ pub fn inline(sess: &Session, module: &mut Module) -> super::Result<()> {
|
||||
true
|
||||
}
|
||||
});
|
||||
if !inlined_dont_inlines.is_empty() {
|
||||
let names = get_names(module);
|
||||
for f in inlined_dont_inlines {
|
||||
sess.warn(&format!(
|
||||
"`#[inline(never)]` function `{}` needs to be inlined \
|
||||
because it has illegal argument or return types",
|
||||
get_name(&names, f)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Drop OpName etc. for inlined functions
|
||||
module.debug_names.retain(|inst| {
|
||||
!inst.operands.iter().any(|op| {
|
||||
@ -204,6 +219,12 @@ fn compute_disallowed_argument_and_return_types(
|
||||
(disallowed_argument_types, disallowed_return_types)
|
||||
}
|
||||
|
||||
fn has_dont_inline(function: &Function) -> bool {
|
||||
let def = function.def.as_ref().unwrap();
|
||||
let control = def.operands[0].unwrap_function_control();
|
||||
control.contains(FunctionControl::DONT_INLINE)
|
||||
}
|
||||
|
||||
fn should_inline(
|
||||
disallowed_argument_types: &FxHashSet<Word>,
|
||||
disallowed_return_types: &FxHashSet<Word>,
|
||||
|
@ -651,7 +651,7 @@ fn parse_entry_attrs(
|
||||
.execution_modes
|
||||
.push((origin_mode, ExecutionModeExtra::new([])));
|
||||
}
|
||||
GLCompute => {
|
||||
GLCompute | MeshNV | TaskNV => {
|
||||
if let Some(local_size) = local_size {
|
||||
entry
|
||||
.execution_modes
|
||||
@ -660,7 +660,7 @@ fn parse_entry_attrs(
|
||||
return Err((
|
||||
arg.span(),
|
||||
String::from(
|
||||
"The `threads` argument must be specified when using `#[spirv(compute)]`",
|
||||
"The `threads` argument must be specified when using `#[spirv(compute)]`, `#[spirv(mesh_nv)]` or `#[spirv(task_nv)]`",
|
||||
),
|
||||
));
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
[package]
|
||||
name = "spirv-builder"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.4.0-alpha.14"
|
||||
authors = ["Embark <opensource@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/EmbarkStudios/rust-gpu"
|
||||
description = "Helper for building shaders with rust-gpu"
|
||||
|
||||
# See rustc_codegen_spirv/Cargo.toml for details on these features
|
||||
[features]
|
||||
@ -16,8 +18,8 @@ watch = ["notify"]
|
||||
memchr = "2.4"
|
||||
raw-string = "0.3.5"
|
||||
nanoserde = "0.1.9"
|
||||
rustc_codegen_spirv-types = { path = "../rustc_codegen_spirv-types" }
|
||||
rustc_codegen_spirv-types = { path = "../rustc_codegen_spirv-types", version = "0.4.0-alpha.14" }
|
||||
# See comment in lib.rs invoke_rustc for why this is here
|
||||
rustc_codegen_spirv = { path = "../rustc_codegen_spirv", default-features = false }
|
||||
rustc_codegen_spirv = { path = "../rustc_codegen_spirv", version = "0.4.0-alpha.14", default-features = false }
|
||||
|
||||
notify = { version = "5.0.0-pre.11", optional = true }
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "spirv-std"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.4.0-alpha.14"
|
||||
authors = ["Embark <opensource@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
@ -10,9 +10,9 @@ description = "Standard functions and types for SPIR-V"
|
||||
[dependencies]
|
||||
bitflags = "1.2.1"
|
||||
num-traits = { version = "0.2.14", default-features = false, features = ["libm"] }
|
||||
spirv-types = { path = "./shared", version = "0.4.0-alpha.12" }
|
||||
spirv-std-macros = { path = "./macros", version = "0.4.0-alpha.12" }
|
||||
glam = { version = ">=0.17, <=0.20", default-features = false, features = ["libm"], optional = true }
|
||||
spirv-std-types = { path = "./shared", version = "0.4.0-alpha.14" }
|
||||
spirv-std-macros = { path = "./macros", version = "0.4.0-alpha.13" }
|
||||
glam = { version = ">=0.17, <=0.21", default-features = false, features = ["libm"], optional = true }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "spirv-std-macros"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.4.0-alpha.14"
|
||||
authors = ["Embark <opensource@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
@ -11,7 +11,7 @@ description = "Macros for spirv-std"
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
spirv-types = { path = "../shared", version = "0.4.0-alpha.12" }
|
||||
spirv-std-types = { path = "../shared", version = "0.4.0-alpha.14" }
|
||||
proc-macro2 = "1.0.24"
|
||||
quote = "1.0.8"
|
||||
syn = { version = "1.0.58", features=["full"] }
|
||||
|
@ -1,7 +1,7 @@
|
||||
use proc_macro2::Ident;
|
||||
|
||||
use quote::{quote, TokenStreamExt};
|
||||
use spirv_types::image_params::*;
|
||||
use spirv_std_types::image_params::*;
|
||||
use syn::parse::{Parse, ParseStream};
|
||||
|
||||
use self::params::SampledType;
|
||||
|
@ -121,7 +121,7 @@ use quote::ToTokens;
|
||||
/// - `depth` — Whether it is known that the image is a depth image.
|
||||
/// Accepted values: `true` or `false`. Default: `unknown`.
|
||||
///
|
||||
/// [`ImageFormat`]: spirv_types::image_params::ImageFormat
|
||||
/// [`ImageFormat`]: spirv_std_types::image_params::ImageFormat
|
||||
///
|
||||
/// Keep in mind that `sampled` here is a different concept than the `SampledImage` type:
|
||||
/// `sampled=true` means that this image requires a sampler to be able to access, while the
|
||||
|
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "spirv-types"
|
||||
name = "spirv-std-types"
|
||||
description = "SPIR-V types shared between spirv-std and spirv-std-macros"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.4.0-alpha.14"
|
||||
authors = ["Embark <opensource@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
@ -11,12 +11,14 @@ use crate::{
|
||||
#[cfg(target_arch = "spirv")]
|
||||
use core::arch::asm;
|
||||
|
||||
mod atomics;
|
||||
mod barrier;
|
||||
mod demote_to_helper_invocation_ext;
|
||||
mod derivative;
|
||||
mod primitive;
|
||||
mod ray_tracing;
|
||||
|
||||
pub use atomics::*;
|
||||
pub use barrier::*;
|
||||
pub use demote_to_helper_invocation_ext::*;
|
||||
pub use derivative::*;
|
||||
@ -226,29 +228,6 @@ pub fn signed_max<T: SignedInteger>(a: T, b: T) -> T {
|
||||
unsafe { call_glsl_op_with_ints::<_, 42>(a, b) }
|
||||
}
|
||||
|
||||
/// Atomically increment an integer and return the old value.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpAtomicIIncrement")]
|
||||
pub unsafe fn atomic_i_increment<I: Integer, const SCOPE: u32, const SEMANTICS: u32>(
|
||||
ptr: &mut I,
|
||||
) -> I {
|
||||
let mut old = I::default();
|
||||
|
||||
asm! {
|
||||
"%u32 = OpTypeInt 32 0",
|
||||
"%scope = OpConstant %u32 {scope}",
|
||||
"%semantics = OpConstant %u32 {semantics}",
|
||||
"%old = OpAtomicIIncrement _ {ptr} %scope %semantics",
|
||||
"OpStore {old} %old",
|
||||
scope = const SCOPE,
|
||||
semantics = const SEMANTICS,
|
||||
ptr = in(reg) ptr,
|
||||
old = in(reg) &mut old,
|
||||
}
|
||||
|
||||
old
|
||||
}
|
||||
|
||||
/// Index into an array without bounds checking.
|
||||
///
|
||||
/// The main purpose of this trait is to work around the fact that the regular `get_unchecked*`
|
||||
|
611
crates/spirv-std/src/arch/atomics.rs
Normal file
611
crates/spirv-std/src/arch/atomics.rs
Normal file
@ -0,0 +1,611 @@
|
||||
#[cfg(target_arch = "spirv")]
|
||||
use core::arch::asm;
|
||||
|
||||
use crate::{
|
||||
float::Float,
|
||||
integer::{Integer, SignedInteger, UnsignedInteger},
|
||||
number::Number,
|
||||
};
|
||||
|
||||
/// Atomically load through `ptr` using the given `SEMANTICS`. All subparts of
|
||||
/// the value that is loaded are read atomically with respect to all other
|
||||
/// atomic accesses to it within `SCOPE`.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpAtomicLoad")]
|
||||
#[inline]
|
||||
pub unsafe fn atomic_load<N: Number, const SCOPE: u32, const SEMANTICS: u32>(ptr: &N) -> N {
|
||||
let mut result = N::default();
|
||||
|
||||
asm! {
|
||||
"%u32 = OpTypeInt 32 0",
|
||||
"%scope = OpConstant %u32 {scope}",
|
||||
"%semantics = OpConstant %u32 {semantics}",
|
||||
"%result = OpAtomicLoad _ {ptr} %scope %semantics",
|
||||
"OpStore {result} %result",
|
||||
scope = const SCOPE,
|
||||
semantics = const SEMANTICS,
|
||||
ptr = in(reg) ptr,
|
||||
result = in(reg) &mut result
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// Atomically store through `ptr` using the given `SEMANTICS`. All subparts of
|
||||
/// `value` are written atomically with respect to all other atomic accesses to
|
||||
/// it within `SCOPE`.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpAtomicStore")]
|
||||
#[inline]
|
||||
pub unsafe fn atomic_store<N: Number, const SCOPE: u32, const SEMANTICS: u32>(
|
||||
ptr: &mut N,
|
||||
value: N,
|
||||
) {
|
||||
asm! {
|
||||
"%u32 = OpTypeInt 32 0",
|
||||
"%scope = OpConstant %u32 {scope}",
|
||||
"%semantics = OpConstant %u32 {semantics}",
|
||||
"%value = OpLoad _ {value}",
|
||||
"OpAtomicStore {ptr} %scope %semantics %value",
|
||||
scope = const SCOPE,
|
||||
semantics = const SEMANTICS,
|
||||
ptr = in(reg) ptr,
|
||||
value = in(reg) &value
|
||||
}
|
||||
}
|
||||
|
||||
/// Perform the following steps atomically with respect to any other atomic
|
||||
/// accesses within `SCOPE` to the same location:
|
||||
///
|
||||
/// 1. Load through `ptr` to get the original value,
|
||||
/// 2. Get a new value from copying `value`, and
|
||||
/// 3. Store the new value back through `ptr`.
|
||||
///
|
||||
/// The result is the original value.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpAtomicExchange")]
|
||||
#[inline]
|
||||
pub unsafe fn atomic_exchange<N: Number, const SCOPE: u32, const SEMANTICS: u32>(
|
||||
ptr: &mut N,
|
||||
value: N,
|
||||
) -> N {
|
||||
let mut old = N::default();
|
||||
|
||||
asm! {
|
||||
"%u32 = OpTypeInt 32 0",
|
||||
"%scope = OpConstant %u32 {scope}",
|
||||
"%semantics = OpConstant %u32 {semantics}",
|
||||
"%value = OpLoad _ {value}",
|
||||
"%old = OpAtomicExchange _ {ptr} %scope %semantics %value",
|
||||
"OpStore {old} %old",
|
||||
scope = const SCOPE,
|
||||
semantics = const SEMANTICS,
|
||||
ptr = in(reg) ptr,
|
||||
old = in(reg) &mut old,
|
||||
value = in(reg) &value
|
||||
}
|
||||
|
||||
old
|
||||
}
|
||||
|
||||
/// Perform the following steps atomically with respect to any other atomic
|
||||
/// accesses within `SCOPE` to the same location:
|
||||
///
|
||||
/// 1. Load through `ptr` to get the original value
|
||||
/// 2. Get a new value from `value` only if the original value equals
|
||||
/// `comparator`, and
|
||||
/// 3. Store the new value back through `ptr`, only if the original value
|
||||
/// equaled `comparator`.
|
||||
///
|
||||
/// The result is the original value.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpAtomicCompareExchange")]
|
||||
#[inline]
|
||||
pub unsafe fn atomic_compare_exchange<
|
||||
I: Integer,
|
||||
const SCOPE: u32,
|
||||
const EQUAL: u32,
|
||||
const UNEQUAL: u32,
|
||||
>(
|
||||
ptr: &mut I,
|
||||
value: I,
|
||||
comparator: I,
|
||||
) -> I {
|
||||
let mut old = I::default();
|
||||
|
||||
asm! {
|
||||
"%u32 = OpTypeInt 32 0",
|
||||
"%scope = OpConstant %u32 {scope}",
|
||||
"%equal = OpConstant %u32 {equal}",
|
||||
"%unequal = OpConstant %u32 {unequal}",
|
||||
"%value = OpLoad _ {value}",
|
||||
"%comparator = OpLoad _ {comparator}",
|
||||
"%old = OpAtomicCompareExchange _ {ptr} %scope %equal %unequal %value %comparator",
|
||||
"OpStore {old} %old",
|
||||
scope = const SCOPE,
|
||||
equal = const EQUAL,
|
||||
unequal = const UNEQUAL,
|
||||
ptr = in(reg) ptr,
|
||||
value = in(reg) &value,
|
||||
comparator = in(reg) &comparator,
|
||||
old = in(reg) &mut old,
|
||||
}
|
||||
|
||||
old
|
||||
}
|
||||
|
||||
/// Perform the following steps atomically with respect to any other atomic
|
||||
/// accesses within `SCOPE` to the same location:
|
||||
///
|
||||
/// 1. Load through `ptr` to get an original value,
|
||||
/// 2. Get a new value through integer addition of 1 to original value, and
|
||||
/// 3. Store the new value back through `ptr`.
|
||||
///
|
||||
/// The result is the original value.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpAtomicIIncrement")]
|
||||
#[inline]
|
||||
pub unsafe fn atomic_i_increment<I: Integer, const SCOPE: u32, const SEMANTICS: u32>(
|
||||
ptr: &mut I,
|
||||
) -> I {
|
||||
let mut old = I::default();
|
||||
|
||||
asm! {
|
||||
"%u32 = OpTypeInt 32 0",
|
||||
"%scope = OpConstant %u32 {scope}",
|
||||
"%semantics = OpConstant %u32 {semantics}",
|
||||
"%old = OpAtomicIIncrement _ {ptr} %scope %semantics",
|
||||
"OpStore {old} %old",
|
||||
scope = const SCOPE,
|
||||
semantics = const SEMANTICS,
|
||||
ptr = in(reg) ptr,
|
||||
old = in(reg) &mut old
|
||||
}
|
||||
|
||||
old
|
||||
}
|
||||
|
||||
/// Perform the following steps atomically with respect to any other atomic
|
||||
/// accesses within `SCOPE` to the same location:
|
||||
///
|
||||
/// 1) load through `ptr` to get an original value,
|
||||
/// 2) get a new value through integer subtraction of 1 from original value, and
|
||||
/// 3) store the new value back through `ptr`.
|
||||
///
|
||||
/// The result is the original value.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpAtomicIDecrement")]
|
||||
#[inline]
|
||||
pub unsafe fn atomic_i_decrement<I: Integer, const SCOPE: u32, const SEMANTICS: u32>(
|
||||
ptr: &mut I,
|
||||
) -> I {
|
||||
let mut old = I::default();
|
||||
|
||||
asm! {
|
||||
"%u32 = OpTypeInt 32 0",
|
||||
"%scope = OpConstant %u32 {scope}",
|
||||
"%semantics = OpConstant %u32 {semantics}",
|
||||
"%old = OpAtomicIDecrement _ {ptr} %scope %semantics",
|
||||
"OpStore {old} %old",
|
||||
scope = const SCOPE,
|
||||
semantics = const SEMANTICS,
|
||||
ptr = in(reg) ptr,
|
||||
old = in(reg) &mut old
|
||||
}
|
||||
|
||||
old
|
||||
}
|
||||
|
||||
/// Perform the following steps atomically with respect to any other atomic
|
||||
/// accesses within `SCOPE` to the same location:
|
||||
///
|
||||
/// 1) load through `ptr` to get an original value,
|
||||
/// 2) get a new value by integer addition of original value and `value`, and
|
||||
/// 3) store the new value back through `ptr`.
|
||||
///
|
||||
/// The result is the Original Value.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpAtomicIAdd")]
|
||||
#[inline]
|
||||
pub unsafe fn atomic_i_add<I: Integer, const SCOPE: u32, const SEMANTICS: u32>(
|
||||
ptr: &mut I,
|
||||
value: I,
|
||||
) -> I {
|
||||
let mut old = I::default();
|
||||
|
||||
asm! {
|
||||
"%u32 = OpTypeInt 32 0",
|
||||
"%scope = OpConstant %u32 {scope}",
|
||||
"%semantics = OpConstant %u32 {semantics}",
|
||||
"%value = OpLoad _ {value}",
|
||||
"%old = OpAtomicIAdd _ {ptr} %scope %semantics %value",
|
||||
"OpStore {old} %old",
|
||||
scope = const SCOPE,
|
||||
semantics = const SEMANTICS,
|
||||
ptr = in(reg) ptr,
|
||||
old = in(reg) &mut old,
|
||||
value = in(reg) &value
|
||||
}
|
||||
|
||||
old
|
||||
}
|
||||
|
||||
/// Perform the following steps atomically with respect to any other atomic
|
||||
/// accesses within `SCOPE` to the same location:
|
||||
///
|
||||
/// 1) load through `ptr` to get an original value,
|
||||
/// 2) get a new value by integer subtraction of original value and `value`, and
|
||||
/// 3) store the new value back through `ptr`.
|
||||
///
|
||||
/// The result is the Original Value.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpAtomicISub")]
|
||||
#[inline]
|
||||
pub unsafe fn atomic_i_sub<I: Integer, const SCOPE: u32, const SEMANTICS: u32>(
|
||||
ptr: &mut I,
|
||||
value: I,
|
||||
) -> I {
|
||||
let mut old = I::default();
|
||||
|
||||
asm! {
|
||||
"%u32 = OpTypeInt 32 0",
|
||||
"%scope = OpConstant %u32 {scope}",
|
||||
"%semantics = OpConstant %u32 {semantics}",
|
||||
"%value = OpLoad _ {value}",
|
||||
"%old = OpAtomicISub _ {ptr} %scope %semantics %value",
|
||||
"OpStore {old} %old",
|
||||
scope = const SCOPE,
|
||||
semantics = const SEMANTICS,
|
||||
ptr = in(reg) ptr,
|
||||
old = in(reg) &mut old,
|
||||
value = in(reg) &value
|
||||
}
|
||||
|
||||
old
|
||||
}
|
||||
|
||||
/// Perform the following steps atomically with respect to any other atomic
|
||||
/// accesses within Scope to the same location:
|
||||
///
|
||||
/// 1. Load through `ptr` to get an original value,
|
||||
/// 2. Get a new value by finding the smallest signed integer of original value
|
||||
/// and `value`, and
|
||||
/// 3. Store the new value back through `ptr`.
|
||||
///
|
||||
/// The result is the original value.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpAtomicSMin")]
|
||||
#[inline]
|
||||
pub unsafe fn atomic_s_min<S: SignedInteger, const SCOPE: u32, const SEMANTICS: u32>(
|
||||
ptr: &mut S,
|
||||
value: S,
|
||||
) -> S {
|
||||
let mut old = S::default();
|
||||
|
||||
asm! {
|
||||
"%u32 = OpTypeInt 32 0",
|
||||
"%scope = OpConstant %u32 {scope}",
|
||||
"%semantics = OpConstant %u32 {semantics}",
|
||||
"%value = OpLoad _ {value}",
|
||||
"%old = OpAtomicSMin _ {ptr} %scope %semantics %value",
|
||||
"OpStore {old} %old",
|
||||
scope = const SCOPE,
|
||||
semantics = const SEMANTICS,
|
||||
ptr = in(reg) ptr,
|
||||
old = in(reg) &mut old,
|
||||
value = in(reg) &value
|
||||
}
|
||||
|
||||
old
|
||||
}
|
||||
|
||||
/// Perform the following steps atomically with respect to any other atomic
|
||||
/// accesses within Scope to the same location:
|
||||
///
|
||||
/// 1. Load through `ptr` to get an original value,
|
||||
/// 2. Get a new value by finding the smallest unsigned integer of original
|
||||
/// value and `value`, and
|
||||
/// 3. Store the new value back through `ptr`.
|
||||
///
|
||||
/// The result is the original value.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpAtomicUMin")]
|
||||
#[inline]
|
||||
pub unsafe fn atomic_u_min<U: UnsignedInteger, const SCOPE: u32, const SEMANTICS: u32>(
|
||||
ptr: &mut U,
|
||||
value: U,
|
||||
) -> U {
|
||||
let mut old = U::default();
|
||||
|
||||
asm! {
|
||||
"%u32 = OpTypeInt 32 0",
|
||||
"%scope = OpConstant %u32 {scope}",
|
||||
"%semantics = OpConstant %u32 {semantics}",
|
||||
"%value = OpLoad _ {value}",
|
||||
"%old = OpAtomicUMin _ {ptr} %scope %semantics %value",
|
||||
"OpStore {old} %old",
|
||||
scope = const SCOPE,
|
||||
semantics = const SEMANTICS,
|
||||
ptr = in(reg) ptr,
|
||||
old = in(reg) &mut old,
|
||||
value = in(reg) &value
|
||||
}
|
||||
|
||||
old
|
||||
}
|
||||
|
||||
/// Perform the following steps atomically with respect to any other atomic
|
||||
/// accesses within Scope to the same location:
|
||||
///
|
||||
/// 1. Load through `ptr` to get an original value,
|
||||
/// 2. Get a new value by finding the largest signed integer of original value
|
||||
/// and `value`, and
|
||||
/// 3. Store the new value back through `ptr`.
|
||||
///
|
||||
/// The result is the original value.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpAtomicSMax")]
|
||||
#[inline]
|
||||
pub unsafe fn atomic_s_max<S: SignedInteger, const SCOPE: u32, const SEMANTICS: u32>(
|
||||
ptr: &mut S,
|
||||
value: S,
|
||||
) -> S {
|
||||
let mut old = S::default();
|
||||
|
||||
asm! {
|
||||
"%u32 = OpTypeInt 32 0",
|
||||
"%scope = OpConstant %u32 {scope}",
|
||||
"%semantics = OpConstant %u32 {semantics}",
|
||||
"%value = OpLoad _ {value}",
|
||||
"%old = OpAtomicSMax _ {ptr} %scope %semantics %value",
|
||||
"OpStore {old} %old",
|
||||
scope = const SCOPE,
|
||||
semantics = const SEMANTICS,
|
||||
ptr = in(reg) ptr,
|
||||
old = in(reg) &mut old,
|
||||
value = in(reg) &value
|
||||
}
|
||||
|
||||
old
|
||||
}
|
||||
|
||||
/// Perform the following steps atomically with respect to any other atomic
|
||||
/// accesses within Scope to the same location:
|
||||
///
|
||||
/// 1. Load through `ptr` to get an original value,
|
||||
/// 2. Get a new value by finding the largest unsigned integer of original
|
||||
/// value and `value`, and
|
||||
/// 3. Store the new value back through `ptr`.
|
||||
///
|
||||
/// The result is the original value.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpAtomicUMax")]
|
||||
#[inline]
|
||||
pub unsafe fn atomic_u_max<U: UnsignedInteger, const SCOPE: u32, const SEMANTICS: u32>(
|
||||
ptr: &mut U,
|
||||
value: U,
|
||||
) -> U {
|
||||
let mut old = U::default();
|
||||
|
||||
asm! {
|
||||
"%u32 = OpTypeInt 32 0",
|
||||
"%scope = OpConstant %u32 {scope}",
|
||||
"%semantics = OpConstant %u32 {semantics}",
|
||||
"%value = OpLoad _ {value}",
|
||||
"%old = OpAtomicUMax _ {ptr} %scope %semantics %value",
|
||||
"OpStore {old} %old",
|
||||
scope = const SCOPE,
|
||||
semantics = const SEMANTICS,
|
||||
ptr = in(reg) ptr,
|
||||
old = in(reg) &mut old,
|
||||
value = in(reg) &value
|
||||
}
|
||||
|
||||
old
|
||||
}
|
||||
|
||||
/// Perform the following steps atomically with respect to any other atomic
|
||||
/// accesses within Scope to the same location:
|
||||
///
|
||||
/// 1. Load through `ptr` to get an original value,
|
||||
/// 2. Get a new value by the bitwise AND of the original value and `value`, and
|
||||
/// 3. Store the new value back through `ptr`.
|
||||
///
|
||||
/// The result is the original value.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpAtomicAnd")]
|
||||
#[inline]
|
||||
pub unsafe fn atomic_and<I: Integer, const SCOPE: u32, const SEMANTICS: u32>(
|
||||
ptr: &mut I,
|
||||
value: I,
|
||||
) -> I {
|
||||
let mut old = I::default();
|
||||
|
||||
asm! {
|
||||
"%u32 = OpTypeInt 32 0",
|
||||
"%scope = OpConstant %u32 {scope}",
|
||||
"%semantics = OpConstant %u32 {semantics}",
|
||||
"%value = OpLoad _ {value}",
|
||||
"%old = OpAtomicAnd _ {ptr} %scope %semantics %value",
|
||||
"OpStore {old} %old",
|
||||
scope = const SCOPE,
|
||||
semantics = const SEMANTICS,
|
||||
ptr = in(reg) ptr,
|
||||
old = in(reg) &mut old,
|
||||
value = in(reg) &value
|
||||
}
|
||||
|
||||
old
|
||||
}
|
||||
|
||||
/// Perform the following steps atomically with respect to any other atomic
|
||||
/// accesses within Scope to the same location:
|
||||
///
|
||||
/// 1. Load through `ptr` to get an original value,
|
||||
/// 2. Get a new value by the bitwise OR of the original value and `value`, and
|
||||
/// 3. Store the new value back through `ptr`.
|
||||
///
|
||||
/// The result is the original value.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpAtomicOr")]
|
||||
#[inline]
|
||||
pub unsafe fn atomic_or<I: Integer, const SCOPE: u32, const SEMANTICS: u32>(
|
||||
ptr: &mut I,
|
||||
value: I,
|
||||
) -> I {
|
||||
let mut old = I::default();
|
||||
|
||||
asm! {
|
||||
"%u32 = OpTypeInt 32 0",
|
||||
"%scope = OpConstant %u32 {scope}",
|
||||
"%semantics = OpConstant %u32 {semantics}",
|
||||
"%value = OpLoad _ {value}",
|
||||
"%old = OpAtomicOr _ {ptr} %scope %semantics %value",
|
||||
"OpStore {old} %old",
|
||||
scope = const SCOPE,
|
||||
semantics = const SEMANTICS,
|
||||
ptr = in(reg) ptr,
|
||||
old = in(reg) &mut old,
|
||||
value = in(reg) &value
|
||||
}
|
||||
|
||||
old
|
||||
}
|
||||
|
||||
/// Perform the following steps atomically with respect to any other atomic
|
||||
/// accesses within Scope to the same location:
|
||||
///
|
||||
/// 1. Load through `ptr` to get an original value,
|
||||
/// 2. Get a new value by the bitwise XOR of the original value and `value`, and
|
||||
/// 3. Store the new value back through `ptr`.
|
||||
///
|
||||
/// The result is the original value.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpAtomicXor")]
|
||||
#[inline]
|
||||
pub unsafe fn atomic_xor<I: Integer, const SCOPE: u32, const SEMANTICS: u32>(
|
||||
ptr: &mut I,
|
||||
value: I,
|
||||
) -> I {
|
||||
let mut old = I::default();
|
||||
|
||||
asm! {
|
||||
"%u32 = OpTypeInt 32 0",
|
||||
"%scope = OpConstant %u32 {scope}",
|
||||
"%semantics = OpConstant %u32 {semantics}",
|
||||
"%value = OpLoad _ {value}",
|
||||
"%old = OpAtomicXor _ {ptr} %scope %semantics %value",
|
||||
"OpStore {old} %old",
|
||||
scope = const SCOPE,
|
||||
semantics = const SEMANTICS,
|
||||
ptr = in(reg) ptr,
|
||||
old = in(reg) &mut old,
|
||||
value = in(reg) &value
|
||||
}
|
||||
|
||||
old
|
||||
}
|
||||
|
||||
/// Perform the following steps atomically with respect to any other atomic
|
||||
/// accesses within Scope to the same location:
|
||||
///
|
||||
/// 1. Load through `ptr` to get an original value,
|
||||
/// 2. Get a new value by finding the smallest signed integer of original value
|
||||
/// and `value`, and
|
||||
/// 3. Store the new value back through `ptr`.
|
||||
///
|
||||
/// The result is the original value.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpAtomicFMinEXT")]
|
||||
#[inline]
|
||||
pub unsafe fn atomic_f_min<F: Float, const SCOPE: u32, const SEMANTICS: u32>(
|
||||
ptr: &mut F,
|
||||
value: F,
|
||||
) -> F {
|
||||
let mut old = F::default();
|
||||
|
||||
asm! {
|
||||
"%u32 = OpTypeInt 32 0",
|
||||
"%scope = OpConstant %u32 {scope}",
|
||||
"%semantics = OpConstant %u32 {semantics}",
|
||||
"%value = OpLoad _ {value}",
|
||||
"%old = OpAtomicFMinEXT _ {ptr} %scope %semantics %value",
|
||||
"OpStore {old} %old",
|
||||
scope = const SCOPE,
|
||||
semantics = const SEMANTICS,
|
||||
ptr = in(reg) ptr,
|
||||
old = in(reg) &mut old,
|
||||
value = in(reg) &value
|
||||
}
|
||||
|
||||
old
|
||||
}
|
||||
|
||||
/// Perform the following steps atomically with respect to any other atomic
|
||||
/// accesses within Scope to the same location:
|
||||
///
|
||||
/// 1. Load through `ptr` to get an original value,
|
||||
/// 2. Get a new value by finding the largest signed integer of original value
|
||||
/// and `value`, and
|
||||
/// 3. Store the new value back through `ptr`.
|
||||
///
|
||||
/// The result is the original value.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpAtomicFMaxEXT")]
|
||||
#[inline]
|
||||
pub unsafe fn atomic_f_max<F: Float, const SCOPE: u32, const SEMANTICS: u32>(
|
||||
ptr: &mut F,
|
||||
value: F,
|
||||
) -> F {
|
||||
let mut old = F::default();
|
||||
|
||||
asm! {
|
||||
"%u32 = OpTypeInt 32 0",
|
||||
"%scope = OpConstant %u32 {scope}",
|
||||
"%semantics = OpConstant %u32 {semantics}",
|
||||
"%value = OpLoad _ {value}",
|
||||
"%old = OpAtomicFMaxEXT _ {ptr} %scope %semantics %value",
|
||||
"OpStore {old} %old",
|
||||
scope = const SCOPE,
|
||||
semantics = const SEMANTICS,
|
||||
ptr = in(reg) ptr,
|
||||
old = in(reg) &mut old,
|
||||
value = in(reg) &value
|
||||
}
|
||||
|
||||
old
|
||||
}
|
||||
|
||||
/// Perform the following steps atomically with respect to any other atomic
|
||||
/// accesses within `SCOPE` to the same location:
|
||||
///
|
||||
/// 1) load through `ptr` to get an original value,
|
||||
/// 2) get a new value by integer addition of original value and `value`, and
|
||||
/// 3) store the new value back through `ptr`.
|
||||
///
|
||||
/// The result is the Original Value.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpAtomicFAddEXT")]
|
||||
#[inline]
|
||||
pub unsafe fn atomic_f_add<F: Float, const SCOPE: u32, const SEMANTICS: u32>(
|
||||
ptr: &mut F,
|
||||
value: F,
|
||||
) -> F {
|
||||
let mut old = F::default();
|
||||
|
||||
asm! {
|
||||
"%u32 = OpTypeInt 32 0",
|
||||
"%scope = OpConstant %u32 {scope}",
|
||||
"%semantics = OpConstant %u32 {semantics}",
|
||||
"%value = OpLoad _ {value}",
|
||||
"%old = OpAtomicFMaxEXT _ {ptr} %scope %semantics %value",
|
||||
"OpStore {old} %old",
|
||||
scope = const SCOPE,
|
||||
semantics = const SEMANTICS,
|
||||
ptr = in(reg) ptr,
|
||||
old = in(reg) &mut old,
|
||||
value = in(reg) &value
|
||||
}
|
||||
|
||||
old
|
||||
}
|
@ -10,7 +10,7 @@ mod params;
|
||||
|
||||
pub use self::params::{ImageCoordinate, ImageCoordinateSubpassData, SampleType};
|
||||
pub use crate::macros::Image;
|
||||
pub use spirv_types::image_params::{
|
||||
pub use spirv_std_types::image_params::{
|
||||
AccessQualifier, Arrayed, Dimensionality, ImageDepth, ImageFormat, Multisampled, Sampled,
|
||||
};
|
||||
|
||||
|
@ -102,6 +102,7 @@ pub mod float;
|
||||
pub mod image;
|
||||
pub mod integer;
|
||||
pub mod memory;
|
||||
pub mod number;
|
||||
pub mod ray_tracing;
|
||||
mod runtime_array;
|
||||
mod sampler;
|
||||
@ -130,7 +131,7 @@ extern "C" fn rust_eh_personality() {}
|
||||
|
||||
// See: https://github.com/rust-lang/rust/issues/84738
|
||||
#[doc(hidden)]
|
||||
/// [spirv_types]
|
||||
/// [spirv_std_types]
|
||||
pub fn workaround_rustdoc_ice_84738() {}
|
||||
|
||||
#[doc(hidden)]
|
||||
|
15
crates/spirv-std/src/number.rs
Normal file
15
crates/spirv-std/src/number.rs
Normal file
@ -0,0 +1,15 @@
|
||||
//! Traits and helper functions related to numbers.
|
||||
|
||||
/// Abstract trait representing a SPIR-V integer or floating-point type.
|
||||
pub trait Number: crate::scalar::Scalar {}
|
||||
|
||||
impl Number for u8 {}
|
||||
impl Number for u16 {}
|
||||
impl Number for u32 {}
|
||||
impl Number for u64 {}
|
||||
impl Number for i8 {}
|
||||
impl Number for i16 {}
|
||||
impl Number for i32 {}
|
||||
impl Number for i64 {}
|
||||
impl Number for f32 {}
|
||||
impl Number for f64 {}
|
10
deny.toml
10
deny.toml
@ -36,11 +36,11 @@ skip = [
|
||||
# by default infinite
|
||||
skip-tree = [
|
||||
# we don't really care if our example brings in some duplicate dependencies, for now
|
||||
{ name = "example-runner-ash", version = "0.4.0-alpha.12", depth = 20 },
|
||||
{ name = "example-runner-cpu", version = "0.4.0-alpha.12", depth = 20 },
|
||||
{ name = "example-runner-wgpu", version = "0.4.0-alpha.12", depth = 20 },
|
||||
{ name = "compiletests", version = "0.4.0-alpha.12", depth = 20 },
|
||||
{ name = "compiletests-deps-helper", version = "0.4.0-alpha.12", depth = 20 },
|
||||
{ name = "example-runner-ash", version = "0.0.0", depth = 20 },
|
||||
{ name = "example-runner-cpu", version = "0.0.0", depth = 20 },
|
||||
{ name = "example-runner-wgpu", version = "0.0.0", depth = 20 },
|
||||
{ name = "compiletests", version = "0.0.0", depth = 20 },
|
||||
{ name = "compiletests-deps-helper", version = "0.0.0", depth = 20 },
|
||||
]
|
||||
|
||||
|
||||
|
@ -67,6 +67,8 @@ rustdoc for documentation.
|
||||
const SHADER: &[u8] = include_bytes!(env!("<shader_name>.spv"));
|
||||
```
|
||||
|
||||
> **Note** If your shader name contains hyphens, the name of environment variable will be the name with hyphens changed to underscores.
|
||||
|
||||
Keep in mind that by default, build-dependencies are built in debug mode. This
|
||||
means that the rust-gpu compiler (`rustc_codegen_spirv`) will be built in debug
|
||||
mode, and will be *incredibly* slow. You can solve this by placing this bit of
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "multibuilder"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
authors = ["Embark <opensource@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "example-runner-ash"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
authors = ["Embark <opensource@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "example-runner-cpu"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
authors = ["Embark <opensource@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "example-runner-wgpu"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
authors = ["Embark <opensource@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
@ -35,6 +35,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
"--target-dir",
|
||||
])
|
||||
.arg(dir)
|
||||
.env_remove("CARGO_ENCODED_RUSTFLAGS")
|
||||
.stderr(std::process::Stdio::inherit())
|
||||
.stdout(std::process::Stdio::inherit())
|
||||
.status()?;
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "example-runner-wgpu-builder"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
authors = ["Embark <opensource@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
@ -2,7 +2,7 @@ use wgpu::util::DeviceExt;
|
||||
|
||||
use super::Options;
|
||||
use futures::future::join;
|
||||
use std::{convert::TryInto, future::Future, num::NonZeroU64, time::Duration};
|
||||
use std::{convert::TryInto, future::Future, time::Duration};
|
||||
|
||||
fn block_on<T>(future: impl Future<Output = T>) -> T {
|
||||
cfg_if::cfg_if! {
|
||||
@ -63,20 +63,16 @@ pub async fn start_internal(
|
||||
|
||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: None,
|
||||
entries: &[
|
||||
// XXX - some graphics cards do not support empty bind layout groups, so
|
||||
// create a dummy entry.
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
count: None,
|
||||
visibility: wgpu::ShaderStages::COMPUTE,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: Some(NonZeroU64::new(1).unwrap()),
|
||||
ty: wgpu::BufferBindingType::Storage { read_only: false },
|
||||
},
|
||||
entries: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
count: None,
|
||||
visibility: wgpu::ShaderStages::COMPUTE,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
ty: wgpu::BufferBindingType::Storage { read_only: false },
|
||||
},
|
||||
],
|
||||
}],
|
||||
});
|
||||
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "compute-shader"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
authors = ["Embark <opensource@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "mouse-shader"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
authors = ["Embark <opensource@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "reduce"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
authors = ["Embark <opensource@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "shared"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
authors = ["Embark <opensource@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "simplest-shader"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
authors = ["Embark <opensource@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "sky-shader"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
authors = ["Embark <opensource@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "compiletests"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
authors = ["Embark <opensource@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
@ -14,5 +14,5 @@ use-compiled-tools = ["rustc_codegen_spirv/use-compiled-tools"]
|
||||
|
||||
[dependencies]
|
||||
compiletest = { version = "0.7.0", package = "compiletest_rs" }
|
||||
rustc_codegen_spirv = { path = "../crates/rustc_codegen_spirv", default-features = false }
|
||||
rustc_codegen_spirv = { path = "../crates/rustc_codegen_spirv", version = "0.4.0-alpha.14", default-features = false }
|
||||
structopt = "0.3.21"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "compiletests-deps-helper"
|
||||
version = "0.4.0-alpha.12"
|
||||
version = "0.0.0"
|
||||
description = "Shared dependencies of all the compiletest tests"
|
||||
authors = ["Embark <opensource@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
|
@ -260,14 +260,16 @@ fn find_lib(
|
||||
.map(|entry| entry.path())
|
||||
.filter(|path| {
|
||||
let name = {
|
||||
let name = path.file_name();
|
||||
let name = path.file_stem();
|
||||
if name.is_none() {
|
||||
return false;
|
||||
}
|
||||
name.unwrap()
|
||||
};
|
||||
|
||||
let name_matches = name.to_str().unwrap().starts_with(&expected_name);
|
||||
let name_matches = name.to_str().unwrap().starts_with(&expected_name)
|
||||
&& name.len() == expected_name.len() + 17 // we expect our name, '-', and then 16 hexadecimal digits
|
||||
&& ends_with_dash_hash(name.to_str().unwrap());
|
||||
let extension_matches = path
|
||||
.extension()
|
||||
.map_or(false, |ext| ext == expected_extension);
|
||||
@ -283,6 +285,20 @@ fn find_lib(
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns whether this string ends with a dash ('-'), followed by 16 lowercase hexadecimal characters
|
||||
fn ends_with_dash_hash(s: &str) -> bool {
|
||||
let n = s.len();
|
||||
if n < 17 {
|
||||
return false;
|
||||
}
|
||||
let mut bytes = s.bytes().skip(n - 17);
|
||||
if bytes.next() != Some(b'-') {
|
||||
return false;
|
||||
}
|
||||
|
||||
bytes.all(|b| b.is_ascii_hexdigit())
|
||||
}
|
||||
|
||||
/// Paths to all of the library artifacts of dependencies needed to compile tests.
|
||||
struct TestDeps {
|
||||
core: PathBuf,
|
||||
|
@ -100,9 +100,9 @@ error[E0277]: the trait bound `{float}: Vector<f32, 2_usize>` is not satisfied
|
||||
<IVec3 as Vector<i32, 3_usize>>
|
||||
and 9 others
|
||||
note: required by a bound in `debug_printf_assert_is_vector`
|
||||
--> $SPIRV_STD_SRC/lib.rs:144:8
|
||||
--> $SPIRV_STD_SRC/lib.rs:145:8
|
||||
|
|
||||
144 | V: crate::vector::Vector<TY, SIZE>,
|
||||
145 | V: crate::vector::Vector<TY, SIZE>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `debug_printf_assert_is_vector`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
|
@ -9,7 +9,7 @@ OpMemoryModel Logical Simple
|
||||
OpEntryPoint Fragment %1 "main"
|
||||
OpExecutionMode %1 OriginUpperLeft
|
||||
%2 = OpString "$OPSTRING_FILENAME/generic-fn-op-name.rs"
|
||||
OpName %3 "generic_fn_op_name::generic::<f32, {spirv_types::image_params::Dimensionality::TwoD}>"
|
||||
OpName %3 "generic_fn_op_name::generic::<f32, {spirv_std_types::image_params::Dimensionality::TwoD}>"
|
||||
OpName %4 "generic_fn_op_name::main"
|
||||
%5 = OpTypeVoid
|
||||
%6 = OpTypeFunction %5
|
||||
|
@ -8,16 +8,34 @@ pub fn main(
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image: &Image!(2D, type=f32, sampled),
|
||||
#[spirv(descriptor_set = 1, binding = 1)] image_array: &Image!(2D, type=f32, arrayed, sampled),
|
||||
#[spirv(descriptor_set = 2, binding = 2)] sampler: &Sampler,
|
||||
#[spirv(descriptor_set = 3, binding = 3)] cubemap: &Image!(3D, type=f32, sampled),
|
||||
output: &mut f32,
|
||||
) {
|
||||
let v2 = glam::Vec2::new(0.0, 1.0);
|
||||
let v2_dx = glam::Vec2::new(0.0, 1.0);
|
||||
let v2_dy = glam::Vec2::new(0.0, 1.0);
|
||||
let v3 = glam::Vec3A::new(0.0, 0.0, 1.0);
|
||||
let v3_dx = glam::Vec3A::new(0.0, 1.0, 0.5);
|
||||
let v3_dy = glam::Vec3A::new(0.0, 1.0, 0.5);
|
||||
*output = image.sample_depth_reference_by_gradient(*sampler, v2, 1.0, v2_dx, v2_dy);
|
||||
*output += image_array.sample_depth_reference_by_gradient(*sampler, v3, 1.0, v2_dx, v2_dy);
|
||||
}
|
||||
|
||||
// NOTE(eddyb) this is separate because it runs afoul of this rule:
|
||||
// > VUID-StandaloneSpirv-OpImage-04777
|
||||
// > `OpImage*Dref*` instructions **must** not consume an image whose `Dim` is 3D
|
||||
// FIXME(eddyb) look into whether non-Vulkan `OpImage*Dref*` usage can ever be 3D
|
||||
#[cfg(not(any(
|
||||
target_env = "vulkan1.0",
|
||||
target_env = "vulkan1.1",
|
||||
target_env = "vulkan1.1spv1.4",
|
||||
target_env = "vulkan1.2"
|
||||
)))]
|
||||
#[spirv(fragment)]
|
||||
pub fn main_cubemap(
|
||||
#[spirv(descriptor_set = 2, binding = 2)] sampler: &Sampler,
|
||||
#[spirv(descriptor_set = 3, binding = 3)] cubemap: &Image!(3D, type=f32, sampled),
|
||||
output: &mut f32,
|
||||
) {
|
||||
let v3 = glam::Vec3A::new(0.0, 0.0, 1.0);
|
||||
let v3_dx = glam::Vec3A::new(0.0, 1.0, 0.5);
|
||||
let v3_dy = glam::Vec3A::new(0.0, 1.0, 0.5);
|
||||
*output += cubemap.sample_depth_reference_by_gradient(*sampler, v3, 1.0, v3_dx, v3_dy);
|
||||
}
|
||||
|
@ -8,12 +8,30 @@ pub fn main(
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image: &Image!(2D, type=f32, sampled),
|
||||
#[spirv(descriptor_set = 1, binding = 1)] image_array: &Image!(2D, type=f32, arrayed, sampled),
|
||||
#[spirv(descriptor_set = 2, binding = 2)] sampler: &Sampler,
|
||||
#[spirv(descriptor_set = 3, binding = 3)] cubemap: &Image!(3D, type=f32, sampled),
|
||||
output: &mut f32,
|
||||
) {
|
||||
let v2 = glam::Vec2::new(0.0, 1.0);
|
||||
let v3 = glam::Vec3A::new(0.0, 0.0, 1.0);
|
||||
*output = image.sample_depth_reference_by_lod(*sampler, v2, 1.0, 0.0);
|
||||
*output += image_array.sample_depth_reference_by_lod(*sampler, v3, 1.0, 0.0);
|
||||
}
|
||||
|
||||
// NOTE(eddyb) this is separate because it runs afoul of this rule:
|
||||
// > VUID-StandaloneSpirv-OpImage-04777
|
||||
// > `OpImage*Dref*` instructions **must** not consume an image whose `Dim` is 3D
|
||||
// FIXME(eddyb) look into whether non-Vulkan `OpImage*Dref*` usage can ever be 3D
|
||||
#[cfg(not(any(
|
||||
target_env = "vulkan1.0",
|
||||
target_env = "vulkan1.1",
|
||||
target_env = "vulkan1.1spv1.4",
|
||||
target_env = "vulkan1.2"
|
||||
)))]
|
||||
#[spirv(fragment)]
|
||||
pub fn main_cubemap(
|
||||
#[spirv(descriptor_set = 2, binding = 2)] sampler: &Sampler,
|
||||
#[spirv(descriptor_set = 3, binding = 3)] cubemap: &Image!(3D, type=f32, sampled),
|
||||
output: &mut f32,
|
||||
) {
|
||||
let v3 = glam::Vec3A::new(0.0, 0.0, 1.0);
|
||||
*output += cubemap.sample_depth_reference_by_lod(*sampler, v3, 1.0, 0.0);
|
||||
}
|
||||
|
6
tests/ui/lang/consts/nested-ref.stderr
Normal file
6
tests/ui/lang/consts/nested-ref.stderr
Normal file
@ -0,0 +1,6 @@
|
||||
warning: `#[inline(never)]` function `nested_ref::deep_load` needs to be inlined because it has illegal argument or return types
|
||||
|
||||
warning: `#[inline(never)]` function `nested_ref::deep_transpose` needs to be inlined because it has illegal argument or return types
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
18
tests/ui/lang/core/ref/zst_member_ref_arg.rs
Normal file
18
tests/ui/lang/core/ref/zst_member_ref_arg.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// build-pass
|
||||
|
||||
use spirv_std as _;
|
||||
struct A;
|
||||
struct B;
|
||||
|
||||
struct S {
|
||||
x: A,
|
||||
y: B,
|
||||
}
|
||||
|
||||
fn f(x: &B) {}
|
||||
|
||||
#[spirv(fragment)]
|
||||
pub fn main() {
|
||||
let s = S { x: A, y: B };
|
||||
f(&s.y);
|
||||
}
|
Loading…
Reference in New Issue
Block a user