Texture cache: Fix dangling references on multichannel.
This commit is contained in:
parent
e462191482
commit
9cf4c8831d
|
@ -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;
|
||||||
|
|
|
@ -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,6 +30,7 @@ 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++;
|
||||||
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
auto& channel_info = channel_storage[c];
|
||||||
if constexpr (ENABLE_VALIDATION) {
|
if constexpr (ENABLE_VALIDATION) {
|
||||||
std::ranges::fill(channel_info.graphics_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);
|
std::ranges::fill(channel_info.compute_image_view_ids, CORRUPT_ID);
|
||||||
}
|
}
|
||||||
channel_info.graphics_image_table.Invalidate();
|
channel_info.graphics_image_table.Invalidate();
|
||||||
channel_info.compute_image_table.Invalidate();
|
channel_info.compute_image_table.Invalidate();
|
||||||
|
}
|
||||||
has_deleted_images = true;
|
has_deleted_images = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1690,29 +1689,33 @@ 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];
|
||||||
|
auto it = channel_info.image_views.begin();
|
||||||
|
while (it != channel_info.image_views.end()) {
|
||||||
const auto found = std::ranges::find(removed_views, it->second);
|
const auto found = std::ranges::find(removed_views, it->second);
|
||||||
if (found != removed_views.end()) {
|
if (found != removed_views.end()) {
|
||||||
it = channel_state->image_views.erase(it);
|
it = channel_info.image_views.erase(it);
|
||||||
} else {
|
} else {
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <class P>
|
template <class P>
|
||||||
void TextureCache<P>::RemoveFramebuffers(std::span<const ImageViewId> removed_views) {
|
void TextureCache<P>::RemoveFramebuffers(std::span<const ImageViewId> removed_views) {
|
||||||
|
|
Reference in New Issue