taby said:
I've gone through a few tutorials on enabling validation layers, but it's not clear to me how to enable them.
It's really a must do. It's a debug callback. When there is an error, in the callback you get pointers to involved VK objects and a text message explaining the error. It's then easy to track back and fix things.
Posting some code to enable it, which i've got from some minimal ‘render a rotating cube’ example that came with the Vulkan SDK.
It won't help you much, but at least it gives some functions to search for.
I know this whole setup should be much easier nowadays. See the usual VK tutorials. I'm sure Sascha Willems has this too. Nobody could start with VK without this help.
static VKAPI_ATTR VkBool32 VKAPI_CALL
BreakCallback (VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
uint64_t srcObject, size_t location, int32_t msgCode,
const char *pLayerPrefix, const char *pMsg,
void *pUserData)
{
SystemTools::Log (pMsg); // the text massage describing the error
SystemTools::Log ("\n");
// some messages i have disabled manually, which i got after uninmstalling Steam or NVidia GPU...
//if (!strcmp(pMsg, " [ UNASSIGNED-CoreValidation-Shader-DescriptorTypeMismatch ] Object: VK_NULL_HANDLE (Type = 0) | Type mismatch on descriptor slot 0.0 (expected `VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC`) but descriptor of type VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER")) return false;
if (!strcmp(pMsg, "loader_get_json: Failed to open JSON file C:\\Program Files (x86)\\Steam\\SteamFossilizeVulkanLayer64.json")) return false; // uninstalling Steam? how dare you !!?
if (!strcmp(pMsg, "loader_get_json: Failed to open JSON file C:\\Program Files (x86)\\Steam\\SteamOverlayVulkanLayer64.json")) return false;
DebugBreak(); // Win32 function acting like a breakpoint
return false;
}
struct Context
{
enum
{
MAX_GPUS = 8,
};
VkInstance inst; // Vulkan instance, stores all per-application states
struct Gpu gpus[MAX_GPUS];
uint32_t gpuCount;
bool validate;
bool use_break;
PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallback;
PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallback;
VkDebugReportCallbackEXT msg_callback;
PFN_vkDebugReportMessageEXT DebugReportMessage;
void InitVK (const char* APP_SHORT_NAME, const bool validate = false, const bool use_break = false);
void Destroy ()
{
for (uint32_t i=0; i<gpuCount; i++) gpus[i].Destroy();
if (validate) DestroyDebugReportCallback (inst, msg_callback, NULL);
vkDestroyInstance (inst, NULL);
}
};
void Context::InitVK (const char* APP_SHORT_NAME, const bool validate, const bool use_break)
{
SystemTools::Log ("InitVK...\n");
this->validate = validate;
this->use_break = use_break;
for (int i=0; i<MAX_GPUS; i++) gpus[i].Init();
gpuCount = 0;
uint32_t instance_validation_layer_count = 0;
//@char *instance_validation_layers[MAX_LAYERS] = {};
const char *instance_validation_layers[] = {""};//"VK_LAYER_LUNARG_standard_validation"};
uint32_t enabled_instance_extension_count = 0;
char const *instance_extension_names[MAX_EXTENSIONS] = {};
VkResult err;
// Look for instance layers
if (validate)
{
//@VkBool32 validation_found = FindInstanceValidationLayers (instance_validation_layers, instance_validation_layer_count);
instance_validation_layer_count = 0;//1;
}
// Look for instance extensions
VkExtensionProperties* instance_extensions = NULL;
FindInstanceExtensions (instance_extensions,
enabled_instance_extension_count, instance_extension_names,
MAX_EXTENSIONS, validate, true);
inst = CreateInstance (APP_SHORT_NAME,
instance_validation_layer_count,
instance_validation_layers,
enabled_instance_extension_count,
instance_extension_names,
validate, use_break);
if(instance_extensions) free(instance_extensions);
// Make initial call to query gpu_count, then second call for physicalDevice info
err = vkEnumeratePhysicalDevices(inst, &gpuCount, NULL);
assert(!err && gpuCount > 0);
SystemTools::Log ("\nfound GPUs: %i\n", gpuCount);
if (gpuCount > 0)
{
VkPhysicalDevice *physical_devices = (VkPhysicalDevice*) malloc(sizeof(VkPhysicalDevice) * gpuCount);
err = vkEnumeratePhysicalDevices(inst, &gpuCount, physical_devices);
assert(!err);
for (uint32_t i=0; i<min(MAX_GPUS, gpuCount); i++)
{
gpus[i].physicalDevice = physical_devices[i]; //@@@
vkGetPhysicalDeviceProperties(gpus[i].physicalDevice, &gpus[i].physicalDeviceProps);
vkGetPhysicalDeviceFeatures(gpus[i].physicalDevice, &gpus[i].features);
vkGetPhysicalDeviceMemoryProperties(gpus[i].physicalDevice, &gpus[i].memoryProperties);
SystemTools::Log ("deviceName: %s\n", gpus[i].physicalDeviceProps.deviceName);
SystemTools::Log ("apiVersion: %i\n", gpus[i].physicalDeviceProps.apiVersion);
SystemTools::Log ("driverVersion: %i\n", gpus[i].physicalDeviceProps.driverVersion);
#if 0
// Look for validation layers
if (validate)
{
uint32_t device_enabled_layer_count;
VkBool32 validation_found = CheckDeviceValidationLayers (device_enabled_layer_count,
gpus[i].physicalDevice, instance_validation_layer_count, instance_validation_layers, validate);
}
#endif
// Look for device extensions
uint32_t enabled_device_extension_count = 0;
char *device_extension_names[MAX_EXTENSIONS] = {};
VkExtensionProperties* device_extensions = NULL;
LoadDeviceExtensions (device_extensions, enabled_device_extension_count, device_extension_names,
gpus[i].physicalDevice, MAX_EXTENSIONS, true, /*true*/false); // todo: loading all Extensions causes vkCreateDevice to fail on AMD
gpus[i].device = CreateDevice (
gpus[i].queueFamilyProps,
gpus[i].queueFamilyCount,
gpus[i].physicalDevice,
instance_validation_layer_count,
(const char *const *)((validate) ? instance_validation_layers : NULL),
enabled_device_extension_count,
device_extension_names);
if (device_extensions) free(device_extensions); // should we keep them?
/*VkDevice device2 = 0;
device2 = CreateDevice (
gpus[i].queueFamilyProps,
gpus[i].queueFamilyCount,
gpus[i].physicalDevice,
instance_validation_layer_count,
(const char *const *)((validate) ? instance_validation_layers : NULL),
enabled_extension_count,
extension_names);*/
VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {};
pipelineCacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
err = vkCreatePipelineCache (gpus[i].device, &pipelineCacheCreateInfo, nullptr, &gpus[i].pipelineCache);
assert(!err);
SystemTools::Log ("\n");
}
free(physical_devices);
}
else
{
ERR_EXIT("vkEnumeratePhysicalDevices reported zero accessible devices.\n\n"
"Do you have a compatible Vulkan installable client driver (ICD) "
"installed?\nPlease look at the Getting Started guide for "
"additional information.\n",
"vkEnumeratePhysicalDevices Failure");
}
//*
if (validate)
{
CreateDebugReportCallback = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT");
if (!CreateDebugReportCallback) ERR_EXIT("GetProcAddr: Unable to find vkCreateDebugReportCallbackEXT\n", "vkGetProcAddr Failure");
DestroyDebugReportCallback = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT");
if (!DestroyDebugReportCallback) ERR_EXIT("GetProcAddr: Unable to find vkDestroyDebugReportCallbackEXT\n", "vkGetProcAddr Failure");
DebugReportMessage = (PFN_vkDebugReportMessageEXT)vkGetInstanceProcAddr(inst, "vkDebugReportMessageEXT");
if (!DebugReportMessage) ERR_EXIT("GetProcAddr: Unable to find vkDebugReportMessageEXT\n", "vkGetProcAddr Failure");
PFN_vkDebugReportCallbackEXT callback = use_break ? BreakCallback : dbgFunc;
VkDebugReportCallbackCreateInfoEXT dbgCreateInfo = {};
dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
dbgCreateInfo.pNext = NULL;
dbgCreateInfo.pfnCallback = callback;
dbgCreateInfo.pUserData = NULL;
dbgCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
err = CreateDebugReportCallback(inst, &dbgCreateInfo, NULL, &msg_callback);
switch (err)
{
case VK_SUCCESS:
break;
case VK_ERROR_OUT_OF_HOST_MEMORY:
ERR_EXIT("CreateDebugReportCallback: out of host memory\n", "CreateDebugReportCallback Failure");
break;
default:
ERR_EXIT("CreateDebugReportCallback: unknown failure\n", "CreateDebugReportCallback Failure");
break;
}
}
//*/
}