From 683a223c1b771e212421ee123d9575a19c75f2e9 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Mon, 14 Apr 2025 20:58:33 -0700 Subject: [PATCH 1/3] vk_rasterizer: Control mapped_ranges access with shared lock. (#2788) --- src/video_core/renderer_vulkan/vk_rasterizer.cpp | 16 ++++++++++++---- src/video_core/renderer_vulkan/vk_rasterizer.h | 3 +++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 30102960a..13779977d 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -930,12 +930,17 @@ bool Rasterizer::IsMapped(VAddr addr, u64 size) { // There is no memory, so not mapped. return false; } - return mapped_ranges.find(boost::icl::interval::right_open(addr, addr + size)) != - mapped_ranges.end(); + const auto range = decltype(mapped_ranges)::interval_type::right_open(addr, addr + size); + + std::shared_lock lock{mapped_ranges_mutex}; + return boost::icl::contains(mapped_ranges, range); } void Rasterizer::MapMemory(VAddr addr, u64 size) { - mapped_ranges += boost::icl::interval::right_open(addr, addr + size); + { + std::unique_lock lock{mapped_ranges_mutex}; + mapped_ranges += decltype(mapped_ranges)::interval_type::right_open(addr, addr + size); + } page_manager.OnGpuMap(addr, size); } @@ -943,7 +948,10 @@ void Rasterizer::UnmapMemory(VAddr addr, u64 size) { buffer_cache.InvalidateMemory(addr, size); texture_cache.UnmapMemory(addr, size); page_manager.OnGpuUnmap(addr, size); - mapped_ranges -= boost::icl::interval::right_open(addr, addr + size); + { + std::unique_lock lock{mapped_ranges_mutex}; + mapped_ranges -= decltype(mapped_ranges)::interval_type::right_open(addr, addr + size); + } } void Rasterizer::UpdateDynamicState(const GraphicsPipeline& pipeline) const { diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 54bf3d253..4e0ed0996 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -3,6 +3,8 @@ #pragma once +#include + #include "video_core/buffer_cache/buffer_cache.h" #include "video_core/page_manager.h" #include "video_core/renderer_vulkan/vk_pipeline_cache.h" @@ -106,6 +108,7 @@ private: AmdGpu::Liverpool* liverpool; Core::MemoryManager* memory; boost::icl::interval_set mapped_ranges; + std::shared_mutex mapped_ranges_mutex; PipelineCache pipeline_cache; boost::container::static_vector< From 4bea00135dbb47c79a15fd31a1dd8fc192d34b17 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Mon, 14 Apr 2025 20:58:49 -0700 Subject: [PATCH 2/3] resource_tracking_pass: Add heuristic to detect incorrectly tracked buffer sharp. (#2786) --- .../ir/passes/resource_tracking_pass.cpp | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp index c5bfe5796..778da149f 100644 --- a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp +++ b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp @@ -235,9 +235,12 @@ std::pair TryDisableAnisoLod0(const IR::Inst* inst) { return {prod2, true}; } -SharpLocation TrackSharp(const IR::Inst* inst, const Shader::Info& info) { +SharpLocation AttemptTrackSharp(const IR::Inst* inst, auto& visited_insts) { // Search until we find a potential sharp source. - const auto pred = [](const IR::Inst* inst) -> std::optional { + const auto pred = [&visited_insts](const IR::Inst* inst) -> std::optional { + if (std::ranges::find(visited_insts, inst) != visited_insts.end()) { + return std::nullopt; + } if (inst->GetOpcode() == IR::Opcode::GetUserData || inst->GetOpcode() == IR::Opcode::ReadConst) { return inst; @@ -247,6 +250,7 @@ SharpLocation TrackSharp(const IR::Inst* inst, const Shader::Info& info) { const auto result = IR::BreadthFirstSearch(inst, pred); ASSERT_MSG(result, "Unable to track sharp source"); inst = result.value(); + visited_insts.emplace_back(inst); if (inst->GetOpcode() == IR::Opcode::GetUserData) { return static_cast(inst->Arg(0).ScalarReg()); } else { @@ -256,6 +260,29 @@ SharpLocation TrackSharp(const IR::Inst* inst, const Shader::Info& info) { } } +/// Tracks a sharp with validation of the chosen data type. +template +std::pair TrackSharp(const IR::Inst* inst, const Info& info) { + boost::container::small_vector visited_insts{}; + while (true) { + const auto prev_size = visited_insts.size(); + const auto sharp = AttemptTrackSharp(inst, visited_insts); + if (const auto data = info.ReadUdSharp(sharp); data.Valid()) { + return std::make_pair(sharp, data); + } + if (prev_size == visited_insts.size()) { + // No change in visited instructions, we've run out of paths. + UNREACHABLE_MSG("Unable to find valid sharp."); + } + } +} + +/// Tracks a sharp without data validation. +SharpLocation TrackSharp(const IR::Inst* inst, const Info& info) { + boost::container::static_vector visited_insts{}; + return AttemptTrackSharp(inst, visited_insts); +} + s32 TryHandleInlineCbuf(IR::Inst& inst, Info& info, Descriptors& descriptors, AmdGpu::Buffer& cbuf) { @@ -293,8 +320,8 @@ void PatchBufferSharp(IR::Block& block, IR::Inst& inst, Info& info, Descriptors& if (binding = TryHandleInlineCbuf(inst, info, descriptors, buffer); binding == -1) { IR::Inst* handle = inst.Arg(0).InstRecursive(); IR::Inst* producer = handle->Arg(0).InstRecursive(); - const auto sharp = TrackSharp(producer, info); - buffer = info.ReadUdSharp(sharp); + SharpLocation sharp; + std::tie(sharp, buffer) = TrackSharp(producer, info); binding = descriptors.Add(BufferResource{ .sharp_idx = sharp, .used_types = BufferDataType(inst, buffer.GetNumberFmt()), From 247e935353852bdb64bcfe76a5f74ab2c6c01239 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Tue, 15 Apr 2025 17:13:19 -0700 Subject: [PATCH 3/3] externals: Update MoltenVK (#2791) --- .gitmodules | 2 +- externals/MoltenVK/MoltenVK | 2 +- externals/MoltenVK/SPIRV-Cross | 2 +- src/video_core/renderer_vulkan/vk_instance.cpp | 5 +---- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/.gitmodules b/.gitmodules index 065a4570f..9daefe305 100644 --- a/.gitmodules +++ b/.gitmodules @@ -97,7 +97,7 @@ shallow = true [submodule "externals/MoltenVK/SPIRV-Cross"] path = externals/MoltenVK/SPIRV-Cross - url = https://github.com/KhronosGroup/SPIRV-Cross + url = https://github.com/billhollings/SPIRV-Cross shallow = true [submodule "externals/MoltenVK/MoltenVK"] path = externals/MoltenVK/MoltenVK diff --git a/externals/MoltenVK/MoltenVK b/externals/MoltenVK/MoltenVK index 83510e0f3..067fc6c85 160000 --- a/externals/MoltenVK/MoltenVK +++ b/externals/MoltenVK/MoltenVK @@ -1 +1 @@ -Subproject commit 83510e0f3835c3c43651dda087305abc42572e17 +Subproject commit 067fc6c85b02f37dfda58eeda49d8458e093ed60 diff --git a/externals/MoltenVK/SPIRV-Cross b/externals/MoltenVK/SPIRV-Cross index 68300dc07..185833a61 160000 --- a/externals/MoltenVK/SPIRV-Cross +++ b/externals/MoltenVK/SPIRV-Cross @@ -1 +1 @@ -Subproject commit 68300dc07ac3dc592dbbdb87e02d5180f984ad12 +Subproject commit 185833a61cbe29ce3bfb5a499ffb3dfeaee3bbe7 diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index d45889054..f83f63036 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -249,7 +249,7 @@ bool Instance::CreateDevice() { add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME); add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME); - const bool maintenance4 = add_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME); + add_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME); add_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); add_extension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); @@ -422,9 +422,6 @@ bool Instance::CreateDevice() { #endif }; - if (!maintenance4) { - device_chain.unlink(); - } if (!custom_border_color) { device_chain.unlink(); }