diff options
| author | 2021-12-17 16:45:06 +0100 | |
|---|---|---|
| committer | 2022-10-06 21:00:52 +0200 | |
| commit | e462191482c6507daed67802c6c1d2c50f10c96e (patch) | |
| tree | a6b4d851075d93b3052637d1382691e71b9b8c0e | |
| parent | General: Rebase fixes. (diff) | |
| download | yuzu-e462191482c6507daed67802c6c1d2c50f10c96e.tar.gz yuzu-e462191482c6507daed67802c6c1d2c50f10c96e.tar.xz yuzu-e462191482c6507daed67802c6c1d2c50f10c96e.zip | |
Refactor VideoCore to use AS sepparate from Channel.
| -rw-r--r-- | src/common/hash.h | 7 | ||||
| -rw-r--r-- | src/video_core/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/video_core/control/channel_state_cache.cpp | 8 | ||||
| -rw-r--r-- | src/video_core/control/channel_state_cache.h | 28 | ||||
| -rw-r--r-- | src/video_core/control/channel_state_cache.inc | 23 | ||||
| -rw-r--r-- | src/video_core/memory_manager.cpp | 5 | ||||
| -rw-r--r-- | src/video_core/memory_manager.h | 9 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.cpp | 16 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 130 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache_base.h | 96 |
10 files changed, 171 insertions, 152 deletions
diff --git a/src/common/hash.h b/src/common/hash.h index b6f3e6d6f..e8fe78b07 100644 --- a/src/common/hash.h +++ b/src/common/hash.h | |||
| @@ -18,4 +18,11 @@ struct PairHash { | |||
| 18 | } | 18 | } |
| 19 | }; | 19 | }; |
| 20 | 20 | ||
| 21 | template <typename T> | ||
| 22 | struct IdentityHash { | ||
| 23 | [[nodiscard]] size_t operator()(T value) const noexcept { | ||
| 24 | return static_cast<size_t>(value); | ||
| 25 | } | ||
| 26 | }; | ||
| 27 | |||
| 21 | } // namespace Common | 28 | } // namespace Common |
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index e216c51a2..35faa70a0 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -203,6 +203,7 @@ add_library(video_core STATIC | |||
| 203 | texture_cache/render_targets.h | 203 | texture_cache/render_targets.h |
| 204 | texture_cache/samples_helper.h | 204 | texture_cache/samples_helper.h |
| 205 | texture_cache/slot_vector.h | 205 | texture_cache/slot_vector.h |
| 206 | texture_cache/texture_cache.cpp | ||
| 206 | texture_cache/texture_cache.h | 207 | texture_cache/texture_cache.h |
| 207 | texture_cache/texture_cache_base.h | 208 | texture_cache/texture_cache_base.h |
| 208 | texture_cache/types.h | 209 | texture_cache/types.h |
diff --git a/src/video_core/control/channel_state_cache.cpp b/src/video_core/control/channel_state_cache.cpp index f72a97b2f..ec7ba907c 100644 --- a/src/video_core/control/channel_state_cache.cpp +++ b/src/video_core/control/channel_state_cache.cpp | |||
| @@ -1,5 +1,11 @@ | |||
| 1 | #include "video_core/control/channel_state_cache.inc" | 1 | #include "video_core/control/channel_state_cache.inc" |
| 2 | 2 | ||
| 3 | namespace VideoCommon { | 3 | namespace VideoCommon { |
| 4 | |||
| 5 | ChannelInfo::ChannelInfo(Tegra::Control::ChannelState& channel_state) | ||
| 6 | : maxwell3d{*channel_state.maxwell_3d}, kepler_compute{*channel_state.kepler_compute}, | ||
| 7 | gpu_memory{*channel_state.memory_manager} {} | ||
| 8 | |||
| 4 | template class VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo>; | 9 | template class VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo>; |
| 5 | } | 10 | |
| 11 | } // namespace VideoCommon | ||
diff --git a/src/video_core/control/channel_state_cache.h b/src/video_core/control/channel_state_cache.h index c8298c003..c51040c83 100644 --- a/src/video_core/control/channel_state_cache.h +++ b/src/video_core/control/channel_state_cache.h | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | 2 | ||
| 3 | #include <deque> | 3 | #include <deque> |
| 4 | #include <limits> | 4 | #include <limits> |
| 5 | #include <mutex> | ||
| 5 | #include <unordered_map> | 6 | #include <unordered_map> |
| 6 | 7 | ||
| 7 | #include "common/common_types.h" | 8 | #include "common/common_types.h" |
| @@ -41,9 +42,10 @@ template <class P> | |||
| 41 | class ChannelSetupCaches { | 42 | class ChannelSetupCaches { |
| 42 | public: | 43 | public: |
| 43 | /// Operations for seting the channel of execution. | 44 | /// Operations for seting the channel of execution. |
| 45 | virtual ~ChannelSetupCaches(); | ||
| 44 | 46 | ||
| 45 | /// Create channel state. | 47 | /// Create channel state. |
| 46 | void CreateChannel(Tegra::Control::ChannelState& channel); | 48 | virtual void CreateChannel(Tegra::Control::ChannelState& channel); |
| 47 | 49 | ||
| 48 | /// Bind a channel for execution. | 50 | /// Bind a channel for execution. |
| 49 | void BindToChannel(s32 id); | 51 | void BindToChannel(s32 id); |
| @@ -51,18 +53,34 @@ public: | |||
| 51 | /// Erase channel's state. | 53 | /// Erase channel's state. |
| 52 | void EraseChannel(s32 id); | 54 | void EraseChannel(s32 id); |
| 53 | 55 | ||
| 56 | Tegra::MemoryManager* GetFromID(size_t id) const { | ||
| 57 | std::unique_lock<std::mutex> lk(config_mutex); | ||
| 58 | const auto ref = address_spaces.find(id); | ||
| 59 | return ref->second.gpu_memory; | ||
| 60 | } | ||
| 61 | |||
| 54 | protected: | 62 | protected: |
| 55 | static constexpr size_t UNSET_CHANNEL{std::numeric_limits<size_t>::max()}; | 63 | static constexpr size_t UNSET_CHANNEL{std::numeric_limits<size_t>::max()}; |
| 56 | 64 | ||
| 57 | std::deque<P> channel_storage; | ||
| 58 | std::deque<size_t> free_channel_ids; | ||
| 59 | std::unordered_map<s32, size_t> channel_map; | ||
| 60 | |||
| 61 | P* channel_state; | 65 | P* channel_state; |
| 62 | size_t current_channel_id{UNSET_CHANNEL}; | 66 | size_t current_channel_id{UNSET_CHANNEL}; |
| 67 | size_t current_address_space{}; | ||
| 63 | Tegra::Engines::Maxwell3D* maxwell3d; | 68 | Tegra::Engines::Maxwell3D* maxwell3d; |
| 64 | Tegra::Engines::KeplerCompute* kepler_compute; | 69 | Tegra::Engines::KeplerCompute* kepler_compute; |
| 65 | Tegra::MemoryManager* gpu_memory; | 70 | Tegra::MemoryManager* gpu_memory; |
| 71 | |||
| 72 | std::deque<P> channel_storage; | ||
| 73 | std::deque<size_t> free_channel_ids; | ||
| 74 | std::unordered_map<s32, size_t> channel_map; | ||
| 75 | struct AddresSpaceRef { | ||
| 76 | size_t ref_count; | ||
| 77 | size_t storage_id; | ||
| 78 | Tegra::MemoryManager* gpu_memory; | ||
| 79 | }; | ||
| 80 | std::unordered_map<size_t, AddresSpaceRef> address_spaces; | ||
| 81 | mutable std::mutex config_mutex; | ||
| 82 | |||
| 83 | virtual void OnGPUASRegister([[maybe_unused]] size_t map_id) {} | ||
| 66 | }; | 84 | }; |
| 67 | 85 | ||
| 68 | } // namespace VideoCommon | 86 | } // namespace VideoCommon |
diff --git a/src/video_core/control/channel_state_cache.inc b/src/video_core/control/channel_state_cache.inc index 3eb73af9f..185eabc35 100644 --- a/src/video_core/control/channel_state_cache.inc +++ b/src/video_core/control/channel_state_cache.inc | |||
| @@ -6,18 +6,18 @@ | |||
| 6 | 6 | ||
| 7 | namespace VideoCommon { | 7 | namespace VideoCommon { |
| 8 | 8 | ||
| 9 | ChannelInfo::ChannelInfo(Tegra::Control::ChannelState& channel_state) | 9 | template <class P> |
| 10 | : maxwell3d{*channel_state.maxwell_3d}, kepler_compute{*channel_state.kepler_compute}, | 10 | ChannelSetupCaches<P>::~ChannelSetupCaches() = default; |
| 11 | gpu_memory{*channel_state.memory_manager} {} | ||
| 12 | 11 | ||
| 13 | template <class P> | 12 | template <class P> |
| 14 | void ChannelSetupCaches<P>::CreateChannel(struct Tegra::Control::ChannelState& channel) { | 13 | void ChannelSetupCaches<P>::CreateChannel(struct Tegra::Control::ChannelState& channel) { |
| 14 | std::unique_lock<std::mutex> lk(config_mutex); | ||
| 15 | ASSERT(channel_map.find(channel.bind_id) == channel_map.end() && channel.bind_id >= 0); | 15 | ASSERT(channel_map.find(channel.bind_id) == channel_map.end() && channel.bind_id >= 0); |
| 16 | auto new_id = [this, &channel]() { | 16 | auto new_id = [this, &channel]() { |
| 17 | if (!free_channel_ids.empty()) { | 17 | if (!free_channel_ids.empty()) { |
| 18 | auto id = free_channel_ids.front(); | 18 | auto id = free_channel_ids.front(); |
| 19 | free_channel_ids.pop_front(); | 19 | free_channel_ids.pop_front(); |
| 20 | new (&channel_storage[id]) ChannelInfo(channel); | 20 | new (&channel_storage[id]) P(channel); |
| 21 | return id; | 21 | return id; |
| 22 | } | 22 | } |
| 23 | channel_storage.emplace_back(channel); | 23 | channel_storage.emplace_back(channel); |
| @@ -27,11 +27,24 @@ void ChannelSetupCaches<P>::CreateChannel(struct Tegra::Control::ChannelState& c | |||
| 27 | if (current_channel_id != UNSET_CHANNEL) { | 27 | if (current_channel_id != UNSET_CHANNEL) { |
| 28 | channel_state = &channel_storage[current_channel_id]; | 28 | channel_state = &channel_storage[current_channel_id]; |
| 29 | } | 29 | } |
| 30 | auto as_it = address_spaces.find(channel.memory_manager->GetID()); | ||
| 31 | if (as_it != address_spaces.end()) { | ||
| 32 | as_it->second.ref_count++; | ||
| 33 | return; | ||
| 34 | } | ||
| 35 | AddresSpaceRef new_gpu_mem_ref{ | ||
| 36 | .ref_count = 1, | ||
| 37 | .storage_id = address_spaces.size(), | ||
| 38 | .gpu_memory = channel.memory_manager.get(), | ||
| 39 | }; | ||
| 40 | address_spaces.emplace(channel.memory_manager->GetID(), new_gpu_mem_ref); | ||
| 41 | OnGPUASRegister(channel.memory_manager->GetID()); | ||
| 30 | } | 42 | } |
| 31 | 43 | ||
| 32 | /// Bind a channel for execution. | 44 | /// Bind a channel for execution. |
| 33 | template <class P> | 45 | template <class P> |
| 34 | void ChannelSetupCaches<P>::BindToChannel(s32 id) { | 46 | void ChannelSetupCaches<P>::BindToChannel(s32 id) { |
| 47 | std::unique_lock<std::mutex> lk(config_mutex); | ||
| 35 | auto it = channel_map.find(id); | 48 | auto it = channel_map.find(id); |
| 36 | ASSERT(it != channel_map.end() && id >= 0); | 49 | ASSERT(it != channel_map.end() && id >= 0); |
| 37 | current_channel_id = it->second; | 50 | current_channel_id = it->second; |
| @@ -39,11 +52,13 @@ void ChannelSetupCaches<P>::BindToChannel(s32 id) { | |||
| 39 | maxwell3d = &channel_state->maxwell3d; | 52 | maxwell3d = &channel_state->maxwell3d; |
| 40 | kepler_compute = &channel_state->kepler_compute; | 53 | kepler_compute = &channel_state->kepler_compute; |
| 41 | gpu_memory = &channel_state->gpu_memory; | 54 | gpu_memory = &channel_state->gpu_memory; |
| 55 | current_address_space = gpu_memory->GetID(); | ||
| 42 | } | 56 | } |
| 43 | 57 | ||
| 44 | /// Erase channel's channel_state. | 58 | /// Erase channel's channel_state. |
| 45 | template <class P> | 59 | template <class P> |
| 46 | void ChannelSetupCaches<P>::EraseChannel(s32 id) { | 60 | void ChannelSetupCaches<P>::EraseChannel(s32 id) { |
| 61 | std::unique_lock<std::mutex> lk(config_mutex); | ||
| 47 | const auto it = channel_map.find(id); | 62 | const auto it = channel_map.find(id); |
| 48 | ASSERT(it != channel_map.end() && id >= 0); | 63 | ASSERT(it != channel_map.end() && id >= 0); |
| 49 | const auto this_id = it->second; | 64 | const auto this_id = it->second; |
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index fc68bcc73..d4c0dca78 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp | |||
| @@ -16,9 +16,12 @@ | |||
| 16 | 16 | ||
| 17 | namespace Tegra { | 17 | namespace Tegra { |
| 18 | 18 | ||
| 19 | std::atomic<size_t> MemoryManager::unique_identifier_generator{}; | ||
| 20 | |||
| 19 | MemoryManager::MemoryManager(Core::System& system_, u64 address_space_bits_, u64 page_bits_) | 21 | MemoryManager::MemoryManager(Core::System& system_, u64 address_space_bits_, u64 page_bits_) |
| 20 | : system{system_}, address_space_bits{address_space_bits_}, page_bits{page_bits_}, entries{}, | 22 | : system{system_}, address_space_bits{address_space_bits_}, page_bits{page_bits_}, entries{}, |
| 21 | page_table{address_space_bits, address_space_bits + page_bits - 38, page_bits} { | 23 | page_table{address_space_bits, address_space_bits + page_bits - 38, page_bits}, |
| 24 | unique_identifier{unique_identifier_generator.fetch_add(1, std::memory_order_acq_rel)} { | ||
| 22 | address_space_size = 1ULL << address_space_bits; | 25 | address_space_size = 1ULL << address_space_bits; |
| 23 | allocate_start = address_space_bits > 32 ? 1ULL << 32 : 0; | 26 | allocate_start = address_space_bits > 32 ? 1ULL << 32 : 0; |
| 24 | page_size = 1ULL << page_bits; | 27 | page_size = 1ULL << page_bits; |
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h index b8878476a..56604ef3e 100644 --- a/src/video_core/memory_manager.h +++ b/src/video_core/memory_manager.h | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <atomic> | ||
| 6 | #include <map> | 7 | #include <map> |
| 7 | #include <optional> | 8 | #include <optional> |
| 8 | #include <vector> | 9 | #include <vector> |
| @@ -26,6 +27,10 @@ public: | |||
| 26 | u64 page_bits_ = 16); | 27 | u64 page_bits_ = 16); |
| 27 | ~MemoryManager(); | 28 | ~MemoryManager(); |
| 28 | 29 | ||
| 30 | size_t GetID() const { | ||
| 31 | return unique_identifier; | ||
| 32 | } | ||
| 33 | |||
| 29 | /// Binds a renderer to the memory manager. | 34 | /// Binds a renderer to the memory manager. |
| 30 | void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); | 35 | void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); |
| 31 | 36 | ||
| @@ -140,6 +145,10 @@ private: | |||
| 140 | void SetEntry(size_t position, EntryType entry); | 145 | void SetEntry(size_t position, EntryType entry); |
| 141 | 146 | ||
| 142 | Common::MultiLevelPageTable<u32> page_table; | 147 | Common::MultiLevelPageTable<u32> page_table; |
| 148 | |||
| 149 | const size_t unique_identifier; | ||
| 150 | |||
| 151 | static std::atomic<size_t> unique_identifier_generator; | ||
| 143 | }; | 152 | }; |
| 144 | 153 | ||
| 145 | } // namespace Tegra | 154 | } // namespace Tegra |
diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp new file mode 100644 index 000000000..bc905a1a4 --- /dev/null +++ b/src/video_core/texture_cache/texture_cache.cpp | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv3 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "video_core/control/channel_state_cache.inc" | ||
| 6 | #include "video_core/texture_cache/texture_cache_base.h" | ||
| 7 | |||
| 8 | namespace VideoCommon { | ||
| 9 | |||
| 10 | TextureCacheChannelInfo::TextureCacheChannelInfo(Tegra::Control::ChannelState& state) noexcept | ||
| 11 | : ChannelInfo(state), graphics_image_table{gpu_memory}, graphics_sampler_table{gpu_memory}, | ||
| 12 | compute_image_table{gpu_memory}, compute_sampler_table{gpu_memory} {} | ||
| 13 | |||
| 14 | template class VideoCommon::ChannelSetupCaches<VideoCommon::TextureCacheChannelInfo>; | ||
| 15 | |||
| 16 | } // namespace VideoCommon | ||
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 0ec999d63..89c5faf88 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: 2021 yuzu emulator team |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // (https://github.com/skyline-emu/) |
| 3 | // SPDX-License-Identifier: GPL-3.0-or-later Licensed under GPLv3 | ||
| 4 | // or any later version Refer to the license.txt file included. | ||
| 3 | 5 | ||
| 4 | #pragma once | 6 | #pragma once |
| 5 | 7 | ||
| @@ -41,10 +43,6 @@ TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface& | |||
| 41 | 43 | ||
| 42 | // Setup channels | 44 | // Setup channels |
| 43 | current_channel_id = UNSET_CHANNEL; | 45 | current_channel_id = UNSET_CHANNEL; |
| 44 | state = nullptr; | ||
| 45 | maxwell3d = nullptr; | ||
| 46 | kepler_compute = nullptr; | ||
| 47 | gpu_memory = nullptr; | ||
| 48 | 46 | ||
| 49 | // Make sure the first index is reserved for the null resources | 47 | // Make sure the first index is reserved for the null resources |
| 50 | // This way the null resource becomes a compile time constant | 48 | // This way the null resource becomes a compile time constant |
| @@ -156,23 +154,24 @@ void TextureCache<P>::MarkModification(ImageId id) noexcept { | |||
| 156 | template <class P> | 154 | template <class P> |
| 157 | template <bool has_blacklists> | 155 | template <bool has_blacklists> |
| 158 | void TextureCache<P>::FillGraphicsImageViews(std::span<ImageViewInOut> views) { | 156 | void TextureCache<P>::FillGraphicsImageViews(std::span<ImageViewInOut> views) { |
| 159 | FillImageViews<has_blacklists>(state->graphics_image_table, state->graphics_image_view_ids, | 157 | FillImageViews<has_blacklists>(channel_state->graphics_image_table, |
| 160 | views); | 158 | channel_state->graphics_image_view_ids, views); |
| 161 | } | 159 | } |
| 162 | 160 | ||
| 163 | template <class P> | 161 | template <class P> |
| 164 | void TextureCache<P>::FillComputeImageViews(std::span<ImageViewInOut> views) { | 162 | void TextureCache<P>::FillComputeImageViews(std::span<ImageViewInOut> views) { |
| 165 | FillImageViews<true>(state->compute_image_table, state->compute_image_view_ids, views); | 163 | FillImageViews<true>(channel_state->compute_image_table, channel_state->compute_image_view_ids, |
| 164 | views); | ||
| 166 | } | 165 | } |
| 167 | 166 | ||
| 168 | template <class P> | 167 | template <class P> |
| 169 | typename P::Sampler* TextureCache<P>::GetGraphicsSampler(u32 index) { | 168 | typename P::Sampler* TextureCache<P>::GetGraphicsSampler(u32 index) { |
| 170 | if (index > state->graphics_sampler_table.Limit()) { | 169 | if (index > channel_state->graphics_sampler_table.Limit()) { |
| 171 | LOG_DEBUG(HW_GPU, "Invalid sampler index={}", index); | 170 | LOG_DEBUG(HW_GPU, "Invalid sampler index={}", index); |
| 172 | return &slot_samplers[NULL_SAMPLER_ID]; | 171 | return &slot_samplers[NULL_SAMPLER_ID]; |
| 173 | } | 172 | } |
| 174 | const auto [descriptor, is_new] = state->graphics_sampler_table.Read(index); | 173 | const auto [descriptor, is_new] = channel_state->graphics_sampler_table.Read(index); |
| 175 | SamplerId& id = state->graphics_sampler_ids[index]; | 174 | SamplerId& id = channel_state->graphics_sampler_ids[index]; |
| 176 | if (is_new) { | 175 | if (is_new) { |
| 177 | id = FindSampler(descriptor); | 176 | id = FindSampler(descriptor); |
| 178 | } | 177 | } |
| @@ -181,12 +180,12 @@ typename P::Sampler* TextureCache<P>::GetGraphicsSampler(u32 index) { | |||
| 181 | 180 | ||
| 182 | template <class P> | 181 | template <class P> |
| 183 | typename P::Sampler* TextureCache<P>::GetComputeSampler(u32 index) { | 182 | typename P::Sampler* TextureCache<P>::GetComputeSampler(u32 index) { |
| 184 | if (index > state->compute_sampler_table.Limit()) { | 183 | if (index > channel_state->compute_sampler_table.Limit()) { |
| 185 | LOG_DEBUG(HW_GPU, "Invalid sampler index={}", index); | 184 | LOG_DEBUG(HW_GPU, "Invalid sampler index={}", index); |
| 186 | return &slot_samplers[NULL_SAMPLER_ID]; | 185 | return &slot_samplers[NULL_SAMPLER_ID]; |
| 187 | } | 186 | } |
| 188 | const auto [descriptor, is_new] = state->compute_sampler_table.Read(index); | 187 | const auto [descriptor, is_new] = channel_state->compute_sampler_table.Read(index); |
| 189 | SamplerId& id = state->compute_sampler_ids[index]; | 188 | SamplerId& id = channel_state->compute_sampler_ids[index]; |
| 190 | if (is_new) { | 189 | if (is_new) { |
| 191 | id = FindSampler(descriptor); | 190 | id = FindSampler(descriptor); |
| 192 | } | 191 | } |
| @@ -199,11 +198,12 @@ void TextureCache<P>::SynchronizeGraphicsDescriptors() { | |||
| 199 | const bool linked_tsc = maxwell3d->regs.sampler_index == SamplerIndex::ViaHeaderIndex; | 198 | const bool linked_tsc = maxwell3d->regs.sampler_index == SamplerIndex::ViaHeaderIndex; |
| 200 | const u32 tic_limit = maxwell3d->regs.tic.limit; | 199 | const u32 tic_limit = maxwell3d->regs.tic.limit; |
| 201 | const u32 tsc_limit = linked_tsc ? tic_limit : maxwell3d->regs.tsc.limit; | 200 | const u32 tsc_limit = linked_tsc ? tic_limit : maxwell3d->regs.tsc.limit; |
| 202 | if (state->graphics_sampler_table.Synchornize(maxwell3d->regs.tsc.Address(), tsc_limit)) { | 201 | if (channel_state->graphics_sampler_table.Synchornize(maxwell3d->regs.tsc.Address(), |
| 203 | state->graphics_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID); | 202 | tsc_limit)) { |
| 203 | channel_state->graphics_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID); | ||
| 204 | } | 204 | } |
| 205 | if (state->graphics_image_table.Synchornize(maxwell3d->regs.tic.Address(), tic_limit)) { | 205 | if (channel_state->graphics_image_table.Synchornize(maxwell3d->regs.tic.Address(), tic_limit)) { |
| 206 | state->graphics_image_view_ids.resize(tic_limit + 1, CORRUPT_ID); | 206 | channel_state->graphics_image_view_ids.resize(tic_limit + 1, CORRUPT_ID); |
| 207 | } | 207 | } |
| 208 | } | 208 | } |
| 209 | 209 | ||
| @@ -213,11 +213,12 @@ void TextureCache<P>::SynchronizeComputeDescriptors() { | |||
| 213 | const u32 tic_limit = kepler_compute->regs.tic.limit; | 213 | const u32 tic_limit = kepler_compute->regs.tic.limit; |
| 214 | const u32 tsc_limit = linked_tsc ? tic_limit : kepler_compute->regs.tsc.limit; | 214 | const u32 tsc_limit = linked_tsc ? tic_limit : kepler_compute->regs.tsc.limit; |
| 215 | const GPUVAddr tsc_gpu_addr = kepler_compute->regs.tsc.Address(); | 215 | const GPUVAddr tsc_gpu_addr = kepler_compute->regs.tsc.Address(); |
| 216 | if (state->compute_sampler_table.Synchornize(tsc_gpu_addr, tsc_limit)) { | 216 | if (channel_state->compute_sampler_table.Synchornize(tsc_gpu_addr, tsc_limit)) { |
| 217 | state->compute_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID); | 217 | channel_state->compute_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID); |
| 218 | } | 218 | } |
| 219 | if (state->compute_image_table.Synchornize(kepler_compute->regs.tic.Address(), tic_limit)) { | 219 | if (channel_state->compute_image_table.Synchornize(kepler_compute->regs.tic.Address(), |
| 220 | state->compute_image_view_ids.resize(tic_limit + 1, CORRUPT_ID); | 220 | tic_limit)) { |
| 221 | channel_state->compute_image_view_ids.resize(tic_limit + 1, CORRUPT_ID); | ||
| 221 | } | 222 | } |
| 222 | } | 223 | } |
| 223 | 224 | ||
| @@ -738,7 +739,7 @@ ImageViewId TextureCache<P>::FindImageView(const TICEntry& config) { | |||
| 738 | if (!IsValidEntry(*gpu_memory, config)) { | 739 | if (!IsValidEntry(*gpu_memory, config)) { |
| 739 | return NULL_IMAGE_VIEW_ID; | 740 | return NULL_IMAGE_VIEW_ID; |
| 740 | } | 741 | } |
| 741 | const auto [pair, is_new] = state->image_views.try_emplace(config); | 742 | const auto [pair, is_new] = channel_state->image_views.try_emplace(config); |
| 742 | ImageViewId& image_view_id = pair->second; | 743 | ImageViewId& image_view_id = pair->second; |
| 743 | if (is_new) { | 744 | if (is_new) { |
| 744 | image_view_id = CreateImageView(config); | 745 | image_view_id = CreateImageView(config); |
| @@ -1198,7 +1199,7 @@ SamplerId TextureCache<P>::FindSampler(const TSCEntry& config) { | |||
| 1198 | if (std::ranges::all_of(config.raw, [](u64 value) { return value == 0; })) { | 1199 | if (std::ranges::all_of(config.raw, [](u64 value) { return value == 0; })) { |
| 1199 | return NULL_SAMPLER_ID; | 1200 | return NULL_SAMPLER_ID; |
| 1200 | } | 1201 | } |
| 1201 | const auto [pair, is_new] = state->samplers.try_emplace(config); | 1202 | const auto [pair, is_new] = channel_state->samplers.try_emplace(config); |
| 1202 | if (is_new) { | 1203 | if (is_new) { |
| 1203 | pair->second = slot_samplers.insert(runtime, config); | 1204 | pair->second = slot_samplers.insert(runtime, config); |
| 1204 | } | 1205 | } |
| @@ -1327,8 +1328,8 @@ void TextureCache<P>::ForEachImageInRegionGPU(GPUVAddr gpu_addr, size_t size, Fu | |||
| 1327 | static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>; | 1328 | static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>; |
| 1328 | boost::container::small_vector<ImageId, 8> images; | 1329 | boost::container::small_vector<ImageId, 8> images; |
| 1329 | ForEachGPUPage(gpu_addr, size, [this, &images, gpu_addr, size, func](u64 page) { | 1330 | ForEachGPUPage(gpu_addr, size, [this, &images, gpu_addr, size, func](u64 page) { |
| 1330 | const auto it = state->gpu_page_table.find(page); | 1331 | const auto it = channel_state->gpu_page_table->find(page); |
| 1331 | if (it == state->gpu_page_table.end()) { | 1332 | if (it == channel_state->gpu_page_table->end()) { |
| 1332 | if constexpr (BOOL_BREAK) { | 1333 | if constexpr (BOOL_BREAK) { |
| 1333 | return false; | 1334 | return false; |
| 1334 | } else { | 1335 | } else { |
| @@ -1454,8 +1455,9 @@ void TextureCache<P>::RegisterImage(ImageId image_id) { | |||
| 1454 | } | 1455 | } |
| 1455 | image.lru_index = lru_cache.Insert(image_id, frame_tick); | 1456 | image.lru_index = lru_cache.Insert(image_id, frame_tick); |
| 1456 | 1457 | ||
| 1457 | ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, | 1458 | ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, image_id](u64 page) { |
| 1458 | [this, image_id](u64 page) { state->gpu_page_table[page].push_back(image_id); }); | 1459 | (*channel_state->gpu_page_table)[page].push_back(image_id); |
| 1460 | }); | ||
| 1459 | if (False(image.flags & ImageFlagBits::Sparse)) { | 1461 | if (False(image.flags & ImageFlagBits::Sparse)) { |
| 1460 | auto map_id = | 1462 | auto map_id = |
| 1461 | slot_map_views.insert(image.gpu_addr, image.cpu_addr, image.guest_size_bytes, image_id); | 1463 | slot_map_views.insert(image.gpu_addr, image.cpu_addr, image.guest_size_bytes, image_id); |
| @@ -1486,9 +1488,9 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) { | |||
| 1486 | image.flags &= ~ImageFlagBits::BadOverlap; | 1488 | image.flags &= ~ImageFlagBits::BadOverlap; |
| 1487 | lru_cache.Free(image.lru_index); | 1489 | lru_cache.Free(image.lru_index); |
| 1488 | const auto& clear_page_table = | 1490 | const auto& clear_page_table = |
| 1489 | [this, image_id]( | 1491 | [this, image_id](u64 page, |
| 1490 | u64 page, | 1492 | std::unordered_map<u64, std::vector<ImageId>, Common::IdentityHash<u64>>& |
| 1491 | std::unordered_map<u64, std::vector<ImageId>, IdentityHash<u64>>& selected_page_table) { | 1493 | selected_page_table) { |
| 1492 | const auto page_it = selected_page_table.find(page); | 1494 | const auto page_it = selected_page_table.find(page); |
| 1493 | if (page_it == selected_page_table.end()) { | 1495 | if (page_it == selected_page_table.end()) { |
| 1494 | ASSERT_MSG(false, "Unregistering unregistered page=0x{:x}", page << YUZU_PAGEBITS); | 1496 | ASSERT_MSG(false, "Unregistering unregistered page=0x{:x}", page << YUZU_PAGEBITS); |
| @@ -1504,7 +1506,7 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) { | |||
| 1504 | image_ids.erase(vector_it); | 1506 | image_ids.erase(vector_it); |
| 1505 | }; | 1507 | }; |
| 1506 | ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, &clear_page_table](u64 page) { | 1508 | ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, &clear_page_table](u64 page) { |
| 1507 | clear_page_table(page, state->gpu_page_table); | 1509 | clear_page_table(page, (*channel_state->gpu_page_table)); |
| 1508 | }); | 1510 | }); |
| 1509 | if (False(image.flags & ImageFlagBits::Sparse)) { | 1511 | if (False(image.flags & ImageFlagBits::Sparse)) { |
| 1510 | const auto map_id = image.map_view_id; | 1512 | const auto map_id = image.map_view_id; |
| @@ -1701,11 +1703,11 @@ void TextureCache<P>::DeleteImage(ImageId image_id, bool immediate_delete) { | |||
| 1701 | 1703 | ||
| 1702 | template <class P> | 1704 | template <class P> |
| 1703 | void TextureCache<P>::RemoveImageViewReferences(std::span<const ImageViewId> removed_views) { | 1705 | void TextureCache<P>::RemoveImageViewReferences(std::span<const ImageViewId> removed_views) { |
| 1704 | auto it = state->image_views.begin(); | 1706 | auto it = channel_state->image_views.begin(); |
| 1705 | while (it != state->image_views.end()) { | 1707 | while (it != channel_state->image_views.end()) { |
| 1706 | const auto found = std::ranges::find(removed_views, it->second); | 1708 | const auto found = std::ranges::find(removed_views, it->second); |
| 1707 | if (found != removed_views.end()) { | 1709 | if (found != removed_views.end()) { |
| 1708 | it = state->image_views.erase(it); | 1710 | it = channel_state->image_views.erase(it); |
| 1709 | } else { | 1711 | } else { |
| 1710 | ++it; | 1712 | ++it; |
| 1711 | } | 1713 | } |
| @@ -1968,60 +1970,18 @@ bool TextureCache<P>::IsFullClear(ImageViewId id) { | |||
| 1968 | } | 1970 | } |
| 1969 | 1971 | ||
| 1970 | template <class P> | 1972 | template <class P> |
| 1971 | TextureCache<P>::ChannelInfo::ChannelInfo(Tegra::Control::ChannelState& state) noexcept | ||
| 1972 | : maxwell3d{*state.maxwell_3d}, kepler_compute{*state.kepler_compute}, | ||
| 1973 | gpu_memory{*state.memory_manager}, graphics_image_table{gpu_memory}, | ||
| 1974 | graphics_sampler_table{gpu_memory}, compute_image_table{gpu_memory}, compute_sampler_table{ | ||
| 1975 | gpu_memory} {} | ||
| 1976 | |||
| 1977 | template <class P> | ||
| 1978 | void TextureCache<P>::CreateChannel(struct Tegra::Control::ChannelState& channel) { | 1973 | void TextureCache<P>::CreateChannel(struct Tegra::Control::ChannelState& channel) { |
| 1979 | ASSERT(channel_map.find(channel.bind_id) == channel_map.end() && channel.bind_id >= 0); | 1974 | VideoCommon::ChannelSetupCaches<TextureCacheChannelInfo>::CreateChannel(channel); |
| 1980 | auto new_id = [this, &channel]() { | 1975 | const auto it = channel_map.find(channel.bind_id); |
| 1981 | if (!free_channel_ids.empty()) { | 1976 | auto* this_state = &channel_storage[it->second]; |
| 1982 | auto id = free_channel_ids.front(); | 1977 | const auto& this_as_ref = address_spaces[channel.memory_manager->GetID()]; |
| 1983 | free_channel_ids.pop_front(); | 1978 | this_state->gpu_page_table = &gpu_page_table_storage[this_as_ref.storage_id]; |
| 1984 | new (&channel_storage[id]) ChannelInfo(channel); | ||
| 1985 | return id; | ||
| 1986 | } | ||
| 1987 | channel_storage.emplace_back(channel); | ||
| 1988 | return channel_storage.size() - 1; | ||
| 1989 | }(); | ||
| 1990 | channel_map.emplace(channel.bind_id, new_id); | ||
| 1991 | if (current_channel_id != UNSET_CHANNEL) { | ||
| 1992 | state = &channel_storage[current_channel_id]; | ||
| 1993 | } | ||
| 1994 | } | 1979 | } |
| 1995 | 1980 | ||
| 1996 | /// Bind a channel for execution. | 1981 | /// Bind a channel for execution. |
| 1997 | template <class P> | 1982 | template <class P> |
| 1998 | void TextureCache<P>::BindToChannel(s32 id) { | 1983 | void TextureCache<P>::OnGPUASRegister([[maybe_unused]] size_t map_id) { |
| 1999 | auto it = channel_map.find(id); | 1984 | gpu_page_table_storage.emplace_back(); |
| 2000 | ASSERT(it != channel_map.end() && id >= 0); | ||
| 2001 | current_channel_id = it->second; | ||
| 2002 | state = &channel_storage[current_channel_id]; | ||
| 2003 | maxwell3d = &state->maxwell3d; | ||
| 2004 | kepler_compute = &state->kepler_compute; | ||
| 2005 | gpu_memory = &state->gpu_memory; | ||
| 2006 | } | ||
| 2007 | |||
| 2008 | /// Erase channel's state. | ||
| 2009 | template <class P> | ||
| 2010 | void TextureCache<P>::EraseChannel(s32 id) { | ||
| 2011 | const auto it = channel_map.find(id); | ||
| 2012 | ASSERT(it != channel_map.end() && id >= 0); | ||
| 2013 | const auto this_id = it->second; | ||
| 2014 | free_channel_ids.push_back(this_id); | ||
| 2015 | channel_map.erase(it); | ||
| 2016 | if (this_id == current_channel_id) { | ||
| 2017 | current_channel_id = UNSET_CHANNEL; | ||
| 2018 | state = nullptr; | ||
| 2019 | maxwell3d = nullptr; | ||
| 2020 | kepler_compute = nullptr; | ||
| 2021 | gpu_memory = nullptr; | ||
| 2022 | } else if (current_channel_id != UNSET_CHANNEL) { | ||
| 2023 | state = &channel_storage[current_channel_id]; | ||
| 2024 | } | ||
| 2025 | } | 1985 | } |
| 2026 | 1986 | ||
| 2027 | } // namespace VideoCommon | 1987 | } // namespace VideoCommon |
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 69efcb718..b24968b03 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: 2021 yuzu emulator team |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // (https://github.com/skyline-emu/) |
| 3 | // SPDX-License-Identifier: GPL-3.0-or-later Licensed under GPLv3 | ||
| 4 | // or any later version Refer to the license.txt file included. | ||
| 3 | 5 | ||
| 4 | #pragma once | 6 | #pragma once |
| 5 | 7 | ||
| @@ -13,9 +15,11 @@ | |||
| 13 | #include <queue> | 15 | #include <queue> |
| 14 | 16 | ||
| 15 | #include "common/common_types.h" | 17 | #include "common/common_types.h" |
| 18 | #include "common/hash.h" | ||
| 16 | #include "common/literals.h" | 19 | #include "common/literals.h" |
| 17 | #include "common/lru_cache.h" | 20 | #include "common/lru_cache.h" |
| 18 | #include "video_core/compatible_formats.h" | 21 | #include "video_core/compatible_formats.h" |
| 22 | #include "video_core/control/channel_state_cache.h" | ||
| 19 | #include "video_core/delayed_destruction_ring.h" | 23 | #include "video_core/delayed_destruction_ring.h" |
| 20 | #include "video_core/engines/fermi_2d.h" | 24 | #include "video_core/engines/fermi_2d.h" |
| 21 | #include "video_core/surface.h" | 25 | #include "video_core/surface.h" |
| @@ -50,8 +54,35 @@ struct ImageViewInOut { | |||
| 50 | ImageViewId id{}; | 54 | ImageViewId id{}; |
| 51 | }; | 55 | }; |
| 52 | 56 | ||
| 57 | using TextureCacheGPUMap = std::unordered_map<u64, std::vector<ImageId>, Common::IdentityHash<u64>>; | ||
| 58 | |||
| 59 | class TextureCacheChannelInfo : public ChannelInfo { | ||
| 60 | public: | ||
| 61 | TextureCacheChannelInfo() = delete; | ||
| 62 | TextureCacheChannelInfo(Tegra::Control::ChannelState& state) noexcept; | ||
| 63 | TextureCacheChannelInfo(const TextureCacheChannelInfo& state) = delete; | ||
| 64 | TextureCacheChannelInfo& operator=(const TextureCacheChannelInfo&) = delete; | ||
| 65 | TextureCacheChannelInfo(TextureCacheChannelInfo&& other) noexcept = default; | ||
| 66 | TextureCacheChannelInfo& operator=(TextureCacheChannelInfo&& other) noexcept = default; | ||
| 67 | |||
| 68 | DescriptorTable<TICEntry> graphics_image_table{gpu_memory}; | ||
| 69 | DescriptorTable<TSCEntry> graphics_sampler_table{gpu_memory}; | ||
| 70 | std::vector<SamplerId> graphics_sampler_ids; | ||
| 71 | std::vector<ImageViewId> graphics_image_view_ids; | ||
| 72 | |||
| 73 | DescriptorTable<TICEntry> compute_image_table{gpu_memory}; | ||
| 74 | DescriptorTable<TSCEntry> compute_sampler_table{gpu_memory}; | ||
| 75 | std::vector<SamplerId> compute_sampler_ids; | ||
| 76 | std::vector<ImageViewId> compute_image_view_ids; | ||
| 77 | |||
| 78 | std::unordered_map<TICEntry, ImageViewId> image_views; | ||
| 79 | std::unordered_map<TSCEntry, SamplerId> samplers; | ||
| 80 | |||
| 81 | TextureCacheGPUMap* gpu_page_table; | ||
| 82 | }; | ||
| 83 | |||
| 53 | template <class P> | 84 | template <class P> |
| 54 | class TextureCache { | 85 | class TextureCache : public VideoCommon::ChannelSetupCaches<TextureCacheChannelInfo> { |
| 55 | /// Address shift for caching images into a hash table | 86 | /// Address shift for caching images into a hash table |
| 56 | static constexpr u64 YUZU_PAGEBITS = 20; | 87 | static constexpr u64 YUZU_PAGEBITS = 20; |
| 57 | 88 | ||
| @@ -85,13 +116,6 @@ class TextureCache { | |||
| 85 | PixelFormat src_format; | 116 | PixelFormat src_format; |
| 86 | }; | 117 | }; |
| 87 | 118 | ||
| 88 | template <typename T> | ||
| 89 | struct IdentityHash { | ||
| 90 | [[nodiscard]] size_t operator()(T value) const noexcept { | ||
| 91 | return static_cast<size_t>(value); | ||
| 92 | } | ||
| 93 | }; | ||
| 94 | |||
| 95 | public: | 119 | public: |
| 96 | explicit TextureCache(Runtime&, VideoCore::RasterizerInterface&); | 120 | explicit TextureCache(Runtime&, VideoCore::RasterizerInterface&); |
| 97 | 121 | ||
| @@ -179,13 +203,7 @@ public: | |||
| 179 | [[nodiscard]] bool IsRescaling(const ImageViewBase& image_view) const noexcept; | 203 | [[nodiscard]] bool IsRescaling(const ImageViewBase& image_view) const noexcept; |
| 180 | 204 | ||
| 181 | /// Create channel state. | 205 | /// Create channel state. |
| 182 | void CreateChannel(struct Tegra::Control::ChannelState& channel); | 206 | void CreateChannel(Tegra::Control::ChannelState& channel) final override; |
| 183 | |||
| 184 | /// Bind a channel for execution. | ||
| 185 | void BindToChannel(s32 id); | ||
| 186 | |||
| 187 | /// Erase channel's state. | ||
| 188 | void EraseChannel(s32 id); | ||
| 189 | 207 | ||
| 190 | std::mutex mutex; | 208 | std::mutex mutex; |
| 191 | 209 | ||
| @@ -221,6 +239,8 @@ private: | |||
| 221 | } | 239 | } |
| 222 | } | 240 | } |
| 223 | 241 | ||
| 242 | void OnGPUASRegister(size_t map_id) final override; | ||
| 243 | |||
| 224 | /// Runs the Garbage Collector. | 244 | /// Runs the Garbage Collector. |
| 225 | void RunGarbageCollector(); | 245 | void RunGarbageCollector(); |
| 226 | 246 | ||
| @@ -355,51 +375,15 @@ private: | |||
| 355 | 375 | ||
| 356 | Runtime& runtime; | 376 | Runtime& runtime; |
| 357 | 377 | ||
| 358 | struct ChannelInfo { | ||
| 359 | ChannelInfo() = delete; | ||
| 360 | ChannelInfo(struct Tegra::Control::ChannelState& state) noexcept; | ||
| 361 | ChannelInfo(const ChannelInfo& state) = delete; | ||
| 362 | ChannelInfo& operator=(const ChannelInfo&) = delete; | ||
| 363 | ChannelInfo(ChannelInfo&& other) noexcept = default; | ||
| 364 | ChannelInfo& operator=(ChannelInfo&& other) noexcept = default; | ||
| 365 | |||
| 366 | Tegra::Engines::Maxwell3D& maxwell3d; | ||
| 367 | Tegra::Engines::KeplerCompute& kepler_compute; | ||
| 368 | Tegra::MemoryManager& gpu_memory; | ||
| 369 | |||
| 370 | DescriptorTable<TICEntry> graphics_image_table{gpu_memory}; | ||
| 371 | DescriptorTable<TSCEntry> graphics_sampler_table{gpu_memory}; | ||
| 372 | std::vector<SamplerId> graphics_sampler_ids; | ||
| 373 | std::vector<ImageViewId> graphics_image_view_ids; | ||
| 374 | |||
| 375 | DescriptorTable<TICEntry> compute_image_table{gpu_memory}; | ||
| 376 | DescriptorTable<TSCEntry> compute_sampler_table{gpu_memory}; | ||
| 377 | std::vector<SamplerId> compute_sampler_ids; | ||
| 378 | std::vector<ImageViewId> compute_image_view_ids; | ||
| 379 | |||
| 380 | std::unordered_map<TICEntry, ImageViewId> image_views; | ||
| 381 | std::unordered_map<TSCEntry, SamplerId> samplers; | ||
| 382 | |||
| 383 | std::unordered_map<u64, std::vector<ImageId>, IdentityHash<u64>> gpu_page_table; | ||
| 384 | }; | ||
| 385 | |||
| 386 | std::deque<ChannelInfo> channel_storage; | ||
| 387 | std::deque<size_t> free_channel_ids; | ||
| 388 | std::unordered_map<s32, size_t> channel_map; | ||
| 389 | |||
| 390 | ChannelInfo* state; | ||
| 391 | size_t current_channel_id{UNSET_CHANNEL}; | ||
| 392 | VideoCore::RasterizerInterface& rasterizer; | 378 | VideoCore::RasterizerInterface& rasterizer; |
| 393 | Tegra::Engines::Maxwell3D* maxwell3d; | 379 | std::deque<TextureCacheGPUMap> gpu_page_table_storage; |
| 394 | Tegra::Engines::KeplerCompute* kepler_compute; | ||
| 395 | Tegra::MemoryManager* gpu_memory; | ||
| 396 | 380 | ||
| 397 | RenderTargets render_targets; | 381 | RenderTargets render_targets; |
| 398 | 382 | ||
| 399 | std::unordered_map<RenderTargets, FramebufferId> framebuffers; | 383 | std::unordered_map<RenderTargets, FramebufferId> framebuffers; |
| 400 | 384 | ||
| 401 | std::unordered_map<u64, std::vector<ImageMapId>, IdentityHash<u64>> page_table; | 385 | std::unordered_map<u64, std::vector<ImageMapId>, Common::IdentityHash<u64>> page_table; |
| 402 | std::unordered_map<u64, std::vector<ImageId>, IdentityHash<u64>> sparse_page_table; | 386 | std::unordered_map<u64, std::vector<ImageId>, Common::IdentityHash<u64>> sparse_page_table; |
| 403 | std::unordered_map<ImageId, std::vector<ImageViewId>> sparse_views; | 387 | std::unordered_map<ImageId, std::vector<ImageViewId>> sparse_views; |
| 404 | 388 | ||
| 405 | VAddr virtual_invalid_space{}; | 389 | VAddr virtual_invalid_space{}; |