aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/vulkan_common/vulkan_device.cpp
diff options
context:
space:
mode:
authorCamilleLaVey <camillelavey99@gmail.com>2026-08-05 16:58:43 +0200
committercrueter <crueter@eden-emu.dev>2026-08-05 16:58:43 +0200
commit49a0ca6d5d9929391e0633163ebbfec564d27cc1 (patch)
treea5b1a0aea77126d134c60b7c79cca02356566792 /src/video_core/vulkan_common/vulkan_device.cpp
parent5e1d5e82dcc98627c769b7ca32384ded16bc5e1d (diff)
[vulkan] Initial implementation on Bindless Buffer/Descriptors (#4251)
Adds a VK_EXT_descriptor_buffer, VK_KHR_device_buffer_address path alongside push descriptors and descriptor sets. The ring is chunked and sized from the device limits, so drivers with a small sampler range (QCOM reports 128 KiB) get more, chunks per frame instead of losing the feature. A pipeline uses one path or the other, never both, since some drivers do not support bufferless push descriptors. The chunk binding is only re-emitted when it changes, and a draw that repeats the previous payload reuses its allocation instead of rewriting it. This whole change will help to reduce the constant use of descriptors on the slower path, improves the "slow implementation" on QCOM drivers (A7xx and older) for push descriptors, improves latency when compiling pipelines. The implementation on indexing descriptors was also refined. _Special Thanks_ 1.- Meowly The Bindless Smol (@Gidoly) Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4251
Diffstat (limited to 'src/video_core/vulkan_common/vulkan_device.cpp')
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp50
1 files changed, 50 insertions, 0 deletions
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index 7e9df7fed0..8c41a7eb67 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -506,6 +506,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
if (is_qualcomm) {
must_emulate_scaled_formats = true;
LOG_WARNING(Render_Vulkan, "Qualcomm drivers require scaled vertex format emulation.");
+ has_broken_descriptor_aliasing = true;
+ LOG_WARNING(Render_Vulkan, "Qualcomm drivers have broken descriptor aliasing.");
LOG_WARNING(Render_Vulkan, "Qualcomm drivers have broken custom border color.");
RemoveExtensionFeature(extensions.custom_border_color, features.custom_border_color,
VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
@@ -713,6 +715,37 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
RemoveExtensionFeature(extensions.vertex_input_dynamic_state, features.vertex_input_dynamic_state, VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
}
+ // Descriptors feature list
+ {
+ auto& descriptor_indexing = features.descriptor_indexing;
+ descriptor_indexing.shaderInputAttachmentArrayDynamicIndexing = false;
+ descriptor_indexing.shaderUniformTexelBufferArrayDynamicIndexing = false;
+ descriptor_indexing.shaderStorageTexelBufferArrayDynamicIndexing = false;
+ descriptor_indexing.shaderUniformBufferArrayNonUniformIndexing = false;
+ descriptor_indexing.shaderStorageBufferArrayNonUniformIndexing = false;
+ descriptor_indexing.shaderInputAttachmentArrayNonUniformIndexing = false;
+ descriptor_indexing.descriptorBindingUniformBufferUpdateAfterBind = false;
+ descriptor_indexing.descriptorBindingSampledImageUpdateAfterBind = false;
+ descriptor_indexing.descriptorBindingStorageImageUpdateAfterBind = false;
+ descriptor_indexing.descriptorBindingStorageBufferUpdateAfterBind = false;
+ descriptor_indexing.descriptorBindingUniformTexelBufferUpdateAfterBind = false;
+ descriptor_indexing.descriptorBindingStorageTexelBufferUpdateAfterBind = false;
+ descriptor_indexing.descriptorBindingUpdateUnusedWhilePending = false;
+ descriptor_indexing.descriptorBindingVariableDescriptorCount = false;
+ descriptor_indexing.runtimeDescriptorArray = false;
+ }
+
+ // VK_EXT_descriptor_buffer requires VK_KHR_buffer_device_address
+ if (extensions.descriptor_buffer && !features.buffer_device_address.bufferDeviceAddress) {
+ LOG_WARNING(Render_Vulkan, "Descriptor buffer needs buffer device address, disabling.");
+ RemoveExtensionFeature(extensions.descriptor_buffer, features.descriptor_buffer,
+ VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME);
+ }
+ if (!extensions.descriptor_buffer) {
+ RemoveExtensionFeature(extensions.buffer_device_address, features.buffer_device_address,
+ VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
+ }
+
logical = vk::Device::Create(physical, queue_cis, ExtensionListForVulkan(loaded_extensions), first_next, dld);
graphics_queue = logical.GetQueue(graphics_family);
@@ -726,6 +759,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
if (extensions.memory_budget) {
flags |= VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT;
}
+ if (extensions.buffer_device_address) {
+ flags |= VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
+ }
const VmaAllocatorCreateInfo allocator_info{
.flags = flags,
.physicalDevice = physical,
@@ -972,6 +1008,10 @@ bool Device::GetSuitability(bool requires_swapchain) {
CHECK_EXTENSION(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
}
+ if (instance_version < VK_API_VERSION_1_2) {
+ CHECK_EXTENSION(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
+ }
+
#undef LOG_EXTENSION
#undef CHECK_EXTENSION
@@ -1082,6 +1122,11 @@ bool Device::GetSuitability(bool requires_swapchain) {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR;
SetNext(next, properties.push_descriptor);
}
+ if (extensions.descriptor_buffer) {
+ properties.descriptor_buffer.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT;
+ SetNext(next, properties.descriptor_buffer);
+ }
if (extensions.subgroup_size_control || features.subgroup_size_control.subgroupSizeControl) {
properties.subgroup_size_control.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES;
@@ -1213,6 +1258,11 @@ void Device::RemoveUnsuitableExtensions() {
RemoveExtensionFeatureIfUnsuitable(extensions.depth_clip_control, features.depth_clip_control,
VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME);
+ // VK_EXT_descriptor_buffer
+ extensions.descriptor_buffer = features.descriptor_buffer.descriptorBuffer;
+ RemoveExtensionFeatureIfUnsuitable(extensions.descriptor_buffer, features.descriptor_buffer,
+ VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME);
+
// VK_EXT_extended_dynamic_state
extensions.extended_dynamic_state = features.extended_dynamic_state.extendedDynamicState;
RemoveExtensionFeatureIfUnsuitable(extensions.extended_dynamic_state,