surface_params.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. // Copyright 2019 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <map>
  6. #include "common/alignment.h"
  7. #include "common/bit_util.h"
  8. #include "common/common_types.h"
  9. #include "video_core/engines/fermi_2d.h"
  10. #include "video_core/engines/maxwell_3d.h"
  11. #include "video_core/shader/shader_ir.h"
  12. #include "video_core/surface.h"
  13. #include "video_core/textures/decoders.h"
  14. namespace VideoCommon {
  15. using VideoCore::Surface::SurfaceCompression;
  16. class SurfaceParams {
  17. public:
  18. /// Creates SurfaceCachedParams from a texture configuration.
  19. static SurfaceParams CreateForTexture(Core::System& system,
  20. const Tegra::Texture::FullTextureInfo& config,
  21. const VideoCommon::Shader::Sampler& entry);
  22. /// Creates SurfaceCachedParams for a depth buffer configuration.
  23. static SurfaceParams CreateForDepthBuffer(
  24. Core::System& system, u32 zeta_width, u32 zeta_height, Tegra::DepthFormat format,
  25. u32 block_width, u32 block_height, u32 block_depth,
  26. Tegra::Engines::Maxwell3D::Regs::InvMemoryLayout type);
  27. /// Creates SurfaceCachedParams from a framebuffer configuration.
  28. static SurfaceParams CreateForFramebuffer(Core::System& system, std::size_t index);
  29. /// Creates SurfaceCachedParams from a Fermi2D surface configuration.
  30. static SurfaceParams CreateForFermiCopySurface(
  31. const Tegra::Engines::Fermi2D::Regs::Surface& config);
  32. std::size_t Hash() const;
  33. bool operator==(const SurfaceParams& rhs) const;
  34. bool operator!=(const SurfaceParams& rhs) const {
  35. return !operator==(rhs);
  36. }
  37. std::size_t GetGuestSizeInBytes() const {
  38. return GetInnerMemorySize(false, false, false);
  39. }
  40. std::size_t GetHostSizeInBytes() const {
  41. std::size_t host_size_in_bytes;
  42. if (GetCompressionType() == SurfaceCompression::Converted) {
  43. constexpr std::size_t rgb8_bpp = 4ULL;
  44. // ASTC is uncompressed in software, in emulated as RGBA8
  45. host_size_in_bytes = 0;
  46. for (u32 level = 0; level < num_levels; ++level) {
  47. host_size_in_bytes += GetConvertedMipmapSize(level);
  48. }
  49. } else {
  50. host_size_in_bytes = GetInnerMemorySize(true, false, false);
  51. }
  52. return host_size_in_bytes;
  53. }
  54. u32 GetBlockAlignedWidth() const {
  55. return Common::AlignUp(width, 64 / GetBytesPerPixel());
  56. }
  57. /// Returns the width of a given mipmap level.
  58. u32 GetMipWidth(u32 level) const {
  59. return std::max(1U, width >> level);
  60. }
  61. /// Returns the height of a given mipmap level.
  62. u32 GetMipHeight(u32 level) const {
  63. return std::max(1U, height >> level);
  64. }
  65. /// Returns the depth of a given mipmap level.
  66. u32 GetMipDepth(u32 level) const {
  67. return is_layered ? depth : std::max(1U, depth >> level);
  68. }
  69. /// Returns the block height of a given mipmap level.
  70. u32 GetMipBlockHeight(u32 level) const;
  71. /// Returns the block depth of a given mipmap level.
  72. u32 GetMipBlockDepth(u32 level) const;
  73. u32 GetRowAlignment(u32 level) const {
  74. const u32 bpp =
  75. GetCompressionType() == SurfaceCompression::Converted ? 4 : GetBytesPerPixel();
  76. return 1U << Common::CountTrailingZeroes32(GetMipWidth(level) * bpp);
  77. }
  78. // Helper used for out of class size calculations
  79. static std::size_t AlignLayered(const std::size_t out_size, const u32 block_height,
  80. const u32 block_depth) {
  81. return Common::AlignBits(out_size,
  82. Tegra::Texture::GetGOBSizeShift() + block_height + block_depth);
  83. }
  84. /// Returns the offset in bytes in guest memory of a given mipmap level.
  85. std::size_t GetGuestMipmapLevelOffset(u32 level) const;
  86. /// Returns the offset in bytes in host memory (linear) of a given mipmap level.
  87. std::size_t GetHostMipmapLevelOffset(u32 level) const;
  88. std::size_t GetConvertedMipmapOffset(u32 level) const;
  89. /// Returns the size in bytes in guest memory of a given mipmap level.
  90. std::size_t GetGuestMipmapSize(u32 level) const;
  91. /// Returns the size in bytes in host memory (linear) of a given mipmap level.
  92. std::size_t GetHostMipmapSize(u32 level) const;
  93. std::size_t GetConvertedMipmapSize(u32 level) const;
  94. /// Returns the size of a layer in bytes in guest memory.
  95. std::size_t GetGuestLayerSize() const;
  96. /// Returns the size of a layer in bytes in host memory for a given mipmap level.
  97. std::size_t GetHostLayerSize(u32 level) const;
  98. static u32 ConvertWidth(u32 width, VideoCore::Surface::PixelFormat pixel_format_from,
  99. VideoCore::Surface::PixelFormat pixel_format_to) {
  100. const u32 bw1 = VideoCore::Surface::GetDefaultBlockWidth(pixel_format_from);
  101. const u32 bw2 = VideoCore::Surface::GetDefaultBlockWidth(pixel_format_to);
  102. return (width * bw2 + bw1 - 1) / bw1;
  103. }
  104. static u32 ConvertHeight(u32 height, VideoCore::Surface::PixelFormat pixel_format_from,
  105. VideoCore::Surface::PixelFormat pixel_format_to) {
  106. const u32 bh1 = VideoCore::Surface::GetDefaultBlockHeight(pixel_format_from);
  107. const u32 bh2 = VideoCore::Surface::GetDefaultBlockHeight(pixel_format_to);
  108. return (height * bh2 + bh1 - 1) / bh1;
  109. }
  110. // this finds the maximun possible width between 2 2D layers of different formats
  111. static u32 IntersectWidth(const SurfaceParams& src_params, const SurfaceParams& dst_params,
  112. const u32 src_level, const u32 dst_level) {
  113. const u32 bw1 = src_params.GetDefaultBlockWidth();
  114. const u32 bw2 = dst_params.GetDefaultBlockWidth();
  115. const u32 t_src_width = (src_params.GetMipWidth(src_level) * bw2 + bw1 - 1) / bw1;
  116. const u32 t_dst_width = (dst_params.GetMipWidth(dst_level) * bw1 + bw2 - 1) / bw2;
  117. return std::min(t_src_width, t_dst_width);
  118. }
  119. // this finds the maximun possible height between 2 2D layers of different formats
  120. static u32 IntersectHeight(const SurfaceParams& src_params, const SurfaceParams& dst_params,
  121. const u32 src_level, const u32 dst_level) {
  122. const u32 bh1 = src_params.GetDefaultBlockHeight();
  123. const u32 bh2 = dst_params.GetDefaultBlockHeight();
  124. const u32 t_src_height = (src_params.GetMipHeight(src_level) * bh2 + bh1 - 1) / bh1;
  125. const u32 t_dst_height = (dst_params.GetMipHeight(dst_level) * bh1 + bh2 - 1) / bh2;
  126. return std::min(t_src_height, t_dst_height);
  127. }
  128. u32 MaxPossibleMipmap() const {
  129. const u32 max_mipmap_w = Common::Log2Ceil32(width) + 1U;
  130. const u32 max_mipmap_h = Common::Log2Ceil32(height) + 1U;
  131. const u32 max_mipmap = std::max(max_mipmap_w, max_mipmap_h);
  132. if (target != VideoCore::Surface::SurfaceTarget::Texture3D)
  133. return max_mipmap;
  134. return std::max(max_mipmap, Common::Log2Ceil32(depth) + 1U);
  135. }
  136. bool IsCompressed() const {
  137. return GetDefaultBlockHeight() > 1 || GetDefaultBlockWidth() > 1;
  138. }
  139. /// Returns the default block width.
  140. u32 GetDefaultBlockWidth() const {
  141. return VideoCore::Surface::GetDefaultBlockWidth(pixel_format);
  142. }
  143. /// Returns the default block height.
  144. u32 GetDefaultBlockHeight() const {
  145. return VideoCore::Surface::GetDefaultBlockHeight(pixel_format);
  146. }
  147. /// Returns the bits per pixel.
  148. u32 GetBitsPerPixel() const {
  149. return VideoCore::Surface::GetFormatBpp(pixel_format);
  150. }
  151. /// Returns the bytes per pixel.
  152. u32 GetBytesPerPixel() const {
  153. return VideoCore::Surface::GetBytesPerPixel(pixel_format);
  154. }
  155. /// Returns true if the pixel format is a depth and/or stencil format.
  156. bool IsPixelFormatZeta() const;
  157. SurfaceCompression GetCompressionType() const {
  158. return VideoCore::Surface::GetFormatCompressionType(pixel_format);
  159. }
  160. bool IsBuffer() const {
  161. return target == VideoCore::Surface::SurfaceTarget::TextureBuffer;
  162. }
  163. std::string TargetName() const;
  164. bool is_tiled;
  165. bool srgb_conversion;
  166. bool is_layered;
  167. u32 block_width;
  168. u32 block_height;
  169. u32 block_depth;
  170. u32 tile_width_spacing;
  171. u32 width;
  172. u32 height;
  173. u32 depth;
  174. u32 pitch;
  175. u32 num_levels;
  176. u32 emulated_levels;
  177. VideoCore::Surface::PixelFormat pixel_format;
  178. VideoCore::Surface::ComponentType component_type;
  179. VideoCore::Surface::SurfaceType type;
  180. VideoCore::Surface::SurfaceTarget target;
  181. private:
  182. /// Returns the size of a given mipmap level inside a layer.
  183. std::size_t GetInnerMipmapMemorySize(u32 level, bool as_host_size, bool uncompressed) const;
  184. /// Returns the size of all mipmap levels and aligns as needed.
  185. std::size_t GetInnerMemorySize(bool as_host_size, bool layer_only, bool uncompressed) const;
  186. /// Returns the size of a layer
  187. std::size_t GetLayerSize(bool as_host_size, bool uncompressed) const;
  188. std::size_t GetNumLayers() const {
  189. return is_layered ? depth : 1;
  190. }
  191. /// Returns true if these parameters are from a layered surface.
  192. bool IsLayered() const;
  193. };
  194. } // namespace VideoCommon
  195. namespace std {
  196. template <>
  197. struct hash<VideoCommon::SurfaceParams> {
  198. std::size_t operator()(const VideoCommon::SurfaceParams& k) const noexcept {
  199. return k.Hash();
  200. }
  201. };
  202. } // namespace std