diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 0deaeea93a..15ec5ba8fc 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -714,6 +714,17 @@ 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); } + // 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); @@ -727,6 +738,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, @@ -1105,6 +1119,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; diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 4d12a73901..e9cb5f7b24 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -36,6 +36,7 @@ VK_DEFINE_HANDLE(VmaAllocator) FEATURE(EXT, DescriptorIndexing, DESCRIPTOR_INDEXING, descriptor_indexing) \ FEATURE(EXT, HostQueryReset, HOST_QUERY_RESET, host_query_reset) \ FEATURE(KHR, 8BitStorage, 8BIT_STORAGE, bit8_storage) \ + FEATURE(KHR, BufferDeviceAddress, BUFFER_DEVICE_ADDRESS, buffer_device_address) \ FEATURE(KHR, TimelineSemaphore, TIMELINE_SEMAPHORE, timeline_semaphore) #define FOR_EACH_VK_FEATURE_1_3(FEATURE) \ @@ -58,6 +59,7 @@ VK_DEFINE_HANDLE(VmaAllocator) FEATURE(EXT, DepthClampZeroOne, DEPTH_CLAMP_ZERO_ONE, depth_clamp_zero_one) \ FEATURE(EXT, DepthClipControl, DEPTH_CLIP_CONTROL, depth_clip_control) \ FEATURE(EXT, DepthClipEnable, DEPTH_CLIP_ENABLE, depth_clip_enable) \ + FEATURE(EXT, DescriptorBuffer, DESCRIPTOR_BUFFER, descriptor_buffer) \ FEATURE(EXT, ExtendedDynamicState, EXTENDED_DYNAMIC_STATE, extended_dynamic_state) \ FEATURE(EXT, ExtendedDynamicState2, EXTENDED_DYNAMIC_STATE_2, extended_dynamic_state2) \ FEATURE(EXT, ExtendedDynamicState3, EXTENDED_DYNAMIC_STATE_3, extended_dynamic_state3) \ @@ -481,6 +483,21 @@ FN_MAX_LIMIT_LIST return properties.push_descriptor.maxPushDescriptors; } + /// Returns true if the device supports descriptor buffers. + bool IsExtDescriptorBufferSupported() const { + return extensions.descriptor_buffer; + } + + /// Returns the descriptor buffer properties of the device. + const VkPhysicalDeviceDescriptorBufferPropertiesEXT& DescriptorBufferProperties() const { + return properties.descriptor_buffer; + } + + /// Returns true if the device supports buffer device address. + bool IsBufferDeviceAddressSupported() const { + return extensions.buffer_device_address; + } + /// Returns true if formatless image load is supported. bool IsFormatlessImageLoadSupported() const { return features.features.shaderStorageImageReadWithoutFormat; @@ -1209,6 +1226,7 @@ private: VkPhysicalDeviceSubgroupProperties subgroup_properties{}; VkPhysicalDeviceFloatControlsProperties float_controls{}; VkPhysicalDevicePushDescriptorPropertiesKHR push_descriptor{}; + VkPhysicalDeviceDescriptorBufferPropertiesEXT descriptor_buffer{}; VkPhysicalDeviceSubgroupSizeControlProperties subgroup_size_control{}; VkPhysicalDeviceTransformFeedbackPropertiesEXT transform_feedback{}; VkPhysicalDeviceMaintenance5PropertiesKHR maintenance5{}; diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index a2ab85475b..9fcca60ea9 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp @@ -299,6 +299,12 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { X(vkUnmapMemory); X(vkUpdateDescriptorSetWithTemplate); X(vkUpdateDescriptorSets); + X(vkGetBufferDeviceAddress); + X(vkGetDescriptorSetLayoutSizeEXT); + X(vkGetDescriptorSetLayoutBindingOffsetEXT); + X(vkGetDescriptorEXT); + X(vkCmdBindDescriptorBuffersEXT); + X(vkCmdSetDescriptorBufferOffsetsEXT); X(vkWaitForFences); X(vkWaitSemaphores); diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index 66f8c09e9c..8fbddf55ad 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h @@ -365,6 +365,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{}; @@ -1104,6 +1110,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, @@ -1425,6 +1459,18 @@ public: PipelineBarrier(src_stage_mask, dst_stage_mask, dependency_flags, {}, {}, image_barrier); } + void BindDescriptorBuffersEXT(Span bindings) const noexcept { + dld->vkCmdBindDescriptorBuffersEXT(handle, bindings.size(), bindings.data()); + } + + void SetDescriptorBufferOffsetsEXT(VkPipelineBindPoint bind_point, VkPipelineLayout layout, + u32 first_set, Span buffer_indices, + Span offsets) const noexcept { + dld->vkCmdSetDescriptorBufferOffsetsEXT(handle, bind_point, layout, first_set, + buffer_indices.size(), buffer_indices.data(), + offsets.data()); + } + [[nodiscard]] bool HasPipelineBarrier2() const noexcept { return dld->vkCmdPipelineBarrier2 != nullptr; }