From 3f8e7a55851a613becf715cbf3016a8e9f63d65f Mon Sep 17 00:00:00 2001
From: Fernando Sahmkow <fsahmkow27@gmail.com>
Date: Sun, 7 Nov 2021 17:52:45 +0100
Subject: [PATCH] VideoCore: Fix channels with disk pipeline/shader cache.

---
 .../renderer_opengl/gl_compute_pipeline.cpp   | 19 ++++++-------
 .../renderer_opengl/gl_compute_pipeline.h     | 16 +++++++----
 .../renderer_opengl/gl_graphics_pipeline.cpp  | 28 +++++++++----------
 .../renderer_opengl/gl_graphics_pipeline.h    | 16 +++++++----
 .../renderer_opengl/gl_rasterizer.cpp         |  1 +
 .../renderer_opengl/gl_shader_cache.cpp       | 11 ++++----
 .../renderer_vulkan/vk_graphics_pipeline.cpp  | 17 ++++++-----
 .../renderer_vulkan/vk_graphics_pipeline.h    | 28 +++++++++++--------
 .../renderer_vulkan/vk_pipeline_cache.cpp     |  8 +++---
 .../renderer_vulkan/vk_rasterizer.cpp         |  2 ++
 src/video_core/texture_cache/texture_cache.h  | 12 ++++----
 11 files changed, 87 insertions(+), 71 deletions(-)

diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp
index 1f0f156ed..26b51f442 100644
--- a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp
+++ b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp
@@ -28,12 +28,11 @@ bool ComputePipelineKey::operator==(const ComputePipelineKey& rhs) const noexcep
 }
 
 ComputePipeline::ComputePipeline(const Device& device, TextureCache& texture_cache_,
-                                 BufferCache& buffer_cache_, Tegra::MemoryManager& gpu_memory_,
-                                 Tegra::Engines::KeplerCompute& kepler_compute_,
-                                 ProgramManager& program_manager_, const Shader::Info& info_,
-                                 std::string code, std::vector<u32> code_v)
-    : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, gpu_memory{gpu_memory_},
-      kepler_compute{kepler_compute_}, program_manager{program_manager_}, info{info_} {
+                                 BufferCache& buffer_cache_, ProgramManager& program_manager_,
+                                 const Shader::Info& info_, std::string code,
+                                 std::vector<u32> code_v)
+    : texture_cache{texture_cache_}, buffer_cache{buffer_cache_},
+      program_manager{program_manager_}, info{info_} {
     switch (device.GetShaderBackend()) {
     case Settings::ShaderBackend::GLSL:
         source_program = CreateProgram(code, GL_COMPUTE_SHADER);
@@ -86,7 +85,7 @@ void ComputePipeline::Configure() {
     GLsizei texture_binding{};
     GLsizei image_binding{};
 
-    const auto& qmd{kepler_compute.launch_description};
+    const auto& qmd{kepler_compute->launch_description};
     const auto& cbufs{qmd.const_buffer_config};
     const bool via_header_index{qmd.linked_tsc != 0};
     const auto read_handle{[&](const auto& desc, u32 index) {
@@ -101,12 +100,12 @@ void ComputePipeline::Configure() {
                 const u32 secondary_offset{desc.secondary_cbuf_offset + index_offset};
                 const GPUVAddr separate_addr{cbufs[desc.secondary_cbuf_index].Address() +
                                              secondary_offset};
-                const u32 lhs_raw{gpu_memory.Read<u32>(addr)};
-                const u32 rhs_raw{gpu_memory.Read<u32>(separate_addr)};
+                const u32 lhs_raw{gpu_memory->Read<u32>(addr)};
+                const u32 rhs_raw{gpu_memory->Read<u32>(separate_addr)};
                 return TexturePair(lhs_raw | rhs_raw, via_header_index);
             }
         }
-        return TexturePair(gpu_memory.Read<u32>(addr), via_header_index);
+        return TexturePair(gpu_memory->Read<u32>(addr), via_header_index);
     }};
     const auto add_image{[&](const auto& desc, bool blacklist) {
         for (u32 index = 0; index < desc.count; ++index) {
diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.h b/src/video_core/renderer_opengl/gl_compute_pipeline.h
index 723f27f11..6534dec32 100644
--- a/src/video_core/renderer_opengl/gl_compute_pipeline.h
+++ b/src/video_core/renderer_opengl/gl_compute_pipeline.h
@@ -49,10 +49,8 @@ static_assert(std::is_trivially_constructible_v<ComputePipelineKey>);
 class ComputePipeline {
 public:
     explicit ComputePipeline(const Device& device, TextureCache& texture_cache_,
-                             BufferCache& buffer_cache_, Tegra::MemoryManager& gpu_memory_,
-                             Tegra::Engines::KeplerCompute& kepler_compute_,
-                             ProgramManager& program_manager_, const Shader::Info& info_,
-                             std::string code, std::vector<u32> code_v);
+                             BufferCache& buffer_cache_, ProgramManager& program_manager_,
+                             const Shader::Info& info_, std::string code, std::vector<u32> code_v);
 
     void Configure();
 
@@ -60,11 +58,17 @@ public:
         return writes_global_memory;
     }
 
+    void SetEngine(Tegra::Engines::KeplerCompute* kepler_compute_,
+                   Tegra::MemoryManager* gpu_memory_) {
+        kepler_compute = kepler_compute_;
+        gpu_memory = gpu_memory_;
+    }
+
 private:
     TextureCache& texture_cache;
     BufferCache& buffer_cache;
-    Tegra::MemoryManager& gpu_memory;
-    Tegra::Engines::KeplerCompute& kepler_compute;
+    Tegra::MemoryManager* gpu_memory;
+    Tegra::Engines::KeplerCompute* kepler_compute;
     ProgramManager& program_manager;
 
     Shader::Info info;
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
index 67eae369d..c877d7792 100644
--- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
+++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp
@@ -169,15 +169,15 @@ ConfigureFuncPtr ConfigureFunc(const std::array<Shader::Info, 5>& infos, u32 ena
 }
 } // Anonymous namespace
 
-GraphicsPipeline::GraphicsPipeline(
-    const Device& device, TextureCache& texture_cache_, BufferCache& buffer_cache_,
-    Tegra::MemoryManager& gpu_memory_, Tegra::Engines::Maxwell3D& maxwell3d_,
-    ProgramManager& program_manager_, StateTracker& state_tracker_, ShaderWorker* thread_worker,
-    VideoCore::ShaderNotify* shader_notify, std::array<std::string, 5> sources,
-    std::array<std::vector<u32>, 5> sources_spirv, const std::array<const Shader::Info*, 5>& infos,
-    const GraphicsPipelineKey& key_)
-    : texture_cache{texture_cache_}, buffer_cache{buffer_cache_},
-      gpu_memory{gpu_memory_}, maxwell3d{maxwell3d_}, program_manager{program_manager_},
+GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_cache_,
+                                   BufferCache& buffer_cache_, ProgramManager& program_manager_,
+                                   StateTracker& state_tracker_, ShaderWorker* thread_worker,
+                                   VideoCore::ShaderNotify* shader_notify,
+                                   std::array<std::string, 5> sources,
+                                   std::array<std::vector<u32>, 5> sources_spirv,
+                                   const std::array<const Shader::Info*, 5>& infos,
+                                   const GraphicsPipelineKey& key_)
+    : texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, program_manager{program_manager_},
       state_tracker{state_tracker_}, key{key_} {
     if (shader_notify) {
         shader_notify->MarkShaderBuilding();
@@ -285,7 +285,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
     buffer_cache.runtime.SetBaseStorageBindings(base_storage_bindings);
     buffer_cache.runtime.SetEnableStorageBuffers(use_storage_buffers);
 
-    const auto& regs{maxwell3d.regs};
+    const auto& regs{maxwell3d->regs};
     const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex};
     const auto config_stage{[&](size_t stage) LAMBDA_FORCEINLINE {
         const Shader::Info& info{stage_infos[stage]};
@@ -299,7 +299,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
                 ++ssbo_index;
             }
         }
-        const auto& cbufs{maxwell3d.state.shader_stages[stage].const_buffers};
+        const auto& cbufs{maxwell3d->state.shader_stages[stage].const_buffers};
         const auto read_handle{[&](const auto& desc, u32 index) {
             ASSERT(cbufs[desc.cbuf_index].enabled);
             const u32 index_offset{index << desc.size_shift};
@@ -312,13 +312,13 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
                     const u32 second_offset{desc.secondary_cbuf_offset + index_offset};
                     const GPUVAddr separate_addr{cbufs[desc.secondary_cbuf_index].address +
                                                  second_offset};
-                    const u32 lhs_raw{gpu_memory.Read<u32>(addr)};
-                    const u32 rhs_raw{gpu_memory.Read<u32>(separate_addr)};
+                    const u32 lhs_raw{gpu_memory->Read<u32>(addr)};
+                    const u32 rhs_raw{gpu_memory->Read<u32>(separate_addr)};
                     const u32 raw{lhs_raw | rhs_raw};
                     return TexturePair(raw, via_header_index);
                 }
             }
-            return TexturePair(gpu_memory.Read<u32>(addr), via_header_index);
+            return TexturePair(gpu_memory->Read<u32>(addr), via_header_index);
         }};
         const auto add_image{[&](const auto& desc, bool blacklist) LAMBDA_FORCEINLINE {
             for (u32 index = 0; index < desc.count; ++index) {
diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.h b/src/video_core/renderer_opengl/gl_graphics_pipeline.h
index 4ec15b966..a0f0e63cb 100644
--- a/src/video_core/renderer_opengl/gl_graphics_pipeline.h
+++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.h
@@ -71,10 +71,9 @@ static_assert(std::is_trivially_constructible_v<GraphicsPipelineKey>);
 class GraphicsPipeline {
 public:
     explicit GraphicsPipeline(const Device& device, TextureCache& texture_cache_,
-                              BufferCache& buffer_cache_, Tegra::MemoryManager& gpu_memory_,
-                              Tegra::Engines::Maxwell3D& maxwell3d_,
-                              ProgramManager& program_manager_, StateTracker& state_tracker_,
-                              ShaderWorker* thread_worker, VideoCore::ShaderNotify* shader_notify,
+                              BufferCache& buffer_cache_, ProgramManager& program_manager_,
+                              StateTracker& state_tracker_, ShaderWorker* thread_worker,
+                              VideoCore::ShaderNotify* shader_notify,
                               std::array<std::string, 5> sources,
                               std::array<std::vector<u32>, 5> sources_spirv,
                               const std::array<const Shader::Info*, 5>& infos,
@@ -107,6 +106,11 @@ public:
         };
     }
 
+    void SetEngine(Tegra::Engines::Maxwell3D* maxwell3d_, Tegra::MemoryManager* gpu_memory_) {
+        maxwell3d = maxwell3d_;
+        gpu_memory = gpu_memory_;
+    }
+
 private:
     template <typename Spec>
     void ConfigureImpl(bool is_indexed);
@@ -119,8 +123,8 @@ private:
 
     TextureCache& texture_cache;
     BufferCache& buffer_cache;
-    Tegra::MemoryManager& gpu_memory;
-    Tegra::Engines::Maxwell3D& maxwell3d;
+    Tegra::MemoryManager* gpu_memory;
+    Tegra::Engines::Maxwell3D* maxwell3d;
     ProgramManager& program_manager;
     StateTracker& state_tracker;
     const GraphicsPipelineKey key;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 8cfa0013f..4eb9bd116 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -216,6 +216,7 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
         return;
     }
     std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
+    pipeline->SetEngine(maxwell3d, gpu_memory);
     pipeline->Configure(is_indexed);
 
     SyncState();
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 494581d0d..5a29a41d2 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -477,9 +477,9 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline(
         previous_program = &program;
     }
     auto* const thread_worker{build_in_parallel ? workers.get() : nullptr};
-    return std::make_unique<GraphicsPipeline>(
-        device, texture_cache, buffer_cache, *gpu_memory, *maxwell3d, program_manager,
-        state_tracker, thread_worker, &shader_notify, sources, sources_spirv, infos, key);
+    return std::make_unique<GraphicsPipeline>(device, texture_cache, buffer_cache, program_manager,
+                                              state_tracker, thread_worker, &shader_notify, sources,
+                                              sources_spirv, infos, key);
 
 } catch (Shader::Exception& exception) {
     LOG_ERROR(Render_OpenGL, "{}", exception.what());
@@ -533,9 +533,8 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline(
         break;
     }
 
-    return std::make_unique<ComputePipeline>(device, texture_cache, buffer_cache, *gpu_memory,
-                                             *kepler_compute, program_manager, program.info, code,
-                                             code_spirv);
+    return std::make_unique<ComputePipeline>(device, texture_cache, buffer_cache, program_manager,
+                                             program.info, code, code_spirv);
 } catch (Shader::Exception& exception) {
     LOG_ERROR(Render_OpenGL, "{}", exception.what());
     return nullptr;
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index 5aca8f038..1e993185f 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -215,15 +215,14 @@ ConfigureFuncPtr ConfigureFunc(const std::array<vk::ShaderModule, NUM_STAGES>& m
 } // Anonymous namespace
 
 GraphicsPipeline::GraphicsPipeline(
-    Tegra::Engines::Maxwell3D& maxwell3d_, Tegra::MemoryManager& gpu_memory_, Scheduler& scheduler_,
-    BufferCache& buffer_cache_, TextureCache& texture_cache_,
+    Scheduler& scheduler_, BufferCache& buffer_cache_, TextureCache& texture_cache_,
     VideoCore::ShaderNotify* shader_notify, const Device& device_, DescriptorPool& descriptor_pool,
     UpdateDescriptorQueue& update_descriptor_queue_, Common::ThreadWorker* worker_thread,
     PipelineStatistics* pipeline_statistics, RenderPassCache& render_pass_cache,
     const GraphicsPipelineCacheKey& key_, std::array<vk::ShaderModule, NUM_STAGES> stages,
     const std::array<const Shader::Info*, NUM_STAGES>& infos)
-    : key{key_}, maxwell3d{maxwell3d_}, gpu_memory{gpu_memory_}, device{device_},
-      texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, scheduler{scheduler_},
+    : key{key_}, device{device_}, texture_cache{texture_cache_},
+      buffer_cache{buffer_cache_}, scheduler{scheduler_},
       update_descriptor_queue{update_descriptor_queue_}, spv_modules{std::move(stages)} {
     if (shader_notify) {
         shader_notify->MarkShaderBuilding();
@@ -288,7 +287,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
 
     buffer_cache.SetUniformBuffersState(enabled_uniform_buffer_masks, &uniform_buffer_sizes);
 
-    const auto& regs{maxwell3d.regs};
+    const auto& regs{maxwell3d->regs};
     const bool via_header_index{regs.sampler_index == Maxwell::SamplerIndex::ViaHeaderIndex};
     const auto config_stage{[&](size_t stage) LAMBDA_FORCEINLINE {
         const Shader::Info& info{stage_infos[stage]};
@@ -302,7 +301,7 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
                 ++ssbo_index;
             }
         }
-        const auto& cbufs{maxwell3d.state.shader_stages[stage].const_buffers};
+        const auto& cbufs{maxwell3d->state.shader_stages[stage].const_buffers};
         const auto read_handle{[&](const auto& desc, u32 index) {
             ASSERT(cbufs[desc.cbuf_index].enabled);
             const u32 index_offset{index << desc.size_shift};
@@ -315,13 +314,13 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
                     const u32 second_offset{desc.secondary_cbuf_offset + index_offset};
                     const GPUVAddr separate_addr{cbufs[desc.secondary_cbuf_index].address +
                                                  second_offset};
-                    const u32 lhs_raw{gpu_memory.Read<u32>(addr)};
-                    const u32 rhs_raw{gpu_memory.Read<u32>(separate_addr)};
+                    const u32 lhs_raw{gpu_memory->Read<u32>(addr)};
+                    const u32 rhs_raw{gpu_memory->Read<u32>(separate_addr)};
                     const u32 raw{lhs_raw | rhs_raw};
                     return TexturePair(raw, via_header_index);
                 }
             }
-            return TexturePair(gpu_memory.Read<u32>(addr), via_header_index);
+            return TexturePair(gpu_memory->Read<u32>(addr), via_header_index);
         }};
         const auto add_image{[&](const auto& desc, bool blacklist) LAMBDA_FORCEINLINE {
             for (u32 index = 0; index < desc.count; ++index) {
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
index e8949a9ab..85602592b 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h
@@ -69,15 +69,16 @@ class GraphicsPipeline {
     static constexpr size_t NUM_STAGES = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage;
 
 public:
-    explicit GraphicsPipeline(
-        Tegra::Engines::Maxwell3D& maxwell3d, Tegra::MemoryManager& gpu_memory,
-        Scheduler& scheduler, BufferCache& buffer_cache, TextureCache& texture_cache,
-        VideoCore::ShaderNotify* shader_notify, const Device& device,
-        DescriptorPool& descriptor_pool, UpdateDescriptorQueue& update_descriptor_queue,
-        Common::ThreadWorker* worker_thread, PipelineStatistics* pipeline_statistics,
-        RenderPassCache& render_pass_cache, const GraphicsPipelineCacheKey& key,
-        std::array<vk::ShaderModule, NUM_STAGES> stages,
-        const std::array<const Shader::Info*, NUM_STAGES>& infos);
+    explicit GraphicsPipeline(Scheduler& scheduler, BufferCache& buffer_cache,
+                              TextureCache& texture_cache, VideoCore::ShaderNotify* shader_notify,
+                              const Device& device, DescriptorPool& descriptor_pool,
+                              UpdateDescriptorQueue& update_descriptor_queue,
+                              Common::ThreadWorker* worker_thread,
+                              PipelineStatistics* pipeline_statistics,
+                              RenderPassCache& render_pass_cache,
+                              const GraphicsPipelineCacheKey& key,
+                              std::array<vk::ShaderModule, NUM_STAGES> stages,
+                              const std::array<const Shader::Info*, NUM_STAGES>& infos);
 
     GraphicsPipeline& operator=(GraphicsPipeline&&) noexcept = delete;
     GraphicsPipeline(GraphicsPipeline&&) noexcept = delete;
@@ -109,6 +110,11 @@ public:
         return [](GraphicsPipeline* pl, bool is_indexed) { pl->ConfigureImpl<Spec>(is_indexed); };
     }
 
+    void SetEngine(Tegra::Engines::Maxwell3D* maxwell3d_, Tegra::MemoryManager* gpu_memory_) {
+        maxwell3d = maxwell3d_;
+        gpu_memory = gpu_memory_;
+    }
+
 private:
     template <typename Spec>
     void ConfigureImpl(bool is_indexed);
@@ -120,8 +126,8 @@ private:
     void Validate();
 
     const GraphicsPipelineCacheKey key;
-    Tegra::Engines::Maxwell3D& maxwell3d;
-    Tegra::MemoryManager& gpu_memory;
+    Tegra::Engines::Maxwell3D* maxwell3d;
+    Tegra::MemoryManager* gpu_memory;
     const Device& device;
     TextureCache& texture_cache;
     BufferCache& buffer_cache;
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index b1e0b96c4..732e7b6f2 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -555,10 +555,10 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline(
         previous_stage = &program;
     }
     Common::ThreadWorker* const thread_worker{build_in_parallel ? &workers : nullptr};
-    return std::make_unique<GraphicsPipeline>(
-        *maxwell3d, *gpu_memory, scheduler, buffer_cache, texture_cache, &shader_notify, device,
-        descriptor_pool, update_descriptor_queue, thread_worker, statistics, render_pass_cache, key,
-        std::move(modules), infos);
+    return std::make_unique<GraphicsPipeline>(scheduler, buffer_cache, texture_cache,
+                                              &shader_notify, device, descriptor_pool,
+                                              update_descriptor_queue, thread_worker, statistics,
+                                              render_pass_cache, key, std::move(modules), infos);
 
 } catch (const Shader::Exception& exception) {
     LOG_ERROR(Render_Vulkan, "{}", exception.what());
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index bf750452f..7e0805544 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -190,6 +190,8 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) {
         return;
     }
     std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
+    // update engine as channel may be different.
+    pipeline->SetEngine(maxwell3d, gpu_memory);
     pipeline->Configure(is_indexed);
 
     BeginTransformFeedback();
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 2731aead0..e8b0b0a3b 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -885,12 +885,14 @@ void TextureCache<P>::InvalidateScale(Image& image) {
     }
     image.image_view_ids.clear();
     image.image_view_infos.clear();
-    if constexpr (ENABLE_VALIDATION) {
-        std::ranges::fill(state->graphics_image_view_ids, CORRUPT_ID);
-        std::ranges::fill(state->compute_image_view_ids, CORRUPT_ID);
+    for (auto& this_state : channel_storage) {
+        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);
+        }
+        this_state.graphics_image_table.Invalidate();
+        this_state.compute_image_table.Invalidate();
     }
-    state->graphics_image_table.Invalidate();
-    state->compute_image_table.Invalidate();
     has_deleted_images = true;
 }