surface_base.h 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  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 <algorithm>
  6. #include <unordered_map>
  7. #include <vector>
  8. #include "common/assert.h"
  9. #include "common/common_funcs.h"
  10. #include "common/common_types.h"
  11. #include "video_core/gpu.h"
  12. #include "video_core/morton.h"
  13. #include "video_core/texture_cache/copy_params.h"
  14. #include "video_core/texture_cache/surface_params.h"
  15. #include "video_core/texture_cache/surface_view.h"
  16. namespace Tegra {
  17. class MemoryManager;
  18. }
  19. namespace VideoCommon {
  20. using VideoCore::MortonSwizzleMode;
  21. using VideoCore::Surface::SurfaceTarget;
  22. enum class MatchStructureResult : u32 {
  23. FullMatch = 0,
  24. SemiMatch = 1,
  25. None = 2,
  26. };
  27. enum class MatchTopologyResult : u32 {
  28. FullMatch = 0,
  29. CompressUnmatch = 1,
  30. None = 2,
  31. };
  32. class StagingCache {
  33. public:
  34. StagingCache() {}
  35. ~StagingCache() = default;
  36. std::vector<u8>& GetBuffer(std::size_t index) {
  37. return staging_buffer[index];
  38. }
  39. void SetSize(std::size_t size) {
  40. staging_buffer.resize(size);
  41. }
  42. private:
  43. std::vector<std::vector<u8>> staging_buffer;
  44. };
  45. class SurfaceBaseImpl {
  46. public:
  47. void LoadBuffer(Tegra::MemoryManager& memory_manager, StagingCache& staging_cache);
  48. void FlushBuffer(Tegra::MemoryManager& memory_manager, StagingCache& staging_cache);
  49. GPUVAddr GetGpuAddr() const {
  50. return gpu_addr;
  51. }
  52. bool Overlaps(const CacheAddr start, const CacheAddr end) const {
  53. return (cache_addr < end) && (cache_addr_end > start);
  54. }
  55. bool IsInside(const GPUVAddr other_start, const GPUVAddr other_end) {
  56. const GPUVAddr gpu_addr_end = gpu_addr + guest_memory_size;
  57. return (gpu_addr <= other_start && other_end <= gpu_addr_end);
  58. }
  59. // Use only when recycling a surface
  60. void SetGpuAddr(const GPUVAddr new_addr) {
  61. gpu_addr = new_addr;
  62. }
  63. VAddr GetCpuAddr() const {
  64. return cpu_addr;
  65. }
  66. void SetCpuAddr(const VAddr new_addr) {
  67. cpu_addr = new_addr;
  68. }
  69. CacheAddr GetCacheAddr() const {
  70. return cache_addr;
  71. }
  72. CacheAddr GetCacheAddrEnd() const {
  73. return cache_addr_end;
  74. }
  75. void SetCacheAddr(const CacheAddr new_addr) {
  76. cache_addr = new_addr;
  77. cache_addr_end = new_addr + guest_memory_size;
  78. }
  79. const SurfaceParams& GetSurfaceParams() const {
  80. return params;
  81. }
  82. std::size_t GetSizeInBytes() const {
  83. return guest_memory_size;
  84. }
  85. std::size_t GetHostSizeInBytes() const {
  86. return host_memory_size;
  87. }
  88. std::size_t GetMipmapSize(const u32 level) const {
  89. return mipmap_sizes[level];
  90. }
  91. void MarkAsContinuous(const bool is_continuous) {
  92. this->is_continuous = is_continuous;
  93. }
  94. bool IsContinuous() const {
  95. return is_continuous;
  96. }
  97. bool IsLinear() const {
  98. return !params.is_tiled;
  99. }
  100. bool MatchFormat(VideoCore::Surface::PixelFormat pixel_format) const {
  101. return params.pixel_format == pixel_format;
  102. }
  103. VideoCore::Surface::PixelFormat GetFormat() const {
  104. return params.pixel_format;
  105. }
  106. bool MatchTarget(VideoCore::Surface::SurfaceTarget target) const {
  107. return params.target == target;
  108. }
  109. MatchTopologyResult MatchesTopology(const SurfaceParams& rhs) const;
  110. MatchStructureResult MatchesStructure(const SurfaceParams& rhs) const;
  111. bool MatchesSubTexture(const SurfaceParams& rhs, const GPUVAddr other_gpu_addr) const {
  112. return std::tie(gpu_addr, params.target, params.num_levels) ==
  113. std::tie(other_gpu_addr, rhs.target, rhs.num_levels) &&
  114. params.target == SurfaceTarget::Texture2D && params.num_levels == 1;
  115. }
  116. std::optional<std::pair<u32, u32>> GetLayerMipmap(const GPUVAddr candidate_gpu_addr) const;
  117. std::vector<CopyParams> BreakDown(const SurfaceParams& in_params) const {
  118. return params.is_layered ? BreakDownLayered(in_params) : BreakDownNonLayered(in_params);
  119. }
  120. protected:
  121. explicit SurfaceBaseImpl(GPUVAddr gpu_addr, const SurfaceParams& params);
  122. ~SurfaceBaseImpl() = default;
  123. virtual void DecorateSurfaceName() = 0;
  124. const SurfaceParams params;
  125. std::size_t layer_size;
  126. std::size_t guest_memory_size;
  127. const std::size_t host_memory_size;
  128. GPUVAddr gpu_addr{};
  129. CacheAddr cache_addr{};
  130. CacheAddr cache_addr_end{};
  131. VAddr cpu_addr{};
  132. bool is_continuous{};
  133. std::vector<std::size_t> mipmap_sizes;
  134. std::vector<std::size_t> mipmap_offsets;
  135. private:
  136. void SwizzleFunc(MortonSwizzleMode mode, u8* memory, const SurfaceParams& params, u8* buffer,
  137. u32 level);
  138. std::vector<CopyParams> BreakDownLayered(const SurfaceParams& in_params) const;
  139. std::vector<CopyParams> BreakDownNonLayered(const SurfaceParams& in_params) const;
  140. };
  141. template <typename TView>
  142. class SurfaceBase : public SurfaceBaseImpl {
  143. public:
  144. virtual void UploadTexture(std::vector<u8>& staging_buffer) = 0;
  145. virtual void DownloadTexture(std::vector<u8>& staging_buffer) = 0;
  146. void MarkAsModified(const bool is_modified_, const u64 tick) {
  147. is_modified = is_modified_ || is_target;
  148. modification_tick = tick;
  149. }
  150. void MarkAsRenderTarget(const bool is_target) {
  151. this->is_target = is_target;
  152. }
  153. void MarkAsPicked(const bool is_picked) {
  154. this->is_picked = is_picked;
  155. }
  156. bool IsModified() const {
  157. return is_modified;
  158. }
  159. bool IsProtected() const {
  160. // Only 3D Slices are to be protected
  161. return is_target && params.block_depth > 0;
  162. }
  163. bool IsRenderTarget() const {
  164. return is_target;
  165. }
  166. bool IsRegistered() const {
  167. return is_registered;
  168. }
  169. bool IsPicked() const {
  170. return is_picked;
  171. }
  172. void MarkAsRegistered(bool is_reg) {
  173. is_registered = is_reg;
  174. }
  175. u64 GetModificationTick() const {
  176. return modification_tick;
  177. }
  178. TView EmplaceOverview(const SurfaceParams& overview_params) {
  179. const u32 num_layers{(params.is_layered && !overview_params.is_layered) ? 1 : params.depth};
  180. return GetView(ViewParams(overview_params.target, 0, num_layers, 0, params.num_levels));
  181. }
  182. std::optional<TView> EmplaceIrregularView(const SurfaceParams& view_params,
  183. const GPUVAddr view_addr,
  184. const std::size_t candidate_size, const u32 mipmap,
  185. const u32 layer) {
  186. const auto layer_mipmap{GetLayerMipmap(view_addr + candidate_size)};
  187. if (!layer_mipmap) {
  188. return {};
  189. }
  190. const u32 end_layer{layer_mipmap->first};
  191. const u32 end_mipmap{layer_mipmap->second};
  192. if (layer != end_layer) {
  193. if (mipmap == 0 && end_mipmap == 0) {
  194. return GetView(ViewParams(view_params.target, layer, end_layer - layer + 1, 0, 1));
  195. }
  196. return {};
  197. } else {
  198. return GetView(
  199. ViewParams(view_params.target, layer, 1, mipmap, end_mipmap - mipmap + 1));
  200. }
  201. }
  202. std::optional<TView> EmplaceView(const SurfaceParams& view_params, const GPUVAddr view_addr,
  203. const std::size_t candidate_size) {
  204. if (params.target == SurfaceTarget::Texture3D ||
  205. (params.num_levels == 1 && !params.is_layered) ||
  206. view_params.target == SurfaceTarget::Texture3D) {
  207. return {};
  208. }
  209. const auto layer_mipmap{GetLayerMipmap(view_addr)};
  210. if (!layer_mipmap) {
  211. return {};
  212. }
  213. const u32 layer{layer_mipmap->first};
  214. const u32 mipmap{layer_mipmap->second};
  215. if (GetMipmapSize(mipmap) != candidate_size) {
  216. return EmplaceIrregularView(view_params, view_addr, candidate_size, mipmap, layer);
  217. }
  218. return GetView(ViewParams(view_params.target, layer, 1, mipmap, 1));
  219. }
  220. TView GetMainView() const {
  221. return main_view;
  222. }
  223. protected:
  224. explicit SurfaceBase(const GPUVAddr gpu_addr, const SurfaceParams& params)
  225. : SurfaceBaseImpl(gpu_addr, params) {}
  226. ~SurfaceBase() = default;
  227. virtual TView CreateView(const ViewParams& view_key) = 0;
  228. std::unordered_map<ViewParams, TView> views;
  229. TView main_view;
  230. private:
  231. TView GetView(const ViewParams& key) {
  232. const auto [entry, is_cache_miss] = views.try_emplace(key);
  233. auto& view{entry->second};
  234. if (is_cache_miss) {
  235. view = CreateView(key);
  236. }
  237. return view;
  238. }
  239. bool is_modified{};
  240. bool is_target{};
  241. bool is_registered{};
  242. bool is_picked{};
  243. u64 modification_tick{};
  244. };
  245. } // namespace VideoCommon