surface_base.h 8.9 KB

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