|
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. |
| 14 | +/// |
| 15 | +/// clockRealtime2x32EXT() returns the same value encoded as a two-component vector of 32-bit unsigned integers with the first component containing the 32 least significant bits and the second component containing the 32 most significant bits. |
11 | 16 | /// |
12 | | -/// See: <https://github.khronos.org/SPIRV-Registry/extensions/KHR/SPV_KHR_shader_clock.html> |
| 17 | +/// The units of time are not defined for either of these operations and will wrap after exceeding the maximum value |
| 18 | +/// representable in 64 bits. These functions serve as code motion barriers. |
13 | 19 | #[spirv_std_macros::gpu_only] |
14 | 20 | #[doc(alias = "OpReadClockKHR")] |
15 | | -pub fn read_clock_khr<const SCOPE: u32>() -> u64 { |
| 21 | +pub fn read_clock() -> u64 { |
16 | 22 | unsafe { |
17 | | - let mut result: u64; |
18 | | - |
| 23 | + let mut result = Default::default(); |
19 | 24 | asm! { |
20 | 25 | "%uint = OpTypeInt 32 0", |
21 | 26 | "%scope = OpConstant %uint {scope}", |
22 | | - "{result} = OpReadClockKHR typeof*{result} %scope", |
23 | | - result = out(reg) result, |
24 | | - scope = const SCOPE, |
| 27 | + "%result = OpReadClockKHR typeof*{result} %scope", |
| 28 | + "OpStore {result} %result", |
| 29 | + result = in(reg) &mut result, |
| 30 | + scope = const (Scope::Device as u32), |
25 | 31 | }; |
26 | | - |
27 | 32 | result |
28 | 33 | } |
29 | 34 | } |
30 | 35 |
|
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.' |
| 36 | +/// [`read_clock_uvec2`] returns the same value encoded as a two-component vector of 32-bit unsigned integers with the |
| 37 | +/// first component containing the 32 least significant bits and the second component containing the 32 most significant |
| 38 | +/// bits. See [`read_clock`] for a variant that returns a single `u64`. |
35 | 39 | /// |
36 | | -/// See: |
37 | | -/// <https://htmlpreview.github.io/?https://github.com/KhronosGroup/SPIRV-Registry/blob/master/extensions/KHR/SPV_KHR_shader_clock.html> |
| 40 | +/// The units of time are not defined for either of these operations and will wrap after exceeding the maximum value |
| 41 | +/// representable in 64 bits. These functions serve as code motion barriers. |
38 | 42 | #[spirv_std_macros::gpu_only] |
39 | 43 | #[doc(alias = "OpReadClockKHR")] |
40 | | -pub fn read_clock_uvec2_khr<const SCOPE: u32>() -> UVec2 { |
| 44 | +pub fn read_clock_uvec2() -> UVec2 { |
41 | 45 | unsafe { |
42 | | - let mut result = UVec2::default(); |
43 | | - |
| 46 | + let mut result = Default::default(); |
44 | 47 | asm! { |
45 | 48 | "%uint = OpTypeInt 32 0", |
46 | 49 | "%scope = OpConstant %uint {scope}", |
47 | 50 | "%result = OpReadClockKHR typeof*{result} %scope", |
48 | 51 | "OpStore {result} %result", |
49 | 52 | result = in(reg) &mut result, |
50 | | - scope = const SCOPE, |
| 53 | + scope = const (Scope::Device as u32), |
51 | 54 | }; |
52 | | - |
53 | 55 | result |
54 | 56 | } |
55 | 57 | } |
0 commit comments