summaryrefslogtreecommitdiffstats
path: root/src/video_core/texture_cache
diff options
context:
space:
mode:
authorFernando Sahmkow <fsahmkow27@gmail.com>2021-12-17 16:45:06 +0100
committerFernando Sahmkow <fsahmkow27@gmail.com>2022-10-06 21:00:52 +0200
commite462191482c6507daed67802c6c1d2c50f10c96e (patch)
treea6b4d851075d93b3052637d1382691e71b9b8c0e /src/video_core/texture_cache
parentGeneral: Rebase fixes. (diff)
downloadyuzu-e462191482c6507daed67802c6c1d2c50f10c96e.tar
yuzu-e462191482c6507daed67802c6c1d2c50f10c96e.tar.gz
yuzu-e462191482c6507daed67802c6c1d2c50f10c96e.tar.bz2
yuzu-e462191482c6507daed67802c6c1d2c50f10c96e.tar.lz
yuzu-e462191482c6507daed67802c6c1d2c50f10c96e.tar.xz
yuzu-e462191482c6507daed67802c6c1d2c50f10c96e.tar.zst
yuzu-e462191482c6507daed67802c6c1d2c50f10c96e.zip
Diffstat (limited to 'src/video_core/texture_cache')
-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
3 files changed, 101 insertions, 141 deletions
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 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv3 or any later version
+// Refer to the license.txt file included.
+
+#include "video_core/control/channel_state_cache.inc"
+#include "video_core/texture_cache/texture_cache_base.h"
+
+namespace VideoCommon {
+
+TextureCacheChannelInfo::TextureCacheChannelInfo(Tegra::Control::ChannelState& state) noexcept
+ : ChannelInfo(state), graphics_image_table{gpu_memory}, graphics_sampler_table{gpu_memory},
+ compute_image_table{gpu_memory}, compute_sampler_table{gpu_memory} {}
+
+template class VideoCommon::ChannelSetupCaches<VideoCommon::TextureCacheChannelInfo>;
+
+} // 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 @@
-// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2021 yuzu emulator team
+// (https://github.com/skyline-emu/)
+// SPDX-License-Identifier: GPL-3.0-or-later Licensed under GPLv3
+// or any later version Refer to the license.txt file included.
#pragma once
@@ -41,10 +43,6 @@ TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface&
// Setup channels
current_channel_id = UNSET_CHANNEL;
- state = nullptr;
- maxwell3d = nullptr;
- kepler_compute = nullptr;
- gpu_memory = nullptr;
// Make sure the first index is reserved for the null resources
// This way the null resource becomes a compile time constant
@@ -156,23 +154,24 @@ void TextureCache<P>::MarkModification(ImageId id) noexcept {
template <class P>
template <bool has_blacklists>
void TextureCache<P>::FillGraphicsImageViews(std::span<ImageViewInOut> views) {
- FillImageViews<has_blacklists>(state->graphics_image_table, state->graphics_image_view_ids,
- views);
+ FillImageViews<has_blacklists>(channel_state->graphics_image_table,
+ channel_state->graphics_image_view_ids, views);
}
template <class P>
void TextureCache<P>::FillComputeImageViews(std::span<ImageViewInOut> views) {
- FillImageViews<true>(state->compute_image_table, state->compute_image_view_ids, views);
+ FillImageViews<true>(channel_state->compute_image_table, channel_state->compute_image_view_ids,
+ views);
}
template <class P>
typename P::Sampler* TextureCache<P>::GetGraphicsSampler(u32 index) {
- if (index > state->graphics_sampler_table.Limit()) {
+ if (index > channel_state->graphics_sampler_table.Limit()) {
LOG_DEBUG(HW_GPU, "Invalid sampler index={}", index);
return &slot_samplers[NULL_SAMPLER_ID];
}
- const auto [descriptor, is_new] = state->graphics_sampler_table.Read(index);
- SamplerId& id = state->graphics_sampler_ids[index];
+ const auto [descriptor, is_new] = channel_state->graphics_sampler_table.Read(index);
+ SamplerId& id = channel_state->graphics_sampler_ids[index];
if (is_new) {
id = FindSampler(descriptor);
}
@@ -181,12 +180,12 @@ typename P::Sampler* TextureCache<P>::GetGraphicsSampler(u32 index) {
template <class P>
typename P::Sampler* TextureCache<P>::GetComputeSampler(u32 index) {
- if (index > state->compute_sampler_table.Limit()) {
+ if (index > channel_state->compute_sampler_table.Limit()) {
LOG_DEBUG(HW_GPU, "Invalid sampler index={}", index);
return &slot_samplers[NULL_SAMPLER_ID];
}
- const auto [descriptor, is_new] = state->compute_sampler_table.Read(index);
- SamplerId& id = state->compute_sampler_ids[index];
+ const auto [descriptor, is_new] = channel_state->compute_sampler_table.Read(index);
+ SamplerId& id = channel_state->compute_sampler_ids[index];
if (is_new) {
id = FindSampler(descriptor);
}
@@ -199,11 +198,12 @@ void TextureCache<P>::SynchronizeGraphicsDescriptors() {
const bool linked_tsc = maxwell3d->regs.sampler_index == SamplerIndex::ViaHeaderIndex;
const u32 tic_limit = maxwell3d->regs.tic.limit;
const u32 tsc_limit = linked_tsc ? tic_limit : maxwell3d->regs.tsc.limit;
- if (state->graphics_sampler_table.Synchornize(maxwell3d->regs.tsc.Address(), tsc_limit)) {
- state->graphics_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID);
+ if (channel_state->graphics_sampler_table.Synchornize(maxwell3d->regs.tsc.Address(),
+ tsc_limit)) {
+ channel_state->graphics_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID);
}
- if (state->graphics_image_table.Synchornize(maxwell3d->regs.tic.Address(), tic_limit)) {
- state->graphics_image_view_ids.resize(tic_limit + 1, CORRUPT_ID);
+ if (channel_state->graphics_image_table.Synchornize(maxwell3d->regs.tic.Address(), tic_limit)) {
+ channel_state->graphics_image_view_ids.resize(tic_limit + 1, CORRUPT_ID);
}
}
@@ -213,11 +213,12 @@ void TextureCache<P>::SynchronizeComputeDescriptors() {
const u32 tic_limit = kepler_compute->regs.tic.limit;
const u32 tsc_limit = linked_tsc ? tic_limit : kepler_compute->regs.tsc.limit;
const GPUVAddr tsc_gpu_addr = kepler_compute->regs.tsc.Address();
- if (state->compute_sampler_table.Synchornize(tsc_gpu_addr, tsc_limit)) {
- state->compute_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID);
+ if (channel_state->compute_sampler_table.Synchornize(tsc_gpu_addr, tsc_limit)) {
+ channel_state->compute_sampler_ids.resize(tsc_limit + 1, CORRUPT_ID);
}
- if (state->compute_image_table.Synchornize(kepler_compute->regs.tic.Address(), tic_limit)) {
- state->compute_image_view_ids.resize(tic_limit + 1, CORRUPT_ID);
+ if (channel_state->compute_image_table.Synchornize(kepler_compute->regs.tic.Address(),
+ tic_limit)) {
+ channel_state->compute_image_view_ids.resize(tic_limit + 1, CORRUPT_ID);
}
}
@@ -738,7 +739,7 @@ ImageViewId TextureCache<P>::FindImageView(const TICEntry& config) {
if (!IsValidEntry(*gpu_memory, config)) {
return NULL_IMAGE_VIEW_ID;
}
- const auto [pair, is_new] = state->image_views.try_emplace(config);
+ const auto [pair, is_new] = channel_state->image_views.try_emplace(config);
ImageViewId& image_view_id = pair->second;
if (is_new) {
image_view_id = CreateImageView(config);
@@ -1198,7 +1199,7 @@ SamplerId TextureCache<P>::FindSampler(const TSCEntry& config) {
if (std::ranges::all_of(config.raw, [](u64 value) { return value == 0; })) {
return NULL_SAMPLER_ID;
}
- const auto [pair, is_new] = state->samplers.try_emplace(config);
+ const auto [pair, is_new] = channel_state->samplers.try_emplace(config);
if (is_new) {
pair->second = slot_samplers.insert(runtime, config);
}
@@ -1327,8 +1328,8 @@ void TextureCache<P>::ForEachImageInRegionGPU(GPUVAddr gpu_addr, size_t size, Fu
static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>;
boost::container::small_vector<ImageId, 8> images;
ForEachGPUPage(gpu_addr, size, [this, &images, gpu_addr, size, func](u64 page) {
- const auto it = state->gpu_page_table.find(page);
- if (it == state->gpu_page_table.end()) {
+ const auto it = channel_state->gpu_page_table->find(page);
+ if (it == channel_state->gpu_page_table->end()) {
if constexpr (BOOL_BREAK) {
return false;
} else {
@@ -1454,8 +1455,9 @@ void TextureCache<P>::RegisterImage(ImageId image_id) {
}
image.lru_index = lru_cache.Insert(image_id, frame_tick);
- ForEachGPUPage(image.gpu_addr, image.guest_size_bytes,
- [this, image_id](u64 page) { state->gpu_page_table[page].push_back(image_id); });
+ ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, image_id](u64 page) {
+ (*channel_state->gpu_page_table)[page].push_back(image_id);
+ });
if (False(image.flags & ImageFlagBits::Sparse)) {
auto map_id =
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) {
image.flags &= ~ImageFlagBits::BadOverlap;
lru_cache.Free(image.lru_index);
const auto& clear_page_table =
- [this, image_id](
- u64 page,
- std::unordered_map<u64, std::vector<ImageId>, IdentityHash<u64>>& selected_page_table) {
+ [this, image_id](u64 page,
+ std::unordered_map<u64, std::vector<ImageId>, Common::IdentityHash<u64>>&
+ selected_page_table) {
const auto page_it = selected_page_table.find(page);
if (page_it == selected_page_table.end()) {
ASSERT_MSG(false, "Unregistering unregistered page=0x{:x}", page << YUZU_PAGEBITS);
@@ -1504,7 +1506,7 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) {
image_ids.erase(vector_it);
};
ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, &clear_page_table](u64 page) {
- clear_page_table(page, state->gpu_page_table);
+ clear_page_table(page, (*channel_state->gpu_page_table));
});
if (False(image.flags & ImageFlagBits::Sparse)) {
const auto map_id = image.map_view_id;
@@ -1701,11 +1703,11 @@ void TextureCache<P>::DeleteImage(ImageId image_id, bool immediate_delete) {
template <class P>
void TextureCache<P>::RemoveImageViewReferences(std::span<const ImageViewId> removed_views) {
- auto it = state->image_views.begin();
- while (it != state->image_views.end()) {
+ auto it = channel_state->image_views.begin();
+ while (it != channel_state->image_views.end()) {
const auto found = std::ranges::find(removed_views, it->second);
if (found != removed_views.end()) {
- it = state->image_views.erase(it);
+ it = channel_state->image_views.erase(it);
} else {
++it;
}
@@ -1968,60 +1970,18 @@ bool TextureCache<P>::IsFullClear(ImageViewId id) {
}
template <class P>
-TextureCache<P>::ChannelInfo::ChannelInfo(Tegra::Control::ChannelState& state) noexcept
- : maxwell3d{*state.maxwell_3d}, kepler_compute{*state.kepler_compute},
- gpu_memory{*state.memory_manager}, graphics_image_table{gpu_memory},
- graphics_sampler_table{gpu_memory}, compute_image_table{gpu_memory}, compute_sampler_table{
- gpu_memory} {}
-
-template <class P>
void TextureCache<P>::CreateChannel(struct Tegra::Control::ChannelState& channel) {
- ASSERT(channel_map.find(channel.bind_id) == channel_map.end() && channel.bind_id >= 0);
- auto new_id = [this, &channel]() {
- if (!free_channel_ids.empty()) {
- auto id = free_channel_ids.front();
- free_channel_ids.pop_front();
- new (&channel_storage[id]) ChannelInfo(channel);
- return id;
- }
- channel_storage.emplace_back(channel);
- return channel_storage.size() - 1;
- }();
- channel_map.emplace(channel.bind_id, new_id);
- if (current_channel_id != UNSET_CHANNEL) {
- state = &channel_storage[current_channel_id];
- }
+ VideoCommon::ChannelSetupCaches<TextureCacheChannelInfo>::CreateChannel(channel);
+ const auto it = channel_map.find(channel.bind_id);
+ auto* this_state = &channel_storage[it->second];
+ const auto& this_as_ref = address_spaces[channel.memory_manager->GetID()];
+ this_state->gpu_page_table = &gpu_page_table_storage[this_as_ref.storage_id];
}
/// Bind a channel for execution.
template <class P>
-void TextureCache<P>::BindToChannel(s32 id) {
- auto it = channel_map.find(id);
- ASSERT(it != channel_map.end() && id >= 0);
- current_channel_id = it->second;
- state = &channel_storage[current_channel_id];
- maxwell3d = &state->maxwell3d;
- kepler_compute = &state->kepler_compute;
- gpu_memory = &state->gpu_memory;
-}
-
-/// Erase channel's state.
-template <class P>
-void TextureCache<P>::EraseChannel(s32 id) {
- const auto it = channel_map.find(id);
- ASSERT(it != channel_map.end() && id >= 0);
- const auto this_id = it->second;
- free_channel_ids.push_back(this_id);
- channel_map.erase(it);
- if (this_id == current_channel_id) {
- current_channel_id = UNSET_CHANNEL;
- state = nullptr;
- maxwell3d = nullptr;
- kepler_compute = nullptr;
- gpu_memory = nullptr;
- } else if (current_channel_id != UNSET_CHANNEL) {
- state = &channel_storage[current_channel_id];
- }
+void TextureCache<P>::OnGPUASRegister([[maybe_unused]] size_t map_id) {
+ gpu_page_table_storage.emplace_back();
}
} // 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 @@
-// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2021 yuzu emulator team
+// (https://github.com/skyline-emu/)
+// SPDX-License-Identifier: GPL-3.0-or-later Licensed under GPLv3
+// or any later version Refer to the license.txt file included.
#pragma once
@@ -13,9 +15,11 @@
#include <queue>
#include "common/common_types.h"
+#include "common/hash.h"
#include "common/literals.h"
#include "common/lru_cache.h"
#include "video_core/compatible_formats.h"
+#include "video_core/control/channel_state_cache.h"
#include "video_core/delayed_destruction_ring.h"
#include "video_core/engines/fermi_2d.h"
#include "video_core/surface.h"
@@ -50,8 +54,35 @@ struct ImageViewInOut {
ImageViewId id{};
};
+using TextureCacheGPUMap = std::unordered_map<u64, std::vector<ImageId>, Common::IdentityHash<u64>>;
+
+class TextureCacheChannelInfo : public ChannelInfo {
+public:
+ TextureCacheChannelInfo() = delete;
+ TextureCacheChannelInfo(Tegra::Control::ChannelState& state) noexcept;
+ TextureCacheChannelInfo(const TextureCacheChannelInfo& state) = delete;
+ TextureCacheChannelInfo& operator=(const TextureCacheChannelInfo&) = delete;
+ TextureCacheChannelInfo(TextureCacheChannelInfo&& other) noexcept = default;
+ TextureCacheChannelInfo& operator=(TextureCacheChannelInfo&& other) noexcept = default;
+
+ DescriptorTable<TICEntry> graphics_image_table{gpu_memory};
+ DescriptorTable<TSCEntry> graphics_sampler_table{gpu_memory};
+ std::vector<SamplerId> graphics_sampler_ids;
+ std::vector<ImageViewId> graphics_image_view_ids;
+
+ DescriptorTable<TICEntry> compute_image_table{gpu_memory};
+ DescriptorTable<TSCEntry> compute_sampler_table{gpu_memory};
+ std::vector<SamplerId> compute_sampler_ids;
+ std::vector<ImageViewId> compute_image_view_ids;
+
+ std::unordered_map<TICEntry, ImageViewId> image_views;
+ std::unordered_map<TSCEntry, SamplerId> samplers;
+
+ TextureCacheGPUMap* gpu_page_table;
+};
+
template <class P>
-class TextureCache {
+class TextureCache : public VideoCommon::ChannelSetupCaches<TextureCacheChannelInfo> {
/// Address shift for caching images into a hash table
static constexpr u64 YUZU_PAGEBITS = 20;
@@ -85,13 +116,6 @@ class TextureCache {
PixelFormat src_format;
};
- template <typename T>
- struct IdentityHash {
- [[nodiscard]] size_t operator()(T value) const noexcept {
- return static_cast<size_t>(value);
- }
- };
-
public:
explicit TextureCache(Runtime&, VideoCore::RasterizerInterface&);
@@ -179,13 +203,7 @@ public:
[[nodiscard]] bool IsRescaling(const ImageViewBase& image_view) const noexcept;
/// Create channel state.
- void CreateChannel(struct Tegra::Control::ChannelState& channel);
-
- /// Bind a channel for execution.
- void BindToChannel(s32 id);
-
- /// Erase channel's state.
- void EraseChannel(s32 id);
+ void CreateChannel(Tegra::Control::ChannelState& channel) final override;
std::mutex mutex;
@@ -221,6 +239,8 @@ private:
}
}
+ void OnGPUASRegister(size_t map_id) final override;
+
/// Runs the Garbage Collector.
void RunGarbageCollector();
@@ -355,51 +375,15 @@ private:
Runtime& runtime;
- struct ChannelInfo {
- ChannelInfo() = delete;
- ChannelInfo(struct Tegra::Control::ChannelState& state) noexcept;
- ChannelInfo(const ChannelInfo& state) = delete;
- ChannelInfo& operator=(const ChannelInfo&) = delete;
- ChannelInfo(ChannelInfo&& other) noexcept = default;
- ChannelInfo& operator=(ChannelInfo&& other) noexcept = default;
-
- Tegra::Engines::Maxwell3D& maxwell3d;
- Tegra::Engines::KeplerCompute& kepler_compute;
- Tegra::MemoryManager& gpu_memory;
-
- DescriptorTable<TICEntry> graphics_image_table{gpu_memory};
- DescriptorTable<TSCEntry> graphics_sampler_table{gpu_memory};
- std::vector<SamplerId> graphics_sampler_ids;
- std::vector<ImageViewId> graphics_image_view_ids;
-
- DescriptorTable<TICEntry> compute_image_table{gpu_memory};
- DescriptorTable<TSCEntry> compute_sampler_table{gpu_memory};
- std::vector<SamplerId> compute_sampler_ids;
- std::vector<ImageViewId> compute_image_view_ids;
-
- std::unordered_map<TICEntry, ImageViewId> image_views;
- std::unordered_map<TSCEntry, SamplerId> samplers;
-
- std::unordered_map<u64, std::vector<ImageId>, IdentityHash<u64>> gpu_page_table;
- };
-
- std::deque<ChannelInfo> channel_storage;
- std::deque<size_t> free_channel_ids;
- std::unordered_map<s32, size_t> channel_map;
-
- ChannelInfo* state;
- size_t current_channel_id{UNSET_CHANNEL};
VideoCore::RasterizerInterface& rasterizer;
- Tegra::Engines::Maxwell3D* maxwell3d;
- Tegra::Engines::KeplerCompute* kepler_compute;
- Tegra::MemoryManager* gpu_memory;
+ std::deque<TextureCacheGPUMap> gpu_page_table_storage;
RenderTargets render_targets;
std::unordered_map<RenderTargets, FramebufferId> framebuffers;
- std::unordered_map<u64, std::vector<ImageMapId>, IdentityHash<u64>> page_table;
- std::unordered_map<u64, std::vector<ImageId>, IdentityHash<u64>> sparse_page_table;
+ std::unordered_map<u64, std::vector<ImageMapId>, Common::IdentityHash<u64>> page_table;
+ std::unordered_map<u64, std::vector<ImageId>, Common::IdentityHash<u64>> sparse_page_table;
std::unordered_map<ImageId, std::vector<ImageViewId>> sparse_views;
VAddr virtual_invalid_space{};