Blender V5.0
vk_data_conversion.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#pragma once
10
12
14
15#include "vk_common.hh"
16
17namespace blender::gpu {
18struct VKWorkarounds;
19
34void convert_host_to_device(void *dst_buffer,
35 const void *src_buffer,
36 size_t buffer_size,
37 eGPUDataFormat host_format,
38 TextureFormat host_texture_format,
39 TextureFormat device_format);
40
55void convert_device_to_host(void *dst_buffer,
56 const void *src_buffer,
57 size_t buffer_size,
58 eGPUDataFormat host_format,
59 TextureFormat host_texture_format,
60 TextureFormat device_format);
61
62/* -------------------------------------------------------------------- */
65
69template<bool HasSignBit, uint8_t MantissaBitLen, uint8_t ExponentBitLen>
71 public:
72 static constexpr bool HAS_SIGN = HasSignBit;
73 static constexpr uint8_t SIGN_SHIFT = MantissaBitLen + ExponentBitLen;
74 static constexpr uint32_t SIGN_MASK = HasSignBit ? 1 : 0;
75 static constexpr uint8_t MANTISSA_LEN = MantissaBitLen;
76 static constexpr uint8_t MANTISSA_SHIFT = 0;
77 static constexpr uint32_t MANTISSA_MASK = (1 << MantissaBitLen) - 1;
78 static constexpr uint32_t MANTISSA_NAN_MASK = MANTISSA_MASK;
79 static constexpr uint8_t EXPONENT_SHIFT = MantissaBitLen;
80 static constexpr uint8_t EXPONENT_LEN = ExponentBitLen;
81 static constexpr uint32_t EXPONENT_MASK = (1 << ExponentBitLen) - 1;
82 static constexpr int32_t EXPONENT_BIAS = (1 << (ExponentBitLen - 1)) - 1;
84
85 static uint32_t get_mantissa(uint32_t floating_point_number)
86 {
87 return (floating_point_number >> MANTISSA_SHIFT) & MANTISSA_MASK;
88 }
89 static uint32_t clear_mantissa(uint32_t floating_point_number)
90 {
91 return floating_point_number & ~(MANTISSA_MASK << MANTISSA_SHIFT);
92 }
93 static uint32_t set_mantissa(uint32_t mantissa, uint32_t floating_point_number)
94 {
95 uint32_t result = clear_mantissa(floating_point_number);
96 result |= mantissa << MANTISSA_SHIFT;
97 return result;
98 }
99
100 static uint32_t get_exponent(uint32_t floating_point_number)
101 {
102 return ((floating_point_number >> EXPONENT_SHIFT) & EXPONENT_MASK);
103 }
104 static uint32_t clear_exponent(uint32_t floating_point_number)
105 {
106 return floating_point_number & ~(EXPONENT_MASK << EXPONENT_SHIFT);
107 }
108 static uint32_t set_exponent(uint32_t exponent, uint32_t floating_point_number)
109 {
110 uint32_t result = clear_exponent(floating_point_number);
111 result |= (exponent) << EXPONENT_SHIFT;
112 return result;
113 }
114
115 static bool is_signed(uint32_t floating_point_number)
116 {
117 if constexpr (HasSignBit) {
118 return (floating_point_number >> SIGN_SHIFT) & SIGN_MASK;
119 }
120 return false;
121 }
122 static uint32_t clear_sign(uint32_t floating_point_number)
123 {
124 return floating_point_number & ~(1 << SIGN_SHIFT);
125 }
126
127 static uint32_t set_sign(bool sign, uint32_t floating_point_number)
128 {
129 if constexpr (!HasSignBit) {
130 return floating_point_number;
131 }
132 uint32_t result = clear_sign(floating_point_number);
133 result |= uint32_t(sign) << SIGN_SHIFT;
134 return result;
135 }
136};
137
141
150template<
154 typename DestinationFormat,
155
159 typename SourceFormat,
160
168 bool ClampNegativeToZero = true>
169uint32_t convert_float_formats(uint32_t value)
170{
171 bool is_signed = SourceFormat::is_signed(value);
172 uint32_t mantissa = SourceFormat::get_mantissa(value);
173 int32_t exponent = SourceFormat::get_exponent(value);
174
175 const bool is_nan = (exponent == SourceFormat::EXPONENT_SPECIAL_MASK) && mantissa;
176 const bool is_inf = (exponent == SourceFormat::EXPONENT_SPECIAL_MASK) && (mantissa == 0);
177 const bool is_zero = (exponent == 0 && mantissa == 0);
178
179 /* Sign conversion */
180 if constexpr (!DestinationFormat::HAS_SIGN && ClampNegativeToZero) {
181 if (is_signed && !is_nan) {
182 return 0;
183 }
184 }
185 if (is_zero) {
186 return 0;
187 }
188
189 if (is_inf) {
190 exponent = DestinationFormat::EXPONENT_SPECIAL_MASK;
191 }
192 else if (is_nan) {
193 exponent = DestinationFormat::EXPONENT_SPECIAL_MASK;
194 mantissa = DestinationFormat::MANTISSA_NAN_MASK;
195 }
196 else {
197 /* Exponent conversion */
198 exponent -= SourceFormat::EXPONENT_BIAS;
199 /* Clamping when destination has lower precision. */
200 if constexpr (SourceFormat::EXPONENT_LEN > DestinationFormat::EXPONENT_LEN) {
201 if (exponent > DestinationFormat::EXPONENT_BIAS) {
202 exponent = 0;
203 mantissa = SourceFormat::MANTISSA_MASK;
204 }
205 else if (exponent < -DestinationFormat::EXPONENT_BIAS) {
206 return 0;
207 }
208 }
209 exponent += DestinationFormat::EXPONENT_BIAS;
210
211 /* Mantissa conversion */
212 if constexpr (SourceFormat::MANTISSA_LEN > DestinationFormat::MANTISSA_LEN) {
213 mantissa = mantissa >> (SourceFormat::MANTISSA_LEN - DestinationFormat::MANTISSA_LEN);
214 }
215 else if constexpr (SourceFormat::MANTISSA_LEN < DestinationFormat::MANTISSA_LEN) {
216 mantissa = mantissa << (DestinationFormat::MANTISSA_LEN - SourceFormat::MANTISSA_LEN);
217 }
218 }
219
220 uint32_t result = 0;
221 result = DestinationFormat::set_sign(is_signed, result);
222 result = DestinationFormat::set_exponent(exponent, result);
223 result = DestinationFormat::set_mantissa(mantissa, result);
224 return result;
225}
226
228
229}; // namespace blender::gpu
eGPUDataFormat
static uint32_t get_mantissa(uint32_t floating_point_number)
static uint32_t clear_mantissa(uint32_t floating_point_number)
static uint32_t set_mantissa(uint32_t mantissa, uint32_t floating_point_number)
static uint32_t clear_exponent(uint32_t floating_point_number)
static uint32_t clear_sign(uint32_t floating_point_number)
static uint32_t set_exponent(uint32_t exponent, uint32_t floating_point_number)
static uint32_t get_exponent(uint32_t floating_point_number)
static bool is_signed(uint32_t floating_point_number)
static uint32_t set_sign(bool sign, uint32_t floating_point_number)
constexpr T sign(T) RET
ccl_device_inline bool is_zero(const float2 a)
FloatingPointFormat< false, 6, 5 > FormatF11
FloatingPointFormat< false, 5, 5 > FormatF10
FloatingPointFormat< true, 23, 8 > FormatF32
void convert_host_to_device(void *dst_buffer, const void *src_buffer, size_t buffer_size, eGPUDataFormat host_format, TextureFormat host_texture_format, TextureFormat device_format)
uint32_t convert_float_formats(uint32_t value)
void convert_device_to_host(void *dst_buffer, const void *src_buffer, size_t buffer_size, eGPUDataFormat host_format, TextureFormat host_texture_format, TextureFormat device_format)