image_info.cpp 8.1 KB

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