morton.cpp 8.0 KB

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