From 1ba01cc6d596b94934e9725be0dcbaca3a5dfc75 Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Sun, 9 Aug 2026 23:42:29 -0400 Subject: [PATCH] [TEST] Adjustments on queries, XFB and AHB --- src/video_core/buffer_cache/buffer_cache.h | 18 ++++--- .../renderer_vulkan/vk_buffer_cache.cpp | 6 ++- .../renderer_vulkan/vk_buffer_cache.h | 4 ++ .../vulkan_common/vulkan_memory_allocator.cpp | 51 +++++++++++++------ .../vulkan_common/vulkan_memory_allocator.h | 6 +++ 5 files changed, 61 insertions(+), 24 deletions(-) diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index e5706109bb..b183eaf260 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -1146,14 +1146,17 @@ void BufferCache

::BindHostVertexBuffers() { template void BufferCache

::BindHostDrawIndirectBuffers() { - const auto bind_buffer = [this](const Binding& binding) -> std::optional { + const auto bind_buffer = [this](const Binding& binding, + bool as_counter) -> std::optional { Buffer& buffer = slot_buffers[binding.buffer_id]; TouchBuffer(buffer, binding.buffer_id); if constexpr (USE_UNIFIED_DIRECT_BINDING) { - if (auto window = TryObtainWindowBuffer(binding.device_addr, binding.size, - UNIFIED_INDIRECT_BINDING_ALIGNMENT, - ObtainBufferOperation::DoNothing)) { - return window; + if (!as_counter || runtime.SupportsUnifiedCounterBufferBinding()) { + if (auto window = TryObtainWindowBuffer(binding.device_addr, binding.size, + UNIFIED_INDIRECT_BINDING_ALIGNMENT, + ObtainBufferOperation::DoNothing)) { + return window; + } } } SynchronizeBuffer(buffer, binding.device_addr, binding.size); @@ -1162,9 +1165,10 @@ void BufferCache

::BindHostDrawIndirectBuffers() { draw_indirect_count_window.reset(); draw_indirect_window.reset(); if (current_draw_indirect->include_count) { - draw_indirect_count_window = bind_buffer(channel_state->count_buffer_binding); + draw_indirect_count_window = bind_buffer(channel_state->count_buffer_binding, false); } - draw_indirect_window = bind_buffer(channel_state->indirect_buffer_binding); + draw_indirect_window = + bind_buffer(channel_state->indirect_buffer_binding, current_draw_indirect->is_byte_count); } template diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 30ae53ee45..05bb85e4a6 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp @@ -72,7 +72,8 @@ vk::Buffer CreateBuffer(const Device& device, const MemoryAllocator& memory_allo VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; if (device.IsExtTransformFeedbackSupported()) { - flags |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT; + flags |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT | + VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT; } if (device.IsExtConditionalRendering()) { flags |= VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT; @@ -904,7 +905,8 @@ vk::Buffer BufferCacheRuntime::CreateNullBuffer() { .pQueueFamilyIndices = nullptr, }; if (device.IsExtTransformFeedbackSupported()) { - create_info.usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT; + create_info.usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT | + VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT; } if (device.IsBufferDeviceAddressSupported()) { create_info.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index 38cf48158a..1c8ddd46b5 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h @@ -178,6 +178,10 @@ public: return SupportsUnifiedDirectBinding() && device.IsExtTransformFeedbackSupported(); } + [[nodiscard]] bool SupportsUnifiedCounterBufferBinding() const noexcept { + return SupportsUnifiedDirectBinding() && unified_memory->SupportsDirectCounterBuffers(); + } + [[nodiscard]] u64 UnifiedMaxTransformFeedbackBufferSize() const noexcept { return device.GetMaxTransformFeedbackBufferSize(); } diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp index 014a48c7ad..7af12ab81b 100644 --- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp +++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp @@ -72,9 +72,16 @@ namespace Vulkan { return flags; } - [[nodiscard]] VkBufferUsageFlags ImportedDescriptorAddressUsage(const Device &device) { - return ImportedDescriptorUsage(device) | - VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; + [[nodiscard]] VkBufferUsageFlags ImportedWindowUsage(const Device &device, + bool with_address, bool with_counter) { + VkBufferUsageFlags flags = ImportedDescriptorUsage(device); + if (with_address) { + flags |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; + } + if (with_counter) { + flags |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT; + } + return flags; } // Helpers translating MemoryUsage to flags/usage @@ -302,22 +309,31 @@ namespace Vulkan { bool HostMemoryImport::CreateDescriptorCapableWindowBuffer( const void *external_info, VkDeviceSize length, u32 external_type_bits, VkDeviceSize capacity, VkBuffer *out_buffer, u32 *out_type_mask, - bool *out_descriptor_capable, bool *out_address_capable, bool allow_address) const { - if (allow_address && device.IsBufferDeviceAddressSupported() && - TryCreateWindowBuffer(external_info, length, external_type_bits, capacity, - ImportedDescriptorAddressUsage(device), out_buffer, - out_type_mask)) { + bool *out_descriptor_capable, bool *out_address_capable, bool *out_counter_capable, + bool allow_address) const { + const bool address_wanted = allow_address && device.IsBufferDeviceAddressSupported(); + const bool counter_wanted = device.IsExtTransformFeedbackSupported(); + const auto try_descriptor = [&](bool with_address, bool with_counter) { + if ((with_address && !address_wanted) || (with_counter && !counter_wanted)) { + return false; + } + if (!TryCreateWindowBuffer(external_info, length, external_type_bits, capacity, + ImportedWindowUsage(device, with_address, with_counter), + out_buffer, out_type_mask)) { + return false; + } *out_descriptor_capable = true; - *out_address_capable = true; + *out_address_capable = with_address; + *out_counter_capable = with_counter; return true; - } - *out_address_capable = false; - if (TryCreateWindowBuffer(external_info, length, external_type_bits, capacity, - ImportedDescriptorUsage(device), out_buffer, out_type_mask)) { - *out_descriptor_capable = true; + }; + if (try_descriptor(true, true) || try_descriptor(true, false) || + try_descriptor(false, true) || try_descriptor(false, false)) { return true; } *out_descriptor_capable = false; + *out_address_capable = false; + *out_counter_capable = false; return TryCreateWindowBuffer(external_info, length, external_type_bits, capacity, ImportedTransferUsage, out_buffer, out_type_mask); } @@ -458,6 +474,7 @@ namespace Vulkan { base_offset = hardware_buffer_base; bool every_window_descriptor_capable = true; bool every_window_address_capable = true; + bool every_window_counter_capable = true; for (size_t i = 0; i < hardware_buffers.size(); ++i) { const size_t offset = hardware_buffer_base + i * hardware_buffer_window; if (offset >= size) { @@ -486,6 +503,7 @@ namespace Vulkan { Window window{}; bool descriptor_capable = false; bool address_capable = false; + bool counter_capable = false; const auto build_window = [&](bool allow_address) { VkBuffer new_buffer{}; u32 type_mask = 0; @@ -493,7 +511,8 @@ namespace Vulkan { ahb_props.memoryTypeBits, ahb_props.allocationSize, &new_buffer, &type_mask, &descriptor_capable, - &address_capable, allow_address)) { + &address_capable, &counter_capable, + allow_address)) { return false; } const auto type_index = FindImportMemoryType(memory_props, type_mask); @@ -554,10 +573,12 @@ namespace Vulkan { windows.push_back(std::move(window)); every_window_descriptor_capable &= descriptor_capable; every_window_address_capable &= address_capable; + every_window_counter_capable &= counter_capable; imported_size += static_cast(window_len); } direct_descriptors = !windows.empty() && every_window_descriptor_capable; direct_addresses = direct_descriptors && every_window_address_capable; + direct_counter_buffers = direct_descriptors && every_window_counter_capable; if (windows.empty()) { window_size = 0; base_offset = 0; diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.h b/src/video_core/vulkan_common/vulkan_memory_allocator.h index 6e5b873d2d..eb9d132f6e 100644 --- a/src/video_core/vulkan_common/vulkan_memory_allocator.h +++ b/src/video_core/vulkan_common/vulkan_memory_allocator.h @@ -134,6 +134,10 @@ namespace Vulkan { return direct_addresses; } + [[nodiscard]] bool SupportsDirectCounterBuffers() const noexcept { + return direct_counter_buffers; + } + [[nodiscard]] bool IsHardwareBufferBacked() const noexcept { return hardware_buffer_backed; } @@ -165,6 +169,7 @@ namespace Vulkan { VkBuffer *out_buffer, u32 *out_type_mask, bool *out_descriptor_capable, bool *out_address_capable, + bool *out_counter_capable, bool allow_address) const; const Device &device; @@ -175,6 +180,7 @@ namespace Vulkan { bool foreign_ownership{}; bool direct_descriptors{}; bool direct_addresses{}; + bool direct_counter_buffers{}; bool hardware_buffer_backed{}; };