summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2021-12-17 16:45:06 +0100
committerGravatar Fernando Sahmkow2022-10-06 21:00:52 +0200
commite462191482c6507daed67802c6c1d2c50f10c96e (patch)
treea6b4d851075d93b3052637d1382691e71b9b8c0e
parentGeneral: Rebase fixes. (diff)
downloadyuzu-e462191482c6507daed67802c6c1d2c50f10c96e.tar.gz
yuzu-e462191482c6507daed67802c6c1d2c50f10c96e.tar.xz
yuzu-e462191482c6507daed67802c6c1d2c50f10c96e.zip
Refactor VideoCore to use AS sepparate from Channel.
-rw-r--r--src/common/hash.h7
-rw-r--r--src/video_core/CMakeLists.txt1
-rw-r--r--src/video_core/control/channel_state_cache.cpp8
-rw-r--r--src/video_core/control/channel_state_cache.h28
-rw-r--r--src/video_core/control/channel_state_cache.inc23
-rw-r--r--src/video_core/memory_manager.cpp5
-rw-r--r--src/video_core/memory_manager.h9
-rw-r--r--src/video_core/texture_cache/texture_cache.cpp16
-rw-r--r--src/video_core/texture_cache/texture_cache.h130
-rw-r--r--src/video_core/texture_cache/texture_cache_base.h96
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
21template <typename T>
22struct 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
3namespace VideoCommon { 3namespace VideoCommon {
4
5ChannelInfo::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
4template class VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo>; 9template 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>
41class ChannelSetupCaches { 42class ChannelSetupCaches {
42public: 43public:
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
54protected: 62protected:
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
7namespace VideoCommon { 7namespace VideoCommon {
8 8
9ChannelInfo::ChannelInfo(Tegra::Control::ChannelState& channel_state) 9template <class P>
10 : maxwell3d{*channel_state.maxwell_3d}, kepler_compute{*channel_state.kepler_compute}, 10ChannelSetupCaches<P>::~ChannelSetupCaches() = default;
11 gpu_memory{*channel_state.memory_manager} {}
12 11
13template <class P> 12template <class P>
14void ChannelSetupCaches<P>::CreateChannel(struct Tegra::Control::ChannelState& channel) { 13void 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.
33template <class P> 45template <class P>
34void ChannelSetupCaches<P>::BindToChannel(s32 id) { 46void 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.
45template <class P> 59template <class P>
46void ChannelSetupCaches<P>::EraseChannel(s32 id) { 60void 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
17namespace Tegra { 17namespace Tegra {
18 18
19std::atomic<size_t> MemoryManager::unique_identifier_generator{};
20
19MemoryManager::MemoryManager(Core::System& system_, u64 address_space_bits_, u64 page_bits_) 21MemoryManager::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
8namespace VideoCommon {
9
10TextureCacheChannelInfo::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
14template 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 {
156template <class P> 154template <class P>
157template <bool has_blacklists> 155template <bool has_blacklists>
158void TextureCache<P>::FillGraphicsImageViews(std::span<ImageViewInOut> views) { 156void 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
163template <class P> 161template <class P>
164void TextureCache<P>::FillComputeImageViews(std::span<ImageViewInOut> views) { 162void 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
168template <class P> 167template <class P>
169typename P::Sampler* TextureCache<P>::GetGraphicsSampler(u32 index) { 168typename 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
182template <class P> 181template <class P>
183typename P::Sampler* TextureCache<P>::GetComputeSampler(u32 index) { 182typename 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
1702template <class P> 1704template <class P>
1703void TextureCache<P>::RemoveImageViewReferences(std::span<const ImageViewId> removed_views) { 1705void 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
1970template <class P> 1972template <class P>
1971TextureCache<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
1977template <class P>
1978void TextureCache<P>::CreateChannel(struct Tegra::Control::ChannelState& channel) { 1973void 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.
1997template <class P> 1982template <class P>
1998void TextureCache<P>::BindToChannel(s32 id) { 1983void 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.
2009template <class P>
2010void 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
57using TextureCacheGPUMap = std::unordered_map<u64, std::vector<ImageId>, Common::IdentityHash<u64>>;
58
59class TextureCacheChannelInfo : public ChannelInfo {
60public:
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
53template <class P> 84template <class P>
54class TextureCache { 85class 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
95public: 119public:
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{};