morton.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. // Copyright 2018 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <array>
  5. #include <cstring>
  6. #include "common/assert.h"
  7. #include "common/common_types.h"
  8. #include "video_core/morton.h"
  9. #include "video_core/surface.h"
  10. #include "video_core/textures/decoders.h"
  11. namespace VideoCore {
  12. using Surface::GetBytesPerPixel;
  13. using Surface::PixelFormat;
  14. using MortonCopyFn = void (*)(u32, u32, u32, u32, u32, u32, u8*, u8*);
  15. using ConversionArray = std::array<MortonCopyFn, Surface::MaxPixelFormat>;
  16. template <bool morton_to_linear, PixelFormat format>
  17. static void MortonCopy(u32 stride, u32 block_height, u32 height, u32 block_depth, u32 depth,
  18. u32 tile_width_spacing, u8* buffer, u8* addr) {
  19. constexpr u32 bytes_per_pixel = GetBytesPerPixel(format);
  20. // With the BCn formats (DXT and DXN), each 4x4 tile is swizzled instead of just individual
  21. // pixel values.
  22. constexpr u32 tile_size_x{GetDefaultBlockWidth(format)};
  23. constexpr u32 tile_size_y{GetDefaultBlockHeight(format)};
  24. if constexpr (morton_to_linear) {
  25. Tegra::Texture::UnswizzleTexture(buffer, addr, tile_size_x, tile_size_y, bytes_per_pixel,
  26. stride, height, depth, block_height, block_depth,
  27. tile_width_spacing);
  28. } else {
  29. Tegra::Texture::CopySwizzledData((stride + tile_size_x - 1) / tile_size_x,
  30. (height + tile_size_y - 1) / tile_size_y, depth,
  31. bytes_per_pixel, bytes_per_pixel, addr, buffer, false,
  32. block_height, block_depth, tile_width_spacing);
  33. }
  34. }
  35. static constexpr ConversionArray morton_to_linear_fns = {
  36. MortonCopy<true, PixelFormat::A8B8G8R8_UNORM>,
  37. MortonCopy<true, PixelFormat::A8B8G8R8_SNORM>,
  38. MortonCopy<true, PixelFormat::A8B8G8R8_SINT>,
  39. MortonCopy<true, PixelFormat::A8B8G8R8_UINT>,
  40. MortonCopy<true, PixelFormat::R5G6B5_UNORM>,
  41. MortonCopy<true, PixelFormat::B5G6R5_UNORM>,
  42. MortonCopy<true, PixelFormat::A1R5G5B5_UNORM>,
  43. MortonCopy<true, PixelFormat::A2B10G10R10_UNORM>,
  44. MortonCopy<true, PixelFormat::A2B10G10R10_UINT>,
  45. MortonCopy<true, PixelFormat::A1B5G5R5_UNORM>,
  46. MortonCopy<true, PixelFormat::R8_UNORM>,
  47. MortonCopy<true, PixelFormat::R8_SNORM>,
  48. MortonCopy<true, PixelFormat::R8_SINT>,
  49. MortonCopy<true, PixelFormat::R8_UINT>,
  50. MortonCopy<true, PixelFormat::R16G16B16A16_FLOAT>,
  51. MortonCopy<true, PixelFormat::R16G16B16A16_UNORM>,
  52. MortonCopy<true, PixelFormat::R16G16B16A16_SNORM>,
  53. MortonCopy<true, PixelFormat::R16G16B16A16_SINT>,
  54. MortonCopy<true, PixelFormat::R16G16B16A16_UINT>,
  55. MortonCopy<true, PixelFormat::B10G11R11_FLOAT>,
  56. MortonCopy<true, PixelFormat::R32G32B32A32_UINT>,
  57. MortonCopy<true, PixelFormat::BC1_RGBA_UNORM>,
  58. MortonCopy<true, PixelFormat::BC2_UNORM>,
  59. MortonCopy<true, PixelFormat::BC3_UNORM>,
  60. MortonCopy<true, PixelFormat::BC4_UNORM>,
  61. MortonCopy<true, PixelFormat::BC4_SNORM>,
  62. MortonCopy<true, PixelFormat::BC5_UNORM>,
  63. MortonCopy<true, PixelFormat::BC5_SNORM>,
  64. MortonCopy<true, PixelFormat::BC7_UNORM>,
  65. MortonCopy<true, PixelFormat::BC6H_UFLOAT>,
  66. MortonCopy<true, PixelFormat::BC6H_SFLOAT>,
  67. MortonCopy<true, PixelFormat::ASTC_2D_4X4_UNORM>,
  68. MortonCopy<true, PixelFormat::B8G8R8A8_UNORM>,
  69. MortonCopy<true, PixelFormat::R32G32B32A32_FLOAT>,
  70. MortonCopy<true, PixelFormat::R32G32B32A32_SINT>,
  71. MortonCopy<true, PixelFormat::R32G32_FLOAT>,
  72. MortonCopy<true, PixelFormat::R32G32_SINT>,
  73. MortonCopy<true, PixelFormat::R32_FLOAT>,
  74. MortonCopy<true, PixelFormat::R16_FLOAT>,
  75. MortonCopy<true, PixelFormat::R16_UNORM>,
  76. MortonCopy<true, PixelFormat::R16_SNORM>,
  77. MortonCopy<true, PixelFormat::R16_UINT>,
  78. MortonCopy<true, PixelFormat::R16_SINT>,
  79. MortonCopy<true, PixelFormat::R16G16_UNORM>,
  80. MortonCopy<true, PixelFormat::R16G16_FLOAT>,
  81. MortonCopy<true, PixelFormat::R16G16_UINT>,
  82. MortonCopy<true, PixelFormat::R16G16_SINT>,
  83. MortonCopy<true, PixelFormat::R16G16_SNORM>,
  84. MortonCopy<true, PixelFormat::R32G32B32_FLOAT>,
  85. MortonCopy<true, PixelFormat::A8B8G8R8_SRGB>,
  86. MortonCopy<true, PixelFormat::R8G8_UNORM>,
  87. MortonCopy<true, PixelFormat::R8G8_SNORM>,
  88. MortonCopy<true, PixelFormat::R8G8_SINT>,
  89. MortonCopy<true, PixelFormat::R8G8_UINT>,
  90. MortonCopy<true, PixelFormat::R32G32_UINT>,
  91. MortonCopy<true, PixelFormat::R16G16B16X16_FLOAT>,
  92. MortonCopy<true, PixelFormat::R32_UINT>,
  93. MortonCopy<true, PixelFormat::R32_SINT>,
  94. MortonCopy<true, PixelFormat::ASTC_2D_8X8_UNORM>,
  95. MortonCopy<true, PixelFormat::ASTC_2D_8X5_UNORM>,
  96. MortonCopy<true, PixelFormat::ASTC_2D_5X4_UNORM>,
  97. MortonCopy<true, PixelFormat::B8G8R8A8_SRGB>,
  98. MortonCopy<true, PixelFormat::BC1_RGBA_SRGB>,
  99. MortonCopy<true, PixelFormat::BC2_SRGB>,
  100. MortonCopy<true, PixelFormat::BC3_SRGB>,
  101. MortonCopy<true, PixelFormat::BC7_SRGB>,
  102. MortonCopy<true, PixelFormat::A4B4G4R4_UNORM>,
  103. MortonCopy<true, PixelFormat::ASTC_2D_4X4_SRGB>,
  104. MortonCopy<true, PixelFormat::ASTC_2D_8X8_SRGB>,
  105. MortonCopy<true, PixelFormat::ASTC_2D_8X5_SRGB>,
  106. MortonCopy<true, PixelFormat::ASTC_2D_5X4_SRGB>,
  107. MortonCopy<true, PixelFormat::ASTC_2D_5X5_UNORM>,
  108. MortonCopy<true, PixelFormat::ASTC_2D_5X5_SRGB>,
  109. MortonCopy<true, PixelFormat::ASTC_2D_10X8_UNORM>,
  110. MortonCopy<true, PixelFormat::ASTC_2D_10X8_SRGB>,
  111. MortonCopy<true, PixelFormat::ASTC_2D_6X6_UNORM>,
  112. MortonCopy<true, PixelFormat::ASTC_2D_6X6_SRGB>,
  113. MortonCopy<true, PixelFormat::ASTC_2D_10X10_UNORM>,
  114. MortonCopy<true, PixelFormat::ASTC_2D_10X10_SRGB>,
  115. MortonCopy<true, PixelFormat::ASTC_2D_12X12_UNORM>,
  116. MortonCopy<true, PixelFormat::ASTC_2D_12X12_SRGB>,
  117. MortonCopy<true, PixelFormat::ASTC_2D_8X6_UNORM>,
  118. MortonCopy<true, PixelFormat::ASTC_2D_8X6_SRGB>,
  119. MortonCopy<true, PixelFormat::ASTC_2D_6X5_UNORM>,
  120. MortonCopy<true, PixelFormat::ASTC_2D_6X5_SRGB>,
  121. MortonCopy<true, PixelFormat::E5B9G9R9_FLOAT>,
  122. MortonCopy<true, PixelFormat::D32_FLOAT>,
  123. MortonCopy<true, PixelFormat::D16_UNORM>,
  124. MortonCopy<true, PixelFormat::D24_UNORM_S8_UINT>,
  125. MortonCopy<true, PixelFormat::S8_UINT_D24_UNORM>,
  126. MortonCopy<true, PixelFormat::D32_FLOAT_S8_UINT>,
  127. };
  128. static constexpr ConversionArray linear_to_morton_fns = {
  129. MortonCopy<false, PixelFormat::A8B8G8R8_UNORM>,
  130. MortonCopy<false, PixelFormat::A8B8G8R8_SNORM>,
  131. MortonCopy<false, PixelFormat::A8B8G8R8_SINT>,
  132. MortonCopy<false, PixelFormat::A8B8G8R8_UINT>,
  133. MortonCopy<false, PixelFormat::R5G6B5_UNORM>,
  134. MortonCopy<false, PixelFormat::B5G6R5_UNORM>,
  135. MortonCopy<false, PixelFormat::A1R5G5B5_UNORM>,
  136. MortonCopy<false, PixelFormat::A2B10G10R10_UNORM>,
  137. MortonCopy<false, PixelFormat::A2B10G10R10_UINT>,
  138. MortonCopy<false, PixelFormat::A1B5G5R5_UNORM>,
  139. MortonCopy<false, PixelFormat::R8_UNORM>,
  140. MortonCopy<false, PixelFormat::R8_SNORM>,
  141. MortonCopy<false, PixelFormat::R8_SINT>,
  142. MortonCopy<false, PixelFormat::R8_UINT>,
  143. MortonCopy<false, PixelFormat::R16G16B16A16_FLOAT>,
  144. MortonCopy<false, PixelFormat::R16G16B16A16_SNORM>,
  145. MortonCopy<false, PixelFormat::R16G16B16A16_SINT>,
  146. MortonCopy<false, PixelFormat::R16G16B16A16_UNORM>,
  147. MortonCopy<false, PixelFormat::R16G16B16A16_UINT>,
  148. MortonCopy<false, PixelFormat::B10G11R11_FLOAT>,
  149. MortonCopy<false, PixelFormat::R32G32B32A32_UINT>,
  150. MortonCopy<false, PixelFormat::BC1_RGBA_UNORM>,
  151. MortonCopy<false, PixelFormat::BC2_UNORM>,
  152. MortonCopy<false, PixelFormat::BC3_UNORM>,
  153. MortonCopy<false, PixelFormat::BC4_UNORM>,
  154. MortonCopy<false, PixelFormat::BC4_SNORM>,
  155. MortonCopy<false, PixelFormat::BC5_UNORM>,
  156. MortonCopy<false, PixelFormat::BC5_SNORM>,
  157. MortonCopy<false, PixelFormat::BC7_UNORM>,
  158. MortonCopy<false, PixelFormat::BC6H_UFLOAT>,
  159. MortonCopy<false, PixelFormat::BC6H_SFLOAT>,
  160. // TODO(Subv): Swizzling ASTC formats are not supported
  161. nullptr,
  162. MortonCopy<false, PixelFormat::B8G8R8A8_UNORM>,
  163. MortonCopy<false, PixelFormat::R32G32B32A32_FLOAT>,
  164. MortonCopy<false, PixelFormat::R32G32B32A32_SINT>,
  165. MortonCopy<false, PixelFormat::R32G32_FLOAT>,
  166. MortonCopy<false, PixelFormat::R32G32_SINT>,
  167. MortonCopy<false, PixelFormat::R32_FLOAT>,
  168. MortonCopy<false, PixelFormat::R16_FLOAT>,
  169. MortonCopy<false, PixelFormat::R16_UNORM>,
  170. MortonCopy<false, PixelFormat::R16_SNORM>,
  171. MortonCopy<false, PixelFormat::R16_UINT>,
  172. MortonCopy<false, PixelFormat::R16_SINT>,
  173. MortonCopy<false, PixelFormat::R16G16_UNORM>,
  174. MortonCopy<false, PixelFormat::R16G16_FLOAT>,
  175. MortonCopy<false, PixelFormat::R16G16_UINT>,
  176. MortonCopy<false, PixelFormat::R16G16_SINT>,
  177. MortonCopy<false, PixelFormat::R16G16_SNORM>,
  178. MortonCopy<false, PixelFormat::R32G32B32_FLOAT>,
  179. MortonCopy<false, PixelFormat::A8B8G8R8_SRGB>,
  180. MortonCopy<false, PixelFormat::R8G8_UNORM>,
  181. MortonCopy<false, PixelFormat::R8G8_SNORM>,
  182. MortonCopy<false, PixelFormat::R8G8_SINT>,
  183. MortonCopy<false, PixelFormat::R8G8_UINT>,
  184. MortonCopy<false, PixelFormat::R32G32_UINT>,
  185. MortonCopy<false, PixelFormat::R16G16B16X16_FLOAT>,
  186. MortonCopy<false, PixelFormat::R32_UINT>,
  187. MortonCopy<false, PixelFormat::R32_SINT>,
  188. nullptr,
  189. nullptr,
  190. nullptr,
  191. MortonCopy<false, PixelFormat::B8G8R8A8_SRGB>,
  192. MortonCopy<false, PixelFormat::BC1_RGBA_SRGB>,
  193. MortonCopy<false, PixelFormat::BC2_SRGB>,
  194. MortonCopy<false, PixelFormat::BC3_SRGB>,
  195. MortonCopy<false, PixelFormat::BC7_SRGB>,
  196. MortonCopy<false, PixelFormat::A4B4G4R4_UNORM>,
  197. nullptr,
  198. nullptr,
  199. nullptr,
  200. nullptr,
  201. nullptr,
  202. nullptr,
  203. nullptr,
  204. nullptr,
  205. nullptr,
  206. nullptr,
  207. nullptr,
  208. nullptr,
  209. nullptr,
  210. nullptr,
  211. nullptr,
  212. nullptr,
  213. nullptr,
  214. nullptr,
  215. MortonCopy<false, PixelFormat::E5B9G9R9_FLOAT>,
  216. MortonCopy<false, PixelFormat::D32_FLOAT>,
  217. MortonCopy<false, PixelFormat::D16_UNORM>,
  218. MortonCopy<false, PixelFormat::D24_UNORM_S8_UINT>,
  219. MortonCopy<false, PixelFormat::S8_UINT_D24_UNORM>,
  220. MortonCopy<false, PixelFormat::D32_FLOAT_S8_UINT>,
  221. };
  222. static MortonCopyFn GetSwizzleFunction(MortonSwizzleMode mode, Surface::PixelFormat format) {
  223. switch (mode) {
  224. case MortonSwizzleMode::MortonToLinear:
  225. return morton_to_linear_fns[static_cast<std::size_t>(format)];
  226. case MortonSwizzleMode::LinearToMorton:
  227. return linear_to_morton_fns[static_cast<std::size_t>(format)];
  228. }
  229. UNREACHABLE();
  230. return morton_to_linear_fns[static_cast<std::size_t>(format)];
  231. }
  232. void MortonSwizzle(MortonSwizzleMode mode, Surface::PixelFormat format, u32 stride,
  233. u32 block_height, u32 height, u32 block_depth, u32 depth, u32 tile_width_spacing,
  234. u8* buffer, u8* addr) {
  235. GetSwizzleFunction(mode, format)(stride, block_height, height, block_depth, depth,
  236. tile_width_spacing, buffer, addr);
  237. }
  238. } // namespace VideoCore