morton.cpp 9.1 KB

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