1 // Copyright 2014 Citra Emulator Project
2 // Licensed under GPLv2 or any later version
3 // Refer to the license.txt file included.
4 
5 #pragma once
6 
7 #include <climits>
8 #include <utility>
9 #include "common/assert.h"
10 #include "common/common_types.h"
11 #include "common/logging/log.h"
12 #include "video_core/gpu.h"
13 #include "video_core/textures/texture.h"
14 
15 namespace VideoCore::Surface {
16 
17 enum class PixelFormat {
18     A8B8G8R8_UNORM,
19     A8B8G8R8_SNORM,
20     A8B8G8R8_SINT,
21     A8B8G8R8_UINT,
22     R5G6B5_UNORM,
23     B5G6R5_UNORM,
24     A1R5G5B5_UNORM,
25     A2B10G10R10_UNORM,
26     A2B10G10R10_UINT,
27     A1B5G5R5_UNORM,
28     R8_UNORM,
29     R8_SNORM,
30     R8_SINT,
31     R8_UINT,
32     R16G16B16A16_FLOAT,
33     R16G16B16A16_UNORM,
34     R16G16B16A16_SNORM,
35     R16G16B16A16_SINT,
36     R16G16B16A16_UINT,
37     B10G11R11_FLOAT,
38     R32G32B32A32_UINT,
39     BC1_RGBA_UNORM,
40     BC2_UNORM,
41     BC3_UNORM,
42     BC4_UNORM,
43     BC4_SNORM,
44     BC5_UNORM,
45     BC5_SNORM,
46     BC7_UNORM,
47     BC6H_UFLOAT,
48     BC6H_SFLOAT,
49     ASTC_2D_4X4_UNORM,
50     B8G8R8A8_UNORM,
51     R32G32B32A32_FLOAT,
52     R32G32B32A32_SINT,
53     R32G32_FLOAT,
54     R32G32_SINT,
55     R32_FLOAT,
56     R16_FLOAT,
57     R16_UNORM,
58     R16_SNORM,
59     R16_UINT,
60     R16_SINT,
61     R16G16_UNORM,
62     R16G16_FLOAT,
63     R16G16_UINT,
64     R16G16_SINT,
65     R16G16_SNORM,
66     R32G32B32_FLOAT,
67     A8B8G8R8_SRGB,
68     R8G8_UNORM,
69     R8G8_SNORM,
70     R8G8_SINT,
71     R8G8_UINT,
72     R32G32_UINT,
73     R16G16B16X16_FLOAT,
74     R32_UINT,
75     R32_SINT,
76     ASTC_2D_8X8_UNORM,
77     ASTC_2D_8X5_UNORM,
78     ASTC_2D_5X4_UNORM,
79     B8G8R8A8_SRGB,
80     BC1_RGBA_SRGB,
81     BC2_SRGB,
82     BC3_SRGB,
83     BC7_SRGB,
84     A4B4G4R4_UNORM,
85     ASTC_2D_4X4_SRGB,
86     ASTC_2D_8X8_SRGB,
87     ASTC_2D_8X5_SRGB,
88     ASTC_2D_5X4_SRGB,
89     ASTC_2D_5X5_UNORM,
90     ASTC_2D_5X5_SRGB,
91     ASTC_2D_10X8_UNORM,
92     ASTC_2D_10X8_SRGB,
93     ASTC_2D_6X6_UNORM,
94     ASTC_2D_6X6_SRGB,
95     ASTC_2D_10X10_UNORM,
96     ASTC_2D_10X10_SRGB,
97     ASTC_2D_12X12_UNORM,
98     ASTC_2D_12X12_SRGB,
99     ASTC_2D_8X6_UNORM,
100     ASTC_2D_8X6_SRGB,
101     ASTC_2D_6X5_UNORM,
102     ASTC_2D_6X5_SRGB,
103     E5B9G9R9_FLOAT,
104 
105     MaxColorFormat,
106 
107     // Depth formats
108     D32_FLOAT = MaxColorFormat,
109     D16_UNORM,
110 
111     MaxDepthFormat,
112 
113     // DepthStencil formats
114     D24_UNORM_S8_UINT = MaxDepthFormat,
115     S8_UINT_D24_UNORM,
116     D32_FLOAT_S8_UINT,
117 
118     MaxDepthStencilFormat,
119 
120     Max = MaxDepthStencilFormat,
121     Invalid = 255,
122 };
123 static constexpr std::size_t MaxPixelFormat = static_cast<std::size_t>(PixelFormat::Max);
124 
125 enum class SurfaceType {
126     ColorTexture = 0,
127     Depth = 1,
128     DepthStencil = 2,
129     Invalid = 3,
130 };
131 
132 enum class SurfaceTarget {
133     Texture1D,
134     TextureBuffer,
135     Texture2D,
136     Texture3D,
137     Texture1DArray,
138     Texture2DArray,
139     TextureCubemap,
140     TextureCubeArray,
141 };
142 
143 constexpr std::array<u32, MaxPixelFormat> compression_factor_shift_table = {{
144     0, // A8B8G8R8_UNORM
145     0, // A8B8G8R8_SNORM
146     0, // A8B8G8R8_SINT
147     0, // A8B8G8R8_UINT
148     0, // R5G6B5_UNORM
149     0, // B5G6R5_UNORM
150     0, // A1R5G5B5_UNORM
151     0, // A2B10G10R10_UNORM
152     0, // A2B10G10R10_UINT
153     0, // A1B5G5R5_UNORM
154     0, // R8_UNORM
155     0, // R8_SNORM
156     0, // R8_SINT
157     0, // R8_UINT
158     0, // R16G16B16A16_FLOAT
159     0, // R16G16B16A16_UNORM
160     0, // R16G16B16A16_SNORM
161     0, // R16G16B16A16_SINT
162     0, // R16G16B16A16_UINT
163     0, // B10G11R11_FLOAT
164     0, // R32G32B32A32_UINT
165     2, // BC1_RGBA_UNORM
166     2, // BC2_UNORM
167     2, // BC3_UNORM
168     2, // BC4_UNORM
169     2, // BC4_SNORM
170     2, // BC5_UNORM
171     2, // BC5_SNORM
172     2, // BC7_UNORM
173     2, // BC6H_UFLOAT
174     2, // BC6H_SFLOAT
175     2, // ASTC_2D_4X4_UNORM
176     0, // B8G8R8A8_UNORM
177     0, // R32G32B32A32_FLOAT
178     0, // R32G32B32A32_SINT
179     0, // R32G32_FLOAT
180     0, // R32G32_SINT
181     0, // R32_FLOAT
182     0, // R16_FLOAT
183     0, // R16_UNORM
184     0, // R16_SNORM
185     0, // R16_UINT
186     0, // R16_SINT
187     0, // R16G16_UNORM
188     0, // R16G16_FLOAT
189     0, // R16G16_UINT
190     0, // R16G16_SINT
191     0, // R16G16_SNORM
192     0, // R32G32B32_FLOAT
193     0, // A8B8G8R8_SRGB
194     0, // R8G8_UNORM
195     0, // R8G8_SNORM
196     0, // R8G8_SINT
197     0, // R8G8_UINT
198     0, // R32G32_UINT
199     0, // R16G16B16X16_FLOAT
200     0, // R32_UINT
201     0, // R32_SINT
202     2, // ASTC_2D_8X8_UNORM
203     2, // ASTC_2D_8X5_UNORM
204     2, // ASTC_2D_5X4_UNORM
205     0, // B8G8R8A8_SRGB
206     2, // BC1_RGBA_SRGB
207     2, // BC2_SRGB
208     2, // BC3_SRGB
209     2, // BC7_SRGB
210     0, // A4B4G4R4_UNORM
211     2, // ASTC_2D_4X4_SRGB
212     2, // ASTC_2D_8X8_SRGB
213     2, // ASTC_2D_8X5_SRGB
214     2, // ASTC_2D_5X4_SRGB
215     2, // ASTC_2D_5X5_UNORM
216     2, // ASTC_2D_5X5_SRGB
217     2, // ASTC_2D_10X8_UNORM
218     2, // ASTC_2D_10X8_SRGB
219     2, // ASTC_2D_6X6_UNORM
220     2, // ASTC_2D_6X6_SRGB
221     2, // ASTC_2D_10X10_UNORM
222     2, // ASTC_2D_10X10_SRGB
223     2, // ASTC_2D_12X12_UNORM
224     2, // ASTC_2D_12X12_SRGB
225     2, // ASTC_2D_8X6_UNORM
226     2, // ASTC_2D_8X6_SRGB
227     2, // ASTC_2D_6X5_UNORM
228     2, // ASTC_2D_6X5_SRGB
229     0, // E5B9G9R9_FLOAT
230     0, // D32_FLOAT
231     0, // D16_UNORM
232     0, // D24_UNORM_S8_UINT
233     0, // S8_UINT_D24_UNORM
234     0, // D32_FLOAT_S8_UINT
235 }};
236 
237 /**
238  * Gets the compression factor for the specified PixelFormat. This applies to just the
239  * "compressed width" and "compressed height", not the overall compression factor of a
240  * compressed image. This is used for maintaining proper surface sizes for compressed
241  * texture formats.
242  */
GetCompressionFactorShift(PixelFormat format)243 inline constexpr u32 GetCompressionFactorShift(PixelFormat format) {
244     DEBUG_ASSERT(format != PixelFormat::Invalid);
245     DEBUG_ASSERT(static_cast<std::size_t>(format) < compression_factor_shift_table.size());
246     return compression_factor_shift_table[static_cast<std::size_t>(format)];
247 }
248 
GetCompressionFactor(PixelFormat format)249 inline constexpr u32 GetCompressionFactor(PixelFormat format) {
250     return 1U << GetCompressionFactorShift(format);
251 }
252 
253 constexpr std::array<u32, MaxPixelFormat> block_width_table = {{
254     1,  // A8B8G8R8_UNORM
255     1,  // A8B8G8R8_SNORM
256     1,  // A8B8G8R8_SINT
257     1,  // A8B8G8R8_UINT
258     1,  // R5G6B5_UNORM
259     1,  // B5G6R5_UNORM
260     1,  // A1R5G5B5_UNORM
261     1,  // A2B10G10R10_UNORM
262     1,  // A2B10G10R10_UINT
263     1,  // A1B5G5R5_UNORM
264     1,  // R8_UNORM
265     1,  // R8_SNORM
266     1,  // R8_SINT
267     1,  // R8_UINT
268     1,  // R16G16B16A16_FLOAT
269     1,  // R16G16B16A16_UNORM
270     1,  // R16G16B16A16_SNORM
271     1,  // R16G16B16A16_SINT
272     1,  // R16G16B16A16_UINT
273     1,  // B10G11R11_FLOAT
274     1,  // R32G32B32A32_UINT
275     4,  // BC1_RGBA_UNORM
276     4,  // BC2_UNORM
277     4,  // BC3_UNORM
278     4,  // BC4_UNORM
279     4,  // BC4_SNORM
280     4,  // BC5_UNORM
281     4,  // BC5_SNORM
282     4,  // BC7_UNORM
283     4,  // BC6H_UFLOAT
284     4,  // BC6H_SFLOAT
285     4,  // ASTC_2D_4X4_UNORM
286     1,  // B8G8R8A8_UNORM
287     1,  // R32G32B32A32_FLOAT
288     1,  // R32G32B32A32_SINT
289     1,  // R32G32_FLOAT
290     1,  // R32G32_SINT
291     1,  // R32_FLOAT
292     1,  // R16_FLOAT
293     1,  // R16_UNORM
294     1,  // R16_SNORM
295     1,  // R16_UINT
296     1,  // R16_SINT
297     1,  // R16G16_UNORM
298     1,  // R16G16_FLOAT
299     1,  // R16G16_UINT
300     1,  // R16G16_SINT
301     1,  // R16G16_SNORM
302     1,  // R32G32B32_FLOAT
303     1,  // A8B8G8R8_SRGB
304     1,  // R8G8_UNORM
305     1,  // R8G8_SNORM
306     1,  // R8G8_SINT
307     1,  // R8G8_UINT
308     1,  // R32G32_UINT
309     1,  // R16G16B16X16_FLOAT
310     1,  // R32_UINT
311     1,  // R32_SINT
312     8,  // ASTC_2D_8X8_UNORM
313     8,  // ASTC_2D_8X5_UNORM
314     5,  // ASTC_2D_5X4_UNORM
315     1,  // B8G8R8A8_SRGB
316     4,  // BC1_RGBA_SRGB
317     4,  // BC2_SRGB
318     4,  // BC3_SRGB
319     4,  // BC7_SRGB
320     1,  // A4B4G4R4_UNORM
321     4,  // ASTC_2D_4X4_SRGB
322     8,  // ASTC_2D_8X8_SRGB
323     8,  // ASTC_2D_8X5_SRGB
324     5,  // ASTC_2D_5X4_SRGB
325     5,  // ASTC_2D_5X5_UNORM
326     5,  // ASTC_2D_5X5_SRGB
327     10, // ASTC_2D_10X8_UNORM
328     10, // ASTC_2D_10X8_SRGB
329     6,  // ASTC_2D_6X6_UNORM
330     6,  // ASTC_2D_6X6_SRGB
331     10, // ASTC_2D_10X10_UNORM
332     10, // ASTC_2D_10X10_SRGB
333     12, // ASTC_2D_12X12_UNORM
334     12, // ASTC_2D_12X12_SRGB
335     8,  // ASTC_2D_8X6_UNORM
336     8,  // ASTC_2D_8X6_SRGB
337     6,  // ASTC_2D_6X5_UNORM
338     6,  // ASTC_2D_6X5_SRGB
339     1,  // E5B9G9R9_FLOAT
340     1,  // D32_FLOAT
341     1,  // D16_UNORM
342     1,  // D24_UNORM_S8_UINT
343     1,  // S8_UINT_D24_UNORM
344     1,  // D32_FLOAT_S8_UINT
345 }};
346 
GetDefaultBlockWidth(PixelFormat format)347 static constexpr u32 GetDefaultBlockWidth(PixelFormat format) {
348     if (format == PixelFormat::Invalid)
349         return 0;
350 
351     ASSERT(static_cast<std::size_t>(format) < block_width_table.size());
352     return block_width_table[static_cast<std::size_t>(format)];
353 }
354 
355 constexpr std::array<u32, MaxPixelFormat> block_height_table = {{
356     1,  // A8B8G8R8_UNORM
357     1,  // A8B8G8R8_SNORM
358     1,  // A8B8G8R8_SINT
359     1,  // A8B8G8R8_UINT
360     1,  // R5G6B5_UNORM
361     1,  // B5G6R5_UNORM
362     1,  // A1R5G5B5_UNORM
363     1,  // A2B10G10R10_UNORM
364     1,  // A2B10G10R10_UINT
365     1,  // A1B5G5R5_UNORM
366     1,  // R8_UNORM
367     1,  // R8_SNORM
368     1,  // R8_SINT
369     1,  // R8_UINT
370     1,  // R16G16B16A16_FLOAT
371     1,  // R16G16B16A16_UNORM
372     1,  // R16G16B16A16_SNORM
373     1,  // R16G16B16A16_SINT
374     1,  // R16G16B16A16_UINT
375     1,  // B10G11R11_FLOAT
376     1,  // R32G32B32A32_UINT
377     4,  // BC1_RGBA_UNORM
378     4,  // BC2_UNORM
379     4,  // BC3_UNORM
380     4,  // BC4_UNORM
381     4,  // BC4_SNORM
382     4,  // BC5_UNORM
383     4,  // BC5_SNORM
384     4,  // BC7_UNORM
385     4,  // BC6H_UFLOAT
386     4,  // BC6H_SFLOAT
387     4,  // ASTC_2D_4X4_UNORM
388     1,  // B8G8R8A8_UNORM
389     1,  // R32G32B32A32_FLOAT
390     1,  // R32G32B32A32_SINT
391     1,  // R32G32_FLOAT
392     1,  // R32G32_SINT
393     1,  // R32_FLOAT
394     1,  // R16_FLOAT
395     1,  // R16_UNORM
396     1,  // R16_SNORM
397     1,  // R16_UINT
398     1,  // R16_SINT
399     1,  // R16G16_UNORM
400     1,  // R16G16_FLOAT
401     1,  // R16G16_UINT
402     1,  // R16G16_SINT
403     1,  // R16G16_SNORM
404     1,  // R32G32B32_FLOAT
405     1,  // A8B8G8R8_SRGB
406     1,  // R8G8_UNORM
407     1,  // R8G8_SNORM
408     1,  // R8G8_SINT
409     1,  // R8G8_UINT
410     1,  // R32G32_UINT
411     1,  // R16G16B16X16_FLOAT
412     1,  // R32_UINT
413     1,  // R32_SINT
414     8,  // ASTC_2D_8X8_UNORM
415     5,  // ASTC_2D_8X5_UNORM
416     4,  // ASTC_2D_5X4_UNORM
417     1,  // B8G8R8A8_SRGB
418     4,  // BC1_RGBA_SRGB
419     4,  // BC2_SRGB
420     4,  // BC3_SRGB
421     4,  // BC7_SRGB
422     1,  // A4B4G4R4_UNORM
423     4,  // ASTC_2D_4X4_SRGB
424     8,  // ASTC_2D_8X8_SRGB
425     5,  // ASTC_2D_8X5_SRGB
426     4,  // ASTC_2D_5X4_SRGB
427     5,  // ASTC_2D_5X5_UNORM
428     5,  // ASTC_2D_5X5_SRGB
429     8,  // ASTC_2D_10X8_UNORM
430     8,  // ASTC_2D_10X8_SRGB
431     6,  // ASTC_2D_6X6_UNORM
432     6,  // ASTC_2D_6X6_SRGB
433     10, // ASTC_2D_10X10_UNORM
434     10, // ASTC_2D_10X10_SRGB
435     12, // ASTC_2D_12X12_UNORM
436     12, // ASTC_2D_12X12_SRGB
437     6,  // ASTC_2D_8X6_UNORM
438     6,  // ASTC_2D_8X6_SRGB
439     5,  // ASTC_2D_6X5_UNORM
440     5,  // ASTC_2D_6X5_SRGB
441     1,  // E5B9G9R9_FLOAT
442     1,  // D32_FLOAT
443     1,  // D16_UNORM
444     1,  // D24_UNORM_S8_UINT
445     1,  // S8_UINT_D24_UNORM
446     1,  // D32_FLOAT_S8_UINT
447 }};
448 
GetDefaultBlockHeight(PixelFormat format)449 static constexpr u32 GetDefaultBlockHeight(PixelFormat format) {
450     if (format == PixelFormat::Invalid)
451         return 0;
452 
453     ASSERT(static_cast<std::size_t>(format) < block_height_table.size());
454     return block_height_table[static_cast<std::size_t>(format)];
455 }
456 
457 constexpr std::array<u32, MaxPixelFormat> bpp_table = {{
458     32,  // A8B8G8R8_UNORM
459     32,  // A8B8G8R8_SNORM
460     32,  // A8B8G8R8_SINT
461     32,  // A8B8G8R8_UINT
462     16,  // R5G6B5_UNORM
463     16,  // B5G6R5_UNORM
464     16,  // A1R5G5B5_UNORM
465     32,  // A2B10G10R10_UNORM
466     32,  // A2B10G10R10_UINT
467     16,  // A1B5G5R5_UNORM
468     8,   // R8_UNORM
469     8,   // R8_SNORM
470     8,   // R8_SINT
471     8,   // R8_UINT
472     64,  // R16G16B16A16_FLOAT
473     64,  // R16G16B16A16_UNORM
474     64,  // R16G16B16A16_SNORM
475     64,  // R16G16B16A16_SINT
476     64,  // R16G16B16A16_UINT
477     32,  // B10G11R11_FLOAT
478     128, // R32G32B32A32_UINT
479     64,  // BC1_RGBA_UNORM
480     128, // BC2_UNORM
481     128, // BC3_UNORM
482     64,  // BC4_UNORM
483     64,  // BC4_SNORM
484     128, // BC5_UNORM
485     128, // BC5_SNORM
486     128, // BC7_UNORM
487     128, // BC6H_UFLOAT
488     128, // BC6H_SFLOAT
489     128, // ASTC_2D_4X4_UNORM
490     32,  // B8G8R8A8_UNORM
491     128, // R32G32B32A32_FLOAT
492     128, // R32G32B32A32_SINT
493     64,  // R32G32_FLOAT
494     64,  // R32G32_SINT
495     32,  // R32_FLOAT
496     16,  // R16_FLOAT
497     16,  // R16_UNORM
498     16,  // R16_SNORM
499     16,  // R16_UINT
500     16,  // R16_SINT
501     32,  // R16G16_UNORM
502     32,  // R16G16_FLOAT
503     32,  // R16G16_UINT
504     32,  // R16G16_SINT
505     32,  // R16G16_SNORM
506     96,  // R32G32B32_FLOAT
507     32,  // A8B8G8R8_SRGB
508     16,  // R8G8_UNORM
509     16,  // R8G8_SNORM
510     16,  // R8G8_SINT
511     16,  // R8G8_UINT
512     64,  // R32G32_UINT
513     64,  // R16G16B16X16_FLOAT
514     32,  // R32_UINT
515     32,  // R32_SINT
516     128, // ASTC_2D_8X8_UNORM
517     128, // ASTC_2D_8X5_UNORM
518     128, // ASTC_2D_5X4_UNORM
519     32,  // B8G8R8A8_SRGB
520     64,  // BC1_RGBA_SRGB
521     128, // BC2_SRGB
522     128, // BC3_SRGB
523     128, // BC7_UNORM
524     16,  // A4B4G4R4_UNORM
525     128, // ASTC_2D_4X4_SRGB
526     128, // ASTC_2D_8X8_SRGB
527     128, // ASTC_2D_8X5_SRGB
528     128, // ASTC_2D_5X4_SRGB
529     128, // ASTC_2D_5X5_UNORM
530     128, // ASTC_2D_5X5_SRGB
531     128, // ASTC_2D_10X8_UNORM
532     128, // ASTC_2D_10X8_SRGB
533     128, // ASTC_2D_6X6_UNORM
534     128, // ASTC_2D_6X6_SRGB
535     128, // ASTC_2D_10X10_UNORM
536     128, // ASTC_2D_10X10_SRGB
537     128, // ASTC_2D_12X12_UNORM
538     128, // ASTC_2D_12X12_SRGB
539     128, // ASTC_2D_8X6_UNORM
540     128, // ASTC_2D_8X6_SRGB
541     128, // ASTC_2D_6X5_UNORM
542     128, // ASTC_2D_6X5_SRGB
543     32,  // E5B9G9R9_FLOAT
544     32,  // D32_FLOAT
545     16,  // D16_UNORM
546     32,  // D24_UNORM_S8_UINT
547     32,  // S8_UINT_D24_UNORM
548     64,  // D32_FLOAT_S8_UINT
549 }};
550 
GetFormatBpp(PixelFormat format)551 static constexpr u32 GetFormatBpp(PixelFormat format) {
552     if (format == PixelFormat::Invalid)
553         return 0;
554 
555     ASSERT(static_cast<std::size_t>(format) < bpp_table.size());
556     return bpp_table[static_cast<std::size_t>(format)];
557 }
558 
559 /// Returns the sizer in bytes of the specified pixel format
GetBytesPerPixel(PixelFormat pixel_format)560 static constexpr u32 GetBytesPerPixel(PixelFormat pixel_format) {
561     if (pixel_format == PixelFormat::Invalid) {
562         return 0;
563     }
564     return GetFormatBpp(pixel_format) / CHAR_BIT;
565 }
566 
567 SurfaceTarget SurfaceTargetFromTextureType(Tegra::Texture::TextureType texture_type);
568 
569 bool SurfaceTargetIsLayered(SurfaceTarget target);
570 
571 bool SurfaceTargetIsArray(SurfaceTarget target);
572 
573 PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format);
574 
575 PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format);
576 
577 PixelFormat PixelFormatFromGPUPixelFormat(Tegra::FramebufferConfig::PixelFormat format);
578 
579 SurfaceType GetFormatType(PixelFormat pixel_format);
580 
581 bool IsPixelFormatASTC(PixelFormat format);
582 
583 bool IsPixelFormatSRGB(PixelFormat format);
584 
585 std::pair<u32, u32> GetASTCBlockSize(PixelFormat format);
586 
587 } // namespace VideoCore::Surface
588