diff options
| author | Andre Weissflog <floooh@gmail.com> | 2026-01-24 13:47:44 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-24 13:47:44 +0100 |
| commit | 8d0436e28458eb78e664607a9c272d6d9aabf015 (patch) | |
| tree | cf8aea88ab2ba7d14ada4b14c947ecee3e11b3b1 | |
| parent | 5a6100f6b8d94e308aa3023aac0a8635ca5fe185 (diff) | |
Vulkan backend: enable debug object labels. (#1422)
| -rw-r--r-- | CHANGELOG.md | 6 | ||||
| -rw-r--r-- | sokol_app.h | 59 | ||||
| -rw-r--r-- | sokol_gfx.h | 35 | ||||
| -rw-r--r-- | sokol_glue.h | 1 |
4 files changed, 92 insertions, 9 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index dcfe9408..1698b5d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ ## Updates +### 24-Jan-2026 + +- sokol_app.h/sokol_gfx.h vk: object debug labels are now working in the experimental + Vulkan backend (via `VK_EXT_debug_utils`). Debug labels are only set in debug mode + (e.g. `SOKOL_DEBUG` is defined). PR: https://github.com/floooh/sokol/pull/1422 + ### 19-Jan-2026 - sokol_gfx.h gl: merged PR https://github.com/floooh/sokol/pull/1414, this enables diff --git a/sokol_app.h b/sokol_app.h index 5082d23c..d183e893 100644 --- a/sokol_app.h +++ b/sokol_app.h @@ -1811,6 +1811,7 @@ typedef struct sapp_allocator { _SAPP_LOGITEM_XMACRO(WGPU_REQUEST_ADAPTER_STATUS_ERROR, "wgpu: requesting adapter failed with status 'error'") \ _SAPP_LOGITEM_XMACRO(WGPU_REQUEST_ADAPTER_STATUS_UNKNOWN, "wgpu: requesting adapter failed with status 'unknown'") \ _SAPP_LOGITEM_XMACRO(WGPU_CREATE_INSTANCE_FAILED, "wgpu: failed to create instance") \ + _SAPP_LOGITEM_XMACRO(VULKAN_REQUIRED_INSTANCE_EXTENSION_FUNCTION_MISSING, "vulkan: could not lookup a required instance extension function pointer") \ _SAPP_LOGITEM_XMACRO(VULKAN_ALLOC_DEVICE_MEMORY_NO_SUITABLE_MEMORY_TYPE, "vulkan: could not find suitable memory type") \ _SAPP_LOGITEM_XMACRO(VULKAN_ALLOCATE_MEMORY_FAILED, "vulkan: vkAllocateMemory() failed!") \ _SAPP_LOGITEM_XMACRO(VULKAN_CREATE_INSTANCE_FAILED, "vulkan: vkCreateInstance failed") \ @@ -1892,6 +1893,7 @@ typedef struct sapp_wgpu_environment { } sapp_wgpu_environment; typedef struct sapp_vulkan_environment { + const void* instance; const void* physical_device; const void* device; const void* queue; @@ -2807,6 +2809,9 @@ typedef struct { VkSemaphore render_finished_sem; VkSemaphore present_complete_sem; } sync[_SAPP_VK_MAX_SWAPCHAIN_IMAGES]; + struct { + PFN_vkSetDebugUtilsObjectNameEXT set_debug_utils_object_name_ext; + } ext; } _sapp_vk_t; #endif @@ -4274,6 +4279,38 @@ _SOKOL_PRIVATE void _sapp_wgpu_frame(void) { #define _SAPP_VK_MAX_COUNT_AND_ARRAY(num, type, count_name, array_name) uint32_t count_name = num; type array_name[num] = {0} #endif +_SOKOL_PRIVATE void _sapp_vk_load_instance_ext_funcs(void) { + SOKOL_ASSERT(_sapp.vk.instance); + #if defined(SOKOL_DEBUG) + _sapp.vk.ext.set_debug_utils_object_name_ext = (PFN_vkSetDebugUtilsObjectNameEXT)vkGetInstanceProcAddr(_sapp.vk.instance, "vkSetDebugUtilsObjectNameEXT"); + if (0 == _sapp.vk.ext.set_debug_utils_object_name_ext) { + _SAPP_PANIC(VULKAN_REQUIRED_INSTANCE_EXTENSION_FUNCTION_MISSING); + } + #endif +} + +_SOKOL_PRIVATE void _sapp_vk_set_object_label(VkObjectType obj_type, uint64_t obj_handle, const char* label) { + #if defined(SOKOL_DEBUG) + SOKOL_ASSERT(_sapp.vk.device); + SOKOL_ASSERT(_sapp.vk.ext.set_debug_utils_object_name_ext); + SOKOL_ASSERT(obj_handle); + if (label) { + _SAPP_STRUCT(VkDebugUtilsObjectNameInfoEXT, name_info); + name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; + name_info.objectType = obj_type; + name_info.objectHandle = obj_handle, + name_info.pObjectName = label; + VkResult res = _sapp.vk.ext.set_debug_utils_object_name_ext(_sapp.vk.device, &name_info); + SOKOL_ASSERT(res == VK_SUCCESS); + } + #else + _SOKOL_UNUSED(obj_type); + _SOKOL_UNUSED(obj_handle); + _SOKOL_UNUSED(label); + return; + #endif +} + _SOKOL_PRIVATE int _sapp_vk_mem_find_memory_type_index(uint32_t type_filter, VkMemoryPropertyFlags props) { SOKOL_ASSERT(_sapp.vk.physical_device); _SAPP_STRUCT(VkPhysicalDeviceMemoryProperties, mem_props); @@ -4305,6 +4342,9 @@ _SOKOL_PRIVATE void _sapp_vk_create_instance(void) { _SAPP_VK_ZERO_COUNT_AND_ARRAY(32, const char*, ext_count, ext_names); ext_names[ext_count++] = VK_KHR_SURFACE_EXTENSION_NAME; + #if defined(SOKOL_DEBUG) + ext_names[ext_count++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME; + #endif #if defined(VK_USE_PLATFORM_XLIB_KHR) ext_names[ext_count++] = VK_KHR_XLIB_SURFACE_EXTENSION_NAME; #elif defined(VK_USE_PLATFORM_WIN32_KHR) @@ -4588,8 +4628,10 @@ _SOKOL_PRIVATE void _sapp_vk_create_sync_objects(void) { SOKOL_ASSERT(0 == _sapp.vk.sync[i].render_finished_sem); res = vkCreateSemaphore(_sapp.vk.device, &create_info, 0, &_sapp.vk.sync[i].present_complete_sem); SOKOL_ASSERT((res == VK_SUCCESS) && (_sapp.vk.sync[i].present_complete_sem)); + _sapp_vk_set_object_label(VK_OBJECT_TYPE_SEMAPHORE, (uint64_t)_sapp.vk.sync[i].present_complete_sem, "present_complete_sem"); res = vkCreateSemaphore(_sapp.vk.device, &create_info, 0, &_sapp.vk.sync[i].render_finished_sem); SOKOL_ASSERT((res == VK_SUCCESS) && (_sapp.vk.sync[i].render_finished_sem)); + _sapp_vk_set_object_label(VK_OBJECT_TYPE_SEMAPHORE, (uint64_t)_sapp.vk.sync[i].render_finished_sem, "render_finished_sem"); } } @@ -4654,7 +4696,9 @@ _SOKOL_PRIVATE void _sapp_vk_swapchain_create_surface( uint32_t height, VkSampleCountFlagBits sample_count_flags, VkImageUsageFlags usage, - VkImageAspectFlags aspect_mask) + VkImageAspectFlags aspect_mask, + const char* image_debug_label, + const char* view_debug_label) { SOKOL_ASSERT(_sapp.vk.physical_device); SOKOL_ASSERT(_sapp.vk.device); @@ -4686,6 +4730,7 @@ _SOKOL_PRIVATE void _sapp_vk_swapchain_create_surface( _SAPP_PANIC(VULKAN_SWAPCHAIN_CREATE_IMAGE_FAILED); } SOKOL_ASSERT(surf->img); + _sapp_vk_set_object_label(VK_OBJECT_TYPE_IMAGE, (uint64_t)surf->img, image_debug_label); _SAPP_STRUCT(VkMemoryRequirements, mem_reqs); vkGetImageMemoryRequirements(_sapp.vk.device, surf->img, &mem_reqs); @@ -4712,6 +4757,7 @@ _SOKOL_PRIVATE void _sapp_vk_swapchain_create_surface( _SAPP_PANIC(VULKAN_SWAPCHAIN_CREATE_IMAGE_VIEW_FAILED); } SOKOL_ASSERT(surf->view); + _sapp_vk_set_object_label(VK_OBJECT_TYPE_IMAGE_VIEW, (uint64_t)surf->view, view_debug_label); } _SOKOL_PRIVATE void _sapp_vk_create_swapchain(bool recreate) { @@ -4801,6 +4847,7 @@ _SOKOL_PRIVATE void _sapp_vk_create_swapchain(bool recreate) { _SAPP_PANIC(VULKAN_SWAPCHAIN_CREATE_IMAGE_VIEW_FAILED); } SOKOL_ASSERT(_sapp.vk.swapchain_views[i]); + _sapp_vk_set_object_label(VK_OBJECT_TYPE_IMAGE_VIEW, (uint64_t)_sapp.vk.swapchain_views[i], "swapchain_view"); } // create depth-stencil buffer @@ -4811,7 +4858,9 @@ _SOKOL_PRIVATE void _sapp_vk_create_swapchain(bool recreate) { height, (VkSampleCountFlagBits)_sapp.sample_count, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, - VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); + VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, + "swapchain_depthstencil_image", + "swapchain_depthstencil_view"); // optionally create MSAA surface if (_sapp.sample_count > 1) { @@ -4822,7 +4871,9 @@ _SOKOL_PRIVATE void _sapp_vk_create_swapchain(bool recreate) { height, (VkSampleCountFlagBits)_sapp.sample_count, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, - VK_IMAGE_ASPECT_COLOR_BIT); + VK_IMAGE_ASPECT_COLOR_BIT, + "swapchain_msaa_image", + "swapchain_msaa_view"); } // this is the only place in the Vulkan code path which updates @@ -4872,6 +4923,7 @@ _SOKOL_PRIVATE void _sapp_vk_recreate_swapchain(void) { _SOKOL_PRIVATE void _sapp_vk_init(void) { _sapp_vk_create_instance(); + _sapp_vk_load_instance_ext_funcs(); _sapp_vk_create_surface(); _sapp_vk_pick_physical_device(); _sapp_vk_create_device(); @@ -13880,6 +13932,7 @@ SOKOL_API_IMPL sapp_environment sapp_get_environment(void) { res.wgpu.device = (const void*) _sapp.wgpu.device; #endif #if defined(SOKOL_VULKAN) + res.vulkan.instance = (const void*) _sapp.vk.instance; res.vulkan.physical_device = (const void*) _sapp.vk.physical_device; res.vulkan.device = (const void*) _sapp.vk.device; res.vulkan.queue = (const void*) _sapp.vk.queue; diff --git a/sokol_gfx.h b/sokol_gfx.h index 76ebc01e..8a5d6495 100644 --- a/sokol_gfx.h +++ b/sokol_gfx.h @@ -4955,6 +4955,7 @@ typedef struct sg_wgpu_environment { } sg_wgpu_environment; typedef struct sg_vulkan_environment { + const void* instance; const void* physical_device; const void* device; const void* queue; @@ -7099,6 +7100,7 @@ typedef struct { typedef struct { bool valid; + VkInstance instance; VkPhysicalDevice phys_dev; VkDevice dev; VkQueue queue; @@ -7109,6 +7111,7 @@ typedef struct { // extension function pointers struct { + PFN_vkSetDebugUtilsObjectNameEXT set_debug_utils_object_name_ext; PFN_vkGetDescriptorSetLayoutSizeEXT get_descriptor_set_layout_size; PFN_vkGetDescriptorSetLayoutBindingOffsetEXT get_descriptor_set_layout_binding_offset; PFN_vkGetDescriptorEXT get_descriptor; @@ -18620,12 +18623,24 @@ _SOKOL_PRIVATE void _sg_wgpu_update_image(_sg_image_t* img, const sg_image_data* #elif defined(SOKOL_VULKAN) _SOKOL_PRIVATE void _sg_vk_set_object_label(VkObjectType obj_type, uint64_t obj_handle, const char* label) { - SOKOL_ASSERT(_sg.vk.dev); - SOKOL_ASSERT(obj_handle != 0); - if (label) { - // FIXME: use vkSetDebugUtilsObjectNamesEXT - _SOKOL_UNUSED(obj_type && obj_handle && label); - } + #if defined(SOKOL_DEBUG) + SOKOL_ASSERT(_sg.vk.dev); + SOKOL_ASSERT(_sg.vk.ext.set_debug_utils_object_name_ext); + SOKOL_ASSERT(obj_handle != 0); + if (label) { + _SG_STRUCT(VkDebugUtilsObjectNameInfoEXT, name_info); + name_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; + name_info.objectType = obj_type; + name_info.objectHandle = obj_handle, + name_info.pObjectName = label; + VkResult res = _sg.vk.ext.set_debug_utils_object_name_ext(_sg.vk.dev, &name_info); + SOKOL_ASSERT(res == VK_SUCCESS); + } + #else + _SOKOL_UNUSED(obj_type); + _SOKOL_UNUSED(obj_handle); + _SOKOL_UNUSED(label); + #endif } _SOKOL_PRIVATE bool _sg_vk_is_read_access(_sg_vk_access_t access) { @@ -20330,6 +20345,12 @@ _SOKOL_PRIVATE VkBorderColor _sg_vk_sampler_border_color(sg_border_color c) { _SOKOL_PRIVATE void _sg_vk_load_ext_funcs(void) { SOKOL_ASSERT(_sg.vk.dev); + #if defined(SOKOL_DEBUG) + _sg.vk.ext.set_debug_utils_object_name_ext = (PFN_vkSetDebugUtilsObjectNameEXT)vkGetInstanceProcAddr(_sg.vk.instance, "vkSetDebugUtilsObjectNameEXT"); + if (0 == _sg.vk.ext.set_debug_utils_object_name_ext) { + _SG_PANIC(VULKAN_REQUIRED_EXTENSION_FUNCTION_MISSING); + } + #endif _sg.vk.ext.get_descriptor_set_layout_size = (PFN_vkGetDescriptorSetLayoutSizeEXT)vkGetDeviceProcAddr(_sg.vk.dev, "vkGetDescriptorSetLayoutSizeEXT"); if (0 == _sg.vk.ext.get_descriptor_set_layout_size) { _SG_PANIC(VULKAN_REQUIRED_EXTENSION_FUNCTION_MISSING); @@ -20630,11 +20651,13 @@ _SOKOL_PRIVATE void _sg_vk_submit_frame_command_buffers(void) { _SOKOL_PRIVATE void _sg_vk_setup_backend(const sg_desc* desc) { SOKOL_ASSERT(desc); + SOKOL_ASSERT(desc->environment.vulkan.instance); SOKOL_ASSERT(desc->environment.vulkan.physical_device); SOKOL_ASSERT(desc->environment.vulkan.device); SOKOL_ASSERT(desc->environment.vulkan.queue); SOKOL_ASSERT(desc->uniform_buffer_size > 0); _sg.vk.valid = true; + _sg.vk.instance = (VkInstance) desc->environment.vulkan.instance; _sg.vk.phys_dev = (VkPhysicalDevice) desc->environment.vulkan.physical_device; _sg.vk.dev = (VkDevice) desc->environment.vulkan.device; _sg.vk.queue = (VkQueue) desc->environment.vulkan.queue; diff --git a/sokol_glue.h b/sokol_glue.h index c8f2a2ff..d9a2ad4d 100644 --- a/sokol_glue.h +++ b/sokol_glue.h @@ -166,6 +166,7 @@ SOKOL_API_IMPL sg_environment sglue_environment(void) { res.d3d11.device = env.d3d11.device; res.d3d11.device_context = env.d3d11.device_context; res.wgpu.device = env.wgpu.device; + res.vulkan.instance = env.vulkan.instance; res.vulkan.physical_device = env.vulkan.physical_device; res.vulkan.device = env.vulkan.device; res.vulkan.queue = env.vulkan.queue; |