diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt index 4c599c6f44..89a3d2e4b2 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt @@ -32,6 +32,7 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting { USE_OPTIMIZED_VERTEX_BUFFERS("use_optimized_vertex_buffers"), ENABLE_MULTI_RANGE_STORAGE("enable_multi_range_storage"), ENABLE_SPARSE_BUFFER_BINDING("enable_sparse_buffer_binding"), + ENABLE_SHADER_PHI_TRACKING("enable_shader_phi_tracking"), ENABLE_GPU_BUFFER_READBACK("enable_gpu_buffer_readback"), SYNC_MEMORY_OPERATIONS("sync_memory_operations"), BUFFER_REORDER_DISABLE("disable_buffer_reorder"), diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt index c23504819e..d02dd9f3c0 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt @@ -941,6 +941,13 @@ abstract class SettingsItem( descriptionId = R.string.enable_sparse_buffer_binding_description ) ) + put( + SwitchSetting( + BooleanSetting.ENABLE_SHADER_PHI_TRACKING, + titleId = R.string.enable_shader_phi_tracking, + descriptionId = R.string.enable_shader_phi_tracking_description + ) + ) put( SwitchSetting( BooleanSetting.SYNC_MEMORY_OPERATIONS, diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt index d6f7b7db14..06adc4deb1 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -340,6 +340,7 @@ class SettingsFragmentPresenter( add(BooleanSetting.USE_OPTIMIZED_VERTEX_BUFFERS.key) add(BooleanSetting.ENABLE_MULTI_RANGE_STORAGE.key) add(BooleanSetting.ENABLE_SPARSE_BUFFER_BINDING.key) + add(BooleanSetting.ENABLE_SHADER_PHI_TRACKING.key) add(HeaderSetting(R.string.hacks)) diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 0e60042613..de80a8de9c 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -574,6 +574,8 @@ toggle for test on multi-range. Sparse Buffer Binding toggle for test on sparse buffer binding. + Shader Phi Tracking + toggle for test on shader phi tracking. Hacks diff --git a/src/common/settings.h b/src/common/settings.h index abbc119689..e6b6e47b60 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -608,6 +608,14 @@ struct Values { true, true}; + SwitchableSetting enable_shader_phi_tracking{linkage, + true, + "enable_shader_phi_tracking", + Category::RendererAdvanced, + Specialization::Default, + true, + true}; + #ifdef __ANDROID__ SwitchableSetting use_optimized_vertex_buffers{linkage, false, diff --git a/src/qt_common/config/shared_translation.cpp b/src/qt_common/config/shared_translation.cpp index 8667d31ceb..6bb7647d25 100644 --- a/src/qt_common/config/shared_translation.cpp +++ b/src/qt_common/config/shared_translation.cpp @@ -271,6 +271,8 @@ std::unique_ptr InitializeTranslations(QObject* parent) { tr("toggle for test on multi-range.")); INSERT(Settings, enable_sparse_buffer_binding, tr("Sparse buffer binding"), tr("toggle for test on sparse buffer binding.")); + INSERT(Settings, enable_shader_phi_tracking, tr("Shader phi tracking"), + tr("toggle for test on shader phi tracking.")); INSERT(Settings, fix_bloom_effects, tr("Fix bloom effects"), tr("Removes bloom in Burnout.")); INSERT(Settings, rescale_hack, tr("Enable Legacy Rescale Pass"), diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp index a94b0ee799..5707ddee56 100644 --- a/src/shader_recompiler/ir_opt/texture_pass.cpp +++ b/src/shader_recompiler/ir_opt/texture_pass.cpp @@ -359,6 +359,12 @@ std::optional TrackPhi(const IR::Inst* phi, Environment& env, } std::optional Track(const IR::Value& value, Environment& env, const HostTranslateInfo& host_info) { + if (!Settings::values.enable_shader_phi_tracking.GetValue()) { + return IR::BreadthFirstSearch( + value, [&env, &host_info](const IR::Inst* inst) -> std::optional { + return TryGetConstBuffer(inst, env, host_info); + }); + } bool ambiguous = false; const std::optional result{IR::BreadthFirstSearch( value, [&env, &host_info, &ambiguous](const IR::Inst* inst) diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index dd99a4facd..dd5c8e1d57 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -1937,6 +1937,9 @@ void BufferCache

::DownloadBufferMemory(Buffer& buffer, DAddr device_addr, u64 template void BufferCache

::DeleteBuffer(BufferId buffer_id, bool do_not_mark) { + if constexpr (requires { runtime.OnBufferDeleted(slot_buffers[buffer_id]); }) { + runtime.OnBufferDeleted(slot_buffers[buffer_id]); + } bool dirty_index{false}; boost::container::small_vector dirty_vertex_buffers; const auto scalar_replace = [buffer_id](Binding& binding) { diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index 203da3f43d..80e57fb9fb 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h @@ -207,6 +207,10 @@ public: multi_range_buffers.Invalidate(key); } + void OnBufferDeleted(const Buffer& buffer) { + multi_range_buffers.DropOwner(buffer.Handle()); + } + void BindUniformBuffer(const Buffer& buffer, u32 offset, u32 size) { BindBuffer(buffer, offset, size); } diff --git a/src/video_core/renderer_vulkan/vk_multi_range_buffer.cpp b/src/video_core/renderer_vulkan/vk_multi_range_buffer.cpp index 6386e2661a..4d07081317 100644 --- a/src/video_core/renderer_vulkan/vk_multi_range_buffer.cpp +++ b/src/video_core/renderer_vulkan/vk_multi_range_buffer.cpp @@ -246,6 +246,12 @@ MultiRangeRef MultiRangeBufferCache::Get(u64 key, std::spansecond; + bool owned = false; + for (const VkBuffer handle : entry.owners) { + if (handle == owner) { + owned = true; + break; + } + } + if (owned) { + DestroySparse(entry.sparse_handle); + it = entries.erase(it); + } else { + ++it; + } + } +} + void MultiRangeBufferCache::Invalidate(u64 key) { const auto it = entries.find(key); if (it != entries.end()) { diff --git a/src/video_core/renderer_vulkan/vk_multi_range_buffer.h b/src/video_core/renderer_vulkan/vk_multi_range_buffer.h index d64d1f2fa7..41d97b5239 100644 --- a/src/video_core/renderer_vulkan/vk_multi_range_buffer.h +++ b/src/video_core/renderer_vulkan/vk_multi_range_buffer.h @@ -59,6 +59,8 @@ public: void Invalidate(u64 key); + void DropOwner(VkBuffer owner); + void Clear(); private: @@ -74,6 +76,7 @@ private: VkDeviceSize size{}; u64 geometry{}; bool dirty{true}; + std::vector owners; }; [[nodiscard]] u64 HashSources(std::span sources) const; diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp index 763f0b16f5..bee7cd6e57 100644 --- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp +++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp @@ -305,48 +305,13 @@ vk::Buffer MemoryAllocator::CreateBuffer(const VkBufferCreateInfo &ci, MemoryUsa .priority = 0.f, }; - const VkDevice logical = *device.GetLogical(); - const auto &dld = device.GetDispatchLoader(); - VkBuffer handle{}; - vk::Check(dld.vkCreateBuffer(logical, &ci, nullptr, &handle)); - - const VkBufferMemoryRequirementsInfo2 reqs_info{ - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, - .pNext = nullptr, - .buffer = handle, - }; - VkMemoryRequirements2 reqs2{ - .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, - .pNext = nullptr, - .memoryRequirements = {}, - }; - dld.vkGetBufferMemoryRequirements2(logical, &reqs_info, &reqs2); - - VkMemoryRequirements reqs = reqs2.memoryRequirements; - reqs.alignment = (std::max)(reqs.alignment, min_alignment); - reqs.memoryTypeBits &= alloc_ci.memoryTypeBits; - - VmaAllocation allocation{}; VmaAllocationInfo alloc_info{}; - VkResult res = vmaAllocateMemory(allocator, &reqs, &alloc_ci, &allocation, &alloc_info); - if (res != VK_SUCCESS) { - auto relaxed = alloc_ci; - relaxed.flags &= ~VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT; - res = vmaAllocateMemory(allocator, &reqs, &relaxed, &allocation, &alloc_info); - } - if (res != VK_SUCCESS) { - dld.vkDestroyBuffer(logical, handle, nullptr); - vk::Check(res); - } - const VkResult bind_res = vmaBindBufferMemory(allocator, allocation, handle); - if (bind_res != VK_SUCCESS) { - vmaFreeMemory(allocator, allocation); - dld.vkDestroyBuffer(logical, handle, nullptr); - vk::Check(bind_res); - } - + VmaAllocation allocation{}; VkMemoryPropertyFlags property_flags{}; + + vk::Check(vmaCreateBufferWithAlignment(allocator, &ci, &alloc_ci, min_alignment, &handle, + &allocation, &alloc_info)); vmaGetAllocationMemoryProperties(allocator, allocation, &property_flags); u8 *data = reinterpret_cast(alloc_info.pMappedData); @@ -356,7 +321,8 @@ vk::Buffer MemoryAllocator::CreateBuffer(const VkBufferCreateInfo &ci, MemoryUsa } const bool is_coherent = (property_flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0; - return vk::Buffer(handle, logical, allocator, allocation, mapped_data, is_coherent, dld); + return vk::Buffer(handle, *device.GetLogical(), allocator, allocation, mapped_data, is_coherent, + device.GetDispatchLoader()); } MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements &reqs, MemoryUsage usage)