shader_cache.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <array>
  5. #include <memory>
  6. #include <mutex>
  7. #include <span>
  8. #include <unordered_map>
  9. #include <utility>
  10. #include <vector>
  11. #include "common/common_types.h"
  12. #include "common/polyfill_ranges.h"
  13. #include "video_core/control/channel_state_cache.h"
  14. #include "video_core/host1x/gpu_device_memory_manager.h"
  15. #include "video_core/rasterizer_interface.h"
  16. #include "video_core/shader_environment.h"
  17. namespace Tegra {
  18. class MemoryManager;
  19. }
  20. namespace Tegra::Control {
  21. struct ChannelState;
  22. }
  23. namespace VideoCommon {
  24. class GenericEnvironment;
  25. struct ShaderInfo {
  26. u64 unique_hash{};
  27. size_t size_bytes{};
  28. };
  29. class ShaderCache : public VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> {
  30. static constexpr u64 YUZU_PAGEBITS = 14;
  31. static constexpr u64 YUZU_PAGESIZE = u64(1) << YUZU_PAGEBITS;
  32. static constexpr size_t NUM_PROGRAMS = 6;
  33. struct Entry {
  34. VAddr addr_start;
  35. VAddr addr_end;
  36. ShaderInfo* data;
  37. bool is_memory_marked = true;
  38. bool Overlaps(VAddr start, VAddr end) const noexcept {
  39. return start < addr_end && addr_start < end;
  40. }
  41. };
  42. public:
  43. /// @brief Removes shaders inside a given region
  44. /// @note Checks for ranges
  45. /// @param addr Start address of the invalidation
  46. /// @param size Number of bytes of the invalidation
  47. void InvalidateRegion(VAddr addr, size_t size);
  48. /// @brief Unmarks a memory region as cached and marks it for removal
  49. /// @param addr Start address of the CPU write operation
  50. /// @param size Number of bytes of the CPU write operation
  51. void OnCacheInvalidation(VAddr addr, size_t size);
  52. /// @brief Flushes delayed removal operations
  53. void SyncGuestHost();
  54. protected:
  55. struct GraphicsEnvironments {
  56. std::array<GraphicsEnvironment, NUM_PROGRAMS> envs;
  57. std::array<Shader::Environment*, NUM_PROGRAMS> env_ptrs{};
  58. std::span<Shader::Environment* const> Span() const noexcept {
  59. return std::span(env_ptrs.begin(), std::ranges::find(env_ptrs, nullptr));
  60. }
  61. };
  62. explicit ShaderCache(Tegra::MaxwellDeviceMemoryManager& device_memory);
  63. /// @brief Update the hashes and information of shader stages
  64. /// @param unique_hashes Shader hashes to store into when a stage is enabled
  65. /// @return True no success, false on error
  66. bool RefreshStages(std::array<u64, NUM_PROGRAMS>& unique_hashes);
  67. /// @brief Returns information about the current compute shader
  68. /// @return Pointer to a valid shader, nullptr on error
  69. const ShaderInfo* ComputeShader();
  70. /// @brief Collect the current graphics environments
  71. void GetGraphicsEnvironments(GraphicsEnvironments& result,
  72. const std::array<u64, NUM_PROGRAMS>& unique_hashes);
  73. std::array<const ShaderInfo*, NUM_PROGRAMS> shader_infos{};
  74. bool last_shaders_valid = false;
  75. private:
  76. /// @brief Tries to obtain a cached shader starting in a given address
  77. /// @note Doesn't check for ranges, the given address has to be the start of the shader
  78. /// @param addr Start address of the shader, this doesn't cache for region
  79. /// @return Pointer to a valid shader, nullptr when nothing is found
  80. ShaderInfo* TryGet(VAddr addr) const;
  81. /// @brief Register in the cache a given entry
  82. /// @param data Shader to store in the cache
  83. /// @param addr Start address of the shader that will be registered
  84. /// @param size Size in bytes of the shader
  85. void Register(std::unique_ptr<ShaderInfo> data, VAddr addr, size_t size);
  86. /// @brief Invalidate pages in a given region
  87. /// @pre invalidation_mutex is locked
  88. void InvalidatePagesInRegion(VAddr addr, size_t size);
  89. /// @brief Remove shaders marked for deletion
  90. /// @pre invalidation_mutex is locked
  91. void RemovePendingShaders();
  92. /// @brief Invalidates entries in a given range for the passed page
  93. /// @param entries Vector of entries in the page, it will be modified on overlaps
  94. /// @param addr Start address of the invalidation
  95. /// @param addr_end Non-inclusive end address of the invalidation
  96. /// @pre invalidation_mutex is locked
  97. void InvalidatePageEntries(std::vector<Entry*>& entries, VAddr addr, VAddr addr_end);
  98. /// @brief Removes all references to an entry in the invalidation cache
  99. /// @param entry Entry to remove from the invalidation cache
  100. /// @pre invalidation_mutex is locked
  101. void RemoveEntryFromInvalidationCache(const Entry* entry);
  102. /// @brief Unmarks an entry from the rasterizer cache
  103. /// @param entry Entry to unmark from memory
  104. void UnmarkMemory(Entry* entry);
  105. /// @brief Removes a vector of shaders from a list
  106. /// @param removed_shaders Shaders to be removed from the storage
  107. /// @pre invalidation_mutex is locked
  108. /// @pre lookup_mutex is locked
  109. void RemoveShadersFromStorage(std::span<ShaderInfo*> removed_shaders);
  110. /// @brief Creates a new entry in the lookup cache and returns its pointer
  111. /// @pre lookup_mutex is locked
  112. Entry* NewEntry(VAddr addr, VAddr addr_end, ShaderInfo* data);
  113. /// @brief Create a new shader entry and register it
  114. const ShaderInfo* MakeShaderInfo(GenericEnvironment& env, VAddr cpu_addr);
  115. Tegra::MaxwellDeviceMemoryManager& device_memory;
  116. mutable std::mutex lookup_mutex;
  117. std::mutex invalidation_mutex;
  118. std::unordered_map<u64, std::unique_ptr<Entry>> lookup_cache;
  119. std::unordered_map<u64, std::vector<Entry*>> invalidation_cache;
  120. std::vector<std::unique_ptr<ShaderInfo>> storage;
  121. std::vector<Entry*> marked_for_removal;
  122. };
  123. } // namespace VideoCommon