spirv_std/
float.rs

1//! Traits and helper functions related to floats.
2
3#[cfg(target_arch = "spirv")]
4use core::arch::asm;
5use glam::{Vec2, Vec4};
6
7/// Converts two f32 values (floats) into two f16 values (halfs). The result is a u32, with the low
8/// 16 bits being the first f16, and the high 16 bits being the second f16.
9#[spirv_std_macros::gpu_only]
10pub fn vec2_to_f16x2(vec: Vec2) -> u32 {
11    let result;
12    unsafe {
13        asm!(
14            "%glsl = OpExtInstImport \"GLSL.std.450\"",
15            "%uint = OpTypeInt 32 0",
16            "%vec = OpLoad _ {vec}",
17            // 58 = PackHalf2x16
18            "{result} = OpExtInst %uint %glsl 58 %vec",
19            vec = in(reg) &vec,
20            result = out(reg) result,
21        );
22    }
23    result
24}
25
26/// Converts two f16 values (halfs) into two f32 values (floats). The parameter is a u32, with the
27/// low 16 bits being the first f16, and the high 16 bits being the second f16.
28#[spirv_std_macros::gpu_only]
29pub fn f16x2_to_vec2(int: u32) -> Vec2 {
30    let mut result = Default::default();
31    unsafe {
32        asm!(
33            "%glsl = OpExtInstImport \"GLSL.std.450\"",
34            // 62 = UnpackHalf2x16
35            "%result = OpExtInst typeof*{result} %glsl 62 {int}",
36            "OpStore {result} %result",
37            int = in(reg) int,
38            result = in(reg) &mut result,
39        );
40    }
41    result
42}
43
44/// Converts an f32 (float) into an f16 (half). The result is a u32, not a u16, due to GPU support
45/// for u16 not being universal - the upper 16 bits will always be zero.
46#[spirv_std_macros::gpu_only]
47pub fn f32_to_f16(float: f32) -> u32 {
48    vec2_to_f16x2(glam::Vec2::new(float, 0.))
49}
50
51/// Converts an f16 (half) into an f32 (float). The parameter is a u32, due to GPU support for u16
52/// not being universal - the upper 16 bits are ignored.
53#[spirv_std_macros::gpu_only]
54pub fn f16_to_f32(packed: u32) -> f32 {
55    f16x2_to_vec2(packed).x
56}
57
58/// Packs a vec4 into 4 8-bit signed integers. See
59/// [PackSnorm4x8](https://www.khronos.org/registry/SPIR-V/specs/1.0/GLSL.std.450.html) for exact
60/// semantics.
61#[spirv_std_macros::gpu_only]
62pub fn vec4_to_u8x4_snorm(vec: Vec4) -> u32 {
63    let result;
64    unsafe {
65        asm!(
66            "%glsl = OpExtInstImport \"GLSL.std.450\"",
67            "%uint = OpTypeInt 32 0",
68            "%vec = OpLoad _ {vec}",
69            // 54 = PackSnorm4x8
70            "{result} = OpExtInst %uint %glsl 54 %vec",
71            vec = in(reg) &vec,
72            result = out(reg) result,
73        );
74    }
75    result
76}
77
78/// Packs a vec4 into 4 8-bit unsigned integers. See
79/// [PackUnorm4x8](https://www.khronos.org/registry/SPIR-V/specs/1.0/GLSL.std.450.html) for exact
80/// semantics.
81#[spirv_std_macros::gpu_only]
82pub fn vec4_to_u8x4_unorm(vec: Vec4) -> u32 {
83    let result;
84    unsafe {
85        asm!(
86            "%glsl = OpExtInstImport \"GLSL.std.450\"",
87            "%uint = OpTypeInt 32 0",
88            "%vec = OpLoad _ {vec}",
89            // 55 = PackUnorm4x8
90            "{result} = OpExtInst %uint %glsl 55 %vec",
91            vec = in(reg) &vec,
92            result = out(reg) result,
93        );
94    }
95    result
96}
97
98/// Packs a vec2 into 2 16-bit signed integers. See
99/// [PackSnorm2x16](https://www.khronos.org/registry/SPIR-V/specs/1.0/GLSL.std.450.html) for exact
100/// semantics.
101#[spirv_std_macros::gpu_only]
102pub fn vec2_to_u16x2_snorm(vec: Vec2) -> u32 {
103    let result;
104    unsafe {
105        asm!(
106            "%glsl = OpExtInstImport \"GLSL.std.450\"",
107            "%uint = OpTypeInt 32 0",
108            "%vec = OpLoad _ {vec}",
109            // 56 = PackSnorm2x16
110            "{result} = OpExtInst %uint %glsl 56 %vec",
111            vec = in(reg) &vec,
112            result = out(reg) result,
113        );
114    }
115    result
116}
117
118/// Packs a vec2 into 2 16-bit unsigned integers. See
119/// [PackUnorm2x16](https://www.khronos.org/registry/SPIR-V/specs/1.0/GLSL.std.450.html) for exact
120/// semantics.
121#[spirv_std_macros::gpu_only]
122pub fn vec2_to_u16x2_unorm(vec: Vec2) -> u32 {
123    let result;
124    unsafe {
125        asm!(
126            "%glsl = OpExtInstImport \"GLSL.std.450\"",
127            "%uint = OpTypeInt 32 0",
128            "%vec = OpLoad _ {vec}",
129            // 57 = PackUnorm2x16
130            "{result} = OpExtInst %uint %glsl 57 %vec",
131            vec = in(reg) &vec,
132            result = out(reg) result,
133        );
134    }
135    result
136}
137
138/// Unpacks 4 8-bit signed integers into a vec4. See
139/// [UnpackSnorm4x8](https://www.khronos.org/registry/SPIR-V/specs/1.0/GLSL.std.450.html) for exact
140/// semantics.
141#[spirv_std_macros::gpu_only]
142pub fn u8x4_to_vec4_snorm(int: u32) -> Vec4 {
143    let mut result = Default::default();
144    unsafe {
145        asm!(
146            "%glsl = OpExtInstImport \"GLSL.std.450\"",
147            // 63 = UnpackSnorm4x8
148            "%result = OpExtInst typeof*{result} %glsl 63 {int}",
149            "OpStore {result} %result",
150            int = in(reg) int,
151            result = in(reg) &mut result,
152        );
153    }
154    result
155}
156
157/// Unpacks 4 8-bit unsigned integers into a vec4. See
158/// [UnpackSnorm4x8](https://www.khronos.org/registry/SPIR-V/specs/1.0/GLSL.std.450.html) for exact
159/// semantics.
160#[spirv_std_macros::gpu_only]
161pub fn u8x4_to_vec4_unorm(int: u32) -> Vec4 {
162    let mut result = Default::default();
163    unsafe {
164        asm!(
165            "%glsl = OpExtInstImport \"GLSL.std.450\"",
166            // 64 = UnpackUnorm4x8
167            "%result = OpExtInst typeof*{result} %glsl 64 {int}",
168            "OpStore {result} %result",
169            int = in(reg) int,
170            result = in(reg) &mut result,
171        );
172    }
173    result
174}
175
176/// Unpacks 2 16-bit signed integers into a vec2. See
177/// [UnpackSnorm2x16](https://www.khronos.org/registry/SPIR-V/specs/1.0/GLSL.std.450.html) for
178/// exact semantics.
179#[spirv_std_macros::gpu_only]
180pub fn u16x2_to_vec2_snorm(int: u32) -> Vec2 {
181    let mut result = Default::default();
182    unsafe {
183        asm!(
184            "%glsl = OpExtInstImport \"GLSL.std.450\"",
185            // 60 = UnpackSnorm2x16
186            "%result = OpExtInst typeof*{result} %glsl 60 {int}",
187            "OpStore {result} %result",
188            int = in(reg) int,
189            result = in(reg) &mut result,
190        );
191    }
192    result
193}
194
195/// Unpacks 2 16-bit unsigned integers into a vec2. See
196/// [UnpackUnorm2x16](https://www.khronos.org/registry/SPIR-V/specs/1.0/GLSL.std.450.html) for
197/// exact semantics.
198#[spirv_std_macros::gpu_only]
199pub fn u16x2_to_vec2_unorm(int: u32) -> Vec2 {
200    let mut result = Default::default();
201    unsafe {
202        asm!(
203            "%glsl = OpExtInstImport \"GLSL.std.450\"",
204            // 61 = UnpackUnorm2x16
205            "%result = OpExtInst typeof*{result} %glsl 61 {int}",
206            "OpStore {result} %result",
207            int = in(reg) int,
208            result = in(reg) &mut result,
209        );
210    }
211    result
212}