Blender V4.3
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
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 eGPUTextureFormat host_texture_format,
39 eGPUTextureFormat 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 eGPUTextureFormat host_texture_format,
60 eGPUTextureFormat device_format);
61
69bool conversion_needed(const GPUVertFormat &vertex_format);
70
84void convert_in_place(void *data, const GPUVertFormat &vertex_format, const uint vertex_len);
85
86/* -------------------------------------------------------------------- */
101 private:
103 const GPUVertFormat *source_format_ = nullptr;
104
111 const GPUVertFormat *device_format_ = nullptr;
112
113 bool needs_conversion_ = false;
114
119 GPUVertFormat converted_format_;
120
121 public:
127 bool is_initialized() const;
128
139 void init(const GPUVertFormat *vertex_format, const VKWorkarounds &workarounds);
140
147 const GPUVertFormat &device_format_get() const;
148
152 bool needs_conversion() const;
153
163 void convert(void *device_data, const void *src_data, const uint vertex_len) const;
164
170 void reset();
171
172 private:
177 void update_conversion_flags(const GPUVertFormat &vertex_format,
178 const VKWorkarounds &workarounds);
179 void update_conversion_flags(const GPUVertAttr &vertex_attribute,
180 const VKWorkarounds &workarounds);
181
185 void init_device_format(const VKWorkarounds &workarounds);
186 void make_device_compatible(GPUVertAttr &vertex_attribute,
187 const VKWorkarounds &workarounds,
188 bool &needs_repack) const;
189
190 void convert_row(void *device_row_data, const void *source_row_data) const;
191 void convert_attribute(void *device_row_data,
192 const void *source_row_data,
193 const GPUVertAttr &device_attribute,
194 const GPUVertAttr &source_attribute) const;
195};
196
197/* \} */
198
199/* -------------------------------------------------------------------- */
206template<bool HasSignBit, uint8_t MantissaBitLen, uint8_t ExponentBitLen>
208 public:
209 static constexpr bool HAS_SIGN = HasSignBit;
210 static constexpr uint8_t SIGN_SHIFT = MantissaBitLen + ExponentBitLen;
211 static constexpr uint32_t SIGN_MASK = HasSignBit ? 1 : 0;
212 static constexpr uint8_t MANTISSA_LEN = MantissaBitLen;
213 static constexpr uint8_t MANTISSA_SHIFT = 0;
214 static constexpr uint32_t MANTISSA_MASK = (1 << MantissaBitLen) - 1;
216 static constexpr uint8_t EXPONENT_SHIFT = MantissaBitLen;
217 static constexpr uint8_t EXPONENT_LEN = ExponentBitLen;
218 static constexpr uint32_t EXPONENT_MASK = (1 << ExponentBitLen) - 1;
219 static constexpr int32_t EXPONENT_BIAS = (1 << (ExponentBitLen - 1)) - 1;
221
222 static uint32_t get_mantissa(uint32_t floating_point_number)
223 {
224 return (floating_point_number >> MANTISSA_SHIFT) & MANTISSA_MASK;
225 }
226 static uint32_t clear_mantissa(uint32_t floating_point_number)
227 {
228 return floating_point_number & ~(MANTISSA_MASK << MANTISSA_SHIFT);
229 }
230 static uint32_t set_mantissa(uint32_t mantissa, uint32_t floating_point_number)
231 {
232 uint32_t result = clear_mantissa(floating_point_number);
233 result |= mantissa << MANTISSA_SHIFT;
234 return result;
235 }
236
237 static uint32_t get_exponent(uint32_t floating_point_number)
238 {
239 return ((floating_point_number >> EXPONENT_SHIFT) & EXPONENT_MASK);
240 }
241 static uint32_t clear_exponent(uint32_t floating_point_number)
242 {
243 return floating_point_number & ~(EXPONENT_MASK << EXPONENT_SHIFT);
244 }
245 static uint32_t set_exponent(uint32_t exponent, uint32_t floating_point_number)
246 {
247 uint32_t result = clear_exponent(floating_point_number);
248 result |= (exponent) << EXPONENT_SHIFT;
249 return result;
250 }
251
252 static bool is_signed(uint32_t floating_point_number)
253 {
254 if constexpr (HasSignBit) {
255 return (floating_point_number >> SIGN_SHIFT) & SIGN_MASK;
256 }
257 return false;
258 }
259 static uint32_t clear_sign(uint32_t floating_point_number)
260 {
261 return floating_point_number & ~(1 << SIGN_SHIFT);
262 }
263
264 static uint32_t set_sign(bool sign, uint32_t floating_point_number)
265 {
266 if constexpr (!HasSignBit) {
267 return floating_point_number;
268 }
269 uint32_t result = clear_sign(floating_point_number);
270 result |= uint32_t(sign) << SIGN_SHIFT;
271 return result;
272 }
273};
274
278
287template<
291 typename DestinationFormat,
292
296 typename SourceFormat,
297
305 bool ClampNegativeToZero = true>
307{
308 bool is_signed = SourceFormat::is_signed(value);
309 uint32_t mantissa = SourceFormat::get_mantissa(value);
310 int32_t exponent = SourceFormat::get_exponent(value);
311
312 const bool is_nan = (exponent == SourceFormat::EXPONENT_SPECIAL_MASK) && mantissa;
313 const bool is_inf = (exponent == SourceFormat::EXPONENT_SPECIAL_MASK) && (mantissa == 0);
314 const bool is_zero = (exponent == 0 && mantissa == 0);
315
316 /* Sign conversion */
317 if constexpr (!DestinationFormat::HAS_SIGN && ClampNegativeToZero) {
318 if (is_signed && !is_nan) {
319 return 0;
320 }
321 }
322 if (is_zero) {
323 return 0;
324 }
325
326 if (is_inf) {
327 exponent = DestinationFormat::EXPONENT_SPECIAL_MASK;
328 }
329 else if (is_nan) {
330 exponent = DestinationFormat::EXPONENT_SPECIAL_MASK;
331 mantissa = DestinationFormat::MANTISSA_NAN_MASK;
332 }
333 else {
334 /* Exponent conversion */
335 exponent -= SourceFormat::EXPONENT_BIAS;
336 /* Clamping when destination has lower precision. */
337 if constexpr (SourceFormat::EXPONENT_LEN > DestinationFormat::EXPONENT_LEN) {
338 if (exponent > DestinationFormat::EXPONENT_BIAS) {
339 exponent = 0;
340 mantissa = SourceFormat::MANTISSA_MASK;
341 }
342 else if (exponent < -DestinationFormat::EXPONENT_BIAS) {
343 return 0;
344 }
345 }
346 exponent += DestinationFormat::EXPONENT_BIAS;
347
348 /* Mantissa conversion */
349 if constexpr (SourceFormat::MANTISSA_LEN > DestinationFormat::MANTISSA_LEN) {
350 mantissa = mantissa >> (SourceFormat::MANTISSA_LEN - DestinationFormat::MANTISSA_LEN);
351 }
352 else if constexpr (SourceFormat::MANTISSA_LEN < DestinationFormat::MANTISSA_LEN) {
353 mantissa = mantissa << (DestinationFormat::MANTISSA_LEN - SourceFormat::MANTISSA_LEN);
354 }
355 }
356
357 uint32_t result = 0;
358 result = DestinationFormat::set_sign(is_signed, result);
359 result = DestinationFormat::set_exponent(exponent, result);
360 result = DestinationFormat::set_mantissa(mantissa, result);
361 return result;
362}
363
364/* \} */
365
366}; // namespace blender::gpu
unsigned int uint
eGPUDataFormat
eGPUTextureFormat
void init()
static constexpr uint8_t EXPONENT_LEN
static uint32_t get_mantissa(uint32_t floating_point_number)
static constexpr int32_t EXPONENT_BIAS
static uint32_t clear_mantissa(uint32_t floating_point_number)
static constexpr uint8_t MANTISSA_SHIFT
static constexpr uint32_t SIGN_MASK
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 constexpr uint8_t EXPONENT_SHIFT
static constexpr uint32_t MANTISSA_MASK
static constexpr uint8_t MANTISSA_LEN
static constexpr uint32_t EXPONENT_MASK
static constexpr int32_t EXPONENT_SPECIAL_MASK
static uint32_t set_exponent(uint32_t exponent, uint32_t floating_point_number)
static constexpr uint32_t MANTISSA_NAN_MASK
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)
ccl_device_inline bool is_zero(const float2 a)
bool conversion_needed(const GPUVertFormat &vertex_format)
void convert_host_to_device(void *dst_buffer, const void *src_buffer, size_t buffer_size, eGPUDataFormat host_format, eGPUTextureFormat host_texture_format, eGPUTextureFormat device_format)
void convert_device_to_host(void *dst_buffer, const void *src_buffer, size_t buffer_size, eGPUDataFormat host_format, eGPUTextureFormat host_texture_format, eGPUTextureFormat device_format)
void convert_in_place(void *data, const GPUVertFormat &vertex_format, const uint vertex_len)
uint32_t convert_float_formats(uint32_t value)
unsigned int uint32_t
Definition stdint.h:80
signed int int32_t
Definition stdint.h:77
unsigned char uint8_t
Definition stdint.h:78
void convert(void *device_data, const void *src_data, const uint vertex_len) const
const GPUVertFormat & device_format_get() const