Texture cache: Fix dangling references on multichannel.
This commit is contained in:
		| @@ -72,6 +72,7 @@ protected: | ||||
|     std::deque<P> channel_storage; | ||||
|     std::deque<size_t> free_channel_ids; | ||||
|     std::unordered_map<s32, size_t> channel_map; | ||||
|     std::vector<size_t> active_channel_ids; | ||||
|     struct AddresSpaceRef { | ||||
|         size_t ref_count; | ||||
|         size_t storage_id; | ||||
|   | ||||
| @@ -1,3 +1,6 @@ | ||||
|  | ||||
| #include <algorithm> | ||||
|  | ||||
| #include "video_core/control/channel_state.h" | ||||
| #include "video_core/control/channel_state_cache.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) { | ||||
|         channel_state = &channel_storage[current_channel_id]; | ||||
|     } | ||||
|     active_channel_ids.push_back(new_id); | ||||
|     auto as_it = address_spaces.find(channel.memory_manager->GetID()); | ||||
|     if (as_it != address_spaces.end()) { | ||||
|         as_it->second.ref_count++; | ||||
| @@ -73,7 +77,8 @@ void ChannelSetupCaches<P>::EraseChannel(s32 id) { | ||||
|     } else if (current_channel_id != UNSET_CHANNEL) { | ||||
|         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 | ||||
|   | ||||
| @@ -41,9 +41,6 @@ TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface& | ||||
|     sampler_descriptor.mipmap_filter.Assign(Tegra::Texture::TextureMipmapFilter::Linear); | ||||
|     sampler_descriptor.cubemap_anisotropy.Assign(1); | ||||
|  | ||||
|     // Setup channels | ||||
|     current_channel_id = UNSET_CHANNEL; | ||||
|  | ||||
|     // Make sure the first index is reserved for the null resources | ||||
|     // This way the null resource becomes a compile time constant | ||||
|     void(slot_images.insert(NullImageParams{})); | ||||
| @@ -886,13 +883,15 @@ void TextureCache<P>::InvalidateScale(Image& image) { | ||||
|     } | ||||
|     image.image_view_ids.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) { | ||||
|             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(); | ||||
|     } | ||||
|     has_deleted_images = true; | ||||
| } | ||||
|  | ||||
| @@ -1690,28 +1689,32 @@ void TextureCache<P>::DeleteImage(ImageId image_id, bool immediate_delete) { | ||||
|     if (alloc_images.empty()) { | ||||
|         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) { | ||||
|             std::ranges::fill(this_state.graphics_image_view_ids, CORRUPT_ID); | ||||
|             std::ranges::fill(this_state.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); | ||||
|         } | ||||
|         this_state.graphics_image_table.Invalidate(); | ||||
|         this_state.compute_image_table.Invalidate(); | ||||
|         channel_info.graphics_image_table.Invalidate(); | ||||
|         channel_info.compute_image_table.Invalidate(); | ||||
|     } | ||||
|     has_deleted_images = true; | ||||
| } | ||||
|  | ||||
| template <class P> | ||||
| void TextureCache<P>::RemoveImageViewReferences(std::span<const ImageViewId> removed_views) { | ||||
|     auto it = channel_state->image_views.begin(); | ||||
|     while (it != channel_state->image_views.end()) { | ||||
|     for (size_t c : active_channel_ids) { | ||||
|         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); | ||||
|             if (found != removed_views.end()) { | ||||
|             it = channel_state->image_views.erase(it); | ||||
|                 it = channel_info.image_views.erase(it); | ||||
|             } else { | ||||
|                 ++it; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| template <class P> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user