Further improve VK extension loading. Switch to VK_EXT_debug_utils (but fallback to VK_EXT_debug_report if only that is available).

This commit is contained in:
Henrik Rydgard 2019-02-05 13:00:23 +01:00 committed by Henrik Rydgård
parent 014668b9bc
commit 478b0b4278
8 changed files with 225 additions and 54 deletions

View File

@ -120,9 +120,6 @@ VkResult VulkanContext::CreateInstance(const CreateInfo &info) {
//#if defined(VK_USE_PLATFORM_XCB_KHR)
// instance_extensions_enabled_.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
//#endif
//#if defined(VK_USE_PLATFORM_MIR_KHR)
// instance_extensions_enabled_.push_back(VK_KHR_MIR_SURFACE_EXTENSION_NAME);
//#endif
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
if (IsInstanceExtensionAvailable(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME)) {
instance_extensions_enabled_.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
@ -131,12 +128,21 @@ VkResult VulkanContext::CreateInstance(const CreateInfo &info) {
#endif
if (flags_ & VULKAN_FLAG_VALIDATE) {
if (IsInstanceExtensionAvailable(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
if (IsInstanceExtensionAvailable(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
// Enable the validation layers
for (size_t i = 0; i < ARRAY_SIZE(validationLayers); i++) {
instance_layer_names_.push_back(validationLayers[i]);
device_layer_names_.push_back(validationLayers[i]);
}
instance_extensions_enabled_.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
extensionsLookup_.EXT_debug_utils = true;
} else if (IsInstanceExtensionAvailable(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
for (size_t i = 0; i < ARRAY_SIZE(validationLayers); i++) {
instance_layer_names_.push_back(validationLayers[i]);
device_layer_names_.push_back(validationLayers[i]);
}
instance_extensions_enabled_.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
extensionsLookup_.EXT_debug_report = true;
} else {
ELOG("Validation layer extension not available - not enabling Vulkan validation.");
flags_ &= ~VULKAN_FLAG_VALIDATE;
@ -195,7 +201,7 @@ VkResult VulkanContext::CreateInstance(const CreateInfo &info) {
return res;
}
VulkanLoadInstanceFunctions(instance_);
VulkanLoadInstanceFunctions(instance_, extensionsLookup_);
if (!CheckLayers(instance_layer_properties_, instance_layer_names_)) {
WLOG("CheckLayers for instance failed");
// init_error_ = "Failed to validate instance layers";
@ -604,8 +610,8 @@ VkResult VulkanContext::CreateDevice() {
return VK_ERROR_INITIALIZATION_FAILED;
}
VkDeviceQueueCreateInfo queue_info{ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO };
float queue_priorities[1] = { 1.0f };
VkDeviceQueueCreateInfo queue_info{VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO};
float queue_priorities[1] = {1.0f};
queue_info.queueCount = 1;
queue_info.pQueuePriorities = queue_priorities;
bool found = false;
@ -618,12 +624,24 @@ VkResult VulkanContext::CreateDevice() {
}
assert(found);
extensionsLookup_.KHR_maintenance1 = EnableDeviceExtension(VK_KHR_MAINTENANCE1_EXTENSION_NAME);
extensionsLookup_.KHR_maintenance2 = EnableDeviceExtension(VK_KHR_MAINTENANCE2_EXTENSION_NAME);
extensionsLookup_.KHR_maintenance3 = EnableDeviceExtension(VK_KHR_MAINTENANCE3_EXTENSION_NAME);
extensionsLookup_.KHR_multiview = EnableDeviceExtension(VK_KHR_MULTIVIEW_EXTENSION_NAME);
if (EnableDeviceExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME)) {
extensionsLookup_.KHR_get_memory_requirements2 = true;
extensionsLookup_.KHR_dedicated_allocation = EnableDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
}
extensionsLookup_.EXT_external_memory_host = EnableDeviceExtension(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME);
extensionsLookup_.KHR_depth_stencil_resolve = EnableDeviceExtension(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME);
if (EnableDeviceExtension(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME)) {
if (EnableDeviceExtension(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME)) {
extensionsLookup_.EXT_external_memory_host = EnableDeviceExtension(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME);
}
}
if (EnableDeviceExtension(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME)) {
extensionsLookup_.KHR_create_renderpass2 = true;
extensionsLookup_.KHR_depth_stencil_resolve = EnableDeviceExtension(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME);
}
extensionsLookup_.EXT_shader_stencil_export = EnableDeviceExtension(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME);
VkDeviceCreateInfo device_info{ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
@ -640,7 +658,7 @@ VkResult VulkanContext::CreateDevice() {
init_error_ = "Unable to create Vulkan device";
ELOG("Unable to create Vulkan device");
} else {
VulkanLoadDeviceFunctions(device_);
VulkanLoadDeviceFunctions(device_, extensionsLookup_);
}
ILOG("Device created.\n");
VulkanSetAvailable(true);
@ -662,7 +680,7 @@ VkResult VulkanContext::InitDebugMsgCallback(PFN_vkDebugReportCallbackEXT dbgFun
cb.flags = bits;
cb.pfnCallback = dbgFunc;
cb.pUserData = userdata;
VkResult res = dyn_vkCreateDebugReportCallbackEXT(instance_, &cb, nullptr, &msg_callback);
VkResult res = vkCreateDebugReportCallbackEXT(instance_, &cb, nullptr, &msg_callback);
switch (res) {
case VK_SUCCESS:
msg_callbacks.push_back(msg_callback);
@ -676,12 +694,42 @@ VkResult VulkanContext::InitDebugMsgCallback(PFN_vkDebugReportCallbackEXT dbgFun
}
void VulkanContext::DestroyDebugMsgCallback() {
if (!extensionsLookup_.EXT_debug_report)
return;
while (msg_callbacks.size() > 0) {
dyn_vkDestroyDebugReportCallbackEXT(instance_, msg_callbacks.back(), nullptr);
vkDestroyDebugReportCallbackEXT(instance_, msg_callbacks.back(), nullptr);
msg_callbacks.pop_back();
}
}
VkResult VulkanContext::InitDebugUtilsCallback(PFN_vkDebugUtilsMessengerCallbackEXT callback, int bits, void *userdata) {
VkDebugUtilsMessengerCreateInfoEXT callback1{VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT};
callback1.messageSeverity = bits;
callback1.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
callback1.pfnUserCallback = callback;
callback1.pUserData = userdata;
VkDebugUtilsMessengerEXT messenger;
VkResult res = vkCreateDebugUtilsMessengerEXT(instance_, &callback1, nullptr, &messenger);
if (res != VK_SUCCESS) {
ELOG("Failed to register debug callback with vkCreateDebugUtilsMessengerEXT");
// Do error handling for VK_ERROR_OUT_OF_MEMORY
} else {
ILOG("Debug callback registered with vkCreateDebugUtilsMessengerEXT.");
utils_callbacks.push_back(messenger);
}
return res;
}
void VulkanContext::DestroyDebugUtilsCallback() {
if (!extensionsLookup_.EXT_debug_utils)
return;
while (utils_callbacks.size() > 0) {
vkDestroyDebugUtilsMessengerEXT(instance_, utils_callbacks.back(), nullptr);
utils_callbacks.pop_back();
}
}
VkResult VulkanContext::InitSurface(WindowSystem winsys, void *data1, void *data2) {
winsys_ = winsys;
winsysData1_ = data1;

View File

@ -101,17 +101,6 @@ private:
std::vector<Callback> callbacks_;
};
// For fast extension-enabled checks.
struct VulkanDeviceExtensions {
bool KHR_get_memory_requirements2;
bool KHR_dedicated_allocation;
bool EXT_external_memory_host;
bool KHR_get_physical_device_properties2;
bool KHR_depth_stencil_resolve;
bool EXT_shader_stencil_export;
// bool EXT_depth_range_unrestricted; // Allows depth outside [0.0, 1.0] in 32-bit float depth buffers.
};
// Useful for debugging on ARM Mali. This eliminates transaction elimination
// which can cause artifacts if you get barriers wrong (or if there are driver bugs).
// Cost is reduced performance on some GPU architectures.
@ -175,7 +164,11 @@ public:
bool MemoryTypeFromProperties(uint32_t typeBits, VkFlags requirements_mask, uint32_t *typeIndex);
VkResult InitDebugMsgCallback(PFN_vkDebugReportCallbackEXT dbgFunc, int bits, void *userdata = nullptr);
VkResult InitDebugUtilsCallback(PFN_vkDebugUtilsMessengerCallbackEXT callback, int bits, void *userdata);
void DestroyDebugUtilsCallback();
// Legacy reporting
VkResult InitDebugMsgCallback(PFN_vkDebugReportCallbackEXT dbgFunc, int bits, void *userdata);
void DestroyDebugMsgCallback();
VkPhysicalDevice GetPhysicalDevice(int n = 0) const {
@ -334,6 +327,7 @@ private:
VulkanDeleteList globalDeleteList_;
std::vector<VkDebugReportCallbackEXT> msg_callbacks;
std::vector<VkDebugUtilsMessengerEXT> utils_callbacks;
VkSwapchainKHR swapchain_ = VK_NULL_HANDLE;
VkFormat swapchainFormat_;

View File

@ -56,7 +56,7 @@ const char *ObjTypeToString(VkDebugReportObjectTypeEXT type) {
}
}
VkBool32 VKAPI_CALL Vulkan_Dbg(VkDebugReportFlagsEXT msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg, void *pUserData) {
VkBool32 VKAPI_CALL VulkanDebugReportCallback(VkDebugReportFlagsEXT msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg, void *pUserData) {
const VulkanLogOptions *options = (const VulkanLogOptions *)pUserData;
std::ostringstream message;
@ -103,3 +103,60 @@ VkBool32 VKAPI_CALL Vulkan_Dbg(VkDebugReportFlagsEXT msgFlags, VkDebugReportObje
// keep that behavior here.
return false;
}
VkBool32 VKAPI_CALL VulkanDebugUtilsCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData) {
const VulkanLogOptions *options = (const VulkanLogOptions *)pUserData;
std::ostringstream message;
const char *pMessage = pCallbackData->pMessage;
int messageCode = pCallbackData->messageIdNumber;
const char *pLayerPrefix = "";
// Ignore perf warnings for now. Could log them, so still want them registered.
if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
message << "ERROR(";
} else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
message << "WARNING(";
} else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) {
message << "INFO(";
} else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) {
message << "VERBOSE(";
}
if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) {
message << "perf";
} else if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) {
message << "general";
} else if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) {
message << "validation";
}
message << ":" << pCallbackData->messageIdNumber << ") " << pMessage << "\n";
#ifdef _WIN32
std::string msg = message.str();
OutputDebugStringA(msg.c_str());
if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
if (options->breakOnError && IsDebuggerPresent()) {
DebugBreak();
}
if (options->msgBoxOnError) {
MessageBoxA(NULL, pMessage, "Alert", MB_OK);
}
} else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
if (options->breakOnWarning && IsDebuggerPresent() && 0 == (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)) {
DebugBreak();
}
}
#endif
// false indicates that layer should not bail-out of an
// API call that had validation failures. This may mean that the
// app dies inside the driver due to invalid parameter(s).
// That's what would happen without validation layers, so we'll
// keep that behavior here.
return false;
}

View File

@ -25,4 +25,5 @@ struct VulkanLogOptions {
bool msgBoxOnError;
};
VkBool32 VKAPI_CALL Vulkan_Dbg(VkDebugReportFlagsEXT msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg, void *pUserData);
VkBool32 VKAPI_CALL VulkanDebugReportCallback(VkDebugReportFlagsEXT msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg, void *pUserData);
VkBool32 VKAPI_CALL VulkanDebugUtilsCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData);

View File

@ -193,8 +193,16 @@ PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR;
PFN_vkQueuePresentKHR vkQueuePresentKHR;
// And the DEBUG_REPORT extension. We dynamically load this.
PFN_vkCreateDebugReportCallbackEXT dyn_vkCreateDebugReportCallbackEXT;
PFN_vkDestroyDebugReportCallbackEXT dyn_vkDestroyDebugReportCallbackEXT;
PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT;
PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT;
PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT;
PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT;
PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT;
PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT;
PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT;
PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT;
PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT;
PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT;
PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR;
@ -262,19 +270,22 @@ bool VulkanMayBeAvailable() {
VkApplicationInfo info{ VK_STRUCTURE_TYPE_APPLICATION_INFO };
std::vector<VkPhysicalDevice> devices;
bool anyGood = false;
const char *instanceExtensions[1]{};
const char *instanceExtensions[2]{};
VkInstance instance = VK_NULL_HANDLE;
VkResult res;
uint32_t physicalDeviceCount = 0;
uint32_t instanceExtCount = 0;
uint32_t instanceExtCount = 1;
bool surfaceExtensionFound = false;
bool platformSurfaceExtensionFound = false;
std::vector<VkExtensionProperties> instanceExts;
instanceExtensions[ci.enabledExtensionCount++] = VK_KHR_SURFACE_EXTENSION_NAME;
#ifdef _WIN32
const char * const surfaceExtension = VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
const char * const platformSurfaceExtension = VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
#elif defined(__ANDROID__)
const char *surfaceExtension = VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
const char *platformSurfaceExtension = VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
#else
const char *surfaceExtension = 0;
const char *platformSurfaceExtension = 0;
#endif
if (!localEnumerateInstanceExtensionProperties || !localCreateInstance || !localEnumerate || !localDestroyInstance || !localGetPhysicalDeviceProperties)
@ -297,16 +308,18 @@ bool VulkanMayBeAvailable() {
goto bail;
}
if (surfaceExtension) {
if (platformSurfaceExtension) {
for (auto iter : instanceExts) {
if (!strcmp(iter.extensionName, surfaceExtension)) {
instanceExtensions[0] = surfaceExtension;
ci.enabledExtensionCount = 1;
if (!strcmp(iter.extensionName, platformSurfaceExtension)) {
instanceExtensions[ci.enabledExtensionCount++] = platformSurfaceExtension;
platformSurfaceExtensionFound = true;
break;
} else if (!strcmp(iter.extensionName, VK_KHR_SURFACE_EXTENSION_NAME)) {
surfaceExtensionFound = true;
}
}
if (!ci.enabledExtensionCount) {
ELOG("Surface extension not found");
if (!platformSurfaceExtensionFound || !surfaceExtensionFound) {
ELOG("Platform surface extension not found");
goto bail;
}
}
@ -411,7 +424,7 @@ bool VulkanLoad() {
return true;
}
void VulkanLoadInstanceFunctions(VkInstance instance) {
void VulkanLoadInstanceFunctions(VkInstance instance, const VulkanDeviceExtensions &enabledExtensions) {
// OK, let's use the above functions to get the rest.
LOAD_INSTANCE_FUNC(instance, vkDestroyInstance);
LOAD_INSTANCE_FUNC(instance, vkEnumeratePhysicalDevices);
@ -570,11 +583,26 @@ void VulkanLoadInstanceFunctions(VkInstance instance) {
#endif
LOAD_INSTANCE_FUNC(instance, vkDestroySurfaceKHR);
LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceProperties2KHR);
LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceFeatures2KHR);
dyn_vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT");
dyn_vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT");
if (enabledExtensions.KHR_get_physical_device_properties2) {
LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceProperties2KHR);
LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceFeatures2KHR);
}
if (enabledExtensions.EXT_debug_report) {
LOAD_INSTANCE_FUNC(instance, vkCreateDebugReportCallbackEXT);
LOAD_INSTANCE_FUNC(instance, vkDestroyDebugReportCallbackEXT);
}
if (enabledExtensions.EXT_debug_utils) {
LOAD_INSTANCE_FUNC(instance, vkCreateDebugUtilsMessengerEXT);
LOAD_INSTANCE_FUNC(instance, vkDestroyDebugUtilsMessengerEXT);
LOAD_INSTANCE_FUNC(instance, vkCmdBeginDebugUtilsLabelEXT);
LOAD_INSTANCE_FUNC(instance, vkCmdEndDebugUtilsLabelEXT);
LOAD_INSTANCE_FUNC(instance, vkCmdInsertDebugUtilsLabelEXT);
LOAD_INSTANCE_FUNC(instance, vkSetDebugUtilsObjectNameEXT);
LOAD_INSTANCE_FUNC(instance, vkSetDebugUtilsObjectTagEXT);
}
WLOG("Vulkan instance functions loaded.");
}
@ -582,7 +610,7 @@ void VulkanLoadInstanceFunctions(VkInstance instance) {
// On some implementations, loading functions (that have Device as their first parameter) via vkGetDeviceProcAddr may
// increase performance - but then these function pointers will only work on that specific device. Thus, this loader is not very
// good for multi-device.
void VulkanLoadDeviceFunctions(VkDevice device) {
void VulkanLoadDeviceFunctions(VkDevice device, const VulkanDeviceExtensions &enabledExtensions) {
WLOG("Vulkan device functions loaded.");
// TODO: Move more functions VulkanLoadInstanceFunctions to here.
LOAD_DEVICE_FUNC(device, vkCreateSwapchainKHR);
@ -590,9 +618,13 @@ void VulkanLoadDeviceFunctions(VkDevice device) {
LOAD_DEVICE_FUNC(device, vkGetSwapchainImagesKHR);
LOAD_DEVICE_FUNC(device, vkAcquireNextImageKHR);
LOAD_DEVICE_FUNC(device, vkQueuePresentKHR);
LOAD_DEVICE_FUNC(device, vkGetMemoryHostPointerPropertiesEXT);
LOAD_DEVICE_FUNC(device, vkGetBufferMemoryRequirements2KHR);
LOAD_DEVICE_FUNC(device, vkGetImageMemoryRequirements2KHR);
if (enabledExtensions.EXT_external_memory_host) {
LOAD_DEVICE_FUNC(device, vkGetMemoryHostPointerPropertiesEXT);
}
if (enabledExtensions.KHR_dedicated_allocation) {
LOAD_DEVICE_FUNC(device, vkGetBufferMemoryRequirements2KHR);
LOAD_DEVICE_FUNC(device, vkGetImageMemoryRequirements2KHR);
}
}
void VulkanFree() {

View File

@ -197,8 +197,16 @@ extern PFN_vkQueuePresentKHR vkQueuePresentKHR;
// And the DEBUG_REPORT extension. Since we load this dynamically even in static
// linked mode, we have to rename it :(
extern PFN_vkCreateDebugReportCallbackEXT dyn_vkCreateDebugReportCallbackEXT;
extern PFN_vkDestroyDebugReportCallbackEXT dyn_vkDestroyDebugReportCallbackEXT;
extern PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT;
extern PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT;
extern PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT;
extern PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT;
extern PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT;
extern PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT;
extern PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT;
extern PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT;
extern PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT;
// Assorted other extensions.
extern PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR;
@ -207,11 +215,30 @@ extern PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesE
extern PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR;
extern PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR;
// For fast extension-enabled checks.
struct VulkanDeviceExtensions {
bool EXT_debug_report;
bool EXT_debug_utils;
bool KHR_maintenance1; // required for KHR_create_renderpass2
bool KHR_maintenance2;
bool KHR_maintenance3;
bool KHR_multiview; // required for KHR_create_renderpass2
bool KHR_get_memory_requirements2;
bool KHR_dedicated_allocation;
bool KHR_create_renderpass2;
bool EXT_external_memory_host;
bool KHR_get_physical_device_properties2;
bool KHR_depth_stencil_resolve;
bool EXT_shader_stencil_export;
// bool EXT_depth_range_unrestricted; // Allows depth outside [0.0, 1.0] in 32-bit float depth buffers.
};
// Way to do a quick check before even attempting to load.
bool VulkanMayBeAvailable();
void VulkanSetAvailable(bool available);
bool VulkanLoad();
void VulkanLoadInstanceFunctions(VkInstance instance);
void VulkanLoadDeviceFunctions(VkDevice device);
void VulkanLoadInstanceFunctions(VkInstance instance, const VulkanDeviceExtensions &enabledExtensions);
void VulkanLoadDeviceFunctions(VkDevice device, const VulkanDeviceExtensions &enabledExtensions);
void VulkanFree();

View File

@ -124,8 +124,17 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m
return false;
}
if (g_validate_) {
int bits = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
g_Vulkan->InitDebugMsgCallback(&Vulkan_Dbg, bits, &g_LogOptions);
if (g_Vulkan->DeviceExtensions().EXT_debug_utils) {
int bits = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
g_Vulkan->InitDebugUtilsCallback(&VulkanDebugUtilsCallback, bits, &g_LogOptions);
} else {
int bits = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
g_Vulkan->InitDebugMsgCallback(&VulkanDebugReportCallback, bits, &g_LogOptions);
}
}
g_Vulkan->InitSurface(WINDOWSYSTEM_WIN32, (void *)hInst, (void *)hWnd);
if (!g_Vulkan->InitObjects()) {
@ -160,6 +169,7 @@ void WindowsVulkanContext::Shutdown() {
g_Vulkan->WaitUntilQueueIdle();
g_Vulkan->DestroyObjects();
g_Vulkan->DestroyDevice();
g_Vulkan->DestroyDebugUtilsCallback();
g_Vulkan->DestroyDebugMsgCallback();
g_Vulkan->DestroyInstance();

View File

@ -160,6 +160,7 @@ bool AndroidVulkanContext::InitFromRenderThread(ANativeWindow *wnd, int desiredB
if (!success) {
g_Vulkan->DestroyObjects();
g_Vulkan->DestroyDevice();
g_Vulkan->DestroyDebugUtilsCallback();
g_Vulkan->DestroyDebugMsgCallback();
g_Vulkan->DestroyInstance();
@ -181,6 +182,7 @@ void AndroidVulkanContext::ShutdownFromRenderThread() {
void AndroidVulkanContext::Shutdown() {
ILOG("Calling NativeShutdownGraphics");
g_Vulkan->DestroyDevice();
g_Vulkan->DestroyDebugUtilsCallback();
g_Vulkan->DestroyDebugMsgCallback();
g_Vulkan->DestroyInstance();