image_info.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. // Copyright 2020 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "common/assert.h"
  5. #include "video_core/surface.h"
  6. #include "video_core/texture_cache/format_lookup_table.h"
  7. #include "video_core/texture_cache/image_info.h"
  8. #include "video_core/texture_cache/samples_helper.h"
  9. #include "video_core/texture_cache/types.h"
  10. #include "video_core/texture_cache/util.h"
  11. #include "video_core/textures/texture.h"
  12. namespace VideoCommon {
  13. using Tegra::Texture::TextureType;
  14. using Tegra::Texture::TICEntry;
  15. using VideoCore::Surface::PixelFormat;
  16. ImageInfo::ImageInfo(const TICEntry& config) noexcept {
  17. format = PixelFormatFromTextureInfo(config.format, config.r_type, config.g_type, config.b_type,
  18. config.a_type, config.srgb_conversion);
  19. num_samples = NumSamples(config.msaa_mode);
  20. resources.levels = config.max_mip_level + 1;
  21. if (config.IsPitchLinear()) {
  22. pitch = config.Pitch();
  23. } else if (config.IsBlockLinear()) {
  24. block = Extent3D{
  25. .width = config.block_width,
  26. .height = config.block_height,
  27. .depth = config.block_depth,
  28. };
  29. }
  30. rescaleable = false;
  31. tile_width_spacing = config.tile_width_spacing;
  32. if (config.texture_type != TextureType::Texture2D &&
  33. config.texture_type != TextureType::Texture2DNoMipmap) {
  34. ASSERT(!config.IsPitchLinear());
  35. }
  36. switch (config.texture_type) {
  37. case TextureType::Texture1D:
  38. ASSERT(config.BaseLayer() == 0);
  39. type = ImageType::e1D;
  40. size.width = config.Width();
  41. resources.layers = 1;
  42. break;
  43. case TextureType::Texture1DArray:
  44. UNIMPLEMENTED_IF(config.BaseLayer() != 0);
  45. type = ImageType::e1D;
  46. size.width = config.Width();
  47. resources.layers = config.Depth();
  48. break;
  49. case TextureType::Texture2D:
  50. case TextureType::Texture2DNoMipmap:
  51. ASSERT(config.Depth() == 1);
  52. type = config.IsPitchLinear() ? ImageType::Linear : ImageType::e2D;
  53. rescaleable = !config.IsPitchLinear();
  54. size.width = config.Width();
  55. size.height = config.Height();
  56. resources.layers = config.BaseLayer() + 1;
  57. break;
  58. case TextureType::Texture2DArray:
  59. type = ImageType::e2D;
  60. rescaleable = true;
  61. size.width = config.Width();
  62. size.height = config.Height();
  63. resources.layers = config.BaseLayer() + config.Depth();
  64. break;
  65. case TextureType::TextureCubemap:
  66. ASSERT(config.Depth() == 1);
  67. type = ImageType::e2D;
  68. size.width = config.Width();
  69. size.height = config.Height();
  70. resources.layers = config.BaseLayer() + 6;
  71. break;
  72. case TextureType::TextureCubeArray:
  73. UNIMPLEMENTED_IF(config.load_store_hint != 0);
  74. type = ImageType::e2D;
  75. size.width = config.Width();
  76. size.height = config.Height();
  77. resources.layers = config.BaseLayer() + config.Depth() * 6;
  78. break;
  79. case TextureType::Texture3D:
  80. ASSERT(config.BaseLayer() == 0);
  81. type = ImageType::e3D;
  82. size.width = config.Width();
  83. size.height = config.Height();
  84. size.depth = config.Depth();
  85. resources.layers = 1;
  86. break;
  87. case TextureType::Texture1DBuffer:
  88. type = ImageType::Buffer;
  89. size.width = config.Width();
  90. resources.layers = 1;
  91. break;
  92. default:
  93. UNREACHABLE_MSG("Invalid texture_type={}", static_cast<int>(config.texture_type.Value()));
  94. break;
  95. }
  96. if (type != ImageType::Linear) {
  97. // FIXME: Call this without passing *this
  98. layer_stride = CalculateLayerStride(*this);
  99. maybe_unaligned_layer_stride = CalculateLayerSize(*this);
  100. rescaleable &= (block.depth == 0) && resources.levels == 1;
  101. }
  102. }
  103. ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs, size_t index) noexcept {
  104. const auto& rt = regs.rt[index];
  105. format = VideoCore::Surface::PixelFormatFromRenderTargetFormat(rt.format);
  106. rescaleable = false;
  107. if (rt.tile_mode.is_pitch_linear) {
  108. ASSERT(rt.tile_mode.is_3d == 0);
  109. type = ImageType::Linear;
  110. pitch = rt.width;
  111. size = Extent3D{
  112. .width = pitch / BytesPerBlock(format),
  113. .height = rt.height,
  114. .depth = 1,
  115. };
  116. return;
  117. }
  118. size.width = rt.width;
  119. size.height = rt.height;
  120. layer_stride = rt.layer_stride * 4;
  121. maybe_unaligned_layer_stride = layer_stride;
  122. num_samples = NumSamples(regs.multisample_mode);
  123. block = Extent3D{
  124. .width = rt.tile_mode.block_width,
  125. .height = rt.tile_mode.block_height,
  126. .depth = rt.tile_mode.block_depth,
  127. };
  128. if (rt.tile_mode.is_3d) {
  129. type = ImageType::e3D;
  130. size.depth = rt.depth;
  131. } else {
  132. rescaleable = block.depth == 0 && size.height > 256;
  133. type = ImageType::e2D;
  134. resources.layers = rt.depth;
  135. }
  136. }
  137. ImageInfo::ImageInfo(const Tegra::Engines::Maxwell3D::Regs& regs) noexcept {
  138. format = VideoCore::Surface::PixelFormatFromDepthFormat(regs.zeta.format);
  139. size.width = regs.zeta_width;
  140. size.height = regs.zeta_height;
  141. rescaleable = false;
  142. resources.levels = 1;
  143. layer_stride = regs.zeta.layer_stride * 4;
  144. maybe_unaligned_layer_stride = layer_stride;
  145. num_samples = NumSamples(regs.multisample_mode);
  146. block = Extent3D{
  147. .width = regs.zeta.tile_mode.block_width,
  148. .height = regs.zeta.tile_mode.block_height,
  149. .depth = regs.zeta.tile_mode.block_depth,
  150. };
  151. if (regs.zeta.tile_mode.is_pitch_linear) {
  152. ASSERT(regs.zeta.tile_mode.is_3d == 0);
  153. type = ImageType::Linear;
  154. pitch = size.width * BytesPerBlock(format);
  155. } else if (regs.zeta.tile_mode.is_3d) {
  156. ASSERT(regs.zeta.tile_mode.is_pitch_linear == 0);
  157. type = ImageType::e3D;
  158. size.depth = regs.zeta_depth;
  159. } else {
  160. rescaleable = block.depth == 0 && size.height > 256;
  161. type = ImageType::e2D;
  162. resources.layers = regs.zeta_depth;
  163. }
  164. }
  165. ImageInfo::ImageInfo(const Tegra::Engines::Fermi2D::Surface& config) noexcept {
  166. UNIMPLEMENTED_IF_MSG(config.layer != 0, "Surface layer is not zero");
  167. format = VideoCore::Surface::PixelFormatFromRenderTargetFormat(config.format);
  168. rescaleable = false;
  169. if (config.linear == Tegra::Engines::Fermi2D::MemoryLayout::Pitch) {
  170. type = ImageType::Linear;
  171. size = Extent3D{
  172. .width = config.pitch / VideoCore::Surface::BytesPerBlock(format),
  173. .height = config.height,
  174. .depth = 1,
  175. };
  176. pitch = config.pitch;
  177. } else {
  178. type = config.block_depth > 0 ? ImageType::e3D : ImageType::e2D;
  179. block = Extent3D{
  180. .width = config.block_width,
  181. .height = config.block_height,
  182. .depth = config.block_depth,
  183. };
  184. // 3D blits with more than once slice are not implemented for now
  185. // Render to individual slices
  186. size = Extent3D{
  187. .width = config.width,
  188. .height = config.height,
  189. .depth = 1,
  190. };
  191. rescaleable = block.depth == 0 && size.height > 256;
  192. }
  193. }
  194. } // namespace VideoCommon