Texture cache: Fix dangling references on multichannel.
This commit is contained in:
		| @@ -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,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 | ||||||
|   | |||||||
| @@ -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; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user