From 8b85e422d7b2bc061a91aa72db25582ce15a9fde Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 30 Nov 2021 12:24:45 +0900 Subject: [PATCH] [vulkan] Add a debug stack to the vulkan instance The stack is arbitrary strings that the validation layer debug callback prints in reverse order after each message. This makes it easy to work out what nodes in a pipeline/render pass plist are causing validation errors. Still have to narrow down the actual line, but the messages seem to help with that. Putting qfvPushDebug/qfvPopDebug around other calls to vulkan should help out a lot, tool. As a bonus, the stack is printed before debug_breakpoint is called, so it's immediately visible in gdb. --- include/QF/Vulkan/instance.h | 4 ++++ include/vid_vulkan.h | 14 ++++++++++++++ libs/video/renderer/vulkan/instance.c | 5 +++++ libs/video/renderer/vulkan/vkparse.c | 27 ++++++++++++++++++++++++++- libs/video/targets/vid_x11_vulkan.c | 2 +- 5 files changed, 50 insertions(+), 2 deletions(-) diff --git a/include/QF/Vulkan/instance.h b/include/QF/Vulkan/instance.h index 4df1827c5..692dd5964 100644 --- a/include/QF/Vulkan/instance.h +++ b/include/QF/Vulkan/instance.h @@ -28,6 +28,7 @@ #include +#include "QF/darray.h" #include "QF/qtypes.h" typedef struct qfv_instfuncs_s { @@ -36,6 +37,8 @@ typedef struct qfv_instfuncs_s { #include "QF/Vulkan/funclist.h" } qfv_instfuncs_t; +typedef struct DARRAY_TYPE(const char *) qfv_debugstack_t; + typedef struct qfv_physdev_s { struct qfv_instance_s *instance; VkPhysicalDevice dev; @@ -52,6 +55,7 @@ typedef struct qfv_instance_s { VkDebugUtilsMessengerEXT debug_handle; uint32_t numDevices; qfv_physdev_t *devices; + qfv_debugstack_t debug_stack; } qfv_instance_t; struct vulkan_ctx_s; diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 8a7cd1535..55841b1d0 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -110,4 +110,18 @@ typedef struct vulkan_ctx_s { #include "QF/Vulkan/funclist.h" } vulkan_ctx_t; +#define qfvPushDebug(ctx, x) \ + do { \ + if (developer->int_val & SYS_vulkan) { \ + DARRAY_APPEND(&(ctx)->instance->debug_stack, (x)); \ + } \ + } while (0) +#define qfvPopDebug(ctx) \ + do { \ + if (developer->int_val & SYS_vulkan) { \ + __auto_type ds = &(ctx)->instance->debug_stack; \ + DARRAY_REMOVE_AT(ds, ds->size - 1); \ + } \ + } while (0) + #endif//__vid_vulkan_h diff --git a/libs/video/renderer/vulkan/instance.c b/libs/video/renderer/vulkan/instance.c index acb9234bf..4ba0a9cd8 100644 --- a/libs/video/renderer/vulkan/instance.c +++ b/libs/video/renderer/vulkan/instance.c @@ -136,6 +136,7 @@ debug_callback (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, const VkDebugUtilsMessengerCallbackDataEXT* callbackData, void *data) { + qfv_instance_t *instance = data; if (!(messageSeverity & vulkan_use_validation->int_val)) { return 0; } @@ -154,6 +155,9 @@ debug_callback (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, } fprintf (stderr, "validation layer: %s%s\n", msgSev, callbackData->pMessage); + for (size_t i = instance->debug_stack.size; i-- > 0; ) { + fprintf (stderr, " %s\n", instance->debug_stack.a[i]); + } debug_breakpoint (messageSeverity); return VK_FALSE; } @@ -264,6 +268,7 @@ QFV_CreateInstance (vulkan_ctx_t *ctx, inst->funcs = (qfv_instfuncs_t *)(inst + 1); inst->enabled_extensions = new_strset (ext); inst->extension_enabled = instance_extension_enabled; + DARRAY_INIT (&inst->debug_stack, 8); ctx->instance = inst; load_instance_funcs (ctx); diff --git a/libs/video/renderer/vulkan/vkparse.c b/libs/video/renderer/vulkan/vkparse.c index 1873c2d42..822c562a6 100644 --- a/libs/video/renderer/vulkan/vkparse.c +++ b/libs/video/renderer/vulkan/vkparse.c @@ -480,7 +480,10 @@ parse_VkShaderModule (const plitem_t *item, void **data, if (*handle) { return 1; } - if (!(*handle = QFV_CreateShaderModule (device, name))) { + qfvPushDebug (ctx, va (ctx->va_ctx, "parse_VkShaderModule: %d", PL_Line (item))); + *handle = QFV_CreateShaderModule (device, name); + qfvPopDebug (ctx); + if (!*handle) { PL_Message (messages, item, "could not find shader %s", name); return 0; } @@ -1030,10 +1033,12 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) } VkRenderPass renderpass; + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseRenderPass: %d", PL_Line (plist))); renderpass = QFV_CreateRenderPass (device, renderpass_data.attachments, renderpass_data.subpasses, renderpass_data.dependencies); + qfvPopDebug (ctx); delete_memsuper (memsuper); return renderpass; @@ -1055,7 +1060,9 @@ QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) } cInfo->a[0].renderPass = ctx->renderpass; + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParsePipeline: %d", PL_Line (plist))); __auto_type plSet = QFV_CreateGraphicsPipelines (device, 0, cInfo); + qfvPopDebug (ctx); VkPipeline pipeline = plSet->a[0]; free (plSet); delete_memsuper (memsuper); @@ -1079,7 +1086,9 @@ QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist, } VkDescriptorPool pool; + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseDescriptorPool: %d", PL_Line (plist))); dfunc->vkCreateDescriptorPool (device->dev, &cInfo, 0, &pool); + qfvPopDebug (ctx); delete_memsuper (memsuper); return pool; @@ -1103,10 +1112,12 @@ QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, plitem_t *plist, } VkDescriptorSetLayout setLayout; + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseDescriptorSetLayout: %d", PL_Line (plist))); dfunc->vkCreateDescriptorSetLayout (device->dev, &cInfo, 0, &setLayout); QFV_duSetObjectName (device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, setLayout, va (ctx->va_ctx, "descriptorSetLayout:%d", PL_Line (plist))); + qfvPopDebug (ctx); delete_memsuper (memsuper); return setLayout; @@ -1129,10 +1140,12 @@ QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist, } VkPipelineLayout layout; + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParsePipelineLayout: %d", PL_Line (plist))); dfunc->vkCreatePipelineLayout (device->dev, &cInfo, 0, &layout); QFV_duSetObjectName (device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, layout, va (ctx->va_ctx, "pipelineLayout:%d", PL_Line (plist))); + qfvPopDebug (ctx); delete_memsuper (memsuper); return layout; @@ -1154,7 +1167,9 @@ QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) } VkSampler sampler; + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseSampler: %d", PL_Line (plist))); dfunc->vkCreateSampler (device->dev, &cInfo, 0, &sampler); + qfvPopDebug (ctx); delete_memsuper (memsuper); return sampler; @@ -1176,7 +1191,9 @@ QFV_ParseImage (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) } VkImage image; + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseImage: %d", PL_Line (plist))); dfunc->vkCreateImage (device->dev, &cInfo, 0, &image); + qfvPopDebug (ctx); delete_memsuper (memsuper); return image; @@ -1198,7 +1215,9 @@ QFV_ParseImageView (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) } VkImageView imageView; + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseImageView: %d", PL_Line (plist))); dfunc->vkCreateImageView (device->dev, &cInfo, 0, &imageView); + qfvPopDebug (ctx); delete_memsuper (memsuper); return imageView; @@ -1295,11 +1314,13 @@ QFV_ParseImageSet (vulkan_ctx_t *ctx, plitem_t *item, plitem_t *properties) __auto_type set = QFV_AllocImages (create.count, malloc); for (uint32_t i = 0; i < create.count; i++) { + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseImageSet: %d", PL_Line (item))); dfunc->vkCreateImage (device->dev, &create.info[i], 0, &set->a[i]); const char *name = PL_KeyAtIndex (item, i); QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, set->a[i], va (ctx->va_ctx, "image:%s", name)); + qfvPopDebug (ctx); name = resource_path (ctx, "images", name); QFV_AddHandle (ctx->images, name, (uint64_t) set->a[i]); } @@ -1334,7 +1355,9 @@ QFV_ParseImageViewSet (vulkan_ctx_t *ctx, plitem_t *item, __auto_type set = QFV_AllocImageViews (create.count, malloc); for (uint32_t i = 0; i < create.count; i++) { + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseImageViewSet: %d", PL_Line (item))); dfunc->vkCreateImageView (device->dev, &create.info[i], 0, &set->a[i]); + qfvPopDebug (ctx); const char *name = PL_KeyAtIndex (item, i); name = resource_path (ctx, "imageViews", name); @@ -1361,7 +1384,9 @@ QFV_ParseFramebuffer (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties) } VkFramebuffer framebuffer; + qfvPushDebug (ctx, va (ctx->va_ctx, "QFV_ParseFramebuffer: %d", PL_Line (plist))); dfunc->vkCreateFramebuffer (device->dev, &cInfo, 0, &framebuffer); + qfvPopDebug (ctx); Sys_MaskPrintf (SYS_vulkan_parse, "framebuffer, renderPass: %#zx, %#zx\n", (size_t) framebuffer, (size_t) cInfo.renderPass); diff --git a/libs/video/targets/vid_x11_vulkan.c b/libs/video/targets/vid_x11_vulkan.c index a65cd65b0..39bf90310 100644 --- a/libs/video/targets/vid_x11_vulkan.c +++ b/libs/video/targets/vid_x11_vulkan.c @@ -217,7 +217,7 @@ X11_Vulkan_Context (void) ctx->create_window = x11_vulkan_create_window; ctx->create_surface = x11_vulkan_create_surface; ctx->required_extensions = required_extensions; - ctx->va_ctx = va_create_context (4); + ctx->va_ctx = va_create_context (32); return ctx; }