morton.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  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::ABGR8U>,
  37. MortonCopy<true, PixelFormat::ABGR8S>,
  38. MortonCopy<true, PixelFormat::ABGR8I>,
  39. MortonCopy<true, PixelFormat::ABGR8UI>,
  40. MortonCopy<true, PixelFormat::B5G6R5U>,
  41. MortonCopy<true, PixelFormat::A2B10G10R10U>,
  42. MortonCopy<true, PixelFormat::A1B5G5R5U>,
  43. MortonCopy<true, PixelFormat::R8U>,
  44. MortonCopy<true, PixelFormat::R8S>,
  45. MortonCopy<true, PixelFormat::R8I>,
  46. MortonCopy<true, PixelFormat::R8UI>,
  47. MortonCopy<true, PixelFormat::RGBA16F>,
  48. MortonCopy<true, PixelFormat::RGBA16U>,
  49. MortonCopy<true, PixelFormat::RGBA16S>,
  50. MortonCopy<true, PixelFormat::RGBA16I>,
  51. MortonCopy<true, PixelFormat::RGBA16UI>,
  52. MortonCopy<true, PixelFormat::R11FG11FB10F>,
  53. MortonCopy<true, PixelFormat::RGBA32UI>,
  54. MortonCopy<true, PixelFormat::DXT1>,
  55. MortonCopy<true, PixelFormat::DXT23>,
  56. MortonCopy<true, PixelFormat::DXT45>,
  57. MortonCopy<true, PixelFormat::DXN1>,
  58. MortonCopy<true, PixelFormat::DXN2UNORM>,
  59. MortonCopy<true, PixelFormat::DXN2SNORM>,
  60. MortonCopy<true, PixelFormat::BC7U>,
  61. MortonCopy<true, PixelFormat::BC6H_UF16>,
  62. MortonCopy<true, PixelFormat::BC6H_SF16>,
  63. MortonCopy<true, PixelFormat::ASTC_2D_4X4>,
  64. MortonCopy<true, PixelFormat::BGRA8>,
  65. MortonCopy<true, PixelFormat::RGBA32F>,
  66. MortonCopy<true, PixelFormat::RGBA32I>,
  67. MortonCopy<true, PixelFormat::RG32F>,
  68. MortonCopy<true, PixelFormat::RG32I>,
  69. MortonCopy<true, PixelFormat::R32F>,
  70. MortonCopy<true, PixelFormat::R16F>,
  71. MortonCopy<true, PixelFormat::R16U>,
  72. MortonCopy<true, PixelFormat::R16S>,
  73. MortonCopy<true, PixelFormat::R16UI>,
  74. MortonCopy<true, PixelFormat::R16I>,
  75. MortonCopy<true, PixelFormat::RG16>,
  76. MortonCopy<true, PixelFormat::RG16F>,
  77. MortonCopy<true, PixelFormat::RG16UI>,
  78. MortonCopy<true, PixelFormat::RG16I>,
  79. MortonCopy<true, PixelFormat::RG16S>,
  80. MortonCopy<true, PixelFormat::RGB32F>,
  81. MortonCopy<true, PixelFormat::RGBA8_SRGB>,
  82. MortonCopy<true, PixelFormat::RG8U>,
  83. MortonCopy<true, PixelFormat::RG8S>,
  84. MortonCopy<true, PixelFormat::RG8I>,
  85. MortonCopy<true, PixelFormat::RG8UI>,
  86. MortonCopy<true, PixelFormat::RG32UI>,
  87. MortonCopy<true, PixelFormat::RGBX16F>,
  88. MortonCopy<true, PixelFormat::R32UI>,
  89. MortonCopy<true, PixelFormat::R32I>,
  90. MortonCopy<true, PixelFormat::ASTC_2D_8X8>,
  91. MortonCopy<true, PixelFormat::ASTC_2D_8X5>,
  92. MortonCopy<true, PixelFormat::ASTC_2D_5X4>,
  93. MortonCopy<true, PixelFormat::BGRA8_SRGB>,
  94. MortonCopy<true, PixelFormat::DXT1_SRGB>,
  95. MortonCopy<true, PixelFormat::DXT23_SRGB>,
  96. MortonCopy<true, PixelFormat::DXT45_SRGB>,
  97. MortonCopy<true, PixelFormat::BC7U_SRGB>,
  98. MortonCopy<true, PixelFormat::R4G4B4A4U>,
  99. MortonCopy<true, PixelFormat::ASTC_2D_4X4_SRGB>,
  100. MortonCopy<true, PixelFormat::ASTC_2D_8X8_SRGB>,
  101. MortonCopy<true, PixelFormat::ASTC_2D_8X5_SRGB>,
  102. MortonCopy<true, PixelFormat::ASTC_2D_5X4_SRGB>,
  103. MortonCopy<true, PixelFormat::ASTC_2D_5X5>,
  104. MortonCopy<true, PixelFormat::ASTC_2D_5X5_SRGB>,
  105. MortonCopy<true, PixelFormat::ASTC_2D_10X8>,
  106. MortonCopy<true, PixelFormat::ASTC_2D_10X8_SRGB>,
  107. MortonCopy<true, PixelFormat::ASTC_2D_6X6>,
  108. MortonCopy<true, PixelFormat::ASTC_2D_6X6_SRGB>,
  109. MortonCopy<true, PixelFormat::ASTC_2D_10X10>,
  110. MortonCopy<true, PixelFormat::ASTC_2D_10X10_SRGB>,
  111. MortonCopy<true, PixelFormat::ASTC_2D_12X12>,
  112. MortonCopy<true, PixelFormat::ASTC_2D_12X12_SRGB>,
  113. MortonCopy<true, PixelFormat::ASTC_2D_8X6>,
  114. MortonCopy<true, PixelFormat::ASTC_2D_8X6_SRGB>,
  115. MortonCopy<true, PixelFormat::ASTC_2D_6X5>,
  116. MortonCopy<true, PixelFormat::ASTC_2D_6X5_SRGB>,
  117. MortonCopy<true, PixelFormat::E5B9G9R9F>,
  118. MortonCopy<true, PixelFormat::Z32F>,
  119. MortonCopy<true, PixelFormat::Z16>,
  120. MortonCopy<true, PixelFormat::Z24S8>,
  121. MortonCopy<true, PixelFormat::S8Z24>,
  122. MortonCopy<true, PixelFormat::Z32FS8>,
  123. };
  124. static constexpr ConversionArray linear_to_morton_fns = {
  125. MortonCopy<false, PixelFormat::ABGR8U>,
  126. MortonCopy<false, PixelFormat::ABGR8S>,
  127. MortonCopy<false, PixelFormat::ABGR8I>,
  128. MortonCopy<false, PixelFormat::ABGR8UI>,
  129. MortonCopy<false, PixelFormat::B5G6R5U>,
  130. MortonCopy<false, PixelFormat::A2B10G10R10U>,
  131. MortonCopy<false, PixelFormat::A1B5G5R5U>,
  132. MortonCopy<false, PixelFormat::R8U>,
  133. MortonCopy<false, PixelFormat::R8S>,
  134. MortonCopy<false, PixelFormat::R8I>,
  135. MortonCopy<false, PixelFormat::R8UI>,
  136. MortonCopy<false, PixelFormat::RGBA16F>,
  137. MortonCopy<false, PixelFormat::RGBA16S>,
  138. MortonCopy<false, PixelFormat::RGBA16I>,
  139. MortonCopy<false, PixelFormat::RGBA16U>,
  140. MortonCopy<false, PixelFormat::RGBA16UI>,
  141. MortonCopy<false, PixelFormat::R11FG11FB10F>,
  142. MortonCopy<false, PixelFormat::RGBA32UI>,
  143. MortonCopy<false, PixelFormat::DXT1>,
  144. MortonCopy<false, PixelFormat::DXT23>,
  145. MortonCopy<false, PixelFormat::DXT45>,
  146. MortonCopy<false, PixelFormat::DXN1>,
  147. MortonCopy<false, PixelFormat::DXN2UNORM>,
  148. MortonCopy<false, PixelFormat::DXN2SNORM>,
  149. MortonCopy<false, PixelFormat::BC7U>,
  150. MortonCopy<false, PixelFormat::BC6H_UF16>,
  151. MortonCopy<false, PixelFormat::BC6H_SF16>,
  152. // TODO(Subv): Swizzling ASTC formats are not supported
  153. nullptr,
  154. MortonCopy<false, PixelFormat::BGRA8>,
  155. MortonCopy<false, PixelFormat::RGBA32F>,
  156. MortonCopy<false, PixelFormat::RGBA32I>,
  157. MortonCopy<false, PixelFormat::RG32F>,
  158. MortonCopy<false, PixelFormat::RG32I>,
  159. MortonCopy<false, PixelFormat::R32F>,
  160. MortonCopy<false, PixelFormat::R16F>,
  161. MortonCopy<false, PixelFormat::R16U>,
  162. MortonCopy<false, PixelFormat::R16S>,
  163. MortonCopy<false, PixelFormat::R16UI>,
  164. MortonCopy<false, PixelFormat::R16I>,
  165. MortonCopy<false, PixelFormat::RG16>,
  166. MortonCopy<false, PixelFormat::RG16F>,
  167. MortonCopy<false, PixelFormat::RG16UI>,
  168. MortonCopy<false, PixelFormat::RG16I>,
  169. MortonCopy<false, PixelFormat::RG16S>,
  170. MortonCopy<false, PixelFormat::RGB32F>,
  171. MortonCopy<false, PixelFormat::RGBA8_SRGB>,
  172. MortonCopy<false, PixelFormat::RG8U>,
  173. MortonCopy<false, PixelFormat::RG8S>,
  174. MortonCopy<false, PixelFormat::RG8I>,
  175. MortonCopy<false, PixelFormat::RG8UI>,
  176. MortonCopy<false, PixelFormat::RG32UI>,
  177. MortonCopy<false, PixelFormat::RGBX16F>,
  178. MortonCopy<false, PixelFormat::R32UI>,
  179. MortonCopy<false, PixelFormat::R32I>,
  180. nullptr,
  181. nullptr,
  182. nullptr,
  183. MortonCopy<false, PixelFormat::BGRA8_SRGB>,
  184. MortonCopy<false, PixelFormat::DXT1_SRGB>,
  185. MortonCopy<false, PixelFormat::DXT23_SRGB>,
  186. MortonCopy<false, PixelFormat::DXT45_SRGB>,
  187. MortonCopy<false, PixelFormat::BC7U_SRGB>,
  188. MortonCopy<false, PixelFormat::R4G4B4A4U>,
  189. nullptr,
  190. nullptr,
  191. nullptr,
  192. nullptr,
  193. nullptr,
  194. nullptr,
  195. nullptr,
  196. nullptr,
  197. nullptr,
  198. nullptr,
  199. nullptr,
  200. nullptr,
  201. nullptr,
  202. nullptr,
  203. nullptr,
  204. nullptr,
  205. nullptr,
  206. nullptr,
  207. MortonCopy<false, PixelFormat::E5B9G9R9F>,
  208. MortonCopy<false, PixelFormat::Z32F>,
  209. MortonCopy<false, PixelFormat::Z16>,
  210. MortonCopy<false, PixelFormat::Z24S8>,
  211. MortonCopy<false, PixelFormat::S8Z24>,
  212. MortonCopy<false, PixelFormat::Z32FS8>,
  213. };
  214. static MortonCopyFn GetSwizzleFunction(MortonSwizzleMode mode, Surface::PixelFormat format) {
  215. switch (mode) {
  216. case MortonSwizzleMode::MortonToLinear:
  217. return morton_to_linear_fns[static_cast<std::size_t>(format)];
  218. case MortonSwizzleMode::LinearToMorton:
  219. return linear_to_morton_fns[static_cast<std::size_t>(format)];
  220. }
  221. UNREACHABLE();
  222. return morton_to_linear_fns[static_cast<std::size_t>(format)];
  223. }
  224. void MortonSwizzle(MortonSwizzleMode mode, Surface::PixelFormat format, u32 stride,
  225. u32 block_height, u32 height, u32 block_depth, u32 depth, u32 tile_width_spacing,
  226. u8* buffer, u8* addr) {
  227. GetSwizzleFunction(mode, format)(stride, block_height, height, block_depth, depth,
  228. tile_width_spacing, buffer, addr);
  229. }
  230. } // namespace VideoCore