diff options
| author | CamilleLaVey <camillelavey99@gmail.com> | 2026-08-05 16:58:43 +0200 |
|---|---|---|
| committer | crueter <crueter@eden-emu.dev> | 2026-08-05 16:58:43 +0200 |
| commit | 49a0ca6d5d9929391e0633163ebbfec564d27cc1 (patch) | |
| tree | a5b1a0aea77126d134c60b7c79cca02356566792 /src/video_core/vulkan_common/vulkan_wrapper.h | |
| parent | 5e1d5e82dcc98627c769b7ca32384ded16bc5e1d (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_wrapper.h')
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_wrapper.h | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index ef975e2bda..c2d867838d 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h @@ -352,6 +352,12 @@ struct DeviceDispatch : InstanceDispatch { PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT{}; PFN_vkUnmapMemory vkUnmapMemory{}; PFN_vkUpdateDescriptorSetWithTemplate vkUpdateDescriptorSetWithTemplate{}; + PFN_vkGetBufferDeviceAddress vkGetBufferDeviceAddress{}; + PFN_vkGetDescriptorSetLayoutSizeEXT vkGetDescriptorSetLayoutSizeEXT{}; + PFN_vkGetDescriptorSetLayoutBindingOffsetEXT vkGetDescriptorSetLayoutBindingOffsetEXT{}; + PFN_vkGetDescriptorEXT vkGetDescriptorEXT{}; + PFN_vkCmdBindDescriptorBuffersEXT vkCmdBindDescriptorBuffersEXT{}; + PFN_vkCmdSetDescriptorBufferOffsetsEXT vkCmdSetDescriptorBufferOffsetsEXT{}; PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets{}; PFN_vkWaitForFences vkWaitForFences{}; PFN_vkWaitSemaphores vkWaitSemaphores{}; @@ -793,6 +799,11 @@ public: return !mapped.empty(); } + /// Returns true if host writes are visible to the device. + bool IsHostCoherent() const noexcept { + return is_coherent; + } + void Flush() const; void Invalidate() const; @@ -1087,6 +1098,34 @@ public: dld->vkUpdateDescriptorSetWithTemplate(handle, set, update_template, data); } + [[nodiscard]] VkDeviceAddress GetBufferDeviceAddress(VkBuffer buffer) const noexcept { + const VkBufferDeviceAddressInfo info{ + .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + .pNext = nullptr, + .buffer = buffer, + }; + return dld->vkGetBufferDeviceAddress(handle, &info); + } + + [[nodiscard]] VkDeviceSize GetDescriptorSetLayoutSizeEXT( + VkDescriptorSetLayout layout) const noexcept { + VkDeviceSize size{}; + dld->vkGetDescriptorSetLayoutSizeEXT(handle, layout, &size); + return size; + } + + [[nodiscard]] VkDeviceSize GetDescriptorSetLayoutBindingOffsetEXT( + VkDescriptorSetLayout layout, u32 binding) const noexcept { + VkDeviceSize offset{}; + dld->vkGetDescriptorSetLayoutBindingOffsetEXT(handle, layout, binding, &offset); + return offset; + } + + void GetDescriptorEXT(const VkDescriptorGetInfoEXT& info, size_t size, + void* descriptor) const noexcept { + dld->vkGetDescriptorEXT(handle, &info, size, descriptor); + } + VkResult AcquireNextImageKHR(VkSwapchainKHR swapchain, u64 timeout, VkSemaphore semaphore, VkFence fence, u32* image_index) const noexcept { return dld->vkAcquireNextImageKHR(handle, swapchain, timeout, semaphore, fence, @@ -1400,6 +1439,18 @@ public: PipelineBarrier(src_stage_mask, dst_stage_mask, dependency_flags, {}, {}, image_barrier); } + void BindDescriptorBuffersEXT(Span<VkDescriptorBufferBindingInfoEXT> bindings) const noexcept { + dld->vkCmdBindDescriptorBuffersEXT(handle, bindings.size(), bindings.data()); + } + + void SetDescriptorBufferOffsetsEXT(VkPipelineBindPoint bind_point, VkPipelineLayout layout, + u32 first_set, Span<u32> buffer_indices, + Span<VkDeviceSize> offsets) const noexcept { + dld->vkCmdSetDescriptorBufferOffsetsEXT(handle, bind_point, layout, first_set, + buffer_indices.size(), buffer_indices.data(), + offsets.data()); + } + void CopyBufferToImage(VkBuffer src_buffer, VkImage dst_image, VkImageLayout dst_image_layout, Span<VkBufferImageCopy> regions) const noexcept { dld->vkCmdCopyBufferToImage(handle, src_buffer, dst_image, dst_image_layout, regions.size(), |
