diff --git a/src/main.cpp b/src/main.cpp index 1ec1f48e31..589e116d9e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -115,6 +115,7 @@ const struct option *gamescope_options = (struct option[]){ { "synchronous-x11", no_argument, nullptr, 0 }, { "debug-hud", no_argument, nullptr, 'v' }, { "debug-events", no_argument, nullptr, 0 }, + { "vulkan-debug-extension", no_argument, 0}, { "steam", no_argument, nullptr, 'e' }, { "force-composition", no_argument, nullptr, 'c' }, { "composite-debug", no_argument, nullptr, 0 }, @@ -229,7 +230,8 @@ const char usage[] = " --disable-xres disable XRes for PID lookup\n" " --hdr-debug-force-support forces support for HDR, etc even if the display doesn't support it. HDR clients will be outputted as SDR still in that case.\n" " --hdr-debug-force-output forces support and output to HDR10 PQ even if the output does not support it (will look very wrong if it doesn't)\n" - " --hdr-debug-heatmap displays a heatmap-style debug view of HDR luminence across the scene in nits." + " --hdr-debug-heatmap displays a heatmap-style debug view of HDR luminence across the scene in nits.\n" + " --vulkan-debug-extension loads vulkan debug extension(s). Supplies object names to validation layer messages." "\n" "Reshade shader options:\n" " --reshade-effect sets the name of a reshade shader to use in either /usr/share/gamescope/reshade/Shaders or ~/.local/share/gamescope/reshade/Shaders\n" @@ -326,7 +328,7 @@ bool BIsSDLSession( void ) } -static bool initOutput(int preferredWidth, int preferredHeight, int preferredRefresh); +static bool initOutput(int preferredWidth, int preferredHeight, int preferredRefresh, bool vulkanDebugEXT = false); static void steamCompMgrThreadRun(int argc, char **argv); static std::string build_optstring(const struct option *options) @@ -436,6 +438,10 @@ static void handle_signal( int sig ) } fprintf( stderr, "gamescope: Received %s signal, attempting shutdown!\n", strsignal(sig) ); + + if (vulkan_run_at_exit != nullptr) + (*vulkan_run_at_exit)(); + g_bRun = false; break; case SIGUSR1: @@ -554,7 +560,7 @@ int main(int argc, char **argv) static std::string optstring = build_optstring(gamescope_options); gamescope_optstring = optstring.c_str(); - + bool vulkanDebugEXT = false; int o; int opt_index = -1; while ((o = getopt_long(argc, argv, gamescope_optstring, gamescope_options, &opt_index)) != -1) @@ -612,6 +618,15 @@ int main(int argc, char **argv) g_bDebugLayers = true; } else if (strcmp(opt_name, "disable-color-management") == 0) { g_bForceDisableColorMgmt = true; + } else if (strcmp(opt_name, "vulkan-debug-extension") == 0) { + #ifndef NDEBUG + vulkanDebugEXT = true; + #else + fprintf(stderr, "gamescope is not compiled with --vulkan-debug-extension supported\n" + "to enable it, recompile gamescope after reconfiguring it with:\n" + "meson --reconfigure build -Db_ndebug=false\n"); + exit(1); + #endif } else if (strcmp(opt_name, "xwayland-count") == 0) { g_nXWaylandCount = atoi( optarg ); } else if (strcmp(opt_name, "composite-debug") == 0) { @@ -781,7 +796,7 @@ int main(int argc, char **argv) } #endif - if ( !initOutput( g_nPreferredOutputWidth, g_nPreferredOutputHeight, g_nNestedRefresh ) ) + if ( !initOutput( g_nPreferredOutputWidth, g_nPreferredOutputHeight, g_nNestedRefresh, vulkanDebugEXT ) ) { fprintf( stderr, "Failed to initialize output\n" ); return 1; @@ -905,9 +920,9 @@ static void steamCompMgrThreadRun(int argc, char **argv) pthread_kill( g_mainThread, SIGINT ); } -static bool initOutput( int preferredWidth, int preferredHeight, int preferredRefresh ) +static bool initOutput( int preferredWidth, int preferredHeight, int preferredRefresh, bool vulkanDebugEXT ) { - VkInstance instance = vulkan_create_instance(); + VkInstance instance = vulkan_create_instance(vulkanDebugEXT); if ( BIsNested() ) { diff --git a/src/rendervulkan.cpp b/src/rendervulkan.cpp index 3570186070..e9d2ba5369 100644 --- a/src/rendervulkan.cpp +++ b/src/rendervulkan.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #if defined(__linux__) #include @@ -47,6 +48,10 @@ #include "reshade_effect_manager.hpp" +static CVulkanDevice g_device; + +CVulkanDevice * m_device = nullptr; + extern bool g_bWasPartialComposite; static constexpr mat3x4 g_rgb2yuv_srgb_to_bt601_limited = {{ @@ -95,7 +100,8 @@ VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr( const char* pName); } - +bool vulkanDebugExtSupported=false; +static bool vulkanDebugEXT; VulkanOutput_t g_output; uint32_t g_uCompositeDebug = 0u; @@ -139,6 +145,35 @@ Target *pNextFind(const Base *base, VkStructureType sType) return nullptr; } +inline std::optional SetName_impl(const bool cond, void ** ptr, uint64_t objectHandle, const char * name, VkObjectType objectType, const void * pNext) noexcept +{ + if (cond) { + if (m_device != nullptr) { + return m_device->_SetName(objectHandle, name, objectType, pNext); + } else { + return g_device._SetName(objectHandle, name, objectType, pNext); + } + } + + return {}; +} + +inline std::optional CVulkanDevice::SetName_impl(const bool cond, void ** ptr, uint64_t objectHandle, const char * name, VkObjectType objectType, const void * pNext) noexcept +{ + if (cond && (objectType != VK_OBJECT_TYPE_UNKNOWN || ptr != nullptr)) + { + auto search = typeLookupTable.find(ptr); + if ( ptr != nullptr && search != typeLookupTable.end()) + objectType = search->second; + else if (objectType == VK_OBJECT_TYPE_UNKNOWN) { + vk_log.errorf( "couldn't find objectType for obj: %s", name); + } + _SetName(objectHandle, name, objectType, pNext); + } + return {}; +} + + #define VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA (VkStructureType)1000001002 #define VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA (VkStructureType)1000001003 @@ -623,6 +658,15 @@ bool CVulkanDevice::createDevice() #define VK_FUNC(x) vk.x = (PFN_vk##x) vk.GetDeviceProcAddr(device(), "vk"#x); VULKAN_DEVICE_FUNCTIONS #undef VK_FUNC + + + if (vulkanDebugExtSupported) + { + #define VK_FUNC(x) vk.x = (PFN_vk##x) vk.GetDeviceProcAddr(device(), "vk"#x); + VULKAN_DEVICE_FUNCTIONS_DEBUGGING + #undef VK_FUNC + } + vk.GetDeviceQueue(device(), m_queueFamily, 0, &m_queue); if ( m_queueFamily == m_generalQueueFamily ) @@ -688,7 +732,7 @@ bool CVulkanDevice::createLayouts() }; vk.CreateSamplerYcbcrConversion( device(), &ycbcrSamplerConversionCreateInfo, nullptr, &m_ycbcrConversion ); - + MARK(m_ycbcrConversion) VkSamplerYcbcrConversionInfo ycbcrSamplerConversionInfo = { .sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO, .conversion = m_ycbcrConversion, @@ -706,7 +750,7 @@ bool CVulkanDevice::createLayouts() }; vk.CreateSampler( device(), &ycbcrSamplerInfo, nullptr, &m_ycbcrSampler ); - + MARK(m_ycbcrSampler) // Create an array of our ycbcrSampler to fill up std::array ycbcrSamplers; for (auto& sampler : ycbcrSamplers) @@ -766,6 +810,7 @@ bool CVulkanDevice::createLayouts() }; VkResult res = vk.CreateDescriptorSetLayout(device(), &descriptorSetLayoutCreateInfo, 0, &m_descriptorSetLayout); + MARK(m_descriptorSetLayout) if ( res != VK_SUCCESS ) { vk_errorf( res, "vkCreateDescriptorSetLayout failed" ); @@ -779,6 +824,7 @@ bool CVulkanDevice::createLayouts() }; res = vk.CreatePipelineLayout(device(), &pipelineLayoutCreateInfo, nullptr, &m_pipelineLayout); + MARK(m_pipelineLayout) if ( res != VK_SUCCESS ) { vk_errorf( res, "vkCreatePipelineLayout failed" ); @@ -922,6 +968,7 @@ bool CVulkanDevice::createScratchResources() }; res = vk.CreateBuffer( device(), &bufferCreateInfo, nullptr, &m_uploadBuffer ); + MARK(m_uploadBuffer) if ( res != VK_SUCCESS ) { vk_errorf( res, "vkCreateBuffer failed" ); @@ -966,6 +1013,7 @@ bool CVulkanDevice::createScratchResources() }; res = vk.CreateSemaphore( device(), &semCreateInfo, NULL, &m_scratchTimelineSemaphore ); + MARK(m_scratchTimelineSemaphore) if ( res != VK_SUCCESS ) { vk_errorf( res, "vkCreateSemaphore failed" ); @@ -994,7 +1042,7 @@ VkSampler CVulkanDevice::sampler( SamplerState key ) }; vk.CreateSampler( device(), &samplerCreateInfo, nullptr, &ret ); - + MARK_TYPED(ret, VK_OBJECT_TYPE_SAMPLER) m_samplerCache[key] = ret; return ret; @@ -1082,6 +1130,7 @@ VkPipeline CVulkanDevice::compilePipeline(uint32_t layerCount, uint32_t ycbcrMas VkPipeline result; VkResult res = vk.CreateComputePipelines(device(), VK_NULL_HANDLE, 1, &computePipelineCreateInfo, nullptr, &result); + MARK_TYPED(result, VK_OBJECT_TYPE_PIPELINE) if (res != VK_SUCCESS) { vk_errorf( res, "vkCreateComputePipelines failed" ); return VK_NULL_HANDLE; @@ -1183,6 +1232,7 @@ std::unique_ptr CVulkanDevice::commandBuffer() }; VkResult res = vk.AllocateCommandBuffers( device(), &commandBufferAllocateInfo, &rawCmdBuffer ); + MARK_TYPED(rawCmdBuffer, VK_OBJECT_TYPE_BUFFER) if ( res != VK_SUCCESS ) { vk_errorf( res, "vkAllocateCommandBuffers failed" ); @@ -1575,6 +1625,9 @@ void CVulkanCmdBuffer::copyImage(std::shared_ptr src, std::share m_device->vk.CmdCopyImage(m_cmdBuffer, src->vkImage(), VK_IMAGE_LAYOUT_GENERAL, dst->vkImage(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); + MARK_TYPED(src->vkImage(), VK_OBJECT_TYPE_IMAGE) + MARK_TYPED(dst->vkImage(), VK_OBJECT_TYPE_IMAGE) + markDirty(dst.get()); } @@ -1599,6 +1652,8 @@ void CVulkanCmdBuffer::copyBufferToImage(VkBuffer buffer, VkDeviceSize offset, u m_device->vk.CmdCopyBufferToImage(m_cmdBuffer, buffer, dst->vkImage(), VK_IMAGE_LAYOUT_GENERAL, 1, ®ion); + MARK_TYPED(dst->vkImage(), VK_OBJECT_TYPE_IMAGE) + markDirty(dst.get()); } @@ -1686,7 +1741,9 @@ void CVulkanCmdBuffer::insertBarrier(bool flush) .image = image->vkImage(), .subresourceRange = subResRange }; - + + MARK_TYPED(memoryBarrier.image, VK_OBJECT_TYPE_IMAGE) + barriers.push_back(memoryBarrier); state.discarded = false; @@ -1697,9 +1754,9 @@ void CVulkanCmdBuffer::insertBarrier(bool flush) // TODO replace VK_PIPELINE_STAGE_ALL_COMMANDS_BIT m_device->vk.CmdPipelineBarrier(m_cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, nullptr, 0, nullptr, barriers.size(), barriers.data()); + MARK_TYPED(m_cmdBuffer, VK_OBJECT_TYPE_COMMAND_BUFFER); } -static CVulkanDevice g_device; static bool allDMABUFsEqual( wlr_dmabuf_attributes *pDMA ) { @@ -2013,6 +2070,7 @@ bool CVulkanTexture::BInit( uint32_t width, uint32_t height, uint32_t depth, uin m_format = imageInfo.format; res = g_device.vk.CreateImage(g_device.device(), &imageInfo, nullptr, &m_vkImage); + MARK_TYPED(m_vkImage, VK_OBJECT_TYPE_IMAGE) if (res != VK_SUCCESS) { vk_errorf( res, "vkCreateImage failed" ); return false; @@ -3261,8 +3319,54 @@ static bool init_nis_data() return true; } -VkInstance vulkan_create_instance( void ) +VKAPI_ATTR VkBool32 VKAPI_CALL debug_utils_messenger_callback +(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity + , VkDebugUtilsMessageTypeFlagsEXT message_type + , const VkDebugUtilsMessengerCallbackDataEXT *callback_data + , void *user_data) { + if ( g_device.bWantToClearDebug.load(std::memory_order_relaxed) || g_device.debugEXT_clearFlag.test_and_set(std::memory_order_acquire)) { + g_device.debugEXT_clearFlag.notify_all(); + return VK_FALSE; + } + + std::string s; + for (uint32_t i = 0; i < callback_data->objectCount; i++) { + const char * objname = callback_data->pObjects[i].pObjectName; + if (objname == nullptr) + s.append("NULL"); + else + s.append(callback_data->pObjects[i].pObjectName); + s.append("\n"); + } + if (message_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) + { + vk_log.infof("%i - %s: %s\nobject name(s): %s", callback_data->messageIdNumber, callback_data->pMessageIdName, callback_data->pMessage, s.c_str()); + } + else if (message_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) + { + vk_log.errorf("%i - %s: %s\nobject name(s): %s", callback_data->messageIdNumber, callback_data->pMessageIdName, callback_data->pMessage, s.c_str()); + } + + g_device.debugEXT_clearFlag.clear(); + g_device.debugEXT_clearFlag.notify_all(); + return VK_FALSE; +} + +VkDebugUtilsMessengerEXT debug_utils_messenger{VK_NULL_HANDLE}; +void (*vulkan_run_at_exit)(void) = nullptr; + +void vulkan_clear_debugEXT() +{ + g_device.bWantToClearDebug.store(true, std::memory_order_relaxed); + if (g_device.debugEXT_clearFlag.test_and_set(std::memory_order_acquire)) + g_device.debugEXT_clearFlag.wait(true); + auto func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(g_device.m_instance, "vkDestroyDebugUtilsMessengerEXT"); + func(g_device.m_instance, debug_utils_messenger, nullptr); +} + +VkInstance vulkan_create_instance(const bool bShouldDebug ) { + vulkanDebugEXT=bShouldDebug; VkResult result = VK_ERROR_INITIALIZATION_FAILED; std::vector< const char * > sdlExtensions; @@ -3285,7 +3389,26 @@ VkInstance vulkan_create_instance( void ) sdlExtensions.resize( extCount ); SDL_Vulkan_GetInstanceExtensions( nullptr, &extCount, sdlExtensions.data() ); } + + uint32_t instance_extension_count; + vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_count, nullptr); + std::vector available_instance_extensions(instance_extension_count); + + vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_count, available_instance_extensions.data()); + + for (auto &available_extension : available_instance_extensions) { + if (vulkanDebugEXT == true + && strcmp(available_extension.extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0) { + vulkanDebugExtSupported = true; + sdlExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + } + } + + if (vulkanDebugEXT == true && vulkanDebugExtSupported == false) + { + vk_log.errorf("VK_EXT_DEBUG_UTILS_EXTENSION_NAME is not supported, continuing without vulkan debug extension(s)"); + } const VkApplicationInfo appInfo = { .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, .pApplicationName = "gamescope", @@ -3295,7 +3418,7 @@ VkInstance vulkan_create_instance( void ) .apiVersion = VK_API_VERSION_1_3, }; - const VkInstanceCreateInfo createInfo = { + VkInstanceCreateInfo createInfo = { .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, .pApplicationInfo = &appInfo, .enabledExtensionCount = (uint32_t)sdlExtensions.size(), @@ -3303,7 +3426,28 @@ VkInstance vulkan_create_instance( void ) }; VkInstance instance = nullptr; - result = vkCreateInstance(&createInfo, 0, &instance); + if ( vulkanDebugEXT && vulkanDebugExtSupported) + { + VkDebugUtilsMessengerCreateInfoEXT debug_utils_create_info = {VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT}; + + debug_utils_create_info.messageSeverity = 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; + debug_utils_create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT; + debug_utils_create_info.pfnUserCallback = debug_utils_messenger_callback; + createInfo.pNext = &debug_utils_create_info; + + result = vkCreateInstance(&createInfo, 0, &instance); + + auto func = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); + result = func(instance, &debug_utils_create_info, nullptr, &debug_utils_messenger); + if (result == VK_SUCCESS) + vulkan_run_at_exit = vulkan_clear_debugEXT; + + } + else + { + result = vkCreateInstance(&createInfo, 0, &instance); + } + if ( result != VK_SUCCESS ) { vk_errorf( result, "vkCreateInstance failed" ); @@ -4047,6 +4191,7 @@ std::shared_ptr vulkan_create_texture_from_wlr_buffer( struct wl }; VkBuffer buffer; result = g_device.vk.CreateBuffer( g_device.device(), &bufferCreateInfo, nullptr, &buffer ); + MARK_TYPED(buffer, VK_OBJECT_TYPE_BUFFER) if ( result != VK_SUCCESS ) { wlr_buffer_end_data_ptr_access( buf ); diff --git a/src/rendervulkan.hpp b/src/rendervulkan.hpp index 98b3936f1c..f5cb8b9c6c 100644 --- a/src/rendervulkan.hpp +++ b/src/rendervulkan.hpp @@ -365,7 +365,7 @@ namespace CompositeDebugFlag static constexpr uint32_t Tonemap_Reinhard = 1u << 7; }; -VkInstance vulkan_create_instance(void); +VkInstance vulkan_create_instance(bool bShouldDebug); bool vulkan_init(VkInstance instance, VkSurfaceKHR surface); bool vulkan_init_formats(void); bool vulkan_make_output(); @@ -628,6 +628,9 @@ static inline uint32_t div_roundup(uint32_t x, uint32_t y) VK_FUNC(GetPhysicalDeviceSurfacePresentModesKHR) \ VK_FUNC(GetPhysicalDeviceSurfaceSupportKHR) +#define VULKAN_DEVICE_FUNCTIONS_DEBUGGING \ + VK_FUNC(SetDebugUtilsObjectNameEXT) + #define VULKAN_DEVICE_FUNCTIONS \ VK_FUNC(AcquireNextImageKHR) \ VK_FUNC(AllocateCommandBuffers) \ @@ -701,6 +704,8 @@ constexpr T align(T what, U to) { return (what + to - 1) & ~(to - 1); } +extern void (*vulkan_run_at_exit)(void); + class CVulkanDevice { public: @@ -762,14 +767,54 @@ class CVulkanDevice { VULKAN_INSTANCE_FUNCTIONS VULKAN_DEVICE_FUNCTIONS + VULKAN_DEVICE_FUNCTIONS_DEBUGGING } vk; #undef VK_FUNC void resetCmdBuffers(uint64_t sequence); + + std::atomic bWantToClearDebug = false; + + std::optional __attribute__((nothrow, visibility("protected"))) _SetName(uint64_t objectHandle = 0, const char * name = nullptr, VkObjectType objectType = VK_OBJECT_TYPE_UNKNOWN, const void * pNext = nullptr) noexcept + { + VkDebugUtilsObjectNameInfoEXT pNameInfo = { + .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, + .pNext = pNext, + .objectType = objectType, + .objectHandle = objectHandle, + .pObjectName = name + }; + return vk.SetDebugUtilsObjectNameEXT(device(), &pNameInfo); + } + + inline std::optional SetName_impl(const bool cond=false, void ** ptr = nullptr, uint64_t objectHandle = 0, const char * name = nullptr, VkObjectType objectType = VK_OBJECT_TYPE_UNKNOWN, const void * pNext = nullptr) noexcept; + + #define SetName(...) SetName_impl(vulkanDebugEXT == true && vulkanDebugExtSupported == true, ## __VA_ARGS__); + + #define _smark(name) #name + #define smark(name) _smark(name) + #define lineit_impl(line) line + #define lineit(line) lineit_impl(line) + #define _MARK_w_addr(name, ...) SetName( reinterpret_cast((&(name))), reinterpret_cast(name), smark(name lineit((line __LINE__))), ## __VA_ARGS__) + #define _MARK(name, ...) SetName( nullptr, reinterpret_cast(name), smark(name lineit((line __LINE__))), ## __VA_ARGS__) + +#ifndef NDEBUG + #define MARK(name, ...) _MARK_w_addr(name, ## __VA_ARGS__) + #define MARK_TYPED(name, typeinfo, ...) _MARK(name, typeinfo, ## __VA_ARGS__) +#else + #define MARK(...) + #define MARK_TYPED(...) +#endif + protected: friend class CVulkanCmdBuffer; - + friend void vulkan_clear_debugEXT(); + friend VKAPI_ATTR VkBool32 VKAPI_CALL debug_utils_messenger_callback +(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity + , VkDebugUtilsMessageTypeFlagsEXT message_type + , const VkDebugUtilsMessengerCallbackDataEXT *callback_data + , void *user_data); bool selectPhysDev(VkSurfaceKHR surface); bool createDevice(); bool createLayouts(); @@ -802,6 +847,8 @@ class CVulkanDevice bool m_bHasDrmPrimaryDevId = false; bool m_bSupportsModifiers = false; bool m_bInitialized = false; + + std::atomic_flag debugEXT_clearFlag = ATOMIC_FLAG_INIT; VkPhysicalDeviceMemoryProperties m_memoryProperties; @@ -826,8 +873,28 @@ class CVulkanDevice std::atomic m_submissionSeqNo = { 0 }; std::vector> m_unusedCmdBufs; std::map> m_pendingCmdBufs; + const std::unordered_map typeLookupTable = + { + { (reinterpret_cast(&m_device)), VK_OBJECT_TYPE_DEVICE}, + { (reinterpret_cast(&m_physDev)), VK_OBJECT_TYPE_PHYSICAL_DEVICE}, + { (reinterpret_cast(&m_instance)), VK_OBJECT_TYPE_INSTANCE}, + { (reinterpret_cast(&m_queue)), VK_OBJECT_TYPE_QUEUE}, + { (reinterpret_cast(&m_generalQueue)), VK_OBJECT_TYPE_QUEUE}, + { (reinterpret_cast(&m_ycbcrConversion)), VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION}, + { (reinterpret_cast(&m_ycbcrSampler)), VK_OBJECT_TYPE_SAMPLER}, + { (reinterpret_cast(&m_descriptorSetLayout)), VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT}, + { (reinterpret_cast(&m_pipelineLayout)), VK_OBJECT_TYPE_PIPELINE_LAYOUT}, + { (reinterpret_cast(&m_descriptorPool)), VK_OBJECT_TYPE_DESCRIPTOR_POOL}, + { (reinterpret_cast(&m_commandPool)), VK_OBJECT_TYPE_COMMAND_POOL}, + { (reinterpret_cast(&m_generalCommandPool)), VK_OBJECT_TYPE_COMMAND_POOL}, + { (reinterpret_cast(&m_uploadBuffer)), VK_OBJECT_TYPE_BUFFER}, + { (reinterpret_cast(&m_uploadBufferMemory)), VK_OBJECT_TYPE_DEVICE_MEMORY}, + { (reinterpret_cast(&m_scratchTimelineSemaphore)), VK_OBJECT_TYPE_SEMAPHORE} + }; }; +inline std::optional SetName_impl(const bool cond=false, void ** ptr = nullptr, uint64_t objectHandle = 0, const char * name = nullptr, VkObjectType objectType = VK_OBJECT_TYPE_UNKNOWN, const void * pNext = nullptr) noexcept; + struct TextureState { bool discarded : 1; diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 1bbc1dce89..820b68cb27 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -6374,6 +6374,9 @@ error(Display *dpy, XErrorEvent *ev) [[noreturn]] static void steamcompmgr_exit(void) { + if ( vulkan_run_at_exit != nullptr ) + (*vulkan_run_at_exit)(); + g_ImageWaiter.Shutdown(); // Clean up any commits. @@ -6394,7 +6397,7 @@ steamcompmgr_exit(void) statsThreadRun = false; statsThreadSem.signal(); } - + sdlwindow_shutdown(); wlserver_lock();