|
|
|
@ -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);
|
|
|
|
|
}
|
|
|
|
|