Add arch functions for the GLSL.std.450 S/U Min/Max functions (#763)

* Add (un)signed_(min|max) glsl functinos

* Add gpu_only to call glsl op
This commit is contained in:
Ashley 2021-10-11 23:49:02 -07:00 committed by GitHub
parent 14e2152198
commit f8a1130377
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 72 additions and 1 deletions

View File

@ -3,7 +3,11 @@
//! This module is intended as a low level abstraction over SPIR-V instructions.
//! These functions will typically map to a single instruction, and will perform
//! no additional safety checks beyond type-checking.
use crate::{scalar::Scalar, vector::Vector};
use crate::{
integer::{Integer, SignedInteger, UnsignedInteger},
scalar::Scalar,
vector::Vector,
};
mod barrier;
mod demote_to_helper_invocation_ext;
@ -200,3 +204,44 @@ pub unsafe fn read_clock_uvec2_khr<V: Vector<u32, 2>, const SCOPE: u32>() -> V {
result
}
#[spirv_std_macros::gpu_only]
unsafe fn call_glsl_op_with_ints<T: Integer, const OP: u32>(a: T, b: T) -> T {
let mut result = T::default();
asm!(
"%glsl = OpExtInstImport \"GLSL.std.450\"",
"%a = OpLoad _ {a}",
"%b = OpLoad _ {b}",
"%result = OpExtInst typeof*{result} %glsl {op} %a %b",
"OpStore {result} %result",
a = in(reg) &a,
b = in(reg) &b,
result = in(reg) &mut result,
op = const OP
);
result
}
/// Compute the minimum of two unsigned integers via a GLSL extended instruction.
#[spirv_std_macros::gpu_only]
pub fn unsigned_min<T: UnsignedInteger>(a: T, b: T) -> T {
unsafe { call_glsl_op_with_ints::<_, 38>(a, b) }
}
/// Compute the maximum of two unsigned integers via a GLSL extended instruction.
#[spirv_std_macros::gpu_only]
pub fn unsigned_max<T: UnsignedInteger>(a: T, b: T) -> T {
unsafe { call_glsl_op_with_ints::<_, 41>(a, b) }
}
/// Compute the minimum of two signed integers via a GLSL extended instruction.
#[spirv_std_macros::gpu_only]
pub fn signed_min<T: SignedInteger>(a: T, b: T) -> T {
unsafe { call_glsl_op_with_ints::<_, 39>(a, b) }
}
/// Compute the maximum of two signed integers via a GLSL extended instruction.
#[spirv_std_macros::gpu_only]
pub fn signed_max<T: SignedInteger>(a: T, b: T) -> T {
unsafe { call_glsl_op_with_ints::<_, 42>(a, b) }
}

View File

@ -0,0 +1,26 @@
// build-pass
use spirv_std::arch::{signed_max, signed_min, unsigned_max, unsigned_min};
#[spirv(fragment)]
pub fn main() {
assert!(unsigned_min(39_u8, 13) == 13);
assert!(unsigned_min(39_u16, 13) == 13);
assert!(unsigned_min(39_u32, 13) == 13);
assert!(unsigned_min(39_u64, 13) == 13);
assert!(unsigned_max(39_u8, 13) == 39);
assert!(unsigned_max(39_u16, 13) == 39);
assert!(unsigned_max(39_u32, 13) == 39);
assert!(unsigned_max(39_u64, 13) == 39);
assert!(signed_min(-112_i8, -45) == -112);
assert!(signed_min(-112_i16, -45) == -112);
assert!(signed_min(-112_i32, -45) == -112);
assert!(signed_min(-112_i64, -45) == -112);
assert!(signed_max(-112_i8, -45) == -45);
assert!(signed_max(-112_i16, -45) == -45);
assert!(signed_max(-112_i32, -45) == -45);
assert!(signed_max(-112_i64, -45) == -45);
}