|
3 | 3 | //! GLSL: [`GL_EXT_shader_realtime_clock`](https://github.com/KhronosGroup/GLSL/blob/main/extensions/ext/GL_EXT_shader_realtime_clock.txt) |
4 | 4 | //! SPIRV: [`SPV_KHR_shader_clock`](https://github.khronos.org/SPIRV-Registry/extensions/KHR/SPV_KHR_shader_clock.html) |
5 | 5 |
|
| 6 | +#[cfg(target_arch = "spirv")] |
| 7 | +use crate::memory::Scope; |
6 | 8 | #[cfg(target_arch = "spirv")] |
7 | 9 | use core::arch::asm; |
8 | 10 | use glam::UVec2; |
9 | 11 |
|
10 | | -/// Read from the shader clock with either the `Subgroup` or `Device` scope. |
| 12 | +/// The [`read_clock`] function returns a 64-bit value representing a real-time clock that is globally coherent by |
| 13 | +/// all invocations on the GPU. See [`read_clock_uvec2`] for a variant that doesn't require 64-bit support. |
11 | 14 | /// |
12 | | -/// See: <https://github.khronos.org/SPIRV-Registry/extensions/KHR/SPV_KHR_shader_clock.html> |
| 15 | +/// The units of time are not defined for either of these operations and will wrap after exceeding the maximum value |
| 16 | +/// representable in 64 bits. These functions serve as code motion barriers. |
13 | 17 | #[spirv_std_macros::gpu_only] |
14 | 18 | #[doc(alias = "OpReadClockKHR")] |
15 | | -pub fn read_clock_khr<const SCOPE: u32>() -> u64 { |
| 19 | +pub fn read_clock() -> u64 { |
16 | 20 | unsafe { |
17 | | - let mut result: u64; |
18 | | - |
| 21 | + let mut result = Default::default(); |
19 | 22 | asm! { |
20 | 23 | "%uint = OpTypeInt 32 0", |
21 | 24 | "%scope = OpConstant %uint {scope}", |
22 | | - "{result} = OpReadClockKHR typeof*{result} %scope", |
23 | | - result = out(reg) result, |
24 | | - scope = const SCOPE, |
| 25 | + "%result = OpReadClockKHR typeof*{result} %scope", |
| 26 | + "OpStore {result} %result", |
| 27 | + result = in(reg) &mut result, |
| 28 | + scope = const (Scope::Device as u32), |
25 | 29 | }; |
26 | | - |
27 | 30 | result |
28 | 31 | } |
29 | 32 | } |
30 | 33 |
|
31 | | -/// Like `read_clock_khr` but returns a vector to avoid requiring the `Int64` |
32 | | -/// capability. It returns a 'vector of two-components of 32-bit unsigned |
33 | | -/// integer type with the first component containing the 32 least significant |
34 | | -/// bits and the second component containing the 32 most significant bits.' |
| 34 | +/// [`read_clock_uvec2`] returns the same value encoded as a two-component vector of 32-bit unsigned integers with the |
| 35 | +/// first component containing the 32 least significant bits and the second component containing the 32 most significant |
| 36 | +/// bits. See [`read_clock`] for a variant that returns a single `u64`. |
35 | 37 | /// |
36 | | -/// See: |
37 | | -/// <https://htmlpreview.github.io/?https://github.com/KhronosGroup/SPIRV-Registry/blob/master/extensions/KHR/SPV_KHR_shader_clock.html> |
| 38 | +/// The units of time are not defined for either of these operations and will wrap after exceeding the maximum value |
| 39 | +/// representable in 64 bits. These functions serve as code motion barriers. |
38 | 40 | #[spirv_std_macros::gpu_only] |
39 | 41 | #[doc(alias = "OpReadClockKHR")] |
40 | | -pub fn read_clock_uvec2_khr<const SCOPE: u32>() -> UVec2 { |
| 42 | +pub fn read_clock_uvec2() -> UVec2 { |
41 | 43 | unsafe { |
42 | | - let mut result = UVec2::default(); |
43 | | - |
| 44 | + let mut result = Default::default(); |
44 | 45 | asm! { |
45 | 46 | "%uint = OpTypeInt 32 0", |
46 | 47 | "%scope = OpConstant %uint {scope}", |
47 | 48 | "%result = OpReadClockKHR typeof*{result} %scope", |
48 | 49 | "OpStore {result} %result", |
49 | 50 | result = in(reg) &mut result, |
50 | | - scope = const SCOPE, |
| 51 | + scope = const (Scope::Device as u32), |
51 | 52 | }; |
52 | | - |
53 | 53 | result |
54 | 54 | } |
55 | 55 | } |
0 commit comments