Просмотр исходного кода

Texture cache: Fix dangling references on multichannel.

Fernando Sahmkow 4 лет назад
Родитель
Сommit
9cf4c8831d

+ 1 - 0
src/video_core/control/channel_state_cache.h

@@ -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;

+ 11 - 6
src/video_core/control/channel_state_cache.inc

@@ -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,15 +30,16 @@ 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++;
-      return;
+        as_it->second.ref_count++;
+        return;
     }
     AddresSpaceRef new_gpu_mem_ref{
-      .ref_count = 1,
-      .storage_id = address_spaces.size(),
-      .gpu_memory = channel.memory_manager.get(),
+        .ref_count = 1,
+        .storage_id = address_spaces.size(),
+        .gpu_memory = channel.memory_manager.get(),
     };
     address_spaces.emplace(channel.memory_manager->GetID(), new_gpu_mem_ref);
     OnGPUASRegister(channel.memory_manager->GetID());
@@ -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

+ 24 - 21
src/video_core/texture_cache/texture_cache.h

@@ -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];
-    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);
+    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();
     }
-    channel_info.graphics_image_table.Invalidate();
-    channel_info.compute_image_table.Invalidate();
     has_deleted_images = true;
 }
 
@@ -1690,26 +1689,30 @@ 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()) {
-        const auto found = std::ranges::find(removed_views, it->second);
-        if (found != removed_views.end()) {
-            it = channel_state->image_views.erase(it);
-        } else {
-            ++it;
+    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_info.image_views.erase(it);
+            } else {
+                ++it;
+            }
         }
     }
 }