ReXGlue SDK
Loading...
Searching...
No Matches
format.h
Go to the documentation of this file.
1
13
14#pragma once
15
16#include <algorithm>
17#include <bit>
18
19#include <rex/assert.h>
20#include <rex/platform.h>
21#include <rex/types.h>
22
23namespace rex::xenos {
24
26// NOLINTNEXTLINE(performance-enum-size): Xenos bit field, MSVC packs per type
27enum class Endian : u32 {
28 kNone = 0,
29 k8in16 = 1,
30 k8in32 = 2,
31 k16in32 = 3,
32};
33
35// NOLINTNEXTLINE(performance-enum-size): Xenos bit field, MSVC packs per type
36enum class Endian128 : u32 {
37 kNone = 0,
38 k8in16 = 1,
39 k8in32 = 2,
40 k16in32 = 3,
41 k8in64 = 4,
42 k8in128 = 5,
43};
44
45// NOLINTNEXTLINE(performance-enum-size): Xenos bit field, MSVC packs per type
46enum class IndexFormat : u32 {
47 kInt16,
48 kInt32,
49};
50
51// NOLINTNEXTLINE(performance-enum-size): Xenos bit field, MSVC packs per type
52enum class SurfaceNumberFormat : u32 {
55 kUnsignedInteger = 2,
56 kSignedInteger = 3,
57 kFloat = 7,
58};
59
60// NOLINTNEXTLINE(performance-enum-size): Xenos bit field, MSVC packs per type
61enum class ColorRenderTargetFormat : u32 {
66 k_16_16 = 4,
68 k_16_16_FLOAT = 6,
69 k_16_16_16_16_FLOAT = 7,
72 k_32_FLOAT = 14,
73 k_32_32_FLOAT = 15,
74};
75
80
88 format == ColorRenderTargetFormat::k_16_16_16_16_FLOAT ||
89 format == ColorRenderTargetFormat::k_32_32_FLOAT;
90}
91
96 switch (format) {
102 case ColorRenderTargetFormat::k_16_16_16_16_FLOAT:
105 return 4;
107 case ColorRenderTargetFormat::k_16_16_FLOAT:
108 case ColorRenderTargetFormat::k_32_32_FLOAT:
109 return 2;
110 case ColorRenderTargetFormat::k_32_FLOAT:
111 return 1;
112 default:
113 REX_UNHANDLED_CASE(format);
114 return 0;
115 }
116}
117
133
134// NOLINTNEXTLINE(performance-enum-size): Xenos bit field, MSVC packs per type
135enum class DepthRenderTargetFormat : u32 {
136 kD24S8 = 0,
138};
139
144
151f32 PWLGammaToLinear(f32 gamma);
152
159f32 LinearToPWLGamma(f32 linear);
160
166f32 Float7e3To32(u32 f10);
167
175u32 Float32To20e4(f32 value, bool round_to_nearest_even);
176
182f32 Float20e4To32(u32 f24);
183
185constexpr f32 UNorm24To32(u32 n24) {
186 return static_cast<f32>(n24 + (n24 >> 23)) * (1.0f / static_cast<f32>(1 << 24));
187}
188
189constexpr u32 kColorRenderTargetFormatBits = 4;
190constexpr u32 kDepthRenderTargetFormatBits = 1;
193 std::max(kColorRenderTargetFormatBits, kDepthRenderTargetFormatBits);
194
195constexpr u32 kFormatBits = 6;
196
197// NOLINTNEXTLINE(performance-enum-size): Xenos bit field, MSVC packs per type
198enum class TextureFormat : u32 {
200 k_1 = 1,
201 k_8 = 2,
202 k_1_5_5_5 = 3,
203 k_5_6_5 = 4,
204 k_6_5_5 = 5,
205 k_8_8_8_8 = 6,
206 k_2_10_10_10 = 7,
207 k_8_A = 8,
208 k_8_B = 9,
209 k_8_8 = 10,
212 k_16_16_EDRAM = 13,
214 k_4_4_4_4 = 15,
215 k_10_11_11 = 16,
216 k_11_11_10 = 17,
217 k_DXT1 = 18,
218 k_DXT2_3 = 19,
219 k_DXT4_5 = 20,
220 k_16_16_16_16_EDRAM = 21,
221 k_24_8 = 22,
223 k_16 = 24,
224 k_16_16 = 25,
225 k_16_16_16_16 = 26,
226 k_16_EXPAND = 27,
227 k_16_16_EXPAND = 28,
228 k_16_16_16_16_EXPAND = 29,
229 k_16_FLOAT = 30,
230 k_16_16_FLOAT = 31,
231 k_16_16_16_16_FLOAT = 32,
232 k_32 = 33,
233 k_32_32 = 34,
234 k_32_32_32_32 = 35,
235 k_32_FLOAT = 36,
236 k_32_32_FLOAT = 37,
237 k_32_32_32_32_FLOAT = 38,
238 k_32_AS_8 = 39,
239 k_32_AS_8_8 = 40,
240 k_16_MPEG = 41,
241 k_16_16_MPEG = 42,
242 k_8_INTERLACED = 43,
243 k_32_AS_8_INTERLACED = 44,
244 k_32_AS_8_8_INTERLACED = 45,
245 k_16_INTERLACED = 46,
246 k_16_MPEG_INTERLACED = 47,
247 k_16_16_MPEG_INTERLACED = 48,
248 k_DXN = 49,
249 k_8_8_8_8_AS_16_16_16_16 = 50,
250 k_DXT1_AS_16_16_16_16 = 51,
251 k_DXT2_3_AS_16_16_16_16 = 52,
252 k_DXT4_5_AS_16_16_16_16 = 53,
253 k_2_10_10_10_AS_16_16_16_16 = 54,
254 k_10_11_11_AS_16_16_16_16 = 55,
255 k_11_11_10_AS_16_16_16_16 = 56,
256 k_32_32_32_FLOAT = 57,
257 k_DXT3A = 58,
258 k_DXT5A = 59,
259 k_CTX1 = 60,
260 k_DXT3A_AS_1_1_1_1 = 61,
261 k_8_8_8_8_GAMMA_EDRAM = 62,
263};
264
266// NOLINTNEXTLINE(performance-enum-size): Xenos bit field, MSVC packs per type
267enum class ColorFormat : u32 {
268 k_8 = 2,
269 k_1_5_5_5 = 3,
270 k_5_6_5 = 4,
271 k_6_5_5 = 5,
272 k_8_8_8_8 = 6,
273 k_2_10_10_10 = 7,
274 k_8_A = 8,
275 k_8_B = 9,
276 k_8_8 = 10,
277 k_8_8_8_8_A = 14,
278 k_4_4_4_4 = 15,
279 k_10_11_11 = 16,
280 k_11_11_10 = 17,
281 k_16 = 24,
282 k_16_16 = 25,
283 k_16_16_16_16 = 26,
284 k_16_FLOAT = 30,
285 k_16_16_FLOAT = 31,
286 k_16_16_16_16_FLOAT = 32,
287 k_32_FLOAT = 36,
288 k_32_32_FLOAT = 37,
289 k_32_32_32_32_FLOAT = 38,
290 k_8_8_8_8_AS_16_16_16_16 = 50,
291 k_2_10_10_10_AS_16_16_16_16 = 54,
292 k_10_11_11_AS_16_16_16_16 = 55,
293 k_11_11_10_AS_16_16_16_16 = 56,
294};
295
305 ColorFormat color_format) {
306 switch (render_target_format) {
309 return color_format == ColorFormat::k_8_8_8_8 || color_format == ColorFormat::k_8_8_8_8_A ||
310 color_format == ColorFormat::k_8_8_8_8_AS_16_16_16_16;
313 return color_format == ColorFormat::k_2_10_10_10 ||
314 color_format == ColorFormat::k_2_10_10_10_AS_16_16_16_16;
315 case ColorRenderTargetFormat::k_16_16_FLOAT:
316 return color_format == ColorFormat::k_16_16_FLOAT;
317 case ColorRenderTargetFormat::k_16_16_16_16_FLOAT:
318 return color_format == ColorFormat::k_16_16_16_16_FLOAT;
319 case ColorRenderTargetFormat::k_32_FLOAT:
320 return color_format == ColorFormat::k_32_FLOAT;
321 case ColorRenderTargetFormat::k_32_32_FLOAT:
322 return color_format == ColorFormat::k_32_32_FLOAT;
323 default:
324 return false;
325 }
326}
327
328// NOLINTNEXTLINE(performance-enum-size): Xenos bit field, MSVC packs per type
329enum class VertexFormat : u32 {
330 kUndefined = 0,
331 k_8_8_8_8 = 6,
332 k_2_10_10_10 = 7,
333 k_10_11_11 = 16,
334 k_11_11_10 = 17,
335 k_16_16 = 25,
336 k_16_16_16_16 = 26,
337 k_16_16_FLOAT = 31,
338 k_16_16_16_16_FLOAT = 32,
339 k_32 = 33,
340 k_32_32 = 34,
341 k_32_32_32_32 = 35,
342 k_32_FLOAT = 36,
343 k_32_32_FLOAT = 37,
344 k_32_32_32_32_FLOAT = 38,
345 k_32_32_32_FLOAT = 57,
346};
347
351inline int GetVertexFormatComponentCount(VertexFormat format) {
352 switch (format) {
353 case VertexFormat::k_32:
354 case VertexFormat::k_32_FLOAT:
355 return 1;
356 case VertexFormat::k_16_16:
357 case VertexFormat::k_16_16_FLOAT:
358 case VertexFormat::k_32_32:
359 case VertexFormat::k_32_32_FLOAT:
360 return 2;
361 case VertexFormat::k_10_11_11:
362 case VertexFormat::k_11_11_10:
363 case VertexFormat::k_32_32_32_FLOAT:
364 return 3;
365 case VertexFormat::k_8_8_8_8:
366 case VertexFormat::k_2_10_10_10:
367 case VertexFormat::k_16_16_16_16:
368 case VertexFormat::k_16_16_16_16_FLOAT:
369 case VertexFormat::k_32_32_32_32:
370 case VertexFormat::k_32_32_32_32_FLOAT:
371 return 4;
372 default:
373 REX_UNHANDLED_CASE(format);
374 return 0;
375 }
376}
377
383inline u32 GetVertexFormatNeededWords(VertexFormat format, u32 used_components) {
384 REX_ASSERT((used_components & ~static_cast<u32>(0b1111)) == 0);
385 if (!used_components) {
386 return 0;
387 }
388 switch (format) {
389 case VertexFormat::k_8_8_8_8:
390 case VertexFormat::k_2_10_10_10:
391 return 0b0001;
392 case VertexFormat::k_10_11_11:
393 case VertexFormat::k_11_11_10:
394 return (used_components & 0b0111) ? 0b0001 : 0b0000;
395 case VertexFormat::k_16_16:
396 case VertexFormat::k_16_16_FLOAT:
397 return (used_components & 0b0011) ? 0b0001 : 0b0000;
398 case VertexFormat::k_16_16_16_16:
399 case VertexFormat::k_16_16_16_16_FLOAT:
400 return ((used_components & 0b0011) ? 0b0001 : 0b0000) |
401 ((used_components & 0b1100) ? 0b0010 : 0b0000);
402 case VertexFormat::k_32:
403 case VertexFormat::k_32_FLOAT:
404 return used_components & 0b0001;
405 case VertexFormat::k_32_32:
406 case VertexFormat::k_32_32_FLOAT:
407 return used_components & 0b0011;
408 case VertexFormat::k_32_32_32_32:
409 case VertexFormat::k_32_32_32_32_FLOAT:
410 return used_components;
411 case VertexFormat::k_32_32_32_FLOAT:
412 return used_components & 0b0111;
413 default:
414 REX_UNHANDLED_CASE(format);
415 return 0b0000;
416 }
417}
418
424inline u16 GPUSwap(u16 value, Endian endianness) {
425 switch (endianness) {
426 case Endian::kNone:
427 return value;
428 case Endian::k8in16:
429 return ((value << 8) & 0xFF00FF00) | ((value >> 8) & 0x00FF00FF);
430 default:
431 REX_UNHANDLED_CASE(endianness);
432 return value;
433 }
434}
435
436inline u32 GPUSwap(u32 value, Endian endianness) {
437 switch (endianness) {
438 default:
439 case Endian::kNone:
440 return value;
441 case Endian::k8in16:
442 return ((value << 8) & 0xFF00FF00) | ((value >> 8) & 0x00FF00FF);
443 case Endian::k8in32:
444 return std::byteswap(value);
445 case Endian::k16in32:
446 return ((value >> 16) & 0xFFFF) | (value << 16);
447 }
448}
449
451inline f32 GPUSwap(f32 value, Endian endianness) {
452 union {
453 u32 i;
454 f32 f;
455 } v;
456 v.f = value;
457 v.i = GPUSwap(v.i, endianness);
458 return v.f;
459}
460
467inline u32 GPUToCPU(u32 p) {
468 return p;
469}
470
477inline u32 CPUToGPU(u32 p) {
478 return p & 0x1FFFFFFF;
479}
480
490inline u16 FloatToHalf(f32 value, bool preserve_denormal = false,
491 bool round_to_nearest_even = false) {
492 u32 integer_value = std::bit_cast<u32>(value);
493 u32 abs_value = integer_value & 0x7FFFFFFFu;
494 u32 result;
495 if (abs_value >= 0x47FFE000u) {
496 result = 0x7FFFu;
497 } else {
498 if (abs_value < 0x38800000u) {
499 if (preserve_denormal) {
500 u32 shift = std::min(static_cast<u32>(113u - (abs_value >> 23u)), static_cast<u32>(24u));
501 result = (0x800000u | (abs_value & 0x7FFFFFu)) >> shift;
502 } else {
503 result = 0u;
504 }
505 } else {
506 result = abs_value + 0xC8000000u;
507 }
508 if (round_to_nearest_even) {
509 result += 0xFFFu + ((result >> 13u) & 1u);
510 }
511 result = (result >> 13u) & 0x7FFFu;
512 }
513 return static_cast<u16>(result | ((integer_value & 0x80000000u) >> 16u));
514}
515
522inline f32 HalfToFloat(u16 value, bool preserve_denormal = false) {
523 u32 mantissa = value & 0x3FFu;
524 u32 exponent = (value >> 10u) & 0x1Fu;
525 if (!exponent) {
526 if (!preserve_denormal) {
527 mantissa = 0;
528 } else if (mantissa) {
529 u32 mantissa_lzcnt = static_cast<u32>(std::countl_zero(mantissa)) - (32u - 11u);
530 exponent = static_cast<u32>(1 - static_cast<i32>(mantissa_lzcnt));
531 mantissa = (mantissa << mantissa_lzcnt) & 0x3FFu;
532 }
533 if (!mantissa) {
534 exponent = static_cast<u32>(-112);
535 }
536 }
537 u32 result =
538 (static_cast<u32>(value & 0x8000u) << 16u) | ((exponent + 112u) << 23u) | (mantissa << 13u);
539 return std::bit_cast<f32>(result);
540}
541
542} // namespace rex::xenos
#define REX_UNHANDLED_CASE(var)
Definition assert.h:119
#define REX_ASSERT(cond,...)
Definition assert.h:84
u32 GetVertexFormatNeededWords(VertexFormat format, u32 used_components)
Definition format.h:383
u32 CPUToGPU(u32 p)
Definition format.h:477
constexpr ColorRenderTargetFormat GetStorageColorFormat(ColorRenderTargetFormat format)
Definition format.h:123
const char * GetDepthRenderTargetFormatName(DepthRenderTargetFormat format)
u32 GPUToCPU(u32 p)
Definition format.h:467
u16 FloatToHalf(f32 value, bool preserve_denormal=false, bool round_to_nearest_even=false)
Definition format.h:490
constexpr bool IsColorRenderTargetFormat64bpp(ColorRenderTargetFormat format)
Definition format.h:86
constexpr f32 UNorm24To32(u32 n24)
Definition format.h:185
const char * GetColorRenderTargetFormatName(ColorRenderTargetFormat format)
SurfaceNumberFormat
Definition format.h:52
@ kSignedRepeatingFraction
Definition format.h:54
@ kUnsignedRepeatingFraction
Definition format.h:53
u32 Float32To20e4(f32 value, bool round_to_nearest_even)
u16 GPUSwap(u16 value, Endian endianness)
Definition format.h:424
DepthRenderTargetFormat
Definition format.h:135
@ kD24S8
Definition format.h:136
@ kD24FS8
Definition format.h:137
Endian
Definition format.h:27
@ k16in32
Definition format.h:31
@ k8in16
Definition format.h:29
@ k8in32
Definition format.h:30
f32 Float20e4To32(u32 f24)
Endian128
Definition format.h:36
@ k8in64
Definition format.h:41
@ k8in128
Definition format.h:42
constexpr u32 kRenderTargetFormatBits
Definition format.h:192
constexpr bool IsColorResolveFormatBitwiseEquivalent(ColorRenderTargetFormat render_target_format, ColorFormat color_format)
Definition format.h:304
f32 Float7e3To32(u32 f10)
f32 HalfToFloat(u16 value, bool preserve_denormal=false)
Definition format.h:522
f32 LinearToPWLGamma(f32 linear)
f32 PWLGammaToLinear(f32 gamma)
TextureFormat
Definition format.h:198
@ k_24_8_FLOAT
Definition format.h:222
@ k_Cr_Y1_Cb_Y0_REP
Definition format.h:210
@ k_DXN
Definition format.h:248
@ k_8_A
Definition format.h:207
@ k_8_8_8_8_A
Definition format.h:213
@ k_Y1_Cr_Y0_Cb_REP
Definition format.h:211
@ k_8_B
Definition format.h:208
@ k_2_10_10_10_FLOAT_EDRAM
Definition format.h:262
@ k_CTX1
Definition format.h:259
@ k_1_REVERSE
Definition format.h:199
@ k_24_8
Definition format.h:221
ColorRenderTargetFormat
Definition format.h:61
@ k_2_10_10_10_FLOAT
Definition format.h:65
@ k_16_16_16_16
Definition format.h:67
@ k_2_10_10_10_FLOAT_AS_16_16_16_16
Definition format.h:71
@ k_16_16
Definition format.h:66
@ k_2_10_10_10
Definition format.h:64
@ k_2_10_10_10_AS_10_10_10_10
Definition format.h:70
@ k_8_8_8_8
Definition format.h:62
@ k_8_8_8_8_GAMMA
Definition format.h:63
u32 GetColorRenderTargetFormatComponentCount(ColorRenderTargetFormat format)
Definition format.h:95
ColorFormat
Definition format.h:267
int GetVertexFormatComponentCount(VertexFormat format)
Definition format.h:351
Platform flags, packing macros and export markers.
Integer types, byte order wrappers and size literals.