Skip to content

Commit

Permalink
Add any and all arch instructions (#441)
Browse files Browse the repository at this point in the history
  • Loading branch information
XAMPPRocky authored Feb 25, 2021
1 parent dafbbd7 commit 57a9ebb
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 22 deletions.
25 changes: 25 additions & 0 deletions crates/spirv-builder/src/test/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,31 @@ OpFunctionEnd",
);
}

#[test]
fn any() {
val(r#"
#[allow(unused_attributes)]
#[spirv(fragment)]
pub fn main() {
let vector = glam::BVec2::new(true, false);
assert!(arch::any(vector));
}
"#);
}

#[test]
fn all() {
val(r#"
#[allow(unused_attributes)]
#[spirv(fragment)]
pub fn main() {
let vector = glam::BVec2::new(true, true);
assert!(arch::all(vector));
}
"#);
}

#[test]
fn image_read() {
val(r#"
Expand Down
73 changes: 71 additions & 2 deletions crates/spirv-std/src/arch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,72 @@
//! no additional safety checks beyond type-checking.
use crate::{scalar::Scalar, vector::Vector};

/// Result is true if any component of `vector` is true, otherwise result is
/// false.
#[spirv_std_macros::gpu_only]
#[doc(alias = "OpAny")]
#[inline]
pub fn any<V: Vector<bool, N>, const N: usize>(vector: V) -> bool {
let mut result = false;

unsafe {
asm! {
// Types & Constants
"%bool = OpTypeBool",
"%u8 = OpTypeInt 8 0",
"%u8_0 = OpConstant %u8 0",
"%u8_1 = OpConstant %u8 1",
"%glam_vec_type = OpTypeVector %u8 {len}",
"%bool_vec_type = OpTypeVector %bool {len}",
"%false_vec = OpConstantNull %glam_vec_type",
// Code
"%vector = OpLoad %glam_vec_type {vector}",
"%bool_vec = OpINotEqual %bool_vec_type %vector %false_vec",
"%result = OpAny %bool %bool_vec",
"%boolean = OpSelect %u8 %result %u8_1 %u8_0",
"OpStore {result} %boolean",
vector = in(reg) &vector,
len = const N,
result = in(reg) &mut result
}
}

result
}

/// Result is true if all components of `vector` is true, otherwise result is
/// false.
#[spirv_std_macros::gpu_only]
#[doc(alias = "OpAll")]
#[inline]
pub fn all<V: Vector<bool, N>, const N: usize>(vector: V) -> bool {
let mut result = false;

unsafe {
asm! {
// Types & Constants
"%bool = OpTypeBool",
"%u8 = OpTypeInt 8 0",
"%u8_0 = OpConstant %u8 0",
"%u8_1 = OpConstant %u8 1",
"%glam_vec_type = OpTypeVector %u8 {len}",
"%bool_vec_type = OpTypeVector %bool {len}",
"%false_vec = OpConstantNull %glam_vec_type",
// Code
"%vector = OpLoad %glam_vec_type {vector}",
"%bool_vec = OpINotEqual %bool_vec_type %vector %false_vec",
"%result = OpAll %bool %bool_vec",
"%boolean = OpSelect %u8 %result %u8_1 %u8_0",
"OpStore {element} %boolean",
vector = in(reg) &vector,
len = const N,
element = in(reg) &mut result
}
}

result
}

/// Extract a single, dynamically selected, component of a vector.
///
/// # Safety
Expand All @@ -13,7 +79,10 @@ use crate::{scalar::Scalar, vector::Vector};
#[spirv_std_macros::gpu_only]
#[doc(alias = "OpVectorExtractDynamic")]
#[inline]
pub unsafe fn vector_extract_dynamic<T: Scalar, V: Vector<T>>(vector: V, index: usize) -> T {
pub unsafe fn vector_extract_dynamic<T: Scalar, V: Vector<T, N>, const N: usize>(
vector: V,
index: usize,
) -> T {
let mut result = T::default();

asm! {
Expand All @@ -37,7 +106,7 @@ pub unsafe fn vector_extract_dynamic<T: Scalar, V: Vector<T>>(vector: V, index:
#[spirv_std_macros::gpu_only]
#[doc(alias = "OpVectorInsertDynamic")]
#[inline]
pub unsafe fn vector_insert_dynamic<T: Scalar, V: Vector<T>>(
pub unsafe fn vector_insert_dynamic<T: Scalar, V: Vector<T, N>, const N: usize>(
vector: V,
index: usize,
element: T,
Expand Down
12 changes: 6 additions & 6 deletions crates/spirv-std/src/textures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ pub struct StorageImage2d {
impl StorageImage2d {
/// Read a texel from an image without a sampler.
#[spirv_std_macros::gpu_only]
pub fn read<I, V, V2>(&self, coordinate: V) -> V2
pub fn read<I, V, V2, const N: usize>(&self, coordinate: V) -> V2
where
I: Integer,
V: Vector<I>,
V2: Vector<f32>,
V: Vector<I, N>,
V2: Vector<f32, N>,
{
let mut result = V2::default();

Expand All @@ -89,11 +89,11 @@ impl StorageImage2d {

/// Write a texel to an image without a sampler.
#[spirv_std_macros::gpu_only]
pub fn write<I, V, V2>(&self, coordinate: V, texels: V2)
pub fn write<I, V, V2, const N: usize>(&self, coordinate: V, texels: V2)
where
I: Integer,
V: Vector<I>,
V2: Vector<f32>,
V: Vector<I, N>,
V2: Vector<f32, N>,
{
unsafe {
asm! {
Expand Down
31 changes: 17 additions & 14 deletions crates/spirv-std/src/vector.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
/// Abstract trait representing a SPIR-V vector type.
pub trait Vector<T: crate::scalar::Scalar>: crate::sealed::Sealed + Default {}
pub trait Vector<T: crate::scalar::Scalar, const N: usize>:
crate::sealed::Sealed + Default
{
}

impl Vector<bool> for glam::BVec2 {}
impl Vector<bool> for glam::BVec3 {}
impl Vector<bool> for glam::BVec4 {}
impl Vector<f32> for glam::Vec2 {}
impl Vector<f32> for glam::Vec3 {}
impl Vector<f32> for glam::Vec3A {}
impl Vector<f32> for glam::Vec4 {}
impl Vector<u32> for glam::UVec2 {}
impl Vector<u32> for glam::UVec3 {}
impl Vector<u32> for glam::UVec4 {}
impl Vector<i32> for glam::IVec2 {}
impl Vector<i32> for glam::IVec3 {}
impl Vector<i32> for glam::IVec4 {}
impl Vector<bool, 2> for glam::BVec2 {}
impl Vector<bool, 3> for glam::BVec3 {}
impl Vector<bool, 4> for glam::BVec4 {}
impl Vector<f32, 2> for glam::Vec2 {}
impl Vector<f32, 3> for glam::Vec3 {}
impl Vector<f32, 3> for glam::Vec3A {}
impl Vector<f32, 4> for glam::Vec4 {}
impl Vector<u32, 2> for glam::UVec2 {}
impl Vector<u32, 3> for glam::UVec3 {}
impl Vector<u32, 4> for glam::UVec4 {}
impl Vector<i32, 2> for glam::IVec2 {}
impl Vector<i32, 3> for glam::IVec3 {}
impl Vector<i32, 4> for glam::IVec4 {}

0 comments on commit 57a9ebb

Please sign in to comment.