mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-25 00:04:11 +00:00
Add Const Generic Image Type (#359)
* Add parameterized Image type * nits * Update crates/spirv-std/src/lib.rs * Update crates/rustc_codegen_spirv/src/symbols.rs * Update crates/rustc_codegen_spirv/src/symbols.rs * Update symbols.rs
This commit is contained in:
parent
4c8e50d943
commit
f88ae5b28a
48
Cargo.lock
generated
48
Cargo.lock
generated
@ -403,7 +403,6 @@ name = "compute-shader"
|
||||
version = "0.4.0-alpha.5"
|
||||
dependencies = [
|
||||
"spirv-std",
|
||||
"spirv-std-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -792,7 +791,7 @@ checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"redox_syscall 0.2.5",
|
||||
"redox_syscall 0.2.6",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
@ -992,9 +991,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "gfx-backend-dx12"
|
||||
version = "0.7.0"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36dc6ba2b7647e2c2b27b8f74ff5ccdd53c703776588eee5b1de515fdcbd6bc9"
|
||||
checksum = "5032d716a2a5f4dafb4675a794c5dc32081af8fbc7303c93ad93ff5413c6559f"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bit-set",
|
||||
@ -1008,6 +1007,7 @@ dependencies = [
|
||||
"raw-window-handle",
|
||||
"smallvec",
|
||||
"spirv_cross",
|
||||
"thunderdome",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
@ -1262,9 +1262,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.21"
|
||||
version = "0.1.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2"
|
||||
checksum = "972f5ae5d1cb9c6ae417789196c803205313edde988685da5e3aae0827b9e7fd"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
@ -1728,7 +1728,7 @@ checksum = "0c976c5018e7f1db4359616d8b31ef8ae7d9649b11803c0b38fff67fd2999fc8"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"raw-window-handle",
|
||||
"redox_syscall 0.2.5",
|
||||
"redox_syscall 0.2.6",
|
||||
"sdl2",
|
||||
"sdl2-sys",
|
||||
"wasm-bindgen",
|
||||
@ -1779,7 +1779,7 @@ dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"instant",
|
||||
"libc",
|
||||
"redox_syscall 0.2.5",
|
||||
"redox_syscall 0.2.6",
|
||||
"smallvec",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
@ -1855,9 +1855,9 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||
|
||||
[[package]]
|
||||
name = "pretty_assertions"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f297542c27a7df8d45de2b0e620308ab883ad232d06c14b76ac3e144bda50184"
|
||||
checksum = "1cab0e7c02cf376875e9335e0ba1da535775beb5450d21e1dffca068818ed98b"
|
||||
dependencies = [
|
||||
"ansi_term 0.12.1",
|
||||
"ctor",
|
||||
@ -2022,9 +2022,9 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9"
|
||||
checksum = "8270314b5ccceb518e7e578952f0b72b88222d02e8f77f5ecf7abbb673539041"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
@ -2036,7 +2036,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"redox_syscall 0.2.5",
|
||||
"redox_syscall 0.2.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2078,12 +2078,12 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rspirv"
|
||||
version = "0.7.0"
|
||||
source = "git+https://github.com/gfx-rs/rspirv.git?rev=719cf08#719cf08e4af0436242707479e3509add5ec3d514"
|
||||
source = "git+https://github.com/gfx-rs/rspirv?rev=719cf08#719cf08e4af0436242707479e3509add5ec3d514"
|
||||
dependencies = [
|
||||
"derive_more",
|
||||
"fxhash",
|
||||
"num-traits",
|
||||
"spirv_headers 1.5.0 (git+https://github.com/gfx-rs/rspirv.git?rev=719cf08)",
|
||||
"spirv_headers 1.5.0 (git+https://github.com/gfx-rs/rspirv?rev=719cf08)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2267,7 +2267,6 @@ version = "0.4.0-alpha.5"
|
||||
dependencies = [
|
||||
"glam",
|
||||
"spirv-std",
|
||||
"spirv-std-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2282,7 +2281,6 @@ version = "0.4.0-alpha.5"
|
||||
dependencies = [
|
||||
"shared",
|
||||
"spirv-std",
|
||||
"spirv-std-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2291,14 +2289,13 @@ version = "0.4.0-alpha.5"
|
||||
dependencies = [
|
||||
"shared",
|
||||
"spirv-std",
|
||||
"spirv-std-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.2"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
||||
checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527"
|
||||
|
||||
[[package]]
|
||||
name = "slotmap"
|
||||
@ -2351,14 +2348,17 @@ dependencies = [
|
||||
"bitflags",
|
||||
"num-traits",
|
||||
"spirv-std-macros",
|
||||
"spirv-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spirv-std-macros"
|
||||
version = "0.4.0-alpha.5"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"spirv-types",
|
||||
"syn",
|
||||
]
|
||||
|
||||
@ -2382,6 +2382,10 @@ dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spirv-types"
|
||||
version = "0.4.0-alpha.5"
|
||||
|
||||
[[package]]
|
||||
name = "spirv_cross"
|
||||
version = "0.23.1"
|
||||
@ -2396,7 +2400,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "spirv_headers"
|
||||
version = "1.5.0"
|
||||
source = "git+https://github.com/gfx-rs/rspirv.git?rev=719cf08#719cf08e4af0436242707479e3509add5ec3d514"
|
||||
source = "git+https://github.com/gfx-rs/rspirv?rev=719cf08#719cf08e4af0436242707479e3509add5ec3d514"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"num-traits",
|
||||
@ -2515,7 +2519,7 @@ dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"rand",
|
||||
"redox_syscall 0.2.5",
|
||||
"redox_syscall 0.2.6",
|
||||
"remove_dir_all",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
@ -12,6 +12,8 @@ members = [
|
||||
"crates/rustc_codegen_spirv",
|
||||
"crates/spirv-builder",
|
||||
"crates/spirv-std",
|
||||
"crates/spirv-std/shared",
|
||||
"crates/spirv-std/macros",
|
||||
|
||||
"tests",
|
||||
"tests/deps-helper",
|
||||
@ -34,7 +36,7 @@ codegen-units = 256
|
||||
|
||||
[patch.crates-io]
|
||||
spirv-std = { path = "./crates/spirv-std" }
|
||||
spirv-std-macros = { path = "./crates/spirv-std-macros" }
|
||||
spirv-std-macros = { path = "./crates/spirv-std/macros" }
|
||||
# TODO: Remove once next version is released - needed to include these two PRs:
|
||||
# * Manishearth/compiletest-rs#240 (for handling SPIR-V extension across platforms)
|
||||
# * Manishearth/compiletest-rs#241 (for the `$TEST_BUILD_DIR` path normalization)
|
||||
|
@ -10,7 +10,9 @@ use rustc_errors::ErrorReported;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::layout::{FnAbiExt, TyAndLayout};
|
||||
use rustc_middle::ty::subst::SubstsRef;
|
||||
use rustc_middle::ty::{GeneratorSubsts, PolyFnSig, Ty, TyKind, TypeAndMut};
|
||||
use rustc_middle::ty::{
|
||||
Const, FloatTy, GeneratorSubsts, IntTy, ParamEnv, PolyFnSig, Ty, TyKind, TypeAndMut, UintTy,
|
||||
};
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_span::Span;
|
||||
use rustc_target::abi::call::{CastTarget, FnAbi, PassMode, Reg, RegKind};
|
||||
@ -21,6 +23,9 @@ use std::cell::RefCell;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::fmt;
|
||||
|
||||
use num_traits::cast::FromPrimitive;
|
||||
use rspirv::spirv;
|
||||
|
||||
/// If a struct contains a pointer to itself, even indirectly, then doing a naiive recursive walk
|
||||
/// of the fields will result in an infinite loop. Because pointers are the only thing that are
|
||||
/// allowed to be recursive, keep track of what pointers we've translated, or are currently in the
|
||||
@ -768,6 +773,94 @@ fn trans_intrinsic_type<'tcx>(
|
||||
}
|
||||
// Hardcode to float for now
|
||||
let sampled_type = SpirvType::Float(32).def(span, cx);
|
||||
|
||||
let ty = SpirvType::Image {
|
||||
sampled_type,
|
||||
dim,
|
||||
depth,
|
||||
arrayed,
|
||||
multisampled,
|
||||
sampled,
|
||||
image_format,
|
||||
access_qualifier,
|
||||
};
|
||||
|
||||
Ok(ty.def(span, cx))
|
||||
}
|
||||
IntrinsicType::GenericImageType => {
|
||||
// see SpirvType::sizeof
|
||||
if ty.size != Size::from_bytes(4) {
|
||||
cx.tcx
|
||||
.sess
|
||||
.err("#[spirv(generic_image)] type must have size 4");
|
||||
return Err(ErrorReported);
|
||||
}
|
||||
|
||||
fn type_from_variant_discriminant<'tcx, P: FromPrimitive>(
|
||||
cx: &CodegenCx<'tcx>,
|
||||
const_: &'tcx Const<'tcx>,
|
||||
) -> P {
|
||||
let adt_def = const_.ty.ty_adt_def().unwrap();
|
||||
assert!(adt_def.is_enum());
|
||||
let destructured = cx.tcx.destructure_const(ParamEnv::reveal_all().and(const_));
|
||||
let idx = destructured.variant.unwrap();
|
||||
let value = const_.ty.discriminant_for_variant(cx.tcx, idx).unwrap().val as u64;
|
||||
<_>::from_u64(value).unwrap()
|
||||
}
|
||||
|
||||
let sampled_type = match substs.type_at(0).kind() {
|
||||
TyKind::Int(int) => match int {
|
||||
IntTy::Isize => {
|
||||
SpirvType::Integer(cx.tcx.data_layout.pointer_size.bits() as u32, true)
|
||||
.def(span, cx)
|
||||
}
|
||||
IntTy::I8 => SpirvType::Integer(8, true).def(span, cx),
|
||||
IntTy::I16 => SpirvType::Integer(16, true).def(span, cx),
|
||||
IntTy::I32 => SpirvType::Integer(32, true).def(span, cx),
|
||||
IntTy::I64 => SpirvType::Integer(64, true).def(span, cx),
|
||||
IntTy::I128 => SpirvType::Integer(128, true).def(span, cx),
|
||||
},
|
||||
TyKind::Uint(uint) => match uint {
|
||||
UintTy::Usize => {
|
||||
SpirvType::Integer(cx.tcx.data_layout.pointer_size.bits() as u32, false)
|
||||
.def(span, cx)
|
||||
}
|
||||
UintTy::U8 => SpirvType::Integer(8, false).def(span, cx),
|
||||
UintTy::U16 => SpirvType::Integer(16, false).def(span, cx),
|
||||
UintTy::U32 => SpirvType::Integer(32, false).def(span, cx),
|
||||
UintTy::U64 => SpirvType::Integer(64, false).def(span, cx),
|
||||
UintTy::U128 => SpirvType::Integer(128, false).def(span, cx),
|
||||
},
|
||||
TyKind::Float(FloatTy::F32) => SpirvType::Float(32).def(span, cx),
|
||||
TyKind::Float(FloatTy::F64) => SpirvType::Float(64).def(span, cx),
|
||||
_ => {
|
||||
cx.tcx
|
||||
.sess
|
||||
.span_err(span, "Invalid sampled type to `Image`.");
|
||||
return Err(ErrorReported);
|
||||
}
|
||||
};
|
||||
|
||||
let dim: spirv::Dim = type_from_variant_discriminant(cx, substs.const_at(1));
|
||||
let depth: u32 = type_from_variant_discriminant(cx, substs.const_at(2));
|
||||
let arrayed: u32 = type_from_variant_discriminant(cx, substs.const_at(3));
|
||||
let multisampled: u32 = type_from_variant_discriminant(cx, substs.const_at(4));
|
||||
let sampled: u32 = type_from_variant_discriminant(cx, substs.const_at(5));
|
||||
let image_format: spirv::ImageFormat =
|
||||
type_from_variant_discriminant(cx, substs.const_at(6));
|
||||
|
||||
let access_qualifier = {
|
||||
let option = cx
|
||||
.tcx
|
||||
.destructure_const(ParamEnv::reveal_all().and(substs.const_at(7)));
|
||||
|
||||
match option.variant.map(|i| i.as_u32()).unwrap_or(0) {
|
||||
0 => None,
|
||||
1 => Some(type_from_variant_discriminant(cx, option.fields[0])),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
};
|
||||
|
||||
let ty = SpirvType::Image {
|
||||
sampled_type,
|
||||
dim,
|
||||
|
@ -61,6 +61,7 @@ impl From<ExecutionModel> for Entry {
|
||||
/// `struct` types that are used to represent special SPIR-V types.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum IntrinsicType {
|
||||
GenericImageType,
|
||||
ImageType {
|
||||
dim: Dim,
|
||||
depth: u32,
|
||||
|
@ -317,6 +317,10 @@ impl Symbols {
|
||||
"sampler",
|
||||
SpirvAttribute::IntrinsicType(IntrinsicType::Sampler),
|
||||
),
|
||||
(
|
||||
"generic_image_type",
|
||||
SpirvAttribute::IntrinsicType(IntrinsicType::GenericImageType),
|
||||
),
|
||||
(
|
||||
"acceleration_structure",
|
||||
SpirvAttribute::IntrinsicType(IntrinsicType::AccelerationStructureKhr),
|
||||
|
@ -204,7 +204,7 @@ fn invoke_rustc(builder: &SpirvBuilder, multimodule: bool) -> Result<PathBuf, Sp
|
||||
.unwrap_or_default();
|
||||
|
||||
let rustflags = format!(
|
||||
"-Z codegen-backend={} -Z symbol-mangling-version=v0{}",
|
||||
"-Z codegen-backend={} -Zsymbol-mangling-version=v0{}",
|
||||
rustc_codegen_spirv.display(),
|
||||
llvm_args,
|
||||
);
|
||||
|
@ -10,7 +10,8 @@ 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-std-macros = { path = "../spirv-std-macros", version = "0.4.0-alpha.0" }
|
||||
spirv-types = { path = "./shared", version = "0.4.0-alpha.3" }
|
||||
spirv-std-macros = { path = "./macros", version = "0.4.0-alpha.3" }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
@ -11,6 +11,8 @@ description = "Macros for spirv-std"
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
spirv-types = { path = "../shared", version = "0.4.0-alpha.3" }
|
||||
heck = "0.3.2"
|
||||
proc-macro2 = "1.0.24"
|
||||
quote = "1.0.8"
|
||||
syn = { version = "1.0.58", features=["full"] }
|
554
crates/spirv-std/macros/src/image.rs
Normal file
554
crates/spirv-std/macros/src/image.rs
Normal file
@ -0,0 +1,554 @@
|
||||
use proc_macro2::Ident;
|
||||
|
||||
use quote::{quote, TokenStreamExt};
|
||||
use spirv_types::image_params::*;
|
||||
use syn::parse::{Parse, ParseStream};
|
||||
|
||||
use self::params::SampledType;
|
||||
|
||||
mod kw {
|
||||
syn::custom_keyword!(u8);
|
||||
syn::custom_keyword!(u16);
|
||||
syn::custom_keyword!(u32);
|
||||
syn::custom_keyword!(u64);
|
||||
syn::custom_keyword!(i8);
|
||||
syn::custom_keyword!(i16);
|
||||
syn::custom_keyword!(i32);
|
||||
syn::custom_keyword!(i64);
|
||||
syn::custom_keyword!(f32);
|
||||
syn::custom_keyword!(f64);
|
||||
}
|
||||
|
||||
const MISSING_SAMPLE_ERROR: &str = "Expected either `type` or `format` to be \
|
||||
specified. Use `type=<sampled_type>` (e.g. `type=f32`) to specify the sampled \
|
||||
type, or use `format` to set the image to a specific image format.";
|
||||
|
||||
/// Creates an `Image` type using the following syntax.
|
||||
pub struct ImageType {
|
||||
access_qualifier: Option<AccessQualifier>,
|
||||
arrayed: Arrayed,
|
||||
crate_root: Option<syn::Path>,
|
||||
depth: ImageDepth,
|
||||
dimensionality: Dimensionality,
|
||||
format: ImageFormat,
|
||||
multisampled: Multisampled,
|
||||
sampled: Sampled,
|
||||
sampled_type: SampledType,
|
||||
}
|
||||
|
||||
impl Parse for ImageType {
|
||||
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||
let mut access_qualifier = None;
|
||||
let mut sampled_type = None;
|
||||
let mut dimensionality = None;
|
||||
let mut arrayed = None;
|
||||
let mut depth: Option<ImageDepth> = None;
|
||||
let mut format = None;
|
||||
let mut multisampled = None;
|
||||
let mut sampled: Option<Sampled> = None;
|
||||
let mut crate_root = None;
|
||||
|
||||
let starting_span = input.span();
|
||||
|
||||
macro_rules! set_unique {
|
||||
($id:ident = $ex:expr) => {{
|
||||
if $id.replace($ex).is_some() {
|
||||
return Err(syn::Error::new(
|
||||
input.span(),
|
||||
concat!("Unexpected duplicate parameter for `", stringify!($id), "`"),
|
||||
));
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! peek_and_eat_value {
|
||||
($typ:ty) => {{
|
||||
if input.peek(syn::Token![=]) {
|
||||
input.parse::<syn::Token![=]>()?;
|
||||
Some(input.parse::<$typ>()?)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
while !input.is_empty() {
|
||||
if input.peek(syn::LitInt) {
|
||||
let int = input.parse::<syn::LitInt>().unwrap();
|
||||
set_unique!(
|
||||
dimensionality = match (int.base10_digits(), int.suffix()) {
|
||||
("1", "D") | ("1", "d") => Dimensionality::OneD,
|
||||
("2", "D") | ("2", "d") => Dimensionality::TwoD,
|
||||
("3", "D") | ("3", "d") => Dimensionality::ThreeD,
|
||||
_ => return Err(syn::Error::new(int.span(), "Unexpected integer")),
|
||||
}
|
||||
);
|
||||
} else if input.peek(syn::Ident) {
|
||||
let ident = input.parse::<Ident>().unwrap();
|
||||
|
||||
if ident == "access" {
|
||||
let value = peek_and_eat_value!(syn::Ident)
|
||||
.as_ref()
|
||||
.map(|i| params::access_qualifier_from_str(&i.to_string()));
|
||||
|
||||
if value.is_none() {
|
||||
return Err(syn::Error::new(
|
||||
ident.span(),
|
||||
"Expected argument for `access`.",
|
||||
));
|
||||
}
|
||||
|
||||
access_qualifier = value.unwrap().ok();
|
||||
} else if ident == "buffer" {
|
||||
set_unique!(dimensionality = Dimensionality::Buffer);
|
||||
} else if ident == "cube" {
|
||||
set_unique!(dimensionality = Dimensionality::Cube);
|
||||
} else if ident == "rect" {
|
||||
set_unique!(dimensionality = Dimensionality::Rect);
|
||||
} else if ident == "subpass" {
|
||||
set_unique!(dimensionality = Dimensionality::SubpassData);
|
||||
} else if ident == "arrayed" {
|
||||
set_unique!(
|
||||
arrayed = peek_and_eat_value!(syn::LitBool)
|
||||
.as_ref()
|
||||
.map(syn::LitBool::value)
|
||||
.map_or(Arrayed::True, From::from)
|
||||
);
|
||||
} else if ident == "multisampled" {
|
||||
set_unique!(
|
||||
multisampled = peek_and_eat_value!(syn::LitBool)
|
||||
.as_ref()
|
||||
.map(syn::LitBool::value)
|
||||
.map_or(Multisampled::True, From::from)
|
||||
);
|
||||
} else if ident == "sampled" {
|
||||
set_unique!(
|
||||
sampled = peek_and_eat_value!(syn::LitBool)
|
||||
.as_ref()
|
||||
.map(syn::LitBool::value)
|
||||
.map_or(Sampled::Yes, From::from)
|
||||
);
|
||||
} else if ident == "depth" {
|
||||
set_unique!(
|
||||
depth = peek_and_eat_value!(syn::LitBool)
|
||||
.as_ref()
|
||||
.map(syn::LitBool::value)
|
||||
.map_or(ImageDepth::True, From::from)
|
||||
);
|
||||
} else if ident == "format" {
|
||||
let value = peek_and_eat_value!(syn::Ident);
|
||||
|
||||
if value.is_none() {
|
||||
return Err(syn::Error::new(
|
||||
ident.span(),
|
||||
"Expected argument for `format`.",
|
||||
));
|
||||
}
|
||||
|
||||
let value = params::image_format_from_str(&value.unwrap().to_string());
|
||||
|
||||
if let Err(err) = value {
|
||||
return Err(syn::Error::new(ident.span(), err));
|
||||
}
|
||||
|
||||
format = value.ok();
|
||||
} else if ident == "__crate_root" {
|
||||
input.parse::<syn::Token![=]>()?;
|
||||
crate_root = Some(input.parse::<syn::Path>()?);
|
||||
}
|
||||
} else if input.peek(syn::token::Type) {
|
||||
input.parse::<syn::token::Type>()?;
|
||||
input.parse::<syn::Token![=]>()?;
|
||||
|
||||
sampled_type = Some(if input.peek(kw::u8) {
|
||||
input.parse::<kw::u8>()?;
|
||||
|
||||
SampledType::U8
|
||||
} else if input.peek(kw::u16) {
|
||||
input.parse::<kw::u16>()?;
|
||||
|
||||
SampledType::U16
|
||||
} else if input.peek(kw::u32) {
|
||||
input.parse::<kw::u32>()?;
|
||||
|
||||
SampledType::U32
|
||||
} else if input.peek(kw::u64) {
|
||||
input.parse::<kw::u64>()?;
|
||||
|
||||
SampledType::U64
|
||||
} else if input.peek(kw::i8) {
|
||||
input.parse::<kw::i8>()?;
|
||||
|
||||
SampledType::I8
|
||||
} else if input.peek(kw::i16) {
|
||||
input.parse::<kw::i16>()?;
|
||||
|
||||
SampledType::I16
|
||||
} else if input.peek(kw::i32) {
|
||||
input.parse::<kw::i32>()?;
|
||||
|
||||
SampledType::I32
|
||||
} else if input.peek(kw::i64) {
|
||||
input.parse::<kw::i64>()?;
|
||||
|
||||
SampledType::I64
|
||||
} else if input.peek(kw::f32) {
|
||||
input.parse::<kw::f32>()?;
|
||||
|
||||
SampledType::F32
|
||||
} else if input.peek(kw::f64) {
|
||||
input.parse::<kw::f64>()?;
|
||||
|
||||
SampledType::F64
|
||||
} else {
|
||||
return Err(syn::Error::new(
|
||||
input.span(),
|
||||
"Unknown value provided to `unknown(_)`.",
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
if input.peek(syn::Token![,]) {
|
||||
input.parse::<syn::Token![,]>()?;
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if !input.is_empty() {
|
||||
return Err(syn::Error::new(
|
||||
input.span(),
|
||||
"Unexpected trailing arguments.",
|
||||
));
|
||||
}
|
||||
|
||||
let dimensionality = dimensionality.ok_or_else(|| {
|
||||
syn::Error::new(
|
||||
starting_span,
|
||||
"Expected either `1D`, `2D`, `3D`, `cube`, `rect`, `buffer`, \
|
||||
or `subpass` to be present",
|
||||
)
|
||||
})?;
|
||||
|
||||
if format.is_some() && sampled_type.is_some() {
|
||||
if format != Some(ImageFormat::Unknown) {
|
||||
return Err(syn::Error::new(
|
||||
starting_span,
|
||||
"Can't specify `type` with a known image format. Either \
|
||||
specify just the `format` or use `format=unknown`.",
|
||||
));
|
||||
}
|
||||
} else if sampled_type.is_some() {
|
||||
format = Some(ImageFormat::Unknown);
|
||||
} else if let Some(format) = &format {
|
||||
sampled_type = Some(match format {
|
||||
ImageFormat::Rgba32f
|
||||
| ImageFormat::Rgba16f
|
||||
| ImageFormat::R32f
|
||||
| ImageFormat::Rgba8
|
||||
| ImageFormat::Rgba8Snorm
|
||||
| ImageFormat::Rg32f
|
||||
| ImageFormat::Rg16f
|
||||
| ImageFormat::R11fG11fB10f
|
||||
| ImageFormat::R16f
|
||||
| ImageFormat::Rgba16
|
||||
| ImageFormat::Rgb10A2
|
||||
| ImageFormat::Rg16
|
||||
| ImageFormat::Rg8
|
||||
| ImageFormat::R16
|
||||
| ImageFormat::R8
|
||||
| ImageFormat::Rgba16Snorm
|
||||
| ImageFormat::Rg16Snorm
|
||||
| ImageFormat::Rg8Snorm
|
||||
| ImageFormat::R16Snorm
|
||||
| ImageFormat::R8Snorm => SampledType::F32,
|
||||
ImageFormat::Rgba32i
|
||||
| ImageFormat::Rgba16i
|
||||
| ImageFormat::Rgba8i
|
||||
| ImageFormat::R32i
|
||||
| ImageFormat::Rg32i
|
||||
| ImageFormat::Rg16i
|
||||
| ImageFormat::Rg8i
|
||||
| ImageFormat::R16i
|
||||
| ImageFormat::R8i => SampledType::I32,
|
||||
|
||||
ImageFormat::Rgba32ui
|
||||
| ImageFormat::Rgba16ui
|
||||
| ImageFormat::Rgba8ui
|
||||
| ImageFormat::R32ui
|
||||
| ImageFormat::Rgb10A2ui
|
||||
| ImageFormat::Rg32ui
|
||||
| ImageFormat::Rg16ui
|
||||
| ImageFormat::Rg8ui
|
||||
| ImageFormat::R16ui
|
||||
| ImageFormat::R8ui => SampledType::U32,
|
||||
|
||||
ImageFormat::R64ui => SampledType::U64,
|
||||
ImageFormat::R64i => SampledType::I64,
|
||||
|
||||
ImageFormat::Unknown => unreachable!(),
|
||||
});
|
||||
}
|
||||
|
||||
let sampled_type =
|
||||
sampled_type.ok_or_else(|| syn::Error::new(starting_span, MISSING_SAMPLE_ERROR))?;
|
||||
let format = format.ok_or_else(|| syn::Error::new(starting_span, MISSING_SAMPLE_ERROR))?;
|
||||
let depth = depth.unwrap_or(ImageDepth::Unknown);
|
||||
let arrayed = arrayed.unwrap_or(Arrayed::False);
|
||||
let multisampled = multisampled.unwrap_or(Multisampled::False);
|
||||
let sampled = sampled.unwrap_or(Sampled::Unknown);
|
||||
|
||||
Ok(Self {
|
||||
access_qualifier,
|
||||
arrayed,
|
||||
crate_root,
|
||||
depth,
|
||||
dimensionality,
|
||||
format,
|
||||
multisampled,
|
||||
sampled,
|
||||
sampled_type,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl quote::ToTokens for ImageType {
|
||||
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
|
||||
let crate_root = self.crate_root.clone().unwrap_or_else(|| syn::Path {
|
||||
leading_colon: None,
|
||||
segments: {
|
||||
let mut punct = syn::punctuated::Punctuated::new();
|
||||
punct.push(Ident::new("spirv_std", proc_macro2::Span::mixed_site()).into());
|
||||
|
||||
punct
|
||||
},
|
||||
});
|
||||
let access_qualifier = match self.access_qualifier {
|
||||
Some(aq) => {
|
||||
let aq = params::access_qualifier_to_tokens(&aq);
|
||||
quote!(Some(#crate_root::image::#aq))
|
||||
}
|
||||
None => quote!(None),
|
||||
};
|
||||
let dimensionality = params::dimensionality_to_tokens(&self.dimensionality);
|
||||
let arrayed = params::arrayed_to_tokens(&self.arrayed);
|
||||
let depth = params::image_depth_to_tokens(&self.depth);
|
||||
let format = params::image_format_to_tokens(&self.format);
|
||||
let multisampled = params::multisampled_to_tokens(&self.multisampled);
|
||||
let sampled = params::sampled_to_tokens(&self.sampled);
|
||||
let sampled_type = &self.sampled_type;
|
||||
|
||||
tokens.append_all(quote::quote! {
|
||||
#crate_root::image::Image<
|
||||
#crate_root::image::__private::#sampled_type,
|
||||
{ #crate_root::image::#dimensionality },
|
||||
{ #crate_root::image::#depth },
|
||||
{ #crate_root::image::#arrayed },
|
||||
{ #crate_root::image::#multisampled },
|
||||
{ #crate_root::image::#sampled },
|
||||
{ #crate_root::image::#format },
|
||||
{ #access_qualifier },
|
||||
>
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
mod params {
|
||||
use super::*;
|
||||
use proc_macro2::TokenStream;
|
||||
|
||||
pub fn access_qualifier_from_str(s: &str) -> Result<AccessQualifier, &'static str> {
|
||||
match s {
|
||||
"read" => Ok(AccessQualifier::ReadOnly),
|
||||
"write" => Ok(AccessQualifier::WriteOnly),
|
||||
"read_write" => Ok(AccessQualifier::ReadWrite),
|
||||
_ => Err("Invalid access qualifier."),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn image_format_from_str(s: &str) -> Result<ImageFormat, &'static str> {
|
||||
Ok(match s {
|
||||
"rgba32f" => ImageFormat::Rgba32f,
|
||||
"rgba16f" => ImageFormat::Rgba16f,
|
||||
"r32f" => ImageFormat::R32f,
|
||||
"rgba8" => ImageFormat::Rgba8,
|
||||
"rgba8_snorm" => ImageFormat::Rgba8Snorm,
|
||||
"rg32f" => ImageFormat::Rg32f,
|
||||
"rg16f" => ImageFormat::Rg16f,
|
||||
"r11f_g11f_b10f" => ImageFormat::R11fG11fB10f,
|
||||
"r16f" => ImageFormat::R16f,
|
||||
"rgba16" => ImageFormat::Rgba16,
|
||||
"rgb10_a2" => ImageFormat::Rgb10A2,
|
||||
"rg16" => ImageFormat::Rg16,
|
||||
"rg8" => ImageFormat::Rg8,
|
||||
"r16" => ImageFormat::R16,
|
||||
"r8" => ImageFormat::R8,
|
||||
"rgba16_snorm" => ImageFormat::Rgba16Snorm,
|
||||
"rg16_snorm" => ImageFormat::Rg16Snorm,
|
||||
"rg8_snorm" => ImageFormat::Rg8Snorm,
|
||||
"r16_snorm" => ImageFormat::R16Snorm,
|
||||
"r8_snorm" => ImageFormat::R8Snorm,
|
||||
"rgba32i" => ImageFormat::Rgba32i,
|
||||
"rgba16i" => ImageFormat::Rgba16i,
|
||||
"rgba8i" => ImageFormat::Rgba8i,
|
||||
"r32i" => ImageFormat::R32i,
|
||||
"rg32i" => ImageFormat::Rg32i,
|
||||
"rg16i" => ImageFormat::Rg16i,
|
||||
"rg8i" => ImageFormat::Rg8i,
|
||||
"r16i" => ImageFormat::R16i,
|
||||
"r8i" => ImageFormat::R8i,
|
||||
"rgba32ui" => ImageFormat::Rgba32ui,
|
||||
"rgba16ui" => ImageFormat::Rgba16ui,
|
||||
"rgba8ui" => ImageFormat::Rgba8ui,
|
||||
"r32ui" => ImageFormat::R32ui,
|
||||
"rgb10_a2ui" => ImageFormat::Rgb10A2ui,
|
||||
"rg32ui" => ImageFormat::Rg32ui,
|
||||
"rg16ui" => ImageFormat::Rg16ui,
|
||||
"rg8ui" => ImageFormat::Rg8ui,
|
||||
"r16ui" => ImageFormat::R16ui,
|
||||
"r8ui" => ImageFormat::R8ui,
|
||||
"r64ui" => ImageFormat::R64ui,
|
||||
"r64i" => ImageFormat::R64i,
|
||||
_ => return Err(
|
||||
"Unknown specified image format. Use `type=<type>` instead if this is intentional.",
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
/// The sampled type of an unknown image format.
|
||||
pub enum SampledType {
|
||||
U8,
|
||||
U16,
|
||||
U32,
|
||||
U64,
|
||||
I8,
|
||||
I16,
|
||||
I32,
|
||||
I64,
|
||||
F32,
|
||||
F64,
|
||||
}
|
||||
|
||||
impl quote::ToTokens for SampledType {
|
||||
fn to_tokens(&self, stream: &mut TokenStream) {
|
||||
stream.append_all(match self {
|
||||
Self::U8 => quote!(u8),
|
||||
Self::U16 => quote!(u16),
|
||||
Self::U32 => quote!(u32),
|
||||
Self::U64 => quote!(u64),
|
||||
Self::I8 => quote!(i8),
|
||||
Self::I16 => quote!(i16),
|
||||
Self::I32 => quote!(i32),
|
||||
Self::I64 => quote!(i64),
|
||||
Self::F32 => quote!(f32),
|
||||
Self::F64 => quote!(f64),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn access_qualifier_to_tokens(aq: &AccessQualifier) -> TokenStream {
|
||||
match aq {
|
||||
AccessQualifier::ReadOnly => quote!(AccessQualifier::ReadOnly),
|
||||
AccessQualifier::WriteOnly => quote!(AccessQualifier::WriteOnly),
|
||||
AccessQualifier::ReadWrite => quote!(AccessQualifier::ReadWrite),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn image_depth_to_tokens(id: &ImageDepth) -> TokenStream {
|
||||
match id {
|
||||
ImageDepth::True => quote!(ImageDepth::True),
|
||||
ImageDepth::False => quote!(ImageDepth::False),
|
||||
ImageDepth::Unknown => quote!(ImageDepth::Unknown),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn arrayed_to_tokens(arrayed: &Arrayed) -> TokenStream {
|
||||
match arrayed {
|
||||
Arrayed::True => quote!(Arrayed::True),
|
||||
Arrayed::False => quote!(Arrayed::False),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dimensionality_to_tokens(dim: &Dimensionality) -> TokenStream {
|
||||
match dim {
|
||||
Dimensionality::OneD => quote!(Dimensionality::OneD),
|
||||
Dimensionality::TwoD => quote!(Dimensionality::TwoD),
|
||||
Dimensionality::ThreeD => quote!(Dimensionality::ThreeD),
|
||||
Dimensionality::Rect => quote!(Dimensionality::Rect),
|
||||
Dimensionality::Cube => quote!(Dimensionality::Cube),
|
||||
Dimensionality::Buffer => quote!(Dimensionality::Buffer),
|
||||
Dimensionality::SubpassData => quote!(Dimensionality::SubpassData),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn multisampled_to_tokens(multisampled: &Multisampled) -> TokenStream {
|
||||
match multisampled {
|
||||
Multisampled::True => quote!(Multisampled::True),
|
||||
Multisampled::False => quote!(Multisampled::False),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sampled_to_tokens(sampled: &Sampled) -> TokenStream {
|
||||
match sampled {
|
||||
Sampled::Yes => quote!(Sampled::Yes),
|
||||
Sampled::No => quote!(Sampled::No),
|
||||
Sampled::Unknown => quote!(Sampled::Unknown),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn image_format_to_tokens(format: &ImageFormat) -> proc_macro2::TokenStream {
|
||||
let variant = {
|
||||
let variant = match format {
|
||||
ImageFormat::Unknown => "Unknown",
|
||||
ImageFormat::Rgba32f => "Rgba32f",
|
||||
ImageFormat::Rgba16f => "Rgba16f",
|
||||
ImageFormat::R32f => "R32f",
|
||||
ImageFormat::Rgba8 => "Rgba8",
|
||||
ImageFormat::Rgba8Snorm => "Rgba8Snorm",
|
||||
ImageFormat::Rg32f => "Rg32f",
|
||||
ImageFormat::Rg16f => "Rg16f",
|
||||
ImageFormat::R11fG11fB10f => "R11fG11fB10f",
|
||||
ImageFormat::R16f => "R16f",
|
||||
ImageFormat::Rgba16 => "Rgba16",
|
||||
ImageFormat::Rgb10A2 => "Rgb10A2",
|
||||
ImageFormat::Rg16 => "Rg16",
|
||||
ImageFormat::Rg8 => "Rg8",
|
||||
ImageFormat::R16 => "R16",
|
||||
ImageFormat::R8 => "R8",
|
||||
ImageFormat::Rgba16Snorm => "Rgba16Snorm",
|
||||
ImageFormat::Rg16Snorm => "Rg16Snorm",
|
||||
ImageFormat::Rg8Snorm => "Rg8Snorm",
|
||||
ImageFormat::R16Snorm => "R16Snorm",
|
||||
ImageFormat::R8Snorm => "R8Snorm",
|
||||
ImageFormat::Rgba32i => "Rgba32i",
|
||||
ImageFormat::Rgba16i => "Rgba16i",
|
||||
ImageFormat::Rgba8i => "Rgba8i",
|
||||
ImageFormat::R32i => "R32i",
|
||||
ImageFormat::Rg32i => "Rg32i",
|
||||
ImageFormat::Rg16i => "Rg16i",
|
||||
ImageFormat::Rg8i => "Rg8i",
|
||||
ImageFormat::R16i => "R16i",
|
||||
ImageFormat::R8i => "R8i",
|
||||
ImageFormat::Rgba32ui => "Rgba32ui",
|
||||
ImageFormat::Rgba16ui => "Rgba16ui",
|
||||
ImageFormat::Rgba8ui => "Rgba8ui",
|
||||
ImageFormat::R32ui => "R32ui",
|
||||
ImageFormat::Rgb10A2ui => "Rgb10A2ui",
|
||||
ImageFormat::Rg32ui => "Rg32ui",
|
||||
ImageFormat::Rg16ui => "Rg16ui",
|
||||
ImageFormat::Rg8ui => "Rg8ui",
|
||||
ImageFormat::R16ui => "R16ui",
|
||||
ImageFormat::R8ui => "R8ui",
|
||||
ImageFormat::R64ui => "R64ui",
|
||||
ImageFormat::R64i => "R64i",
|
||||
};
|
||||
|
||||
let variant = proc_macro2::Ident::new(variant, proc_macro2::Span::mixed_site());
|
||||
|
||||
quote!(#variant)
|
||||
};
|
||||
|
||||
quote!(ImageFormat::#variant)
|
||||
}
|
||||
}
|
@ -53,11 +53,65 @@
|
||||
// crate-specific exceptions:
|
||||
#![allow()]
|
||||
|
||||
mod image;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::{Delimiter, Group, Ident, Span, TokenTree};
|
||||
|
||||
use syn::{punctuated::Punctuated, spanned::Spanned, ItemFn, Token};
|
||||
|
||||
use quote::ToTokens;
|
||||
|
||||
/// A macro for creating SPIR-V `OpTypeImage` types.
|
||||
///
|
||||
/// The grammar for the macro is as follows:
|
||||
///
|
||||
/// ```no_compile
|
||||
/// Image!(
|
||||
/// <dimensionality>,
|
||||
/// <type|format>,
|
||||
/// [sampled[=<true|false>],]
|
||||
/// [multisampled[=<true|false>],]
|
||||
/// [arrayed[=<true|false>],]
|
||||
/// [depth[=<true|false>],]
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// A basic example looks like this:
|
||||
/// ```no_compile
|
||||
/// #[spirv(vertex)]
|
||||
/// fn main(#[spirv(descriptor_set = 0, binding = 0)] image: &Image!(2D, type=f32)) {}
|
||||
/// ```
|
||||
///
|
||||
/// ## Arguments
|
||||
///
|
||||
/// - `dimensionality` — Dimensionality of an image. Accepted values: `1D`,
|
||||
/// `2D`, `3D`, `rect`, `cube`, `subpass`.
|
||||
/// - `type` — The sampled type of an image, mutually exclusive with `format`,
|
||||
/// when set the image format is unknown. Accepted values: `f32`, `f64`,
|
||||
/// `u8`, `u16`, `u32`, `u64`, `i8`, `i16`, `i32`, `i64`.
|
||||
/// - `format` — The image format of the image, mutually exclusive with `type`,
|
||||
/// Accepted values: Camel case versions of [`ImageFormat`].
|
||||
/// - `sampled` — Whether it is known that the image will be used with a sampler
|
||||
/// at compile time, Accepted values: `true` or `false`. Default: `unknown`.
|
||||
/// - `multisampled` — Whether the image contains multisampled content. Accepted
|
||||
/// values: `true` or `false`. Default: `false`.
|
||||
/// - `arrayed` — Whether the image contains arrayed content. Accepted
|
||||
/// values: `true` or `false`. Default: `false`.
|
||||
/// - `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
|
||||
#[proc_macro]
|
||||
// The `Image` is supposed to be used in the type position, which
|
||||
// uses `PascalCase`.
|
||||
#[allow(nonstandard_style)]
|
||||
pub fn Image(item: TokenStream) -> TokenStream {
|
||||
let output = syn::parse_macro_input!(item as image::ImageType).into_token_stream();
|
||||
|
||||
output.into()
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn spirv(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let mut tokens = Vec::new();
|
8
crates/spirv-std/shared/Cargo.toml
Normal file
8
crates/spirv-std/shared/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "spirv-types"
|
||||
description = "SPIR-V types shared between spirv-std and spirv-std-macros"
|
||||
version = "0.4.0-alpha.5"
|
||||
authors = ["Embark <opensource@embark-studios.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/EmbarkStudios/rust-gpu"
|
228
crates/spirv-std/shared/src/image_params.rs
Normal file
228
crates/spirv-std/shared/src/image_params.rs
Normal file
@ -0,0 +1,228 @@
|
||||
/// The access permissions for the image.
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum AccessQualifier {
|
||||
/// A read only image.
|
||||
ReadOnly = 0,
|
||||
/// A write only image.
|
||||
WriteOnly = 1,
|
||||
/// A readable and writable image.
|
||||
ReadWrite = 2,
|
||||
}
|
||||
|
||||
/// Whether the image uses arrayed content.
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Arrayed {
|
||||
/// The image uses not arrayed content.
|
||||
False = 0,
|
||||
/// The image uses arrayed content.
|
||||
True = 1,
|
||||
}
|
||||
|
||||
impl From<bool> for Arrayed {
|
||||
fn from(val: bool) -> Self {
|
||||
if val {
|
||||
Self::True
|
||||
} else {
|
||||
Self::False
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The dimension of the image.
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Dimensionality {
|
||||
/// 1D
|
||||
OneD = 0,
|
||||
/// 2D
|
||||
TwoD = 1,
|
||||
/// 3D
|
||||
ThreeD = 2,
|
||||
/// 2D Cubemap texture
|
||||
Cube = 3,
|
||||
/// 2D Rectangle texture
|
||||
Rect = 4,
|
||||
/// 1D Buffer texture
|
||||
Buffer = 5,
|
||||
/// Vulkan subpass buffer
|
||||
SubpassData = 6,
|
||||
}
|
||||
|
||||
/// Whether a given image contains [depth] information. **Note** Whether or not
|
||||
/// to perform depth comparisons is a property of the sampling code, not of this
|
||||
/// type.
|
||||
///
|
||||
/// [depth]: https://en.wikipedia.org/wiki/Depth_map
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum ImageDepth {
|
||||
/// Indicates that the image does not contain depth information.
|
||||
False = 0,
|
||||
/// Indicates that the image contains depth information.
|
||||
True = 1,
|
||||
/// Indicates that is not known ahead of time whether the image has depth
|
||||
/// information or not.
|
||||
Unknown = 2,
|
||||
}
|
||||
|
||||
impl From<Option<bool>> for ImageDepth {
|
||||
fn from(val: Option<bool>) -> Self {
|
||||
match val {
|
||||
Some(true) => Self::True,
|
||||
Some(false) => Self::False,
|
||||
None => Self::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for ImageDepth {
|
||||
fn from(val: bool) -> Self {
|
||||
match val {
|
||||
true => Self::True,
|
||||
false => Self::False,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the image uses arrayed content.
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Multisampled {
|
||||
/// The image contains single-sampled content.
|
||||
False = 0,
|
||||
/// The image contains multisampled content.
|
||||
True = 1,
|
||||
}
|
||||
|
||||
impl From<bool> for Multisampled {
|
||||
fn from(val: bool) -> Self {
|
||||
if val {
|
||||
Self::True
|
||||
} else {
|
||||
Self::False
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether or not the image will be accessed in combination with a sampler.
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Sampled {
|
||||
/// Indicates that it is not known ahead of time whether the image will use
|
||||
/// a sampler or not.
|
||||
Unknown = 0,
|
||||
/// The image will be used with a sampler.
|
||||
Yes = 1,
|
||||
/// The image will not be used with a sampler.
|
||||
No = 2,
|
||||
}
|
||||
|
||||
impl From<Option<bool>> for Sampled {
|
||||
fn from(val: Option<bool>) -> Self {
|
||||
match val {
|
||||
Some(true) => Self::Yes,
|
||||
Some(false) => Self::No,
|
||||
None => Self::Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for Sampled {
|
||||
fn from(val: bool) -> Self {
|
||||
match val {
|
||||
true => Self::Yes,
|
||||
false => Self::No,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The underlying internal representation of the image.
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub enum ImageFormat {
|
||||
/// Representation not known at compile time.
|
||||
Unknown,
|
||||
/// RGBA channels, 32 bit floating point integer.
|
||||
Rgba32f,
|
||||
/// RGBA channels, 16 bit floating point integer.
|
||||
Rgba16f,
|
||||
/// RGBA channels, 16 bit floating point integer.
|
||||
R32f,
|
||||
/// RGBA channels, 8 bit floating point integer.
|
||||
Rgba8,
|
||||
/// RGBA channels, 8 bit signed normalized integer.
|
||||
Rgba8Snorm,
|
||||
/// Red+Green channels, 32 bit floating point integer.
|
||||
Rg32f,
|
||||
/// Red+Green channels, 16 bit floating point integer.
|
||||
Rg16f,
|
||||
/// 32 bit unsigned integer containing two 11 bit floating point integers
|
||||
/// for the Red and Green channels, and a 10 bit floating point integer for
|
||||
/// the Blue channel.
|
||||
R11fG11fB10f,
|
||||
/// Red channel, 16 bit floating point.
|
||||
R16f,
|
||||
/// RGBA channel, 16 bit floating point.
|
||||
Rgba16,
|
||||
/// 32 bit unsigned integer containing three 10 bit unsigned normalized
|
||||
/// integers for the Red, Green, and Blue channels; with a 2 unsigned
|
||||
/// normalized integer for the Alpha channel.
|
||||
Rgb10A2,
|
||||
/// Red+Green channels, 16 bit floating point integer.
|
||||
Rg16,
|
||||
/// Red+Green channels, 8 bit floating point integer.
|
||||
Rg8,
|
||||
/// Red+Green channels, 16 bit floating point integer.
|
||||
R16,
|
||||
/// Red channel, 8 bit floating point integer.
|
||||
R8,
|
||||
/// RGBA channels, 16 bit signed normalized integer.
|
||||
Rgba16Snorm,
|
||||
/// RGB channels, 16 bit signed normalized integer.
|
||||
Rg16Snorm,
|
||||
/// Red+Green channels, 8 bit signed normalized integer.
|
||||
Rg8Snorm,
|
||||
/// Red channel, 16 bit signed normalized integer.
|
||||
R16Snorm,
|
||||
/// Red channel, 16 bit signed normalized integer.
|
||||
R8Snorm,
|
||||
/// RGBA channels, 32 bit signed integer.
|
||||
Rgba32i,
|
||||
/// RGBA channels, 16 bit signed integer.
|
||||
Rgba16i,
|
||||
/// RGBA channels, 8 bit signed integer.
|
||||
Rgba8i,
|
||||
/// Red channel, 32 bit signed integer.
|
||||
R32i,
|
||||
/// Red+Green channels, 32 bit signed integer.
|
||||
Rg32i,
|
||||
/// Red+Green channels, 16 bit signed integer.
|
||||
Rg16i,
|
||||
/// Red+Green channels, 8 bit signed integer.
|
||||
Rg8i,
|
||||
/// Red channel, 16 bit signed integer.
|
||||
R16i,
|
||||
/// Red channel, 8 bit signed integer.
|
||||
R8i,
|
||||
/// RGBA channels, 32 bit unsigned integer.
|
||||
Rgba32ui,
|
||||
/// RGBA channels, 16 bit unsigned integer.
|
||||
Rgba16ui,
|
||||
/// RGBA channels, 8 bit unsigned integer.
|
||||
Rgba8ui,
|
||||
/// Red channel, 32 bit unsigned integer.
|
||||
R32ui,
|
||||
/// 32 bit unsigned integer containing three 10 bit unsigned integers for
|
||||
/// the Red, Green, and Blue channels, and a 2 bit unsigned integer for the
|
||||
/// Alpha channel.
|
||||
Rgb10A2ui,
|
||||
/// Red+Green channels, 32 bit unsigned integer.
|
||||
Rg32ui,
|
||||
/// Red+Green channels, 16 bit unsigned integer.
|
||||
Rg16ui,
|
||||
/// Red+Green channels, 8 bit unsigned integer.
|
||||
Rg8ui,
|
||||
/// Red channel, 16 bit unsigned integer.
|
||||
R16ui,
|
||||
/// Red channel, 8 bit unsigned integer.
|
||||
R8ui,
|
||||
/// Red channel, 64 bit unsigned integer.
|
||||
R64ui,
|
||||
/// Red channel, 64 bit signed integer.
|
||||
R64i,
|
||||
}
|
5
crates/spirv-std/shared/src/lib.rs
Normal file
5
crates/spirv-std/shared/src/lib.rs
Normal file
@ -0,0 +1,5 @@
|
||||
//! Small shared crate, to share definitions between `spirv-std`
|
||||
//! and `spirv-std-macros`.
|
||||
#![no_std]
|
||||
|
||||
pub mod image_params;
|
@ -29,8 +29,8 @@ macro_rules! deriv_fn {
|
||||
/// Returns the partial derivative of `component` with respect to the window's X
|
||||
/// coordinate. Returns the same result as either [`ddx_fine`] or
|
||||
/// [`ddx_coarse`], selection of which one is dependent on external factors.
|
||||
#[spirv_std_macros::vectorized]
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[crate::macros::vectorized]
|
||||
#[crate::macros::gpu_only]
|
||||
pub fn ddx<F: Float>(component: F) -> F {
|
||||
deriv_fn!(component, OpDPdx, false)
|
||||
}
|
||||
@ -38,8 +38,8 @@ pub fn ddx<F: Float>(component: F) -> F {
|
||||
/// Returns the partial derivative of `component` with respect to the window's X
|
||||
/// coordinate. Uses local differencing based on the value of `component` for
|
||||
/// the current fragment and its immediate neighbor(s).
|
||||
#[spirv_std_macros::vectorized]
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[crate::macros::vectorized]
|
||||
#[crate::macros::gpu_only]
|
||||
pub fn ddx_fine<F: Float>(component: F) -> F {
|
||||
deriv_fn!(component, OpDPdxFine, true)
|
||||
}
|
||||
@ -50,8 +50,8 @@ pub fn ddx_fine<F: Float>(component: F) -> F {
|
||||
/// includes the value of `component` for the current fragment. That is, over a
|
||||
/// given area, the implementation can compute X derivatives in fewer unique
|
||||
/// locations than would be allowed by [`ddx_fine`].
|
||||
#[spirv_std_macros::vectorized]
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[crate::macros::vectorized]
|
||||
#[crate::macros::gpu_only]
|
||||
pub fn ddx_coarse<F: Float>(component: F) -> F {
|
||||
deriv_fn!(component, OpDPdxCoarse, true)
|
||||
}
|
||||
@ -59,8 +59,8 @@ pub fn ddx_coarse<F: Float>(component: F) -> F {
|
||||
/// Returns the partial derivative of `component` with respect to the window's Y
|
||||
/// coordinate. Returns the same result as either [`ddy_fine`] or
|
||||
/// [`ddy_coarse`], selection of which one is dependent on external factors.
|
||||
#[spirv_std_macros::vectorized]
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[crate::macros::vectorized]
|
||||
#[crate::macros::gpu_only]
|
||||
pub fn ddy<F: Float>(component: F) -> F {
|
||||
deriv_fn!(component, OpDPdy, false)
|
||||
}
|
||||
@ -68,8 +68,8 @@ pub fn ddy<F: Float>(component: F) -> F {
|
||||
/// Returns the partial derivative of `component` with respect to the window's Y
|
||||
/// coordinate. Uses local differencing based on the value of `component` for
|
||||
/// the current fragment and its immediate neighbor(s).
|
||||
#[spirv_std_macros::vectorized]
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[crate::macros::vectorized]
|
||||
#[crate::macros::gpu_only]
|
||||
pub fn ddy_fine<F: Float>(component: F) -> F {
|
||||
deriv_fn!(component, OpDPdyFine, true)
|
||||
}
|
||||
@ -80,32 +80,32 @@ pub fn ddy_fine<F: Float>(component: F) -> F {
|
||||
/// includes the value of `component` for the current fragment. That is, over a
|
||||
/// given area, the implementation can compute Y derivatives in fewer unique
|
||||
/// locations than would be allowed by [`ddy_fine`].
|
||||
#[spirv_std_macros::vectorized]
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[crate::macros::vectorized]
|
||||
#[crate::macros::gpu_only]
|
||||
pub fn ddy_coarse<F: Float>(component: F) -> F {
|
||||
deriv_fn!(component, OpDPdyCoarse, true)
|
||||
}
|
||||
|
||||
/// Returns the sum of the absolute values of [`ddx`] and [`ddy`] as a single
|
||||
/// operation.
|
||||
#[spirv_std_macros::vectorized]
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[crate::macros::vectorized]
|
||||
#[crate::macros::gpu_only]
|
||||
pub fn fwidth<F: Float>(component: F) -> F {
|
||||
deriv_fn!(component, OpFwidth, false)
|
||||
}
|
||||
|
||||
/// Returns the sum of the absolute values of [`ddx_fine`] and [`ddy_fine`] as a
|
||||
/// single operation.
|
||||
#[spirv_std_macros::vectorized]
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[crate::macros::vectorized]
|
||||
#[crate::macros::gpu_only]
|
||||
pub fn fwidth_fine<F: Float>(component: F) -> F {
|
||||
deriv_fn!(component, OpFwidthFine, true)
|
||||
}
|
||||
|
||||
/// Returns the sum of the absolute values of [`ddx_coarse`] and [`ddy_coarse`]
|
||||
/// as a single operation.
|
||||
#[spirv_std_macros::vectorized]
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[crate::macros::vectorized]
|
||||
#[crate::macros::gpu_only]
|
||||
pub fn fwidth_coarse<F: Float>(component: F) -> F {
|
||||
deriv_fn!(component, OpFwidthCoarse, true)
|
||||
}
|
||||
|
715
crates/spirv-std/src/image.rs
Normal file
715
crates/spirv-std/src/image.rs
Normal file
@ -0,0 +1,715 @@
|
||||
//! Image types
|
||||
|
||||
// Rustfmt formats long marker trait impls over multiple lines which makes them
|
||||
// harder to read.
|
||||
#[rustfmt::skip]
|
||||
mod params;
|
||||
|
||||
pub use self::params::{ImageCoordinate, SampleType};
|
||||
pub use crate::macros::Image;
|
||||
pub use spirv_types::image_params::{
|
||||
AccessQualifier, Arrayed, Dimensionality, ImageDepth, ImageFormat, Multisampled, Sampled,
|
||||
};
|
||||
|
||||
use crate::{float::Float, integer::Integer, vector::Vector, Sampler};
|
||||
|
||||
/// Re-export of primitive types to ensure the `Image` proc macro always points
|
||||
/// to the right type.
|
||||
#[doc(hidden)]
|
||||
pub mod __private {
|
||||
pub use {f32, f64, i16, i32, i64, i8, u16, u32, u64, u8};
|
||||
}
|
||||
|
||||
pub type Image2d = crate::Image!(2D, type=f32, sampled, __crate_root=crate);
|
||||
pub type Cubemap = crate::Image!(cube, type=f32, sampled, __crate_root=crate);
|
||||
pub type Image2dArray = crate::Image!(cube, type=f32, sampled, arrayed, __crate_root=crate);
|
||||
pub type StorageImage2d = crate::Image!(cube, type=f32, sampled=false, __crate_root=crate);
|
||||
|
||||
/// An opaque image type. Corresponds to `OpTypeImage`.
|
||||
#[spirv(generic_image_type)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Image<
|
||||
SampledType: SampleType<FORMAT>,
|
||||
const DIM: Dimensionality,
|
||||
const DEPTH: ImageDepth,
|
||||
const ARRAYED: Arrayed,
|
||||
const MULTISAMPLED: Multisampled,
|
||||
const SAMPLED: Sampled,
|
||||
const FORMAT: ImageFormat,
|
||||
const ACCESS_QUALIFIER: Option<AccessQualifier>,
|
||||
> {
|
||||
_x: u32,
|
||||
_marker: core::marker::PhantomData<SampledType>,
|
||||
}
|
||||
|
||||
impl<
|
||||
SampledType: SampleType<FORMAT>,
|
||||
const DIM: Dimensionality,
|
||||
const DEPTH: ImageDepth,
|
||||
const ARRAYED: Arrayed,
|
||||
const MULTISAMPLED: Multisampled,
|
||||
const FORMAT: ImageFormat,
|
||||
const ACCESS_QUALIFIER: Option<AccessQualifier>,
|
||||
>
|
||||
Image<
|
||||
SampledType,
|
||||
DIM,
|
||||
DEPTH,
|
||||
ARRAYED,
|
||||
MULTISAMPLED,
|
||||
{ Sampled::Yes },
|
||||
FORMAT,
|
||||
ACCESS_QUALIFIER,
|
||||
>
|
||||
{
|
||||
/// Fetch a single texel with a sampler set at compile time
|
||||
#[crate::macros::gpu_only]
|
||||
#[doc(alias = "OpImageFetch")]
|
||||
pub fn fetch<V, I>(&self, coordinate: impl ImageCoordinate<I, DIM, ARRAYED>) -> V
|
||||
where
|
||||
V: Vector<SampledType, 4>,
|
||||
I: Integer,
|
||||
{
|
||||
let mut result = V::default();
|
||||
unsafe {
|
||||
asm! {
|
||||
"%image = OpLoad _ {this}",
|
||||
"%coordinate = OpLoad _ {coordinate}",
|
||||
"%result = OpImageFetch typeof*{result} %image %coordinate",
|
||||
"OpStore {result} %result",
|
||||
result = in(reg) &mut result,
|
||||
this = in(reg) self,
|
||||
coordinate = in(reg) &coordinate,
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
SampledType: SampleType<FORMAT>,
|
||||
const DIM: Dimensionality,
|
||||
const DEPTH: ImageDepth,
|
||||
const FORMAT: ImageFormat,
|
||||
const ARRAYED: Arrayed,
|
||||
const SAMPLED: Sampled,
|
||||
const ACCESS_QUALIFIER: Option<AccessQualifier>,
|
||||
>
|
||||
Image<
|
||||
SampledType,
|
||||
DIM,
|
||||
DEPTH,
|
||||
ARRAYED,
|
||||
{ Multisampled::False },
|
||||
SAMPLED,
|
||||
FORMAT,
|
||||
ACCESS_QUALIFIER,
|
||||
>
|
||||
{
|
||||
/// Sample texels at `coord` from the image using `sampler`.
|
||||
#[crate::macros::gpu_only]
|
||||
pub fn sample<F, V>(&self, sampler: Sampler, coord: impl ImageCoordinate<F, DIM, ARRAYED>) -> V
|
||||
where
|
||||
F: Float,
|
||||
V: Vector<SampledType, 4>,
|
||||
{
|
||||
unsafe {
|
||||
let mut result = Default::default();
|
||||
asm!(
|
||||
"%typeSampledImage = OpTypeSampledImage typeof*{1}",
|
||||
"%image = OpLoad typeof*{1} {1}",
|
||||
"%sampler = OpLoad typeof*{2} {2}",
|
||||
"%coord = OpLoad typeof*{3} {3}",
|
||||
"%sampledImage = OpSampledImage %typeSampledImage %image %sampler",
|
||||
"%result = OpImageSampleImplicitLod typeof*{0} %sampledImage %coord",
|
||||
"OpStore {0} %result",
|
||||
in(reg) &mut result,
|
||||
in(reg) self,
|
||||
in(reg) &sampler,
|
||||
in(reg) &coord
|
||||
);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetch a single texel with a sampler set at compile time
|
||||
#[crate::macros::gpu_only]
|
||||
#[doc(alias = "OpImageSampleExplicitLod")]
|
||||
/// Sample the image at a coordinate by a lod
|
||||
pub fn sample_by_lod<F, V>(
|
||||
&self,
|
||||
sampler: Sampler,
|
||||
coordinate: impl ImageCoordinate<F, DIM, ARRAYED>,
|
||||
lod: f32,
|
||||
) -> V
|
||||
where
|
||||
F: Float,
|
||||
V: Vector<SampledType, 4>,
|
||||
{
|
||||
let mut result = Default::default();
|
||||
unsafe {
|
||||
asm!(
|
||||
"%image = OpLoad _ {this}",
|
||||
"%sampler = OpLoad _ {sampler}",
|
||||
"%coordinate = OpLoad _ {coordinate}",
|
||||
"%lod = OpLoad _ {lod}",
|
||||
"%sampledImage = OpSampledImage _ %image %sampler",
|
||||
"%result = OpImageSampleExplicitLod _ %sampledImage %coordinate Lod %lod",
|
||||
"OpStore {result} %result",
|
||||
result = in(reg) &mut result,
|
||||
this = in(reg) self,
|
||||
sampler = in(reg) &sampler,
|
||||
coordinate = in(reg) &coordinate,
|
||||
lod = in(reg) &lod
|
||||
);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
#[crate::macros::gpu_only]
|
||||
#[doc(alias = "OpImageSampleExplicitLod")]
|
||||
/// Sample the image based on a gradient formed by (dx, dy). Specifically, ([du/dx, dv/dx], [du/dy, dv/dy])
|
||||
pub fn sample_by_gradient<F, V>(
|
||||
&self,
|
||||
sampler: Sampler,
|
||||
coordinate: impl ImageCoordinate<F, DIM, ARRAYED>,
|
||||
gradient_dx: impl ImageCoordinate<F, DIM, { Arrayed::False }>,
|
||||
gradient_dy: impl ImageCoordinate<F, DIM, { Arrayed::False }>,
|
||||
) -> V
|
||||
where
|
||||
F: Float,
|
||||
V: Vector<SampledType, 4>,
|
||||
{
|
||||
let mut result = Default::default();
|
||||
unsafe {
|
||||
asm!(
|
||||
"%image = OpLoad _ {this}",
|
||||
"%sampler = OpLoad _ {sampler}",
|
||||
"%coordinate = OpLoad _ {coordinate}",
|
||||
"%gradient_dx = OpLoad _ {gradient_dx}",
|
||||
"%gradient_dy = OpLoad _ {gradient_dy}",
|
||||
"%sampledImage = OpSampledImage _ %image %sampler",
|
||||
"%result = OpImageSampleExplicitLod _ %sampledImage %coordinate Grad %gradient_dx %gradient_dy",
|
||||
"OpStore {result} %result",
|
||||
result = in(reg) &mut result,
|
||||
this = in(reg) self,
|
||||
sampler = in(reg) &sampler,
|
||||
coordinate = in(reg) &coordinate,
|
||||
gradient_dx = in(reg) &gradient_dx,
|
||||
gradient_dy = in(reg) &gradient_dy,
|
||||
);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
#[crate::macros::gpu_only]
|
||||
#[doc(alias = "OpImageSampleDrefImplicitLod")]
|
||||
/// Sample the image's depth reference
|
||||
pub fn sample_depth_reference<F>(
|
||||
&self,
|
||||
sampler: Sampler,
|
||||
coordinate: impl ImageCoordinate<F, DIM, ARRAYED>,
|
||||
depth_reference: f32,
|
||||
) -> SampledType
|
||||
where
|
||||
F: Float,
|
||||
{
|
||||
let mut result = Default::default();
|
||||
unsafe {
|
||||
asm!(
|
||||
"%image = OpLoad _ {this}",
|
||||
"%sampler = OpLoad _ {sampler}",
|
||||
"%coordinate = OpLoad _ {coordinate}",
|
||||
"%depth_reference = OpLoad _ {depth_reference}", // not required to do this way, but done for consistency
|
||||
"%sampledImage = OpSampledImage _ %image %sampler",
|
||||
"%result = OpImageSampleDrefImplicitLod _ %sampledImage %coordinate %depth_reference",
|
||||
"OpStore {result} %result",
|
||||
result = in(reg) &mut result,
|
||||
this = in(reg) self,
|
||||
sampler = in(reg) &sampler,
|
||||
coordinate = in(reg) &coordinate,
|
||||
depth_reference = in(reg) &depth_reference,
|
||||
);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
#[crate::macros::gpu_only]
|
||||
#[doc(alias = "OpImageSampleDrefExplicitLod")]
|
||||
/// Sample the image's depth reference based on an explicit lod
|
||||
pub fn sample_depth_reference_by_lod<F>(
|
||||
&self,
|
||||
sampler: Sampler,
|
||||
coordinate: impl ImageCoordinate<F, DIM, ARRAYED>,
|
||||
depth_reference: f32,
|
||||
lod: f32,
|
||||
) -> SampledType
|
||||
where
|
||||
F: Float,
|
||||
{
|
||||
let mut result = Default::default();
|
||||
unsafe {
|
||||
asm!(
|
||||
"%image = OpLoad _ {this}",
|
||||
"%sampler = OpLoad _ {sampler}",
|
||||
"%coordinate = OpLoad _ {coordinate}",
|
||||
"%depth_reference = OpLoad _ {depth_reference}",
|
||||
"%lod = OpLoad _ {lod}",
|
||||
"%sampledImage = OpSampledImage _ %image %sampler",
|
||||
"%result = OpImageSampleDrefExplicitLod _ %sampledImage %coordinate %depth_reference Lod %lod",
|
||||
"OpStore {result} %result",
|
||||
result = in(reg) &mut result,
|
||||
this = in(reg) self,
|
||||
sampler = in(reg) &sampler,
|
||||
coordinate = in(reg) &coordinate,
|
||||
depth_reference = in(reg) &depth_reference,
|
||||
lod = in(reg) &lod,
|
||||
)
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
#[crate::macros::gpu_only]
|
||||
#[doc(alias = "OpImageSampleDrefExplicitLod")]
|
||||
/// Sample the image's depth reference based on a gradient formed by (dx, dy).
|
||||
/// Specifically, ([du/dx, dv/dx], [du/dy, dv/dy])
|
||||
pub fn sample_depth_reference_by_gradient<F>(
|
||||
&self,
|
||||
sampler: Sampler,
|
||||
coordinate: impl ImageCoordinate<F, DIM, ARRAYED>,
|
||||
depth_reference: f32,
|
||||
gradient_dx: impl ImageCoordinate<F, DIM, { Arrayed::False }>,
|
||||
gradient_dy: impl ImageCoordinate<F, DIM, { Arrayed::False }>,
|
||||
) -> SampledType
|
||||
where
|
||||
F: Float,
|
||||
{
|
||||
let mut result = Default::default();
|
||||
unsafe {
|
||||
asm!(
|
||||
"%image = OpLoad _ {this}",
|
||||
"%sampler = OpLoad _ {sampler}",
|
||||
"%coordinate = OpLoad _ {coordinate}",
|
||||
"%depth_reference = OpLoad _ {depth_reference}",
|
||||
"%gradient_dx = OpLoad _ {gradient_dx}",
|
||||
"%gradient_dy = OpLoad _ {gradient_dy}",
|
||||
"%sampledImage = OpSampledImage _ %image %sampler",
|
||||
"%result = OpImageSampleDrefExplicitLod _ %sampledImage %coordinate %depth_reference Grad %gradient_dx %gradient_dy",
|
||||
"OpStore {result} %result",
|
||||
result = in(reg) &mut result,
|
||||
this = in(reg) self,
|
||||
sampler = in(reg) &sampler,
|
||||
coordinate = in(reg) &coordinate,
|
||||
depth_reference = in(reg) &depth_reference,
|
||||
gradient_dx = in(reg) &gradient_dx,
|
||||
gradient_dy = in(reg) &gradient_dy,
|
||||
);
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
SampledType: SampleType<FORMAT>,
|
||||
const DIM: Dimensionality,
|
||||
const DEPTH: ImageDepth,
|
||||
const SAMPLED: Sampled,
|
||||
const FORMAT: ImageFormat,
|
||||
const ACCESS_QUALIFIER: Option<AccessQualifier>,
|
||||
>
|
||||
Image<
|
||||
SampledType,
|
||||
DIM,
|
||||
DEPTH,
|
||||
{ Arrayed::False },
|
||||
{ Multisampled::False },
|
||||
SAMPLED,
|
||||
FORMAT,
|
||||
ACCESS_QUALIFIER,
|
||||
>
|
||||
{
|
||||
/// Fetch a single texel with a sampler set at compile time
|
||||
#[crate::macros::gpu_only]
|
||||
#[doc(alias = "OpImageFetch")]
|
||||
pub fn sample_with_project_coordinate<F, V>(
|
||||
&self,
|
||||
sampler: Sampler,
|
||||
project_coordinate: impl ImageCoordinate<F, DIM, { Arrayed::True }>,
|
||||
) -> V
|
||||
where
|
||||
F: Float,
|
||||
V: Vector<SampledType, 4>,
|
||||
{
|
||||
unsafe {
|
||||
let mut result = Default::default();
|
||||
asm!(
|
||||
"%image = OpLoad _ {this}",
|
||||
"%sampler = OpLoad _ {sampler}",
|
||||
"%project_coordinate = OpLoad _ {project_coordinate}",
|
||||
"%sampledImage = OpSampledImage _ %image %sampler",
|
||||
"%result = OpImageSampleProjImplicitLod _ %sampledImage %project_coordinate",
|
||||
"OpStore {result} %result",
|
||||
result = in(reg) &mut result,
|
||||
this = in(reg) self,
|
||||
sampler = in(reg) &sampler,
|
||||
project_coordinate = in(reg) &project_coordinate,
|
||||
);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
#[crate::macros::gpu_only]
|
||||
#[doc(alias = "OpImageSampleProjExplicitLod")]
|
||||
/// Sample the image with a project coordinate by a lod
|
||||
pub fn sample_with_project_coordinate_by_lod<F, V>(
|
||||
&self,
|
||||
sampler: Sampler,
|
||||
project_coordinate: impl ImageCoordinate<F, DIM, { Arrayed::True }>,
|
||||
lod: f32,
|
||||
) -> V
|
||||
where
|
||||
F: Float,
|
||||
V: Vector<SampledType, 4>,
|
||||
{
|
||||
let mut result = Default::default();
|
||||
unsafe {
|
||||
asm!(
|
||||
"%image = OpLoad _ {this}",
|
||||
"%sampler = OpLoad _ {sampler}",
|
||||
"%project_coordinate = OpLoad _ {project_coordinate}",
|
||||
"%lod = OpLoad _ {lod}",
|
||||
"%sampledImage = OpSampledImage _ %image %sampler",
|
||||
"%result = OpImageSampleProjExplicitLod _ %sampledImage %project_coordinate Lod %lod",
|
||||
"OpStore {result} %result",
|
||||
result = in(reg) &mut result,
|
||||
this = in(reg) self,
|
||||
sampler = in(reg) &sampler,
|
||||
project_coordinate = in(reg) &project_coordinate,
|
||||
lod = in(reg) &lod
|
||||
);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
#[crate::macros::gpu_only]
|
||||
#[doc(alias = "OpImageSampleProjExplicitLod")]
|
||||
/// Sample the image with a project coordinate based on a gradient formed by (dx, dy). Specifically, ([du/dx, dv/dx], [du/dy, dv/dy])
|
||||
pub fn sample_with_project_coordinate_by_gradient<F, V>(
|
||||
&self,
|
||||
sampler: Sampler,
|
||||
project_coordinate: impl ImageCoordinate<F, DIM, { Arrayed::True }>,
|
||||
gradient_dx: impl ImageCoordinate<F, DIM, { Arrayed::False }>,
|
||||
gradient_dy: impl ImageCoordinate<F, DIM, { Arrayed::False }>,
|
||||
) -> V
|
||||
where
|
||||
F: Float,
|
||||
V: Vector<SampledType, 4>,
|
||||
{
|
||||
let mut result = Default::default();
|
||||
unsafe {
|
||||
asm!(
|
||||
"%image = OpLoad _ {this}",
|
||||
"%sampler = OpLoad _ {sampler}",
|
||||
"%project_coordinate = OpLoad _ {project_coordinate}",
|
||||
"%gradient_dx = OpLoad _ {gradient_dx}",
|
||||
"%gradient_dy = OpLoad _ {gradient_dy}",
|
||||
"%sampledImage = OpSampledImage _ %image %sampler",
|
||||
"%result = OpImageSampleProjExplicitLod _ %sampledImage %project_coordinate Grad %gradient_dx %gradient_dy",
|
||||
"OpStore {result} %result",
|
||||
result = in(reg) &mut result,
|
||||
this = in(reg) self,
|
||||
sampler = in(reg) &sampler,
|
||||
project_coordinate = in(reg) &project_coordinate,
|
||||
gradient_dx = in(reg) &gradient_dx,
|
||||
gradient_dy = in(reg) &gradient_dy,
|
||||
);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
#[crate::macros::gpu_only]
|
||||
#[doc(alias = "OpImageSampleProjDrefImplicitLod")]
|
||||
/// Sample the image's depth reference with the project coordinate
|
||||
pub fn sample_depth_reference_with_project_coordinate<F>(
|
||||
&self,
|
||||
sampler: Sampler,
|
||||
project_coordinate: impl ImageCoordinate<F, DIM, { Arrayed::True }>,
|
||||
depth_reference: f32,
|
||||
) -> SampledType
|
||||
where
|
||||
F: Float,
|
||||
{
|
||||
let mut result = Default::default();
|
||||
unsafe {
|
||||
asm!(
|
||||
"%image = OpLoad _ {this}",
|
||||
"%sampler = OpLoad _ {sampler}",
|
||||
"%project_coordinate = OpLoad _ {project_coordinate}",
|
||||
"%depth_reference = OpLoad _ {depth_reference}", // not required to do this way, but done for consistency
|
||||
"%sampledImage = OpSampledImage _ %image %sampler",
|
||||
"%result = OpImageSampleProjDrefImplicitLod _ %sampledImage %project_coordinate %depth_reference",
|
||||
"OpStore {result} %result",
|
||||
result = in(reg) &mut result,
|
||||
this = in(reg) self,
|
||||
sampler = in(reg) &sampler,
|
||||
project_coordinate = in(reg) &project_coordinate,
|
||||
depth_reference = in(reg) &depth_reference,
|
||||
);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
#[crate::macros::gpu_only]
|
||||
#[doc(alias = "OpImageSampleProjDrefExplicitLod")]
|
||||
/// Sample the image's depth reference with the project coordinate based on an explicit lod
|
||||
pub fn sample_depth_reference_with_project_coordinate_by_lod<F>(
|
||||
&self,
|
||||
sampler: Sampler,
|
||||
coordinate: impl ImageCoordinate<F, DIM, { Arrayed::True }>,
|
||||
depth_reference: f32,
|
||||
lod: f32,
|
||||
) -> SampledType
|
||||
where
|
||||
F: Float,
|
||||
{
|
||||
let mut result = Default::default();
|
||||
unsafe {
|
||||
asm!(
|
||||
"%image = OpLoad _ {this}",
|
||||
"%sampler = OpLoad _ {sampler}",
|
||||
"%coordinate = OpLoad _ {coordinate}",
|
||||
"%depth_reference = OpLoad _ {depth_reference}",
|
||||
"%lod = OpLoad _ {lod}",
|
||||
"%sampledImage = OpSampledImage _ %image %sampler",
|
||||
"%result = OpImageSampleProjDrefExplicitLod _ %sampledImage %coordinate %depth_reference Lod %lod",
|
||||
"OpStore {result} %result",
|
||||
result = in(reg) &mut result,
|
||||
this = in(reg) self,
|
||||
sampler = in(reg) &sampler,
|
||||
coordinate = in(reg) &coordinate,
|
||||
depth_reference = in(reg) &depth_reference,
|
||||
lod = in(reg) &lod,
|
||||
)
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
#[crate::macros::gpu_only]
|
||||
#[doc(alias = "OpImageSampleProjDrefExplicitLod")]
|
||||
/// Sample the image's depth reference with the project coordinate based on a gradient formed by (dx, dy).
|
||||
/// Specifically, ([du/dx, dv/dx], [du/dy, dv/dy])
|
||||
pub fn sample_depth_reference_with_project_coordinate_by_gradient<F>(
|
||||
&self,
|
||||
sampler: Sampler,
|
||||
coordinate: impl ImageCoordinate<F, DIM, { Arrayed::True }>,
|
||||
depth_reference: f32,
|
||||
gradient_dx: impl ImageCoordinate<F, DIM, { Arrayed::False }>,
|
||||
gradient_dy: impl ImageCoordinate<F, DIM, { Arrayed::False }>,
|
||||
) -> SampledType
|
||||
where
|
||||
F: Float,
|
||||
{
|
||||
let mut result = Default::default();
|
||||
unsafe {
|
||||
asm!(
|
||||
"%image = OpLoad _ {this}",
|
||||
"%sampler = OpLoad _ {sampler}",
|
||||
"%coordinate = OpLoad _ {coordinate}",
|
||||
"%depth_reference = OpLoad _ {depth_reference}",
|
||||
"%gradient_dx = OpLoad _ {gradient_dx}",
|
||||
"%gradient_dy = OpLoad _ {gradient_dy}",
|
||||
"%sampledImage = OpSampledImage _ %image %sampler",
|
||||
"%result = OpImageSampleProjDrefExplicitLod _ %sampledImage %coordinate %depth_reference Grad %gradient_dx %gradient_dy",
|
||||
"OpStore {result} %result",
|
||||
result = in(reg) &mut result,
|
||||
this = in(reg) self,
|
||||
sampler = in(reg) &sampler,
|
||||
coordinate = in(reg) &coordinate,
|
||||
depth_reference = in(reg) &depth_reference,
|
||||
gradient_dx = in(reg) &gradient_dx,
|
||||
gradient_dy = in(reg) &gradient_dy,
|
||||
);
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
SampledType: SampleType<FORMAT>,
|
||||
const DIM: Dimensionality,
|
||||
const DEPTH: ImageDepth,
|
||||
const ARRAYED: Arrayed,
|
||||
const MULTISAMPLED: Multisampled,
|
||||
const FORMAT: ImageFormat,
|
||||
const ACCESS_QUALIFIER: Option<AccessQualifier>,
|
||||
>
|
||||
Image<SampledType, DIM, DEPTH, ARRAYED, MULTISAMPLED, { Sampled::No }, FORMAT, ACCESS_QUALIFIER>
|
||||
{
|
||||
/// Read a texel from an image without a sampler.
|
||||
#[crate::macros::gpu_only]
|
||||
#[doc(alias = "OpImageRead")]
|
||||
pub fn read<I, V, const N: usize>(&self, coordinate: impl ImageCoordinate<I, DIM, ARRAYED>) -> V
|
||||
where
|
||||
I: Integer,
|
||||
V: Vector<SampledType, N>,
|
||||
{
|
||||
let mut result = V::default();
|
||||
|
||||
unsafe {
|
||||
asm! {
|
||||
"%image = OpLoad _ {this}",
|
||||
"%coordinate = OpLoad _ {coordinate}",
|
||||
"%result = OpImageRead typeof*{result} %image %coordinate",
|
||||
"OpStore {result} %result",
|
||||
this = in(reg) self,
|
||||
coordinate = in(reg) &coordinate,
|
||||
result = in(reg) &mut result,
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// Write a texel to an image without a sampler.
|
||||
#[crate::macros::gpu_only]
|
||||
#[doc(alias = "OpImageWrite")]
|
||||
pub unsafe fn write<I, const N: usize>(
|
||||
&self,
|
||||
coordinate: impl ImageCoordinate<I, DIM, ARRAYED>,
|
||||
texels: impl Vector<SampledType, N>,
|
||||
) where
|
||||
I: Integer,
|
||||
{
|
||||
asm! {
|
||||
"%image = OpLoad _ {this}",
|
||||
"%coordinate = OpLoad _ {coordinate}",
|
||||
"%texels = OpLoad _ {texels}",
|
||||
"OpImageWrite %image %coordinate %texels",
|
||||
this = in(reg) self,
|
||||
coordinate = in(reg) &coordinate,
|
||||
texels = in(reg) &texels,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
SampledType: SampleType<FORMAT>,
|
||||
const DIM: Dimensionality,
|
||||
const DEPTH: ImageDepth,
|
||||
const FORMAT: ImageFormat,
|
||||
const ARRAYED: Arrayed,
|
||||
const MULTISAMPLED: Multisampled,
|
||||
const ACCESS_QUALIFIER: Option<AccessQualifier>,
|
||||
>
|
||||
Image<
|
||||
SampledType,
|
||||
DIM,
|
||||
DEPTH,
|
||||
ARRAYED,
|
||||
MULTISAMPLED,
|
||||
{ Sampled::Unknown },
|
||||
FORMAT,
|
||||
ACCESS_QUALIFIER,
|
||||
>
|
||||
{
|
||||
/// Read a texel from an image without a sampler.
|
||||
#[crate::macros::gpu_only]
|
||||
#[doc(alias = "OpImageRead")]
|
||||
pub fn read<I, V, const N: usize>(&self, coordinate: impl ImageCoordinate<I, DIM, ARRAYED>) -> V
|
||||
where
|
||||
I: Integer,
|
||||
V: Vector<SampledType, N>,
|
||||
{
|
||||
let mut result = V::default();
|
||||
|
||||
unsafe {
|
||||
asm! {
|
||||
"%image = OpLoad _ {this}",
|
||||
"%coordinate = OpLoad _ {coordinate}",
|
||||
"%result = OpImageRead typeof*{result} %image %coordinate",
|
||||
"OpStore {result} %result",
|
||||
this = in(reg) self,
|
||||
coordinate = in(reg) &coordinate,
|
||||
result = in(reg) &mut result,
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// Write a texel to an image without a sampler.
|
||||
#[crate::macros::gpu_only]
|
||||
#[doc(alias = "OpImageWrite")]
|
||||
pub unsafe fn write<I, const N: usize>(
|
||||
&self,
|
||||
coordinate: impl ImageCoordinate<I, DIM, ARRAYED>,
|
||||
texels: impl Vector<SampledType, N>,
|
||||
) where
|
||||
I: Integer,
|
||||
{
|
||||
asm! {
|
||||
"%image = OpLoad _ {this}",
|
||||
"%coordinate = OpLoad _ {coordinate}",
|
||||
"%texels = OpLoad _ {texels}",
|
||||
"OpImageWrite %image %coordinate %texels",
|
||||
this = in(reg) self,
|
||||
coordinate = in(reg) &coordinate,
|
||||
texels = in(reg) &texels,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An image combined with a sampler, enabling filtered accesses of the
|
||||
/// image’s contents.
|
||||
#[spirv(sampled_image)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct SampledImage<I> {
|
||||
_image: I,
|
||||
}
|
||||
|
||||
impl<
|
||||
SampledType: SampleType<FORMAT>,
|
||||
const DIM: Dimensionality,
|
||||
const DEPTH: ImageDepth,
|
||||
const ARRAYED: Arrayed,
|
||||
const SAMPLED: Sampled,
|
||||
const FORMAT: ImageFormat,
|
||||
const ACCESS_QUALIFIER: Option<AccessQualifier>,
|
||||
>
|
||||
SampledImage<
|
||||
Image<
|
||||
SampledType,
|
||||
DIM,
|
||||
DEPTH,
|
||||
ARRAYED,
|
||||
{ Multisampled::False },
|
||||
SAMPLED,
|
||||
FORMAT,
|
||||
ACCESS_QUALIFIER,
|
||||
>,
|
||||
>
|
||||
{
|
||||
/// Sample texels at `coord` from the sampled image.
|
||||
///
|
||||
/// # Safety
|
||||
/// Sampling with a type (`S`) that doesn't match the image's image format
|
||||
/// will result in undefined behaviour.
|
||||
#[crate::macros::gpu_only]
|
||||
pub unsafe fn sample<F, V>(&self, coord: impl ImageCoordinate<F, DIM, ARRAYED>) -> V
|
||||
where
|
||||
F: Float,
|
||||
V: Vector<SampledType, 4>,
|
||||
{
|
||||
let mut result = Default::default();
|
||||
asm!(
|
||||
"%sampledImage = OpLoad typeof*{1} {1}",
|
||||
"%coord = OpLoad typeof*{2} {2}",
|
||||
"%result = OpImageSampleImplicitLod typeof*{0} %sampledImage %coord",
|
||||
"OpStore {0} %result",
|
||||
in(reg) &mut result,
|
||||
in(reg) self,
|
||||
in(reg) &coord
|
||||
);
|
||||
result
|
||||
}
|
||||
}
|
74
crates/spirv-std/src/image/params.rs
Normal file
74
crates/spirv-std/src/image/params.rs
Normal file
@ -0,0 +1,74 @@
|
||||
use super::{Arrayed, Dimensionality, ImageFormat};
|
||||
use crate::{scalar::Scalar, vector::Vector};
|
||||
|
||||
/// Marker trait for arguments that accept single scalar values or vectors
|
||||
/// of scalars.
|
||||
pub trait SampleType<const FORMAT: ImageFormat>: Scalar {}
|
||||
|
||||
impl SampleType<{ ImageFormat::Unknown }> for i8 {}
|
||||
impl SampleType<{ ImageFormat::Unknown }> for i16 {}
|
||||
impl SampleType<{ ImageFormat::Unknown }> for i32 {}
|
||||
impl SampleType<{ ImageFormat::Unknown }> for i64 {}
|
||||
impl SampleType<{ ImageFormat::Unknown }> for u8 {}
|
||||
impl SampleType<{ ImageFormat::Unknown }> for u16 {}
|
||||
impl SampleType<{ ImageFormat::Unknown }> for u32 {}
|
||||
impl SampleType<{ ImageFormat::Unknown }> for u64 {}
|
||||
impl SampleType<{ ImageFormat::Unknown }> for f32 {}
|
||||
impl SampleType<{ ImageFormat::Unknown }> for f64 {}
|
||||
impl SampleType<{ ImageFormat::Rgba32f }> for f32 {}
|
||||
impl SampleType<{ ImageFormat::Rgba16f }> for f32 {}
|
||||
impl SampleType<{ ImageFormat::R32f }> for f32 {}
|
||||
impl SampleType<{ ImageFormat::Rgba8 }> for f32 {}
|
||||
impl SampleType<{ ImageFormat::Rgba8Snorm }> for f32 {}
|
||||
impl SampleType<{ ImageFormat::Rg32f }> for f32 {}
|
||||
impl SampleType<{ ImageFormat::Rg16f }> for f32 {}
|
||||
impl SampleType<{ ImageFormat::R11fG11fB10f }> for f32 {}
|
||||
impl SampleType<{ ImageFormat::R16f }> for f32 {}
|
||||
impl SampleType<{ ImageFormat::Rgba16 }> for f32 {}
|
||||
impl SampleType<{ ImageFormat::Rgb10A2 }> for f32 {}
|
||||
impl SampleType<{ ImageFormat::Rg16 }> for f32 {}
|
||||
impl SampleType<{ ImageFormat::Rg8 }> for f32 {}
|
||||
impl SampleType<{ ImageFormat::R16 }> for f32 {}
|
||||
impl SampleType<{ ImageFormat::R8 }> for f32 {}
|
||||
impl SampleType<{ ImageFormat::Rgba16Snorm }> for f32 {}
|
||||
impl SampleType<{ ImageFormat::Rg16Snorm }> for f32 {}
|
||||
impl SampleType<{ ImageFormat::Rg8Snorm }> for f32 {}
|
||||
impl SampleType<{ ImageFormat::R16Snorm }> for f32 {}
|
||||
impl SampleType<{ ImageFormat::R8Snorm }> for f32 {}
|
||||
impl SampleType<{ ImageFormat::Rgba32i }> for i32 {}
|
||||
impl SampleType<{ ImageFormat::Rgba16i }> for i32 {}
|
||||
impl SampleType<{ ImageFormat::Rgba8i }> for i32 {}
|
||||
impl SampleType<{ ImageFormat::R32i }> for i32 {}
|
||||
impl SampleType<{ ImageFormat::Rg32i }> for i32 {}
|
||||
impl SampleType<{ ImageFormat::Rg16i }> for i32 {}
|
||||
impl SampleType<{ ImageFormat::Rg8i }> for i32 {}
|
||||
impl SampleType<{ ImageFormat::R16i }> for i32 {}
|
||||
impl SampleType<{ ImageFormat::R8i }> for i32 {}
|
||||
impl SampleType<{ ImageFormat::Rgba32ui }> for u32 {}
|
||||
impl SampleType<{ ImageFormat::Rgba16ui }> for u32 {}
|
||||
impl SampleType<{ ImageFormat::Rgba8ui }> for u32 {}
|
||||
impl SampleType<{ ImageFormat::R32ui }> for u32 {}
|
||||
impl SampleType<{ ImageFormat::Rgb10A2ui }> for u32 {}
|
||||
impl SampleType<{ ImageFormat::Rg32ui }> for u32 {}
|
||||
impl SampleType<{ ImageFormat::Rg16ui }> for u32 {}
|
||||
impl SampleType<{ ImageFormat::Rg8ui }> for u32 {}
|
||||
impl SampleType<{ ImageFormat::R16ui }> for u32 {}
|
||||
impl SampleType<{ ImageFormat::R8ui }> for u32 {}
|
||||
impl SampleType<{ ImageFormat::R64ui }> for u64 {}
|
||||
impl SampleType<{ ImageFormat::R64i }> for i64 {}
|
||||
|
||||
/// Marker trait for arguments that accept a coordinate for an [`crate::Image`].
|
||||
pub trait ImageCoordinate<T, const DIM: Dimensionality, const ARRAYED: Arrayed> {}
|
||||
|
||||
impl<S: Scalar> ImageCoordinate<S, { Dimensionality::OneD }, { Arrayed::False }> for S {}
|
||||
impl<S: Scalar> ImageCoordinate<S, { Dimensionality::Buffer }, { Arrayed::False }> for S {}
|
||||
|
||||
impl<V: Vector<S, 2>, S: Scalar> ImageCoordinate<S, { Dimensionality::TwoD }, { Arrayed::False }> for V {}
|
||||
impl<V: Vector<S, 2>, S: Scalar> ImageCoordinate<S, { Dimensionality::Rect }, { Arrayed::False }> for V {}
|
||||
impl<V: Vector<S, 3>, S: Scalar> ImageCoordinate<S, { Dimensionality::Cube }, { Arrayed::False }> for V {}
|
||||
impl<V: Vector<S, 3>, S: Scalar> ImageCoordinate<S, { Dimensionality::ThreeD }, { Arrayed::False }> for V {}
|
||||
|
||||
impl<V: Vector<S, 3>, S: Scalar> ImageCoordinate<S, { Dimensionality::TwoD }, { Arrayed::True }> for V {}
|
||||
impl<V: Vector<S, 3>, S: Scalar> ImageCoordinate<S, { Dimensionality::Rect }, { Arrayed::True }> for V {}
|
||||
impl<V: Vector<S, 4>, S: Scalar> ImageCoordinate<S, { Dimensionality::Cube }, { Arrayed::True }> for V {}
|
||||
impl<V: Vector<S, 4>, S: Scalar> ImageCoordinate<S, { Dimensionality::ThreeD }, { Arrayed::True }> for V {}
|
@ -68,22 +68,28 @@
|
||||
// We deblierately provide an unimplemented version of our API on CPU
|
||||
// platforms so that code completion still works.
|
||||
clippy::unimplemented,
|
||||
// The part of `const-generics` we're using (C-like enums) is not incomplete.
|
||||
incomplete_features,
|
||||
)]
|
||||
|
||||
#[macro_use]
|
||||
#[cfg(not(target_arch = "spirv"))]
|
||||
#[cfg_attr(not(target_arch = "spirv"), macro_use)]
|
||||
pub extern crate spirv_std_macros as macros;
|
||||
|
||||
pub mod arch;
|
||||
pub mod float;
|
||||
#[cfg(feature = "const-generics")]
|
||||
pub mod image;
|
||||
pub mod integer;
|
||||
pub mod memory;
|
||||
pub mod ray_tracing;
|
||||
mod sampler;
|
||||
pub mod scalar;
|
||||
pub(crate) mod sealed;
|
||||
mod textures;
|
||||
pub mod vector;
|
||||
|
||||
pub use self::sampler::Sampler;
|
||||
pub use crate::macros::Image;
|
||||
pub use num_traits;
|
||||
pub use textures::*;
|
||||
|
||||
|
7
crates/spirv-std/src/sampler.rs
Normal file
7
crates/spirv-std/src/sampler.rs
Normal file
@ -0,0 +1,7 @@
|
||||
/// An opaque reference to settings that describe how to access, filter, or
|
||||
/// sample an image.
|
||||
#[spirv(sampler)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Sampler {
|
||||
_x: u32,
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
use crate::{integer::Integer, vector::Vector};
|
||||
|
||||
#[spirv(sampler)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Sampler {
|
||||
_x: u32,
|
||||
}
|
||||
pub use crate::sampler::Sampler;
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "const-generics",
|
||||
deprecated = "Legacy image type. Use `spirv_std::image::Image2d` instead."
|
||||
)]
|
||||
#[spirv(image_type(
|
||||
// sampled_type is hardcoded to f32 for now
|
||||
dim = "Dim2D",
|
||||
@ -20,6 +20,7 @@ pub struct Image2d {
|
||||
_x: u32,
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl Image2d {
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpImageSampleImplicitLod")]
|
||||
@ -412,6 +413,10 @@ impl Image2d {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "const-generics",
|
||||
deprecated = "Legacy image type. Use `spirv_std::image::StorageImage2d` instead."
|
||||
)]
|
||||
#[spirv(image_type(
|
||||
// sampled_type is hardcoded to f32 for now
|
||||
dim = "Dim2D",
|
||||
@ -426,6 +431,7 @@ pub struct StorageImage2d {
|
||||
_x: u32,
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl StorageImage2d {
|
||||
/// Read a texel from an image without a sampler.
|
||||
#[spirv_std_macros::gpu_only]
|
||||
@ -474,6 +480,10 @@ impl StorageImage2d {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "const-generics",
|
||||
deprecated = "Legacy image type. Use `spirv_std::image::Image2dArray` instead."
|
||||
)]
|
||||
#[spirv(image_type(
|
||||
// sampled_type is hardcoded to f32 for now
|
||||
dim = "Dim2D",
|
||||
@ -488,6 +498,7 @@ pub struct Image2dArray {
|
||||
_x: u32,
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl Image2dArray {
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpImageSampleImplicitLod")]
|
||||
@ -673,6 +684,10 @@ impl Image2dArray {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "const-generics",
|
||||
deprecated = "Legacy image type. Use `spirv_std::image::Cubemap` instead."
|
||||
)]
|
||||
#[spirv(image_type(
|
||||
// sampled_type is hardcoded to f32 for now
|
||||
dim = "DimCube",
|
||||
@ -687,6 +702,7 @@ pub struct Cubemap {
|
||||
_x: u32,
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl Cubemap {
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpSampledImage")]
|
||||
@ -872,12 +888,17 @@ impl Cubemap {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
feature = "const-generics",
|
||||
deprecated = "Legacy image type. Use `spirv_std::image::SampledImage` instead."
|
||||
)]
|
||||
#[spirv(sampled_image)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct SampledImage<I> {
|
||||
_image: I,
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl SampledImage<Image2d> {
|
||||
#[spirv_std_macros::gpu_only]
|
||||
#[doc(alias = "OpImageSampleImplicitLod")]
|
||||
|
@ -9,5 +9,4 @@ license = "MIT OR Apache-2.0"
|
||||
crate-type = ["dylib"]
|
||||
|
||||
[dependencies]
|
||||
spirv-std-macros = { path = "../../../crates/spirv-std-macros" }
|
||||
spirv-std = { path = "../../../crates/spirv-std" }
|
||||
|
@ -10,8 +10,7 @@
|
||||
extern crate spirv_std;
|
||||
|
||||
#[cfg(not(target_arch = "spirv"))]
|
||||
#[macro_use]
|
||||
pub extern crate spirv_std_macros;
|
||||
use spirv_std::macros::spirv;
|
||||
|
||||
// LocalSize/numthreads of (x = 32, y = 1, z = 1)
|
||||
#[spirv(compute(threads(32)))]
|
||||
|
@ -7,6 +7,5 @@ license = "MIT OR Apache-2.0"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
spirv-std-macros = { path = "../../../crates/spirv-std-macros" }
|
||||
spirv-std = { path = "../../../crates/spirv-std" }
|
||||
glam = { version = "0.14", default-features = false, features = ["libm", "scalar-math", "spirv-std"] }
|
||||
|
@ -10,6 +10,5 @@ publish = false
|
||||
crate-type = ["dylib"]
|
||||
|
||||
[dependencies]
|
||||
spirv-std-macros = { path = "../../../crates/spirv-std-macros" }
|
||||
spirv-std = { path = "../../../crates/spirv-std" }
|
||||
shared = { path = "../shared" }
|
||||
|
@ -8,8 +8,8 @@
|
||||
#![deny(warnings)]
|
||||
|
||||
#[cfg(not(target_arch = "spirv"))]
|
||||
#[macro_use]
|
||||
pub extern crate spirv_std_macros;
|
||||
use spirv_std::macros::spirv;
|
||||
|
||||
use shared::glam::{vec4, Vec4};
|
||||
|
||||
#[spirv(fragment)]
|
||||
|
@ -11,5 +11,4 @@ crate-type = ["dylib"]
|
||||
|
||||
[dependencies]
|
||||
shared = { path = "../../shaders/shared" }
|
||||
spirv-std-macros = { path = "../../../crates/spirv-std-macros" }
|
||||
spirv-std = { path = "../../../crates/spirv-std" }
|
||||
|
@ -10,8 +10,7 @@
|
||||
#![deny(warnings)]
|
||||
|
||||
#[cfg(not(target_arch = "spirv"))]
|
||||
#[macro_use]
|
||||
pub extern crate spirv_std_macros;
|
||||
use spirv_std::macros::spirv;
|
||||
|
||||
use core::f32::consts::PI;
|
||||
use glam::{const_vec3, vec2, vec3, Vec2, Vec3, Vec4};
|
||||
|
@ -1,9 +1,12 @@
|
||||
// build-pass
|
||||
|
||||
use spirv_std::{arch, Image2d};
|
||||
use spirv_std::{arch, Image};
|
||||
|
||||
#[spirv(fragment)]
|
||||
pub fn main(#[spirv(descriptor_set = 0, binding = 0)] image: &Image2d, output: &mut glam::Vec4) {
|
||||
pub fn main(
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image: &Image!(2D, type=f32, sampled),
|
||||
output: &mut glam::Vec4,
|
||||
) {
|
||||
let texel = image.fetch(glam::IVec2::new(0, 1));
|
||||
*output = texel;
|
||||
}
|
||||
|
12
tests/ui/image/format.rs
Normal file
12
tests/ui/image/format.rs
Normal file
@ -0,0 +1,12 @@
|
||||
// build-pass
|
||||
|
||||
use spirv_std::{arch, Image};
|
||||
|
||||
#[spirv(fragment)]
|
||||
pub fn main(
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image: &Image!(2D, format=rgba32f, sampled),
|
||||
output: &mut glam::Vec4,
|
||||
) {
|
||||
let texel = image.fetch(glam::IVec2::new(0, 1));
|
||||
*output = texel;
|
||||
}
|
@ -4,7 +4,7 @@ use glam::*;
|
||||
pub fn main_cs(
|
||||
#[spirv(global_invocation_id)] id: UVec3,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] points_buffer: &mut [UVec2; 100],
|
||||
#[spirv(descriptor_set = 1, binding = 1)] image: &spirv_std::StorageImage2d,
|
||||
#[spirv(descriptor_set = 1, binding = 1)] image: &spirv_std::Image!(2D, type=f32, sampled=false),
|
||||
) {
|
||||
unsafe { asm!("OpCapability StorageImageWriteWithoutFormat") };
|
||||
let position = id.xy();
|
||||
|
@ -1,11 +1,11 @@
|
||||
// Test `OpImageRead`
|
||||
// build-pass
|
||||
|
||||
use spirv_std::{arch, StorageImage2d};
|
||||
use spirv_std::{arch, Image};
|
||||
|
||||
#[spirv(fragment)]
|
||||
pub fn main(
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image: &StorageImage2d,
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image: &Image!(2D, type=f32, sampled=false),
|
||||
output: &mut glam::Vec4,
|
||||
) {
|
||||
unsafe { asm!("OpCapability StorageImageReadWithoutFormat") };
|
||||
|
@ -1,13 +1,13 @@
|
||||
// Test `OpImageSampleImplicitLod`
|
||||
// build-pass
|
||||
|
||||
use spirv_std::{arch, Cubemap, Image2d, Image2dArray, Sampler};
|
||||
use spirv_std::{arch, Image, Sampler};
|
||||
|
||||
#[spirv(fragment)]
|
||||
pub fn main(
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image2d: &Image2d,
|
||||
#[spirv(descriptor_set = 1, binding = 1)] image2d_array: &Image2dArray,
|
||||
#[spirv(descriptor_set = 2, binding = 2)] cubemap: &Cubemap,
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image2d: &Image!(2D, type=f32, sampled),
|
||||
#[spirv(descriptor_set = 1, binding = 1)] image2d_array: &Image!(2D, type=f32, arrayed, sampled),
|
||||
#[spirv(descriptor_set = 2, binding = 2)] cubemap: &Image!(3D, type=f32, sampled),
|
||||
#[spirv(descriptor_set = 3, binding = 3)] sampler: &Sampler,
|
||||
output: &mut glam::Vec4,
|
||||
) {
|
||||
|
@ -1,13 +1,13 @@
|
||||
// Test `OpImageSampleDrefImplicitLod`
|
||||
// build-pass
|
||||
|
||||
use spirv_std::{arch, Cubemap, Image2d, Image2dArray, Sampler};
|
||||
use spirv_std::{arch, Image, Sampler};
|
||||
|
||||
#[spirv(fragment)]
|
||||
pub fn main(
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image: &Image2d,
|
||||
#[spirv(descriptor_set = 1, binding = 1)] image_array: &Image2dArray,
|
||||
#[spirv(descriptor_set = 2, binding = 2)] cubemap: &Cubemap,
|
||||
#[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)] cubemap: &Image!(cube, type=f32, sampled),
|
||||
#[spirv(descriptor_set = 3, binding = 3)] sampler: &Sampler,
|
||||
output: &mut f32,
|
||||
) {
|
||||
|
@ -1,14 +1,14 @@
|
||||
// Test `OpImageSampleDrefExplicitLod`
|
||||
// build-pass
|
||||
|
||||
use spirv_std::{arch, Cubemap, Image2d, Image2dArray, Sampler};
|
||||
use spirv_std::{Image, Sampler};
|
||||
|
||||
#[spirv(fragment)]
|
||||
pub fn main(
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image: &Image2d,
|
||||
#[spirv(descriptor_set = 1, binding = 1)] image_array: &Image2dArray,
|
||||
#[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: &Cubemap,
|
||||
#[spirv(descriptor_set = 3, binding = 3)] cubemap: &Image!(3D, type=f32, sampled),
|
||||
output: &mut f32,
|
||||
) {
|
||||
let v2 = glam::Vec2::new(0.0, 1.0);
|
||||
|
@ -1,14 +1,14 @@
|
||||
// Test `OpImageSampleDrefExplicitLod`
|
||||
// build-pass
|
||||
|
||||
use spirv_std::{arch, Cubemap, Image2d, Image2dArray, Sampler};
|
||||
use spirv_std::{Image, Sampler};
|
||||
|
||||
#[spirv(fragment)]
|
||||
pub fn main(
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image: &Image2d,
|
||||
#[spirv(descriptor_set = 1, binding = 1)] image_array: &Image2dArray,
|
||||
#[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: &Cubemap,
|
||||
#[spirv(descriptor_set = 3, binding = 3)] cubemap: &Image!(3D, type=f32),
|
||||
output: &mut f32,
|
||||
) {
|
||||
let v2 = glam::Vec2::new(0.0, 1.0);
|
||||
|
@ -1,11 +1,11 @@
|
||||
// Test `OpImageSampleProjDrefImplicitLod`
|
||||
// build-pass
|
||||
|
||||
use spirv_std::{arch, Image2d, Sampler};
|
||||
use spirv_std::{arch, Image, Sampler};
|
||||
|
||||
#[spirv(fragment)]
|
||||
pub fn main(
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image: &Image2d,
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image: &Image!(2D, type=f32, sampled),
|
||||
#[spirv(descriptor_set = 1, binding = 1)] sampler: &Sampler,
|
||||
output: &mut f32,
|
||||
) {
|
||||
|
@ -1,11 +1,11 @@
|
||||
// Test `OpImageSampleProjDrefExplicitLod`
|
||||
// build-pass
|
||||
|
||||
use spirv_std::{arch, Image2d, Sampler};
|
||||
use spirv_std::{Image, Sampler};
|
||||
|
||||
#[spirv(fragment)]
|
||||
pub fn main(
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image: &Image2d,
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image: &Image!(2D, type=f32, sampled),
|
||||
#[spirv(descriptor_set = 1, binding = 1)] sampler: &Sampler,
|
||||
output: &mut f32,
|
||||
) {
|
||||
|
@ -1,11 +1,11 @@
|
||||
// Test `OpImageSampleProjDrefExplicitLod`
|
||||
// build-pass
|
||||
|
||||
use spirv_std::{arch, Image2d, Sampler};
|
||||
use spirv_std::{Image, Sampler};
|
||||
|
||||
#[spirv(fragment)]
|
||||
pub fn main(
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image: &Image2d,
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image: &Image!(2D, type=f32, sampled),
|
||||
#[spirv(descriptor_set = 1, binding = 1)] sampler: &Sampler,
|
||||
output: &mut f32,
|
||||
) {
|
||||
|
@ -1,13 +1,13 @@
|
||||
// Test `OpImageSampleExplicitLod` Grad
|
||||
// build-pass
|
||||
|
||||
use spirv_std::{arch, Cubemap, Image2d, Image2dArray, Sampler};
|
||||
use spirv_std::{arch, Image, Sampler};
|
||||
|
||||
#[spirv(fragment)]
|
||||
pub fn main(
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image2d: &Image2d,
|
||||
#[spirv(descriptor_set = 1, binding = 1)] image2d_array: &Image2dArray,
|
||||
#[spirv(descriptor_set = 2, binding = 2)] cubemap: &Cubemap,
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image2d: &Image!(2D, type=f32, sampled),
|
||||
#[spirv(descriptor_set = 1, binding = 1)] image2d_array: &Image!(2D, type=f32, arrayed, sampled),
|
||||
#[spirv(descriptor_set = 2, binding = 2)] cubemap: &Image!(3D, type=f32, sampled),
|
||||
#[spirv(descriptor_set = 3, binding = 3)] sampler: &Sampler,
|
||||
output: &mut glam::Vec4,
|
||||
) {
|
||||
|
@ -1,13 +1,13 @@
|
||||
// Test `OpImageSampleExplicitLod` Lod
|
||||
// build-pass
|
||||
|
||||
use spirv_std::{arch, Cubemap, Image2d, Image2dArray, Sampler};
|
||||
use spirv_std::{arch, Image, Sampler};
|
||||
|
||||
#[spirv(fragment)]
|
||||
pub fn main(
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image2d: &Image2d,
|
||||
#[spirv(descriptor_set = 1, binding = 1)] image2d_array: &Image2dArray,
|
||||
#[spirv(descriptor_set = 2, binding = 2)] cubemap: &Cubemap,
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image2d: &Image!(2D, type=f32, sampled),
|
||||
#[spirv(descriptor_set = 1, binding = 1)] image2d_array: &Image!(2D, type=f32, arrayed, sampled),
|
||||
#[spirv(descriptor_set = 2, binding = 2)] cubemap: &Image!(3D, type=f32, sampled),
|
||||
#[spirv(descriptor_set = 3, binding = 3)] sampler: &Sampler,
|
||||
output: &mut glam::Vec4,
|
||||
) {
|
||||
|
@ -1,11 +1,11 @@
|
||||
// Test `OpImageSampleProjImplicitLod`
|
||||
// build-pass
|
||||
|
||||
use spirv_std::{arch, Image2d, Sampler};
|
||||
use spirv_std::{Image, Sampler};
|
||||
|
||||
#[spirv(fragment)]
|
||||
pub fn main(
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image2d: &Image2d,
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image2d: &Image!(2D, type=f32, sampled),
|
||||
#[spirv(descriptor_set = 1, binding = 1)] sampler: &Sampler,
|
||||
output: &mut glam::Vec4,
|
||||
) {
|
||||
|
@ -1,11 +1,11 @@
|
||||
// Test `OpImageSampleProjExplicitLod`
|
||||
// build-pass
|
||||
|
||||
use spirv_std::{arch, Image2d, Sampler};
|
||||
use spirv_std::{arch, Image, Sampler};
|
||||
|
||||
#[spirv(fragment)]
|
||||
pub fn main(
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image2d: &Image2d,
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image2d: &Image!(2D, type=f32, sampled),
|
||||
#[spirv(descriptor_set = 1, binding = 1)] sampler: &Sampler,
|
||||
output: &mut glam::Vec4,
|
||||
) {
|
||||
|
@ -1,11 +1,11 @@
|
||||
// Test `OpImageSampleProjExplicitLod`
|
||||
// build-pass
|
||||
|
||||
use spirv_std::{arch, Image2d, Sampler};
|
||||
use spirv_std::{arch, Image, Sampler};
|
||||
|
||||
#[spirv(fragment)]
|
||||
pub fn main(
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image2d: &Image2d,
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image2d: &Image!(2D, type=f32, sampled),
|
||||
#[spirv(descriptor_set = 1, binding = 1)] sampler: &Sampler,
|
||||
output: &mut glam::Vec4,
|
||||
) {
|
||||
|
@ -1,10 +1,13 @@
|
||||
// Test `OpImageWrite`
|
||||
// build-pass
|
||||
|
||||
use spirv_std::{arch, StorageImage2d};
|
||||
use spirv_std::{arch, Image};
|
||||
|
||||
#[spirv(fragment)]
|
||||
pub fn main(texels: glam::Vec2, #[spirv(descriptor_set = 0, binding = 0)] image: &StorageImage2d) {
|
||||
pub fn main(
|
||||
texels: glam::Vec2,
|
||||
#[spirv(descriptor_set = 0, binding = 0)] image: &Image!(2D, type=f32, sampled=false),
|
||||
) {
|
||||
unsafe {
|
||||
asm!("OpCapability StorageImageWriteWithoutFormat");
|
||||
image.write(glam::UVec2::new(0, 1), texels);
|
||||
|
@ -1,11 +1,15 @@
|
||||
// Tests that storage class inference fails correctly
|
||||
// build-fail
|
||||
|
||||
use spirv_std::Image2d;
|
||||
use spirv_std::Image;
|
||||
|
||||
#[spirv(vertex)]
|
||||
pub fn main(#[spirv(uniform)] error: &Image2d, #[spirv(uniform_constant)] warning: &Image2d) {}
|
||||
pub fn main(
|
||||
#[spirv(uniform)] error: &Image!(2D, type=f32),
|
||||
#[spirv(uniform_constant)] warning: &Image!(2D, type=f32),
|
||||
) {
|
||||
}
|
||||
|
||||
// https://github.com/EmbarkStudios/rust-gpu/issues/585
|
||||
#[spirv(vertex)]
|
||||
pub fn issue_585(invalid: Image2d) {}
|
||||
pub fn issue_585(invalid: Image!(2D, type=f32)) {}
|
||||
|
@ -1,29 +1,31 @@
|
||||
error: storage class mismatch
|
||||
--> $DIR/bad-infer-storage-class.rs:7:13
|
||||
--> $DIR/bad-infer-storage-class.rs:8:5
|
||||
|
|
||||
7 | pub fn main(#[spirv(uniform)] error: &Image2d, #[spirv(uniform_constant)] warning: &Image2d) {}
|
||||
| ^^^^^^^^-------^^^^^^^^^^--------
|
||||
| | |
|
||||
| | UniformConstant inferred from type
|
||||
| Uniform specified in attribute
|
||||
8 | #[spirv(uniform)] error: &Image!(2D, type=f32),
|
||||
| ^^^^^^^^-------^^^^^^^^^^---------------------
|
||||
| | |
|
||||
| | UniformConstant inferred from type
|
||||
| Uniform specified in attribute
|
||||
|
|
||||
help: remove storage class attribute to use UniformConstant as storage class
|
||||
--> $DIR/bad-infer-storage-class.rs:7:21
|
||||
--> $DIR/bad-infer-storage-class.rs:8:13
|
||||
|
|
||||
7 | pub fn main(#[spirv(uniform)] error: &Image2d, #[spirv(uniform_constant)] warning: &Image2d) {}
|
||||
| ^^^^^^^
|
||||
8 | #[spirv(uniform)] error: &Image!(2D, type=f32),
|
||||
| ^^^^^^^
|
||||
|
||||
warning: redundant storage class specifier, storage class is inferred from type
|
||||
--> $DIR/bad-infer-storage-class.rs:7:56
|
||||
--> $DIR/bad-infer-storage-class.rs:9:13
|
||||
|
|
||||
7 | pub fn main(#[spirv(uniform)] error: &Image2d, #[spirv(uniform_constant)] warning: &Image2d) {}
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
9 | #[spirv(uniform_constant)] warning: &Image!(2D, type=f32),
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: entry parameter type must be by-reference: `&spirv_std::Image2d`
|
||||
--> $DIR/bad-infer-storage-class.rs:11:27
|
||||
error: entry parameter type must be by-reference: `&spirv_std::image::Image<f32, spirv_std::image::Dimensionality::TwoD, spirv_std::image::ImageDepth::Unknown, spirv_std::image::Arrayed::False, spirv_std::image::Multisampled::False, spirv_std::image::Sampled::Unknown, spirv_std::image::ImageFormat::Unknown, core::option::Option::<spirv_std::image::AccessQualifier>::None>`
|
||||
--> $DIR/bad-infer-storage-class.rs:15:27
|
||||
|
|
||||
11 | pub fn issue_585(invalid: Image2d) {}
|
||||
| ^^^^^^^
|
||||
15 | pub fn issue_585(invalid: Image!(2D, type=f32)) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user