Texture cache: Fix dangling references on multichannel.

This commit is contained in:
Fernando Sahmkow 2021-12-23 01:40:45 +01:00
parent e462191482
commit 9cf4c8831d
3 changed files with 36 additions and 27 deletions

View File

@ -72,6 +72,7 @@ protected:
std::deque<P> channel_storage; std::deque<P> channel_storage;
std::deque<size_t> free_channel_ids; std::deque<size_t> free_channel_ids;
std::unordered_map<s32, size_t> channel_map; std::unordered_map<s32, size_t> channel_map;
std::vector<size_t> active_channel_ids;
struct AddresSpaceRef { struct AddresSpaceRef {
size_t ref_count; size_t ref_count;
size_t storage_id; size_t storage_id;

View File

@ -1,3 +1,6 @@
#include <algorithm>
#include "video_core/control/channel_state.h" #include "video_core/control/channel_state.h"
#include "video_core/control/channel_state_cache.h" #include "video_core/control/channel_state_cache.h"
#include "video_core/engines/kepler_compute.h" #include "video_core/engines/kepler_compute.h"
@ -27,15 +30,16 @@ void ChannelSetupCaches<P>::CreateChannel(struct Tegra::Control::ChannelState& c
if (current_channel_id != UNSET_CHANNEL) { if (current_channel_id != UNSET_CHANNEL) {
channel_state = &channel_storage[current_channel_id]; channel_state = &channel_storage[current_channel_id];
} }
active_channel_ids.push_back(new_id);
auto as_it = address_spaces.find(channel.memory_manager->GetID()); auto as_it = address_spaces.find(channel.memory_manager->GetID());
if (as_it != address_spaces.end()) { if (as_it != address_spaces.end()) {
as_it->second.ref_count++; as_it->second.ref_count++;
return; return;
} }
AddresSpaceRef new_gpu_mem_ref{ AddresSpaceRef new_gpu_mem_ref{
.ref_count = 1, .ref_count = 1,
.storage_id = address_spaces.size(), .storage_id = address_spaces.size(),
.gpu_memory = channel.memory_manager.get(), .gpu_memory = channel.memory_manager.get(),
}; };
address_spaces.emplace(channel.memory_manager->GetID(), new_gpu_mem_ref); address_spaces.emplace(channel.memory_manager->GetID(), new_gpu_mem_ref);
OnGPUASRegister(channel.memory_manager->GetID()); OnGPUASRegister(channel.memory_manager->GetID());
@ -73,7 +77,8 @@ void ChannelSetupCaches<P>::EraseChannel(s32 id) {
} else if (current_channel_id != UNSET_CHANNEL) { } else if (current_channel_id != UNSET_CHANNEL) {
channel_state = &channel_storage[current_channel_id]; channel_state = &channel_storage[current_channel_id];
} }
active_channel_ids.erase(
std::find(active_channel_ids.begin(), active_channel_ids.end(), this_id));
} }
} // namespace VideoCommon } // namespace VideoCommon

View File

@ -41,9 +41,6 @@ TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface&
sampler_descriptor.mipmap_filter.Assign(Tegra::Texture::TextureMipmapFilter::Linear); sampler_descriptor.mipmap_filter.Assign(Tegra::Texture::TextureMipmapFilter::Linear);
sampler_descriptor.cubemap_anisotropy.Assign(1); sampler_descriptor.cubemap_anisotropy.Assign(1);
// Setup channels
current_channel_id = UNSET_CHANNEL;
// Make sure the first index is reserved for the null resources // Make sure the first index is reserved for the null resources
// This way the null resource becomes a compile time constant // This way the null resource becomes a compile time constant
void(slot_images.insert(NullImageParams{})); void(slot_images.insert(NullImageParams{}));
@ -886,13 +883,15 @@ void TextureCache<P>::InvalidateScale(Image& image) {
} }
image.image_view_ids.clear(); image.image_view_ids.clear();
image.image_view_infos.clear(); image.image_view_infos.clear();
auto& channel_info = channel_storage[image.channel]; for (size_t c : active_channel_ids) {
if constexpr (ENABLE_VALIDATION) { auto& channel_info = channel_storage[c];
std::ranges::fill(channel_info.graphics_image_view_ids, CORRUPT_ID); if constexpr (ENABLE_VALIDATION) {
std::ranges::fill(channel_info.compute_image_view_ids, CORRUPT_ID); std::ranges::fill(channel_info.graphics_image_view_ids, CORRUPT_ID);
std::ranges::fill(channel_info.compute_image_view_ids, CORRUPT_ID);
}
channel_info.graphics_image_table.Invalidate();
channel_info.compute_image_table.Invalidate();
} }
channel_info.graphics_image_table.Invalidate();
channel_info.compute_image_table.Invalidate();
has_deleted_images = true; has_deleted_images = true;
} }
@ -1690,26 +1689,30 @@ void TextureCache<P>::DeleteImage(ImageId image_id, bool immediate_delete) {
if (alloc_images.empty()) { if (alloc_images.empty()) {
image_allocs_table.erase(alloc_it); image_allocs_table.erase(alloc_it);
} }
for (auto& this_state : channel_storage) { for (size_t c : active_channel_ids) {
auto& channel_info = channel_storage[c];
if constexpr (ENABLE_VALIDATION) { if constexpr (ENABLE_VALIDATION) {
std::ranges::fill(this_state.graphics_image_view_ids, CORRUPT_ID); std::ranges::fill(channel_info.graphics_image_view_ids, CORRUPT_ID);
std::ranges::fill(this_state.compute_image_view_ids, CORRUPT_ID); std::ranges::fill(channel_info.compute_image_view_ids, CORRUPT_ID);
} }
this_state.graphics_image_table.Invalidate(); channel_info.graphics_image_table.Invalidate();
this_state.compute_image_table.Invalidate(); channel_info.compute_image_table.Invalidate();
} }
has_deleted_images = true; has_deleted_images = true;
} }
template <class P> template <class P>
void TextureCache<P>::RemoveImageViewReferences(std::span<const ImageViewId> removed_views) { void TextureCache<P>::RemoveImageViewReferences(std::span<const ImageViewId> removed_views) {
auto it = channel_state->image_views.begin(); for (size_t c : active_channel_ids) {
while (it != channel_state->image_views.end()) { auto& channel_info = channel_storage[c];
const auto found = std::ranges::find(removed_views, it->second); auto it = channel_info.image_views.begin();
if (found != removed_views.end()) { while (it != channel_info.image_views.end()) {
it = channel_state->image_views.erase(it); const auto found = std::ranges::find(removed_views, it->second);
} else { if (found != removed_views.end()) {
++it; it = channel_info.image_views.erase(it);
} else {
++it;
}
} }
} }
} }