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{};
};