compatible_formats.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // Copyright 2020 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <array>
  5. #include <cstddef>
  6. #include "common/common_types.h"
  7. #include "video_core/compatible_formats.h"
  8. #include "video_core/surface.h"
  9. namespace VideoCore::Surface {
  10. namespace {
  11. using Table = std::array<std::array<u64, 2>, MaxPixelFormat>;
  12. // Compatibility table taken from Table 3.X.2 in:
  13. // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_view.txt
  14. constexpr std::array VIEW_CLASS_128_BITS{
  15. PixelFormat::R32G32B32A32_FLOAT,
  16. PixelFormat::R32G32B32A32_UINT,
  17. PixelFormat::R32G32B32A32_SINT,
  18. };
  19. constexpr std::array VIEW_CLASS_96_BITS{
  20. PixelFormat::R32G32B32_FLOAT,
  21. };
  22. // Missing formats:
  23. // PixelFormat::RGB32UI,
  24. // PixelFormat::RGB32I,
  25. constexpr std::array VIEW_CLASS_64_BITS{
  26. PixelFormat::R32G32_FLOAT, PixelFormat::R32G32_UINT,
  27. PixelFormat::R32G32_SINT, PixelFormat::R16G16B16A16_FLOAT,
  28. PixelFormat::R16G16B16A16_UNORM, PixelFormat::R16G16B16A16_SNORM,
  29. PixelFormat::R16G16B16A16_UINT, PixelFormat::R16G16B16A16_SINT,
  30. };
  31. // TODO: How should we handle 48 bits?
  32. constexpr std::array VIEW_CLASS_32_BITS{
  33. PixelFormat::R16G16_FLOAT, PixelFormat::B10G11R11_FLOAT, PixelFormat::R32_FLOAT,
  34. PixelFormat::A2B10G10R10_UNORM, PixelFormat::R16G16_UINT, PixelFormat::R32_UINT,
  35. PixelFormat::R16G16_SINT, PixelFormat::R32_SINT, PixelFormat::A8B8G8R8_UNORM,
  36. PixelFormat::R16G16_UNORM, PixelFormat::A8B8G8R8_SNORM, PixelFormat::R16G16_SNORM,
  37. PixelFormat::A8B8G8R8_SRGB, PixelFormat::E5B9G9R9_FLOAT, PixelFormat::B8G8R8A8_UNORM,
  38. PixelFormat::B8G8R8A8_SRGB, PixelFormat::A8B8G8R8_UINT, PixelFormat::A8B8G8R8_SINT,
  39. PixelFormat::A2B10G10R10_UINT,
  40. };
  41. // TODO: How should we handle 24 bits?
  42. constexpr std::array VIEW_CLASS_16_BITS{
  43. PixelFormat::R16_FLOAT, PixelFormat::R8G8_UINT, PixelFormat::R16_UINT,
  44. PixelFormat::R16_SINT, PixelFormat::R8G8_UNORM, PixelFormat::R16_UNORM,
  45. PixelFormat::R8G8_SNORM, PixelFormat::R16_SNORM, PixelFormat::R8G8_SINT,
  46. };
  47. constexpr std::array VIEW_CLASS_8_BITS{
  48. PixelFormat::R8_UINT,
  49. PixelFormat::R8_UNORM,
  50. PixelFormat::R8_SINT,
  51. PixelFormat::R8_SNORM,
  52. };
  53. constexpr std::array VIEW_CLASS_RGTC1_RED{
  54. PixelFormat::BC4_UNORM,
  55. PixelFormat::BC4_SNORM,
  56. };
  57. constexpr std::array VIEW_CLASS_RGTC2_RG{
  58. PixelFormat::BC5_UNORM,
  59. PixelFormat::BC5_SNORM,
  60. };
  61. constexpr std::array VIEW_CLASS_BPTC_UNORM{
  62. PixelFormat::BC7_UNORM,
  63. PixelFormat::BC7_SRGB,
  64. };
  65. constexpr std::array VIEW_CLASS_BPTC_FLOAT{
  66. PixelFormat::BC6H_SFLOAT,
  67. PixelFormat::BC6H_UFLOAT,
  68. };
  69. constexpr std::array VIEW_CLASS_ASTC_4x4_RGBA{
  70. PixelFormat::ASTC_2D_4X4_UNORM,
  71. PixelFormat::ASTC_2D_4X4_SRGB,
  72. };
  73. constexpr std::array VIEW_CLASS_ASTC_5x4_RGBA{
  74. PixelFormat::ASTC_2D_5X4_UNORM,
  75. PixelFormat::ASTC_2D_5X4_SRGB,
  76. };
  77. constexpr std::array VIEW_CLASS_ASTC_5x5_RGBA{
  78. PixelFormat::ASTC_2D_5X5_UNORM,
  79. PixelFormat::ASTC_2D_5X5_SRGB,
  80. };
  81. constexpr std::array VIEW_CLASS_ASTC_6x5_RGBA{
  82. PixelFormat::ASTC_2D_6X5_UNORM,
  83. PixelFormat::ASTC_2D_6X5_SRGB,
  84. };
  85. constexpr std::array VIEW_CLASS_ASTC_6x6_RGBA{
  86. PixelFormat::ASTC_2D_6X6_UNORM,
  87. PixelFormat::ASTC_2D_6X6_SRGB,
  88. };
  89. constexpr std::array VIEW_CLASS_ASTC_8x5_RGBA{
  90. PixelFormat::ASTC_2D_8X5_UNORM,
  91. PixelFormat::ASTC_2D_8X5_SRGB,
  92. };
  93. constexpr std::array VIEW_CLASS_ASTC_8x8_RGBA{
  94. PixelFormat::ASTC_2D_8X8_UNORM,
  95. PixelFormat::ASTC_2D_8X8_SRGB,
  96. };
  97. // Missing formats:
  98. // PixelFormat::ASTC_2D_10X5_UNORM
  99. // PixelFormat::ASTC_2D_10X5_SRGB
  100. // Missing formats:
  101. // PixelFormat::ASTC_2D_10X6_UNORM
  102. // PixelFormat::ASTC_2D_10X6_SRGB
  103. constexpr std::array VIEW_CLASS_ASTC_10x8_RGBA{
  104. PixelFormat::ASTC_2D_10X8_UNORM,
  105. PixelFormat::ASTC_2D_10X8_SRGB,
  106. };
  107. constexpr std::array VIEW_CLASS_ASTC_10x10_RGBA{
  108. PixelFormat::ASTC_2D_10X10_UNORM,
  109. PixelFormat::ASTC_2D_10X10_SRGB,
  110. };
  111. // Missing formats
  112. // ASTC_2D_12X10_UNORM,
  113. // ASTC_2D_12X10_SRGB,
  114. constexpr std::array VIEW_CLASS_ASTC_12x12_RGBA{
  115. PixelFormat::ASTC_2D_12X12_UNORM,
  116. PixelFormat::ASTC_2D_12X12_SRGB,
  117. };
  118. // Compatibility table taken from Table 4.X.1 in:
  119. // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_copy_image.txt
  120. constexpr std::array COPY_CLASS_128_BITS{
  121. PixelFormat::R32G32B32A32_UINT, PixelFormat::R32G32B32A32_FLOAT, PixelFormat::R32G32B32A32_SINT,
  122. PixelFormat::BC2_UNORM, PixelFormat::BC2_SRGB, PixelFormat::BC3_UNORM,
  123. PixelFormat::BC3_SRGB, PixelFormat::BC5_UNORM, PixelFormat::BC5_SNORM,
  124. PixelFormat::BC7_UNORM, PixelFormat::BC7_SRGB, PixelFormat::BC6H_SFLOAT,
  125. PixelFormat::BC6H_UFLOAT,
  126. };
  127. // Missing formats:
  128. // PixelFormat::RGBA32I
  129. // COMPRESSED_RG_RGTC2
  130. constexpr std::array COPY_CLASS_64_BITS{
  131. PixelFormat::R16G16B16A16_FLOAT, PixelFormat::R16G16B16A16_UINT,
  132. PixelFormat::R16G16B16A16_UNORM, PixelFormat::R16G16B16A16_SNORM,
  133. PixelFormat::R16G16B16A16_SINT, PixelFormat::R32G32_UINT,
  134. PixelFormat::R32G32_FLOAT, PixelFormat::R32G32_SINT,
  135. PixelFormat::BC1_RGBA_UNORM, PixelFormat::BC1_RGBA_SRGB,
  136. };
  137. // Missing formats:
  138. // COMPRESSED_RGB_S3TC_DXT1_EXT
  139. // COMPRESSED_SRGB_S3TC_DXT1_EXT
  140. // COMPRESSED_RGBA_S3TC_DXT1_EXT
  141. // COMPRESSED_SIGNED_RED_RGTC1
  142. constexpr void Enable(Table& table, size_t format_a, size_t format_b) {
  143. table[format_a][format_b / 64] |= u64(1) << (format_b % 64);
  144. table[format_b][format_a / 64] |= u64(1) << (format_a % 64);
  145. }
  146. constexpr void Enable(Table& table, PixelFormat format_a, PixelFormat format_b) {
  147. Enable(table, static_cast<size_t>(format_a), static_cast<size_t>(format_b));
  148. }
  149. template <typename Range>
  150. constexpr void EnableRange(Table& table, const Range& range) {
  151. for (auto it_a = range.begin(); it_a != range.end(); ++it_a) {
  152. for (auto it_b = it_a; it_b != range.end(); ++it_b) {
  153. Enable(table, *it_a, *it_b);
  154. }
  155. }
  156. }
  157. constexpr bool IsSupported(const Table& table, PixelFormat format_a, PixelFormat format_b) {
  158. const size_t a = static_cast<size_t>(format_a);
  159. const size_t b = static_cast<size_t>(format_b);
  160. return ((table[a][b / 64] >> (b % 64)) & 1) != 0;
  161. }
  162. constexpr Table MakeViewTable() {
  163. Table view{};
  164. for (size_t i = 0; i < MaxPixelFormat; ++i) {
  165. // Identity is allowed
  166. Enable(view, i, i);
  167. }
  168. EnableRange(view, VIEW_CLASS_128_BITS);
  169. EnableRange(view, VIEW_CLASS_96_BITS);
  170. EnableRange(view, VIEW_CLASS_64_BITS);
  171. EnableRange(view, VIEW_CLASS_32_BITS);
  172. EnableRange(view, VIEW_CLASS_16_BITS);
  173. EnableRange(view, VIEW_CLASS_8_BITS);
  174. EnableRange(view, VIEW_CLASS_RGTC1_RED);
  175. EnableRange(view, VIEW_CLASS_RGTC2_RG);
  176. EnableRange(view, VIEW_CLASS_BPTC_UNORM);
  177. EnableRange(view, VIEW_CLASS_BPTC_FLOAT);
  178. EnableRange(view, VIEW_CLASS_ASTC_4x4_RGBA);
  179. EnableRange(view, VIEW_CLASS_ASTC_5x4_RGBA);
  180. EnableRange(view, VIEW_CLASS_ASTC_5x5_RGBA);
  181. EnableRange(view, VIEW_CLASS_ASTC_6x5_RGBA);
  182. EnableRange(view, VIEW_CLASS_ASTC_6x6_RGBA);
  183. EnableRange(view, VIEW_CLASS_ASTC_8x5_RGBA);
  184. EnableRange(view, VIEW_CLASS_ASTC_8x8_RGBA);
  185. EnableRange(view, VIEW_CLASS_ASTC_10x8_RGBA);
  186. EnableRange(view, VIEW_CLASS_ASTC_10x10_RGBA);
  187. EnableRange(view, VIEW_CLASS_ASTC_12x12_RGBA);
  188. return view;
  189. }
  190. constexpr Table MakeCopyTable() {
  191. Table copy = MakeViewTable();
  192. EnableRange(copy, COPY_CLASS_128_BITS);
  193. EnableRange(copy, COPY_CLASS_64_BITS);
  194. return copy;
  195. }
  196. } // Anonymous namespace
  197. bool IsViewCompatible(PixelFormat format_a, PixelFormat format_b, bool broken_views) {
  198. if (broken_views) {
  199. // If format views are broken, only accept formats that are identical.
  200. return format_a == format_b;
  201. }
  202. static constexpr Table TABLE = MakeViewTable();
  203. return IsSupported(TABLE, format_a, format_b);
  204. }
  205. bool IsCopyCompatible(PixelFormat format_a, PixelFormat format_b) {
  206. static constexpr Table TABLE = MakeCopyTable();
  207. return IsSupported(TABLE, format_a, format_b);
  208. }
  209. } // namespace VideoCore::Surface