|
3 | 3 | //! This module is intended as a low level abstraction over SPIR-V instructions.
|
4 | 4 | //! These functions will typically map to a single instruction, and will perform
|
5 | 5 | //! no additional safety checks beyond type-checking.
|
6 |
| -use crate::{scalar::Scalar, vector::Vector}; |
| 6 | +use crate::{ |
| 7 | + integer::{Integer, SignedInteger, UnsignedInteger}, |
| 8 | + scalar::Scalar, |
| 9 | + vector::Vector, |
| 10 | +}; |
7 | 11 |
|
8 | 12 | mod barrier;
|
9 | 13 | 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 {
|
200 | 204 |
|
201 | 205 | result
|
202 | 206 | }
|
| 207 | + |
| 208 | +#[spirv_std_macros::gpu_only] |
| 209 | +unsafe fn call_glsl_op_with_ints<T: Integer, const OP: u32>(a: T, b: T) -> T { |
| 210 | + let mut result = T::default(); |
| 211 | + asm!( |
| 212 | + "%glsl = OpExtInstImport \"GLSL.std.450\"", |
| 213 | + "%a = OpLoad _ {a}", |
| 214 | + "%b = OpLoad _ {b}", |
| 215 | + "%result = OpExtInst typeof*{result} %glsl {op} %a %b", |
| 216 | + "OpStore {result} %result", |
| 217 | + a = in(reg) &a, |
| 218 | + b = in(reg) &b, |
| 219 | + result = in(reg) &mut result, |
| 220 | + op = const OP |
| 221 | + ); |
| 222 | + result |
| 223 | +} |
| 224 | + |
| 225 | +/// Compute the minimum of two unsigned integers via a GLSL extended instruction. |
| 226 | +#[spirv_std_macros::gpu_only] |
| 227 | +pub fn unsigned_min<T: UnsignedInteger>(a: T, b: T) -> T { |
| 228 | + unsafe { call_glsl_op_with_ints::<_, 38>(a, b) } |
| 229 | +} |
| 230 | + |
| 231 | +/// Compute the maximum of two unsigned integers via a GLSL extended instruction. |
| 232 | +#[spirv_std_macros::gpu_only] |
| 233 | +pub fn unsigned_max<T: UnsignedInteger>(a: T, b: T) -> T { |
| 234 | + unsafe { call_glsl_op_with_ints::<_, 41>(a, b) } |
| 235 | +} |
| 236 | + |
| 237 | +/// Compute the minimum of two signed integers via a GLSL extended instruction. |
| 238 | +#[spirv_std_macros::gpu_only] |
| 239 | +pub fn signed_min<T: SignedInteger>(a: T, b: T) -> T { |
| 240 | + unsafe { call_glsl_op_with_ints::<_, 39>(a, b) } |
| 241 | +} |
| 242 | + |
| 243 | +/// Compute the maximum of two signed integers via a GLSL extended instruction. |
| 244 | +#[spirv_std_macros::gpu_only] |
| 245 | +pub fn signed_max<T: SignedInteger>(a: T, b: T) -> T { |
| 246 | + unsafe { call_glsl_op_with_ints::<_, 42>(a, b) } |
| 247 | +} |
0 commit comments