mirror of
https://github.com/EmbarkStudios/rust-gpu.git
synced 2024-11-25 08:14:12 +00:00
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:
parent
14e2152198
commit
f8a1130377
@ -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) }
|
||||
}
|
||||
|
26
tests/ui/arch/integer_min_and_max.rs
Normal file
26
tests/ui/arch/integer_min_and_max.rs
Normal 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user