#ifndef WITH_VALIDATION #define WITH_VALIDATION #endif #include #include #include #include #include #include "eprintf.h" #include "nelem.h" #include "validation.h" static const char *vlayers[] = { "VK_LAYER_LUNARG_standard_validation", }; static const char *vexts[] = { VK_EXT_DEBUG_REPORT_EXTENSION_NAME, }; // callback: Validation callback static VKAPI_ATTR VkBool32 VKAPI_CALL callback( VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT type, uint64_t obj, size_t location, int32_t code, const char *prefix, const char *msg, void *data) { (void)flags; (void)type; (void)obj; (void)location; (void)code; (void)prefix; (void)data; weprintf("Validation: %s", msg); return VK_FALSE; } // havelayers: Check if all required validation layers are supported static bool havelayers(void) { VkLayerProperties *instlrp; uint32_t ninstlrp; static enum { UNK, NO, YES } have = UNK; if (have != UNK) return have == YES; have = NO; vkEnumerateInstanceLayerProperties(&ninstlrp, NULL); instlrp = emalloc(ninstlrp * sizeof *instlrp); vkEnumerateInstanceLayerProperties(&ninstlrp, instlrp); for (size_t vl = 0; vl < NELEM(vlayers); vl++) { for (uint32_t il = 0; il < ninstlrp; il++) if (strcmp(vlayers[vl], instlrp[il].layerName) == 0) goto next; goto fail_layers; next: ; } have = YES; fail_layers: free(instlrp); return have == YES; } // validation_info: Append validation layers and extension void validation_info(struct strlist *layers, struct strlist *exts) { if (havelayers() && layers != NULL) sl_append(layers, vlayers, NELEM(vlayers)); if (exts != NULL) sl_append(exts, vexts, NELEM(vexts)); } // validation_createcb: Create the validation callback void *validation_createcb(VkInstance inst) { VkDebugReportCallbackCreateInfoEXT rccinf; PFN_vkCreateDebugReportCallbackEXT func; VkDebugReportCallbackEXT *cb; func = (PFN_vkCreateDebugReportCallbackEXT) vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT"); if (func == NULL) eprintf("Validation: Could not create callback: Failed to get constructor"); rccinf = (VkDebugReportCallbackCreateInfoEXT){ .sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT, .flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT, .pfnCallback = callback, }; cb = emalloc(sizeof *cb); if (func(inst, &rccinf, NULL, cb) != VK_SUCCESS) eprintf("Validation: Could not create callback: Constructor"); return cb; } // validation_destroycb: Destroy the validation callback void validation_destroycb(VkInstance inst, void *_cb) { PFN_vkDestroyDebugReportCallbackEXT func; VkDebugReportCallbackEXT *cb = _cb; assert(cb != NULL); func = (PFN_vkDestroyDebugReportCallbackEXT) vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT"); if (func == NULL) eprintf("Validation: Could not destroy callback: Failed to get destructor"); func(inst, *cb, NULL); free(cb); }