VulkanDevice: Potentially re-enable Vulkan 1.0 support

This commit is contained in:
Stenzek 2023-12-25 21:59:30 +10:00
parent c33f415e72
commit c233eb53ab
No known key found for this signature in database
4 changed files with 90 additions and 22 deletions

View file

@ -127,13 +127,34 @@ GPUTexture::Format VulkanDevice::GetFormatForVkFormat(VkFormat format)
return GPUTexture::Format::Unknown; return GPUTexture::Format::Unknown;
} }
VkInstance VulkanDevice::CreateVulkanInstance(const WindowInfo& wi, bool enable_debug_utils, VkInstance VulkanDevice::CreateVulkanInstance(const WindowInfo& wi, u32* apiVersion, OptionalExtensions* oe,
bool enable_validation_layer) bool enable_debug_utils, bool enable_validation_layer)
{ {
ExtensionList enabled_extensions; ExtensionList enabled_extensions;
if (!SelectInstanceExtensions(&enabled_extensions, wi, enable_debug_utils)) if (!SelectInstanceExtensions(&enabled_extensions, wi, oe, enable_debug_utils))
return VK_NULL_HANDLE; return VK_NULL_HANDLE;
u32 maxApiVersion = VK_API_VERSION_1_0;
if (vkEnumerateInstanceVersion)
{
VkResult res = vkEnumerateInstanceVersion(&maxApiVersion);
if (res != VK_SUCCESS)
{
LOG_VULKAN_ERROR(res, "vkEnumerateInstanceVersion() failed: ");
maxApiVersion = VK_API_VERSION_1_0;
}
}
else
{
Log_WarningPrint("Driver does not provide vkEnumerateInstanceVersion().");
}
// Cap out at 1.1 for consistency.
*apiVersion = std::min(maxApiVersion, VK_API_VERSION_1_1);
Log_InfoFmt("Supported instance version: {}.{}.{}, requesting version {}.{}.{}", VK_API_VERSION_MAJOR(maxApiVersion),
VK_API_VERSION_MINOR(maxApiVersion), VK_API_VERSION_PATCH(maxApiVersion),
VK_API_VERSION_MAJOR(*apiVersion), VK_API_VERSION_MINOR(*apiVersion), VK_API_VERSION_PATCH(*apiVersion));
// Remember to manually update this every release. We don't pull in svnrev.h here, because // Remember to manually update this every release. We don't pull in svnrev.h here, because
// it's only the major/minor version, and rebuilding the file every time something else changes // it's only the major/minor version, and rebuilding the file every time something else changes
// is unnecessary. // is unnecessary.
@ -144,7 +165,7 @@ VkInstance VulkanDevice::CreateVulkanInstance(const WindowInfo& wi, bool enable_
app_info.applicationVersion = VK_MAKE_VERSION(0, 1, 0); app_info.applicationVersion = VK_MAKE_VERSION(0, 1, 0);
app_info.pEngineName = "DuckStation"; app_info.pEngineName = "DuckStation";
app_info.engineVersion = VK_MAKE_VERSION(0, 1, 0); app_info.engineVersion = VK_MAKE_VERSION(0, 1, 0);
app_info.apiVersion = VK_API_VERSION_1_1; app_info.apiVersion = *apiVersion;
VkInstanceCreateInfo instance_create_info = {}; VkInstanceCreateInfo instance_create_info = {};
instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
@ -175,7 +196,7 @@ VkInstance VulkanDevice::CreateVulkanInstance(const WindowInfo& wi, bool enable_
return instance; return instance;
} }
bool VulkanDevice::SelectInstanceExtensions(ExtensionList* extension_list, const WindowInfo& wi, bool VulkanDevice::SelectInstanceExtensions(ExtensionList* extension_list, const WindowInfo& wi, OptionalExtensions* oe,
bool enable_debug_utils) bool enable_debug_utils)
{ {
u32 extension_count = 0; u32 extension_count = 0;
@ -245,6 +266,9 @@ bool VulkanDevice::SelectInstanceExtensions(ExtensionList* extension_list, const
// Needed for exclusive fullscreen control. // Needed for exclusive fullscreen control.
SupportsExtension(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, false); SupportsExtension(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, false);
oe->vk_khr_get_physical_device_properties2 =
SupportsExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, false);
return true; return true;
} }
@ -367,6 +391,11 @@ bool VulkanDevice::SelectDeviceExtensions(ExtensionList* extension_list, bool en
SupportsExtension(VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME, false); SupportsExtension(VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME, false);
m_optional_extensions.vk_ext_attachment_feedback_loop_layout = m_optional_extensions.vk_ext_attachment_feedback_loop_layout =
SupportsExtension(VK_EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_EXTENSION_NAME, false); SupportsExtension(VK_EXT_ATTACHMENT_FEEDBACK_LOOP_LAYOUT_EXTENSION_NAME, false);
m_optional_extensions.vk_khr_get_memory_requirements2 =
SupportsExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, false);
m_optional_extensions.vk_khr_bind_memory2 = SupportsExtension(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME, false);
m_optional_extensions.vk_khr_dedicated_allocation =
SupportsExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, false);
m_optional_extensions.vk_khr_driver_properties = SupportsExtension(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME, false); m_optional_extensions.vk_khr_driver_properties = SupportsExtension(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME, false);
m_optional_extensions.vk_khr_dynamic_rendering = m_optional_extensions.vk_khr_dynamic_rendering =
SupportsExtension(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME, false) && SupportsExtension(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME, false) &&
@ -625,23 +654,48 @@ void VulkanDevice::ProcessDeviceExtensions()
m_optional_extensions.vk_ext_rasterization_order_attachment_access ? "supported" : "NOT supported"); m_optional_extensions.vk_ext_rasterization_order_attachment_access ? "supported" : "NOT supported");
Log_InfoPrintf("VK_EXT_attachment_feedback_loop_layout is %s", Log_InfoPrintf("VK_EXT_attachment_feedback_loop_layout is %s",
m_optional_extensions.vk_ext_attachment_feedback_loop_layout ? "supported" : "NOT supported"); m_optional_extensions.vk_ext_attachment_feedback_loop_layout ? "supported" : "NOT supported");
Log_InfoPrintf("VK_KHR_get_memory_requirements2 is %s",
m_optional_extensions.vk_khr_get_memory_requirements2 ? "supported" : "NOT supported");
Log_InfoPrintf("VK_KHR_bind_memory2 is %s",
m_optional_extensions.vk_khr_bind_memory2 ? "supported" : "NOT supported");
Log_InfoPrintf("VK_KHR_get_physical_device_properties2 is %s",
m_optional_extensions.vk_khr_get_physical_device_properties2 ? "supported" : "NOT supported");
Log_InfoPrintf("VK_KHR_dedicated_allocation is %s",
m_optional_extensions.vk_khr_dedicated_allocation ? "supported" : "NOT supported");
Log_InfoPrintf("VK_KHR_dynamic_rendering is %s", Log_InfoPrintf("VK_KHR_dynamic_rendering is %s",
m_optional_extensions.vk_khr_dynamic_rendering ? "supported" : "NOT supported"); m_optional_extensions.vk_khr_dynamic_rendering ? "supported" : "NOT supported");
Log_InfoPrintf("VK_KHR_push_descriptor is %s", Log_InfoPrintf("VK_KHR_push_descriptor is %s",
m_optional_extensions.vk_khr_push_descriptor ? "supported" : "NOT supported"); m_optional_extensions.vk_khr_push_descriptor ? "supported" : "NOT supported");
} }
bool VulkanDevice::CreateAllocator() bool VulkanDevice::CreateAllocator(u32 apiVersion)
{ {
VmaAllocatorCreateInfo ci = {}; VmaAllocatorCreateInfo ci = {};
ci.vulkanApiVersion = VK_API_VERSION_1_1; ci.vulkanApiVersion = apiVersion;
ci.flags = VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT; ci.flags = VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT;
ci.physicalDevice = m_physical_device; ci.physicalDevice = m_physical_device;
ci.device = m_device; ci.device = m_device;
ci.instance = m_instance; ci.instance = m_instance;
if (apiVersion < VK_API_VERSION_1_1)
{
if (m_optional_extensions.vk_khr_get_memory_requirements2 && m_optional_extensions.vk_khr_dedicated_allocation)
{
Log_DevPrint("Enabling VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT on < Vulkan 1.1.");
ci.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT;
}
if (m_optional_extensions.vk_khr_bind_memory2)
{
Log_DevPrint("Enabling VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT on < Vulkan 1.1.");
ci.flags |= VMA_ALLOCATOR_CREATE_KHR_BIND_MEMORY2_BIT;
}
}
if (m_optional_extensions.vk_ext_memory_budget) if (m_optional_extensions.vk_ext_memory_budget)
{
Log_DevPrint("Enabling VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT.");
ci.flags |= VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT; ci.flags |= VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT;
}
// Limit usage of the DEVICE_LOCAL upload heap when we're using a debug device. // Limit usage of the DEVICE_LOCAL upload heap when we're using a debug device.
// On NVIDIA drivers, it results in frequently running out of device memory when trying to // On NVIDIA drivers, it results in frequently running out of device memory when trying to
@ -1715,7 +1769,9 @@ GPUDevice::AdapterAndModeList VulkanDevice::StaticGetAdapterAndModeList()
if (Vulkan::LoadVulkanLibrary()) if (Vulkan::LoadVulkanLibrary())
{ {
ScopedGuard lib_guard([]() { Vulkan::UnloadVulkanLibrary(); }); ScopedGuard lib_guard([]() { Vulkan::UnloadVulkanLibrary(); });
const VkInstance instance = CreateVulkanInstance(WindowInfo(), false, false); u32 apiVersion;
OptionalExtensions oe = {};
const VkInstance instance = CreateVulkanInstance(WindowInfo(), &apiVersion, &oe, false, false);
if (instance != VK_NULL_HANDLE) if (instance != VK_NULL_HANDLE)
{ {
if (Vulkan::LoadVulkanInstanceFunctions(instance)) if (Vulkan::LoadVulkanInstanceFunctions(instance))
@ -1797,7 +1853,9 @@ bool VulkanDevice::CreateDevice(const std::string_view& adapter, bool threaded_p
return false; return false;
} }
m_instance = CreateVulkanInstance(m_window_info, enable_debug_utils, enable_validation_layer); u32 apiVersion;
m_instance = CreateVulkanInstance(m_window_info, &apiVersion, &m_optional_extensions, enable_debug_utils,
enable_validation_layer);
if (m_instance == VK_NULL_HANDLE) if (m_instance == VK_NULL_HANDLE)
{ {
if (enable_debug_utils || enable_validation_layer) if (enable_debug_utils || enable_validation_layer)
@ -1805,7 +1863,8 @@ bool VulkanDevice::CreateDevice(const std::string_view& adapter, bool threaded_p
// Try again without the validation layer. // Try again without the validation layer.
enable_debug_utils = false; enable_debug_utils = false;
enable_validation_layer = false; enable_validation_layer = false;
m_instance = CreateVulkanInstance(m_window_info, enable_debug_utils, enable_validation_layer); m_instance = CreateVulkanInstance(m_window_info, &apiVersion, &m_optional_extensions, enable_debug_utils,
enable_validation_layer);
if (m_instance == VK_NULL_HANDLE) if (m_instance == VK_NULL_HANDLE)
{ {
Host::ReportErrorAsync("Error", Host::ReportErrorAsync("Error",
@ -1894,8 +1953,11 @@ bool VulkanDevice::CreateDevice(const std::string_view& adapter, bool threaded_p
} }
// And critical resources. // And critical resources.
if (!CreateAllocator() || !CreatePersistentDescriptorPool() || !CreateCommandBuffers() || !CreatePipelineLayouts()) if (!CreateAllocator(apiVersion) || !CreatePersistentDescriptorPool() || !CreateCommandBuffers() ||
!CreatePipelineLayouts())
{
return false; return false;
}
if (threaded_presentation) if (threaded_presentation)
StartPresentThread(); StartPresentThread();

View file

@ -44,6 +44,10 @@ public:
bool vk_ext_rasterization_order_attachment_access : 1; bool vk_ext_rasterization_order_attachment_access : 1;
bool vk_ext_attachment_feedback_loop_layout : 1; bool vk_ext_attachment_feedback_loop_layout : 1;
bool vk_ext_full_screen_exclusive : 1; bool vk_ext_full_screen_exclusive : 1;
bool vk_khr_get_memory_requirements2 : 1;
bool vk_khr_bind_memory2 : 1;
bool vk_khr_get_physical_device_properties2 : 1;
bool vk_khr_dedicated_allocation : 1;
bool vk_khr_driver_properties : 1; bool vk_khr_driver_properties : 1;
bool vk_khr_dynamic_rendering : 1; bool vk_khr_dynamic_rendering : 1;
bool vk_khr_push_descriptor : 1; bool vk_khr_push_descriptor : 1;
@ -279,7 +283,8 @@ private:
static void GetAdapterAndModeList(AdapterAndModeList* ret, VkInstance instance); static void GetAdapterAndModeList(AdapterAndModeList* ret, VkInstance instance);
// Helper method to create a Vulkan instance. // Helper method to create a Vulkan instance.
static VkInstance CreateVulkanInstance(const WindowInfo& wi, bool enable_debug_utils, bool enable_validation_layer); static VkInstance CreateVulkanInstance(const WindowInfo& wi, u32* apiVersion, OptionalExtensions* oe,
bool enable_debug_utils, bool enable_validation_layer);
// Returns a list of Vulkan-compatible GPUs. // Returns a list of Vulkan-compatible GPUs.
using GPUList = std::vector<std::pair<VkPhysicalDevice, std::string>>; using GPUList = std::vector<std::pair<VkPhysicalDevice, std::string>>;
@ -307,7 +312,8 @@ private:
bool CheckLastSubmitFail(); bool CheckLastSubmitFail();
using ExtensionList = std::vector<const char*>; using ExtensionList = std::vector<const char*>;
static bool SelectInstanceExtensions(ExtensionList* extension_list, const WindowInfo& wi, bool enable_debug_utils); static bool SelectInstanceExtensions(ExtensionList* extension_list, const WindowInfo& wi, OptionalExtensions* oe,
bool enable_debug_utils);
bool SelectDeviceExtensions(ExtensionList* extension_list, bool enable_surface); bool SelectDeviceExtensions(ExtensionList* extension_list, bool enable_surface);
bool SelectDeviceFeatures(); bool SelectDeviceFeatures();
bool CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer); bool CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer);
@ -315,7 +321,7 @@ private:
bool CheckFeatures(FeatureMask disabled_features); bool CheckFeatures(FeatureMask disabled_features);
bool CreateAllocator(); bool CreateAllocator(u32 apiVersion);
void DestroyAllocator(); void DestroyAllocator();
bool CreateCommandBuffers(); bool CreateCommandBuffers();
void DestroyCommandBuffers(); void DestroyCommandBuffers();

View file

@ -84,9 +84,9 @@ VULKAN_INSTANCE_ENTRY_POINT(vkGetDisplayPlaneCapabilitiesKHR, false)
VULKAN_INSTANCE_ENTRY_POINT(vkCreateDisplayPlaneSurfaceKHR, false) VULKAN_INSTANCE_ENTRY_POINT(vkCreateDisplayPlaneSurfaceKHR, false)
// Vulkan 1.1 functions. // Vulkan 1.1 functions.
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceFeatures2, true) VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceFeatures2, false)
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceProperties2, true) VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceProperties2, false)
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceMemoryProperties2, true) VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceMemoryProperties2, false)
// VK_EXT_calibrated_timestamps // VK_EXT_calibrated_timestamps
VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceCalibrateableTimeDomainsEXT, false) VULKAN_INSTANCE_ENTRY_POINT(vkGetPhysicalDeviceCalibrateableTimeDomainsEXT, false)
@ -222,10 +222,10 @@ VULKAN_DEVICE_ENTRY_POINT(vkAcquireNextImageKHR, false)
VULKAN_DEVICE_ENTRY_POINT(vkQueuePresentKHR, false) VULKAN_DEVICE_ENTRY_POINT(vkQueuePresentKHR, false)
// Vulkan 1.1 functions. // Vulkan 1.1 functions.
VULKAN_DEVICE_ENTRY_POINT(vkGetBufferMemoryRequirements2, true) VULKAN_DEVICE_ENTRY_POINT(vkGetBufferMemoryRequirements2, false)
VULKAN_DEVICE_ENTRY_POINT(vkGetImageMemoryRequirements2, true) VULKAN_DEVICE_ENTRY_POINT(vkGetImageMemoryRequirements2, false)
VULKAN_DEVICE_ENTRY_POINT(vkBindBufferMemory2, true) VULKAN_DEVICE_ENTRY_POINT(vkBindBufferMemory2, false)
VULKAN_DEVICE_ENTRY_POINT(vkBindImageMemory2, true) VULKAN_DEVICE_ENTRY_POINT(vkBindImageMemory2, false)
// Vulkan 1.3 functions. // Vulkan 1.3 functions.
VULKAN_DEVICE_ENTRY_POINT(vkGetDeviceBufferMemoryRequirements, false) VULKAN_DEVICE_ENTRY_POINT(vkGetDeviceBufferMemoryRequirements, false)

View file

@ -81,7 +81,7 @@
#endif #endif
#define VMA_STATIC_VULKAN_FUNCTIONS 1 #define VMA_STATIC_VULKAN_FUNCTIONS 1
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 0 #define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
#define VMA_STATS_STRING_ENABLED 0 #define VMA_STATS_STRING_ENABLED 0
#include "vulkan/vk_mem_alloc.h" #include "vulkan/vk_mem_alloc.h"