diff --git a/src/graphics/host_gpu/renderer/cache/bufferCache.h b/src/graphics/host_gpu/renderer/cache/bufferCache.h index ba2d1a7a3..24de1825c 100644 --- a/src/graphics/host_gpu/renderer/cache/bufferCache.h +++ b/src/graphics/host_gpu/renderer/cache/bufferCache.h @@ -95,10 +95,7 @@ public: private: friend struct BufferCacheTestAccess; - bool IsBufferInvalid(BufferId id) const { - const auto* buffer = m_slot_buffers.try_get(id); - return buffer == nullptr || buffer->is_deleted; - } + bool IsBufferInvalid(BufferId id) const { return !id || m_slot_buffers[id].is_deleted; } using BufferMap = std::map; struct OverlapResult { diff --git a/src/graphics/host_gpu/renderer/cache/textureCache.cpp b/src/graphics/host_gpu/renderer/cache/textureCache.cpp index c33179dd6..ece2c7c0f 100644 --- a/src/graphics/host_gpu/renderer/cache/textureCache.cpp +++ b/src/graphics/host_gpu/renderer/cache/textureCache.cpp @@ -251,24 +251,24 @@ void TextureCache::UnregisterImage(ImageId id) { } void TextureCache::DeleteImage(ImageId id) { - auto* image = m_slot_images.try_get(id); - if (image == nullptr || !image->registered) { + auto& image = m_slot_images[id]; + if (!image.registered) { return; } - if (image->depth_id) { - std::erase(m_slot_images[image->depth_id].stencil_ids, id); + if (image.depth_id) { + std::erase(m_slot_images[image.depth_id].stencil_ids, id); } else { // Detach first: deleting each association also unlinks it from its depth owner. - for (const auto association: std::exchange(image->stencil_ids, {})) { + for (const auto association: std::exchange(image.stencil_ids, {})) { FreeImage(association); } } - if (image->IsGpuModified()) { + if (image.IsGpuModified()) { EXIT("TextureCache: deleting a GPU-modified image without resolving its contents\n"); } m_download_images.erase(id); - if (image->info.metadata.kind == ImageMetadataKind::Htile) { - m_surface_metas.erase(image->info.metadata.range.address); + if (image.info.metadata.kind == ImageMetadataKind::Htile) { + m_surface_metas.erase(image.info.metadata.range.address); } UnregisterImage(id); if (m_scheduler.Active()) { @@ -779,15 +779,14 @@ void Resolve(TextureCache& cache, ImageId cached_id, ImageId merged_id) { TextureCache::OverlapResult TextureCache::ResolveOverlap(const ImageInfo& requested, BindingType binding, ImageId cached_id, ImageId merged_id) { - auto owner = m_slot_images.try_get(cached_id); - if (owner == nullptr || !owner->registered) { + auto& cached = m_slot_images[cached_id]; + if (!cached.registered) { return {merged_id}; } - if (BcAlias::Matches(requested, owner->info) && !owner->IsCpuDirty()) { + if (BcAlias::Matches(requested, cached.info) && !cached.IsCpuDirty()) { BcAlias::Resolve(*this, cached_id, merged_id); return {merged_id}; } - auto& cached = *owner; const auto current_tick = m_scheduler.CurrentTick(); const bool safe_to_delete = current_tick - std::min(current_tick, cached.tick_accessed_last) > NumFramesBeforeRemoval && @@ -861,9 +860,8 @@ TextureCache::OverlapResult TextureCache::ResolveOverlap(const ImageInfo& reques if (requested.pixel_format != cached.info.pixel_format || requested.data.size <= cached.info.data.size) { const auto result_id = merged_id ? merged_id : cached_id; - const auto result = m_slot_images.try_get(result_id); - return {result != nullptr && ImageViewOps::FormatsCompatible(result->info.pixel_format, - requested.pixel_format) + return {ImageViewOps::FormatsCompatible(m_slot_images[result_id].info.pixel_format, + requested.pixel_format) ? result_id : ImageId {}}; } @@ -1210,9 +1208,8 @@ ImageId TextureCache::AssociateStencil(ImageId depth_id, GuestRange stencil) { ImageId association {}; for (const auto id: FindImagesInRegion(stencil.address, stencil.size, false)) { - const auto owner = m_slot_images.try_get(id); - if (owner != nullptr && owner->info.data == stencil && - owner->info.extent == depth.info.extent) { + const auto& owner = m_slot_images[id]; + if (owner.info.data == stencil && owner.info.extent == depth.info.extent) { association = id; } } @@ -1307,10 +1304,9 @@ ImageId TextureCache::FindImage(ImageDesc& desc, bool exact_format) { } } else if (block_alias) { for (const auto candidate: candidates) { - const auto* owner = m_slot_images.try_get(candidate); - if (candidate != result && owner != nullptr && owner->registered && - !owner->IsCpuDirty() && - BcAlias::Matches(m_slot_images[result].info, owner->info)) { + const auto& owner = m_slot_images[candidate]; + if (candidate != result && owner.registered && !owner.IsCpuDirty() && + BcAlias::Matches(m_slot_images[result].info, owner.info)) { BcAlias::Resolve(*this, candidate, result); } } @@ -1373,14 +1369,14 @@ ImageId TextureCache::FindImageFromRange(uint64_t address, uint64_t size, bool e std::scoped_lock lock {m_lock}; ImageIds matches; for (const auto id: FindImagesInRegion(address, size, false)) { - auto owner = m_slot_images.try_get(id); - if (owner == nullptr || owner->info.data.address != address) { + const auto* owner = &m_slot_images[id]; + if (owner->info.data.address != address) { continue; } if (ensure_valid && owner->depth_id) { - owner = m_slot_images.try_get(owner->depth_id); + owner = &m_slot_images[owner->depth_id]; } - if (owner == nullptr || (ensure_valid && !owner->SafeToDownload())) { + if (ensure_valid && !owner->SafeToDownload()) { continue; } matches.push_back(id); @@ -1397,11 +1393,8 @@ ImageId TextureCache::FindImageFromRange(uint64_t address, uint64_t size, bool e } } } - if (selected && ensure_valid) { - const auto owner = m_slot_images.try_get(selected); - if (owner != nullptr && owner->depth_id) { - selected = owner->depth_id; - } + if (selected && ensure_valid && m_slot_images[selected].depth_id) { + selected = m_slot_images[selected].depth_id; } return selected; } @@ -1422,9 +1415,8 @@ vk::ImageView TextureCache::FindTexture(ImageId id, const ImageDesc& desc) { desc.info.data.End() <= image.info.stencil.End()) { for (const auto stencil_id: FindImagesInRegion(image.info.stencil.address, image.info.stencil.size, false)) { - const auto* stencil = m_slot_images.try_get(stencil_id); - if (stencil != nullptr && stencil->depth_id == id && - stencil->info.data == image.info.stencil) { + const auto& stencil = m_slot_images[stencil_id]; + if (stencil.depth_id == id && stencil.info.data == image.info.stencil) { RefreshImage(stencil_id); break; } @@ -1535,27 +1527,24 @@ bool TextureCache::ClearImageFromBuffer(CommandBuffer& command, uint64_t address vk::ImageAspectFlags aspect {}; ImageSubresourceRange subresources; for (const auto id: FindImagesInRegion(address, size, false)) { - auto owner = m_slot_images.try_get(id); - if (owner == nullptr) { - continue; - } + const auto& owner = m_slot_images[id]; vk::ImageAspectFlags candidate {}; ImageId candidate_id = id; ImageSubresourceRange candidate_subresources { - 0, owner->info.resources.levels, 0, owner->info.TransferLayers()}; - if (owner->depth_id && owner->info.data.address == address && - owner->info.data.size == size) { + 0, owner.info.resources.levels, 0, owner.info.TransferLayers()}; + if (owner.depth_id && owner.info.data.address == address && + owner.info.data.size == size) { candidate = vk::ImageAspectFlagBits::eStencil; - candidate_id = owner->depth_id; - candidate_subresources = owner->stencil_subresources; - owner = m_slot_images.try_get(candidate_id); - if (owner == nullptr || owner->backing.image == nullptr || !owner->info.HasStencil()) { + candidate_id = owner.depth_id; + candidate_subresources = owner.stencil_subresources; + const auto& depth = m_slot_images[candidate_id]; + if (depth.backing.image == nullptr || !depth.info.HasStencil()) { continue; } - } else if (!owner->depth_id && owner->info.data.address == address && - owner->info.data.size == size) { - candidate = owner->info.IsDepth() ? vk::ImageAspectFlagBits::eDepth - : vk::ImageAspectFlagBits::eColor; + } else if (!owner.depth_id && owner.info.data.address == address && + owner.info.data.size == size) { + candidate = owner.info.IsDepth() ? vk::ImageAspectFlagBits::eDepth + : vk::ImageAspectFlagBits::eColor; } if (!candidate) { continue; @@ -1896,23 +1885,20 @@ void TextureCache::InvalidateCpuAliases(uint64_t address, uint64_t size) { const auto page_begin = Common::AlignDown(address, TRACKER_PAGE_SIZE); const auto page_end = Common::AlignUp(address + size, TRACKER_PAGE_SIZE); for (const auto id: FindImagesInRegion(address, size, true)) { - auto owner = m_slot_images.try_get(id); - if (owner == nullptr) { - continue; - } - if (owner->Overlaps(address, size)) { - owner->MarkCpuDirty(); + auto& owner = m_slot_images[id]; + if (owner.Overlaps(address, size)) { + owner.MarkCpuDirty(); UntrackImage(id); continue; } - const auto image_begin = owner->info.data.address; - const auto image_end = owner->info.data.End(); + const auto image_begin = owner.info.data.address; + const auto image_end = owner.info.data.End(); if (page_end < image_end) { UntrackImageHead(id); } else if (image_begin < page_begin) { UntrackImageTail(id); } else { - MarkAsMaybeDirty(id, *owner); + MarkAsMaybeDirty(id, owner); } } } @@ -2052,8 +2038,7 @@ void TextureCache::ProcessDownloadImages() { } std::scoped_lock lock {m_lock}; for (const auto id: m_download_images) { - const auto owner = m_slot_images.try_get(id); - if (owner != nullptr && owner->registered && owner->IsGpuModified()) { + if (m_slot_images[id].IsGpuModified()) { (void)DownloadImageMemory(id); } } diff --git a/src/graphics/host_gpu/renderer/pipeline/descriptors.cpp b/src/graphics/host_gpu/renderer/pipeline/descriptors.cpp index 3a3f0abc0..ca99e3be0 100644 --- a/src/graphics/host_gpu/renderer/pipeline/descriptors.cpp +++ b/src/graphics/host_gpu/renderer/pipeline/descriptors.cpp @@ -672,9 +672,7 @@ void RenderExecutor::BindRenderTarget(ImageId id) { void RenderExecutor::ResetBindings() { for (const auto id: m_bound_images) { - if (auto* image = m_context.GetTextureCache().m_slot_images.try_get(id); image != nullptr) { - image->binding = {}; - } + m_context.GetTextureCache().m_slot_images[id].binding = {}; } m_bound_images.clear(); } @@ -823,12 +821,9 @@ void RenderExecutor::RebindImages(PreparedBindings& prepared) { // Acquire each view before a later overlapping descriptor can replace its image. for (uint32_t i = 0; i < program.info.images.size(); i++) { if (!images[i].image_id) continue; - const auto old_image = texture_cache.m_slot_images.try_get(images[i].image_id); - if (old_image == nullptr || !old_image->registered || - old_image->binding.needs_rebind) { - if (old_image != nullptr) { - old_image->binding = {}; - } + auto& old_image = texture_cache.m_slot_images[images[i].image_id]; + if (!old_image.registered || old_image.binding.needs_rebind) { + old_image.binding = {}; images[i] = ResolveTexture(program.info.images[i], snapshot.images[i]); BindImage(images[i].image_id, images[i].desc.type == TextureCache::BindingType::Storage); @@ -879,12 +874,9 @@ void RenderExecutor::PrepareGraphicsBindings(std::span auto& cache = m_context.GetTextureCache(); for (auto& target: colors) { EXIT_IF(!target.image_id); - const auto old_image = cache.m_slot_images.try_get(target.image_id); - if (old_image == nullptr || !old_image->registered || - old_image->binding.needs_rebind) { - if (old_image != nullptr) { - old_image->binding = {}; - } + auto& old_image = cache.m_slot_images[target.image_id]; + if (!old_image.registered || old_image.binding.needs_rebind) { + old_image.binding = {}; target.desc.view_info.base_level = target.guest_mip_level; target.desc.view_info.base_layer = target.guest_array_layer; target.image_id = cache.FindImage(target.desc); @@ -944,11 +936,10 @@ void RenderExecutor::CommitBindings(CommandBuffer& buffer, } for (const auto [address, size]: reads) { for (const auto id: m_bound_images) { - const auto* image = m_context.GetTextureCache().m_slot_images.try_get(id); - if (image == nullptr || - (!image->binding.shader_write && !image->binding.is_target)) continue; - for (const auto written: {image->info.data, image->info.stencil, - image->info.metadata.range}) { + const auto& image = m_context.GetTextureCache().m_slot_images[id]; + if (!image.binding.shader_write && !image.binding.is_target) continue; + for (const auto written: {image.info.data, image.info.stencil, + image.info.metadata.range}) { if (written.size != 0 && ImageRangeOverlaps(address, size, written.address, written.size)) { EXIT("scalar resource reads overlap an image or attachment write\n"); diff --git a/src/graphics/host_gpu/renderer/renderDraw.cpp b/src/graphics/host_gpu/renderer/renderDraw.cpp index 97d38562b..f03c1da7c 100644 --- a/src/graphics/host_gpu/renderer/renderDraw.cpp +++ b/src/graphics/host_gpu/renderer/renderDraw.cpp @@ -474,9 +474,8 @@ RenderState RenderExecutor::AcquireRenderTargets(CommandBuffer& buffer, RenderCo for (uint32_t i = 0; i < color_count; i++) { auto& target = colors[i]; EXIT_IF(!target.image_id); - const auto owner = cache.m_slot_images.try_get(target.image_id); - if (owner == nullptr || (!owner->registered && !owner->info.data.Empty()) || - owner->binding.needs_rebind) { + const auto& owner = cache.m_slot_images[target.image_id]; + if ((!owner.registered && !owner.info.data.Empty()) || owner.binding.needs_rebind) { EXIT("color target changed after render-state discovery\n"); } const auto image_view = cache.FindRenderTarget(target.image_id, target.desc); @@ -502,8 +501,8 @@ RenderState RenderExecutor::AcquireRenderTargets(CommandBuffer& buffer, RenderCo attachment.image_layout = layout; } if (depth.image_id) { - const auto owner = cache.m_slot_images.try_get(depth.image_id); - if (owner == nullptr || !owner->registered || owner->binding.needs_rebind) { + const auto& owner = cache.m_slot_images[depth.image_id]; + if (!owner.registered || owner.binding.needs_rebind) { EXIT("depth target changed after render-state discovery\n"); } const auto image_view = cache.FindDepthTarget(depth.image_id, depth.desc); diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 8f2273ace..d6f59f21a 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -4317,12 +4317,6 @@ public: BufferCacheTestAccess::PageOwner( cache, index_begin + 2 * index_page) == index_bridge, "bridging acquisition did not publish its merged Buffer range"); - scheduler.Finish(); - constexpr uint64_t recycled_offset = index_offset + 4 * index_page; - const auto recycled = cache.FindBuffer(base + recycled_offset + 0x100, - sizeof(uint32_t)); - Require(name, "slot reuse", recycled == index_left || recycled == index_right, - "retired Buffer slot was not reused"); const auto [resolved_left, resolved_left_offset] = cache.ObtainBuffer( index_begin + 0x100, sizeof(uint32_t), true, false, index_left); const auto [resolved_right, resolved_right_offset] = @@ -4333,6 +4327,12 @@ public: resolved_right == resolved_left && resolved_left_offset != resolved_right_offset, "saved descriptor IDs did not resolve through the merged owner"); + scheduler.Finish(); + constexpr uint64_t recycled_offset = index_offset + 4 * index_page; + const auto recycled = cache.FindBuffer(base + recycled_offset + 0x100, + sizeof(uint32_t)); + Require(name, "slot reuse", recycled == index_left || recycled == index_right, + "retired Buffer slot was not reused"); constexpr uint64_t stream_page = BufferCache::CACHING_PAGESIZE; constexpr uint64_t stream_leap = stream_page * 128;