diff --git a/src/vulkanwidget.cpp b/src/vulkanwidget.cpp index 85383f6..cab5a73 100644 --- a/src/vulkanwidget.cpp +++ b/src/vulkanwidget.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,7 @@ VulkanWidget::VulkanWidget(QWidget *parent) , m_lastLockFrameCount(0) , m_lockPaintFrameCount(0) , m_lockCount(0) + , m_isClosing(false) { // Set widget attributes for native window setAttribute(Qt::WA_NativeWindow); @@ -483,9 +485,20 @@ bool VulkanWidget::createSwapchain() qDebug() << "Widget size:" << width() << "x" << height(); qDebug() << "Device pixel ratio:" << devicePixelRatioF(); + // Don't create swapchain if closing + if (m_isClosing) { + qDebug() << "Aborting swapchain creation - widget is closing"; + return false; + } + // Query surface capabilities VkSurfaceCapabilitiesKHR capabilities; - vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_physicalDevice, m_surface, &capabilities); + VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_physicalDevice, m_surface, &capabilities); + + if (result != VK_SUCCESS) { + qDebug() << "Failed to get surface capabilities, error code:" << result; + return false; + } qDebug() << "Surface capabilities - current extent:" << capabilities.currentExtent.width << "x" << capabilities.currentExtent.height; @@ -493,6 +506,16 @@ bool VulkanWidget::createSwapchain() << capabilities.minImageExtent.width << "x" << capabilities.minImageExtent.height; qDebug() << "Surface capabilities - max extent:" << capabilities.maxImageExtent.width << "x" << capabilities.maxImageExtent.height; + + // Validate surface capabilities - detect invalid/corrupted values + // This can happen when the window is being destroyed + if (capabilities.currentExtent.width > 16384 || capabilities.currentExtent.height > 16384 || + capabilities.minImageExtent.width > 16384 || capabilities.minImageExtent.height > 16384 || + capabilities.maxImageExtent.width > 1000000 || capabilities.maxImageExtent.height > 1000000) { + qDebug() << "ERROR: Invalid surface capabilities detected - surface may be destroyed"; + qDebug() << "This usually happens when the window is being closed"; + return false; + } // Query surface formats uint32_t formatCount; @@ -576,9 +599,9 @@ bool VulkanWidget::createSwapchain() createInfo.clipped = VK_TRUE; createInfo.oldSwapchain = VK_NULL_HANDLE; - VkResult result = vkCreateSwapchainKHR(m_device, &createInfo, nullptr, &m_swapchain); - if (result != VK_SUCCESS) { - qDebug() << "Failed to create swapchain, error code:" << result; + VkResult swapchainResult = vkCreateSwapchainKHR(m_device, &createInfo, nullptr, &m_swapchain); + if (swapchainResult != VK_SUCCESS) { + qDebug() << "Failed to create swapchain, error code:" << swapchainResult; return false; } @@ -607,9 +630,9 @@ bool VulkanWidget::createSwapchain() viewInfo.subresourceRange.layerCount = 1; VkImageView imageView; - result = vkCreateImageView(m_device, &viewInfo, nullptr, &imageView); - if (result != VK_SUCCESS) { - qDebug() << "Failed to create image view" << i << ", error code:" << result; + VkResult viewResult = vkCreateImageView(m_device, &viewInfo, nullptr, &imageView); + if (viewResult != VK_SUCCESS) { + qDebug() << "Failed to create image view" << i << ", error code:" << viewResult; return false; } m_swapchainImageViews[i] = reinterpret_cast(imageView); @@ -685,6 +708,12 @@ bool VulkanWidget::createSyncObjects() bool VulkanWidget::recreateSwapchain() { qDebug() << "Recreating swapchain..."; + + // Don't recreate if closing + if (m_isClosing) { + qDebug() << "Aborting swapchain recreation - widget is closing"; + return false; + } // Wait for device to be idle vkDeviceWaitIdle(m_device); @@ -710,7 +739,8 @@ bool VulkanWidget::recreateSwapchain() void VulkanWidget::renderFrame() { - if (!m_initialized) { + // Don't render if closing or not initialized + if (!m_initialized || m_isClosing) { return; } @@ -993,6 +1023,29 @@ void VulkanWidget::hideEvent(QHideEvent *event) setRenderingEnabled(false); } +void VulkanWidget::closeEvent(QCloseEvent *event) +{ + qDebug() << "VulkanWidget closeEvent - stopping rendering and cleaning up"; + + // Set closing flag to prevent any further rendering attempts + m_isClosing = true; + + // Stop the render timer immediately + if (m_renderTimer) { + m_renderTimer->stop(); + qDebug() << "Render timer stopped on close"; + } + + // Wait for device to be idle before accepting close event + if (m_device != VK_NULL_HANDLE) { + vkDeviceWaitIdle(m_device); + qDebug() << "Vulkan device idle on close"; + } + + // Accept the close event + QWidget::closeEvent(event); +} + void VulkanWidget::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); diff --git a/src/vulkanwidget.h b/src/vulkanwidget.h index 16ee5d5..540a4a2 100644 --- a/src/vulkanwidget.h +++ b/src/vulkanwidget.h @@ -62,6 +62,11 @@ protected: */ void hideEvent(QHideEvent *event) override; + /** + * @brief Qt事件:窗口关闭时 + */ + void closeEvent(QCloseEvent *event) override; + /** * @brief Qt事件:组件大小改变时 */ @@ -208,6 +213,7 @@ private: bool m_renderingEnabled; bool m_needsResize; bool m_needsLockedFrameUpdate; // 是否需要渲染锁屏帧(锁屏时只渲染一帧) + bool m_isClosing; // 标记窗口正在关闭,防止在销毁过程中继续渲染 int m_frameCount; uint32_t m_queueFamilyIndex; uint32_t m_currentFrame;