|
|
|
@ -31,10 +31,34 @@ |
|
|
|
|
|
|
|
namespace Vulkan { |
|
|
|
namespace { |
|
|
|
|
|
|
|
[[nodiscard]] bool AreExtensionsSupported(const vk::InstanceDispatch& dld, |
|
|
|
std::span<const char* const> extensions) { |
|
|
|
const std::optional properties = vk::EnumerateInstanceExtensionProperties(dld); |
|
|
|
if (!properties) { |
|
|
|
LOG_ERROR(Render_Vulkan, "Failed to query extension properties"); |
|
|
|
return false; |
|
|
|
} |
|
|
|
for (const char* extension : extensions) { |
|
|
|
const auto it = std::ranges::find_if(*properties, [extension](const auto& prop) { |
|
|
|
return std::strcmp(extension, prop.extensionName) == 0; |
|
|
|
}); |
|
|
|
if (it == properties->end()) { |
|
|
|
LOG_ERROR(Render_Vulkan, "Required instance extension {} is not available", extension); |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
[[nodiscard]] std::vector<const char*> RequiredExtensions( |
|
|
|
Core::Frontend::WindowSystemType window_type, bool enable_validation) { |
|
|
|
const vk::InstanceDispatch& dld, Core::Frontend::WindowSystemType window_type, |
|
|
|
bool enable_validation) { |
|
|
|
std::vector<const char*> extensions; |
|
|
|
extensions.reserve(6); |
|
|
|
#ifdef __APPLE__
|
|
|
|
extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); |
|
|
|
#endif
|
|
|
|
switch (window_type) { |
|
|
|
case Core::Frontend::WindowSystemType::Headless: |
|
|
|
break; |
|
|
|
@ -66,35 +90,14 @@ namespace { |
|
|
|
extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME); |
|
|
|
} |
|
|
|
if (enable_validation) { |
|
|
|
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); |
|
|
|
const bool debug_utils = |
|
|
|
AreExtensionsSupported(dld, std::array{VK_EXT_DEBUG_UTILS_EXTENSION_NAME}); |
|
|
|
extensions.push_back(debug_utils ? VK_EXT_DEBUG_UTILS_EXTENSION_NAME |
|
|
|
: VK_EXT_DEBUG_REPORT_EXTENSION_NAME); |
|
|
|
} |
|
|
|
extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); |
|
|
|
|
|
|
|
#ifdef __APPLE__
|
|
|
|
extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); |
|
|
|
#endif
|
|
|
|
return extensions; |
|
|
|
} |
|
|
|
|
|
|
|
[[nodiscard]] bool AreExtensionsSupported(const vk::InstanceDispatch& dld, |
|
|
|
std::span<const char* const> extensions) { |
|
|
|
const std::optional properties = vk::EnumerateInstanceExtensionProperties(dld); |
|
|
|
if (!properties) { |
|
|
|
LOG_ERROR(Render_Vulkan, "Failed to query extension properties"); |
|
|
|
return false; |
|
|
|
} |
|
|
|
for (const char* extension : extensions) { |
|
|
|
const auto it = std::ranges::find_if(*properties, [extension](const auto& prop) { |
|
|
|
return std::strcmp(extension, prop.extensionName) == 0; |
|
|
|
}); |
|
|
|
if (it == properties->end()) { |
|
|
|
LOG_ERROR(Render_Vulkan, "Required instance extension {} is not available", extension); |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
[[nodiscard]] std::vector<const char*> Layers(bool enable_validation) { |
|
|
|
std::vector<const char*> layers; |
|
|
|
if (enable_validation) { |
|
|
|
@ -138,7 +141,8 @@ vk::Instance CreateInstance(const Common::DynamicLibrary& library, vk::InstanceD |
|
|
|
LOG_ERROR(Render_Vulkan, "Failed to load Vulkan function pointers"); |
|
|
|
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); |
|
|
|
} |
|
|
|
const std::vector<const char*> extensions = RequiredExtensions(window_type, enable_validation); |
|
|
|
const std::vector<const char*> extensions = |
|
|
|
RequiredExtensions(dld, window_type, enable_validation); |
|
|
|
if (!AreExtensionsSupported(dld, extensions)) { |
|
|
|
throw vk::Exception(VK_ERROR_EXTENSION_NOT_PRESENT); |
|
|
|
} |
|
|
|
|