diff --git a/shaders/background.frag b/shaders/background.frag index a87fe53..e1ca705 100644 --- a/shaders/background.frag +++ b/shaders/background.frag @@ -20,13 +20,13 @@ void main() { // Create dynamic gradient based on time float t = ubo.time / 360.0; - // Calculate color components with sine waves - float r = 0.39 + 0.20 * sin(t * 6.28318); - float g = 0.59 + 0.20 * sin(t * 6.28318 + 1.047); - float b = 0.78 + 0.22 * sin(t * 6.28318 + 2.094); + // Calculate color components matching Qt CustomWidget + float r = 0.392 + 0.196 * sin(t * 6.28318); + float g = 0.588 + 0.196 * sin(t * 6.28318 + 1.047); + float b = 0.784 + 0.216 * sin(t * 6.28318 + 2.094); vec3 color1 = vec3(r, g, b); - vec3 color2 = vec3(0.12, 0.12, 0.24); + vec3 color2 = vec3(0.118, 0.118, 0.235); // Linear gradient from top-left to bottom-right float gradient = uv.x * 0.5 + uv.y * 0.5; diff --git a/src/shaders_spirv/background.frag.spv b/src/shaders_spirv/background.frag.spv index 76fbc24..ea195c0 100644 Binary files a/src/shaders_spirv/background.frag.spv and b/src/shaders_spirv/background.frag.spv differ diff --git a/src/shaders_spirv/background_frag.inc b/src/shaders_spirv/background_frag.inc index 95caa7e..a4ad936 100644 --- a/src/shaders_spirv/background_frag.inc +++ b/src/shaders_spirv/background_frag.inc @@ -29,13 +29,13 @@ 0x00000006u, 0x00000007u, 0x00000006u, 0x00000006u, 0x00040020u, 0x00000015u, 0x00000002u, 0x00000014u, 0x0004003bu, 0x00000015u, 0x00000016u, 0x00000002u, 0x00040015u, 0x00000017u, 0x00000020u, 0x00000001u, 0x0004002bu, 0x00000017u, 0x00000018u, 0x00000000u, 0x00040020u, 0x00000019u, 0x00000002u, 0x00000006u, - 0x0004002bu, 0x00000006u, 0x0000001cu, 0x43b40000u, 0x0004002bu, 0x00000006u, 0x0000001fu, 0x3ec7ae14u, - 0x0004002bu, 0x00000006u, 0x00000020u, 0x3e4ccccdu, 0x0004002bu, 0x00000006u, 0x00000022u, 0x40c90fd0u, - 0x0004002bu, 0x00000006u, 0x00000028u, 0x3f170a3du, 0x0004002bu, 0x00000006u, 0x0000002bu, 0x3f860419u, - 0x0004002bu, 0x00000006u, 0x00000031u, 0x3f47ae14u, 0x0004002bu, 0x00000006u, 0x00000032u, 0x3e6147aeu, + 0x0004002bu, 0x00000006u, 0x0000001cu, 0x43b40000u, 0x0004002bu, 0x00000006u, 0x0000001fu, 0x3ec8b439u, + 0x0004002bu, 0x00000006u, 0x00000020u, 0x3e48b439u, 0x0004002bu, 0x00000006u, 0x00000022u, 0x40c90fd0u, + 0x0004002bu, 0x00000006u, 0x00000028u, 0x3f16872bu, 0x0004002bu, 0x00000006u, 0x0000002bu, 0x3f860419u, + 0x0004002bu, 0x00000006u, 0x00000031u, 0x3f48b439u, 0x0004002bu, 0x00000006u, 0x00000032u, 0x3e5d2f1bu, 0x0004002bu, 0x00000006u, 0x00000035u, 0x40060419u, 0x00040017u, 0x0000003au, 0x00000006u, 0x00000003u, - 0x00040020u, 0x0000003bu, 0x00000007u, 0x0000003au, 0x0004002bu, 0x00000006u, 0x00000042u, 0x3df5c28fu, - 0x0004002bu, 0x00000006u, 0x00000043u, 0x3e75c28fu, 0x0006002cu, 0x0000003au, 0x00000044u, 0x00000042u, + 0x00040020u, 0x0000003bu, 0x00000007u, 0x0000003au, 0x0004002bu, 0x00000006u, 0x00000042u, 0x3df1a9fcu, + 0x0004002bu, 0x00000006u, 0x00000043u, 0x3e70a3d7u, 0x0006002cu, 0x0000003au, 0x00000044u, 0x00000042u, 0x00000042u, 0x00000043u, 0x00040015u, 0x00000046u, 0x00000020u, 0x00000000u, 0x0004002bu, 0x00000046u, 0x00000047u, 0x00000000u, 0x0004002bu, 0x00000046u, 0x0000004bu, 0x00000001u, 0x00040017u, 0x00000056u, 0x00000006u, 0x00000004u, 0x00040020u, 0x00000057u, 0x00000003u, 0x00000056u, 0x0004003bu, 0x00000057u, diff --git a/src/vulkanwidget.cpp b/src/vulkanwidget.cpp index 113d441..5ae208a 100644 --- a/src/vulkanwidget.cpp +++ b/src/vulkanwidget.cpp @@ -56,95 +56,95 @@ VulkanWidget::VulkanWidget(QWidget *parent) setAttribute(Qt::WA_NativeWindow); setAttribute(Qt::WA_PaintOnScreen); setAttribute(Qt::WA_OpaquePaintEvent); - + // Create render timer m_renderTimer = new QTimer(this); connect(m_renderTimer, &QTimer::timeout, this, &VulkanWidget::onRenderTimer); - + qDebug() << "VulkanWidget created"; } VulkanWidget::~VulkanWidget() { qDebug() << "VulkanWidget destroying..."; - + if (m_renderTimer) { m_renderTimer->stop(); } - + // Clean up renderer first if (m_renderer) { m_renderer->cleanup(); delete m_renderer; m_renderer = nullptr; } - + cleanupVulkan(); - + qDebug() << "VulkanWidget destroyed"; } bool VulkanWidget::initializeVulkan() { qDebug() << "Initializing Vulkan..."; - + if (m_initialized) { qDebug() << "Vulkan already initialized"; return true; } - + // Step 1: Initialize volk if (!initializeVolk()) { setError("Failed to initialize volk"); return false; } - + // Step 2: Create Vulkan instance if (!createInstance()) { setError("Failed to create Vulkan instance"); return false; } - + // Step 3: Create surface from native window if (!createSurface()) { setError("Failed to create Vulkan surface"); return false; } - + // Step 4: Select physical device if (!selectPhysicalDevice()) { setError("Failed to select physical device"); return false; } - + // Step 5: Create logical device if (!createDevice()) { setError("Failed to create logical device"); return false; } - + // Step 6: Create swapchain if (!createSwapchain()) { setError("Failed to create swapchain"); return false; } - + // Step 7: Create command objects if (!createCommandObjects()) { setError("Failed to create command objects"); return false; } - + // Step 8: Create synchronization objects if (!createSyncObjects()) { setError("Failed to create sync objects"); return false; } - + // Step 9: Create VulkanRenderer - but only if we have reasonable dimensions if (m_surfaceWidth >= 100 && m_surfaceHeight >= 100) { m_renderer = new VulkanRenderer(); - + // Get swapchain format VkSurfaceFormatKHR surfaceFormat; uint32_t formatCount = 0; @@ -154,7 +154,7 @@ bool VulkanWidget::initializeVulkan() vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, formats.data()); surfaceFormat = formats[0]; } - + // Initialize renderer if (!m_renderer->initialize(m_device, m_physicalDevice, m_queue, m_queueFamilyIndex, @@ -165,14 +165,14 @@ bool VulkanWidget::initializeVulkan() m_renderer = nullptr; return false; } - + qDebug() << "VulkanRenderer initialized successfully!"; - qDebug() << "Widget size:" << width() << "x" << height() + qDebug() << "Widget size:" << width() << "x" << height() << "| Surface size:" << m_surfaceWidth << "x" << m_surfaceHeight; } else { qDebug() << "VulkanRenderer initialization deferred - window too small:" << m_surfaceWidth << "x" << m_surfaceHeight; } - + m_initialized = true; qDebug() << "Vulkan initialization successful!"; return true; @@ -181,13 +181,13 @@ bool VulkanWidget::initializeVulkan() bool VulkanWidget::initializeVolk() { qDebug() << "Initializing volk..."; - + VkResult result = volkInitialize(); if (result != VK_SUCCESS) { qDebug() << "Failed to initialize volk, error code:" << result; return false; } - + qDebug() << "Volk initialized successfully"; return true; } @@ -195,7 +195,7 @@ bool VulkanWidget::initializeVolk() bool VulkanWidget::createInstance() { qDebug() << "Creating Vulkan instance..."; - + VkApplicationInfo appInfo = {}; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.pApplicationName = "VulkanWidget"; @@ -203,25 +203,25 @@ bool VulkanWidget::createInstance() appInfo.pEngineName = "No Engine"; appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); appInfo.apiVersion = VK_API_VERSION_1_0; - + std::vector extensions = getRequiredInstanceExtensions(); - + VkInstanceCreateInfo createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; createInfo.pApplicationInfo = &appInfo; createInfo.enabledExtensionCount = static_cast(extensions.size()); createInfo.ppEnabledExtensionNames = extensions.data(); createInfo.enabledLayerCount = 0; - + VkResult result = vkCreateInstance(&createInfo, nullptr, &m_instance); if (result != VK_SUCCESS) { qDebug() << "Failed to create Vulkan instance, error code:" << result; return false; } - + // Load instance-level functions volkLoadInstance(m_instance); - + qDebug() << "Vulkan instance created successfully"; return true; } @@ -229,7 +229,7 @@ bool VulkanWidget::createInstance() bool VulkanWidget::createSurface() { qDebug() << "Creating Vulkan surface from native window..."; - + if (!windowHandle()) { qDebug() << "Window handle not available, creating window..."; create(); @@ -238,17 +238,17 @@ bool VulkanWidget::createSurface() return false; } } - + QWindow *window = windowHandle(); - + #ifdef _WIN32 VkWin32SurfaceCreateInfoKHR createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; createInfo.hwnd = reinterpret_cast(window->winId()); createInfo.hinstance = GetModuleHandle(nullptr); - + VkResult result = vkCreateWin32SurfaceKHR(m_instance, &createInfo, nullptr, &m_surface); - + #elif defined(__linux__) VkXlibSurfaceCreateInfoKHR createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR; @@ -259,26 +259,26 @@ bool VulkanWidget::createSurface() return false; } createInfo.window = static_cast(window->winId()); - + VkResult result = vkCreateXlibSurfaceKHR(m_instance, &createInfo, nullptr, &m_surface); - + #elif defined(__APPLE__) // macOS requires MoltenVK and Metal VkMetalSurfaceCreateInfoEXT createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT; createInfo.pLayer = nullptr; // This needs proper Metal layer setup - + VkResult result = vkCreateMetalSurfaceEXT(m_instance, &createInfo, nullptr, &m_surface); #else qDebug() << "Unsupported platform for Vulkan surface creation"; return false; #endif - + if (result != VK_SUCCESS) { qDebug() << "Failed to create Vulkan surface, error code:" << result; return false; } - + qDebug() << "Vulkan surface created successfully"; return true; } @@ -286,28 +286,28 @@ bool VulkanWidget::createSurface() bool VulkanWidget::selectPhysicalDevice() { qDebug() << "Selecting physical device..."; - + uint32_t deviceCount = 0; vkEnumeratePhysicalDevices(m_instance, &deviceCount, nullptr); - + if (deviceCount == 0) { qDebug() << "Failed to find GPUs with Vulkan support"; return false; } - + std::vector devices(deviceCount); vkEnumeratePhysicalDevices(m_instance, &deviceCount, devices.data()); - + // Select the first suitable device for (const auto& device : devices) { VkPhysicalDeviceProperties properties; vkGetPhysicalDeviceProperties(device, &properties); - + qDebug() << "Found device:" << properties.deviceName; - + // Temporarily set physical device to check queue families m_physicalDevice = device; - + // Check if device supports our queue family uint32_t queueFamilyIndex; if (findQueueFamily(queueFamilyIndex)) { @@ -316,7 +316,7 @@ bool VulkanWidget::selectPhysicalDevice() return true; } } - + // Reset if no suitable device found m_physicalDevice = VK_NULL_HANDLE; qDebug() << "Failed to find suitable physical device"; @@ -327,42 +327,42 @@ bool VulkanWidget::findQueueFamily(uint32_t &queueFamilyIndex) { uint32_t queueFamilyCount = 0; vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &queueFamilyCount, nullptr); - + std::vector queueFamilies(queueFamilyCount); vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &queueFamilyCount, queueFamilies.data()); - + for (uint32_t i = 0; i < queueFamilyCount; i++) { // Check if queue family supports graphics if (queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { // Check if queue family supports presentation VkBool32 presentSupport = false; vkGetPhysicalDeviceSurfaceSupportKHR(m_physicalDevice, i, m_surface, &presentSupport); - + if (presentSupport) { queueFamilyIndex = i; return true; } } } - + return false; } bool VulkanWidget::createDevice() { qDebug() << "Creating logical device..."; - + float queuePriority = 1.0f; VkDeviceQueueCreateInfo queueCreateInfo = {}; queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queueCreateInfo.queueFamilyIndex = m_queueFamilyIndex; queueCreateInfo.queueCount = 1; queueCreateInfo.pQueuePriorities = &queuePriority; - + VkPhysicalDeviceFeatures deviceFeatures = {}; - + std::vector deviceExtensions = getRequiredDeviceExtensions(); - + VkDeviceCreateInfo createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; createInfo.pQueueCreateInfos = &queueCreateInfo; @@ -371,19 +371,19 @@ bool VulkanWidget::createDevice() createInfo.enabledExtensionCount = static_cast(deviceExtensions.size()); createInfo.ppEnabledExtensionNames = deviceExtensions.data(); createInfo.enabledLayerCount = 0; - + VkResult result = vkCreateDevice(m_physicalDevice, &createInfo, nullptr, &m_device); if (result != VK_SUCCESS) { qDebug() << "Failed to create logical device, error code:" << result; return false; } - + // Load device-level functions volkLoadDevice(m_device); - + // Get queue handle vkGetDeviceQueue(m_device, m_queueFamilyIndex, 0, &m_queue); - + qDebug() << "Logical device created successfully"; return true; } @@ -393,40 +393,40 @@ bool VulkanWidget::createSwapchain() qDebug() << "Creating swapchain..."; qDebug() << "Widget size:" << width() << "x" << height(); qDebug() << "Device pixel ratio:" << devicePixelRatioF(); - + // Query surface capabilities VkSurfaceCapabilitiesKHR capabilities; vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_physicalDevice, m_surface, &capabilities); - - qDebug() << "Surface capabilities - current extent:" + + qDebug() << "Surface capabilities - current extent:" << capabilities.currentExtent.width << "x" << capabilities.currentExtent.height; - qDebug() << "Surface capabilities - min extent:" + qDebug() << "Surface capabilities - min extent:" << capabilities.minImageExtent.width << "x" << capabilities.minImageExtent.height; - qDebug() << "Surface capabilities - max extent:" + qDebug() << "Surface capabilities - max extent:" << capabilities.maxImageExtent.width << "x" << capabilities.maxImageExtent.height; - + // Query surface formats uint32_t formatCount; vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, nullptr); std::vector formats(formatCount); vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, formats.data()); - + // Query present modes uint32_t presentModeCount; vkGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &presentModeCount, nullptr); std::vector presentModes(presentModeCount); vkGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &presentModeCount, presentModes.data()); - + // Select format VkSurfaceFormatKHR surfaceFormat = formats[0]; for (const auto& format : formats) { - if (format.format == VK_FORMAT_B8G8R8A8_SRGB && + if (format.format == VK_FORMAT_B8G8R8A8_SRGB && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { surfaceFormat = format; break; } } - + // Select present mode (prefer mailbox, fallback to FIFO) VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR; for (const auto& mode : presentModes) { @@ -435,7 +435,7 @@ bool VulkanWidget::createSwapchain() break; } } - + // Determine extent VkExtent2D extent; if (capabilities.currentExtent.width != UINT32_MAX) { @@ -445,27 +445,27 @@ bool VulkanWidget::createSwapchain() // Calculate extent based on widget size with DPI scaling uint32_t pixelWidth = static_cast(width() * devicePixelRatioF()); uint32_t pixelHeight = static_cast(height() * devicePixelRatioF()); - - extent.width = std::max(capabilities.minImageExtent.width, + + extent.width = std::max(capabilities.minImageExtent.width, std::min(capabilities.maxImageExtent.width, pixelWidth)); extent.height = std::max(capabilities.minImageExtent.height, std::min(capabilities.maxImageExtent.height, pixelHeight)); qDebug() << "Calculated extent from widget:" << extent.width << "x" << extent.height - << "(widget:" << width() << "x" << height() + << "(widget:" << width() << "x" << height() << "* DPR:" << devicePixelRatioF() << ")"; } - + m_surfaceWidth = extent.width; m_surfaceHeight = extent.height; - + qDebug() << "Final swapchain extent:" << m_surfaceWidth << "x" << m_surfaceHeight; - + // Determine image count uint32_t imageCount = capabilities.minImageCount + 1; if (capabilities.maxImageCount > 0 && imageCount > capabilities.maxImageCount) { imageCount = capabilities.maxImageCount; } - + VkSwapchainCreateInfoKHR createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; createInfo.surface = m_surface; @@ -481,19 +481,19 @@ bool VulkanWidget::createSwapchain() createInfo.presentMode = presentMode; 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; return false; } - + // Retrieve swapchain images vkGetSwapchainImagesKHR(m_device, m_swapchain, &imageCount, nullptr); m_swapchainImages.resize(imageCount); - vkGetSwapchainImagesKHR(m_device, m_swapchain, &imageCount, + vkGetSwapchainImagesKHR(m_device, m_swapchain, &imageCount, reinterpret_cast(m_swapchainImages.data())); - + // Create image views for swapchain images m_swapchainImageViews.resize(imageCount); for (uint32_t i = 0; i < imageCount; i++) { @@ -511,7 +511,7 @@ bool VulkanWidget::createSwapchain() viewInfo.subresourceRange.levelCount = 1; viewInfo.subresourceRange.baseArrayLayer = 0; viewInfo.subresourceRange.layerCount = 1; - + VkImageView imageView; result = vkCreateImageView(m_device, &viewInfo, nullptr, &imageView); if (result != VK_SUCCESS) { @@ -520,42 +520,42 @@ bool VulkanWidget::createSwapchain() } m_swapchainImageViews[i] = reinterpret_cast(imageView); } - - qDebug() << "Swapchain created successfully with" << imageCount << "images, size:" + + qDebug() << "Swapchain created successfully with" << imageCount << "images, size:" << m_surfaceWidth << "x" << m_surfaceHeight; - + return true; } bool VulkanWidget::createCommandObjects() { qDebug() << "Creating command objects..."; - + VkCommandPoolCreateInfo poolInfo = {}; poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; poolInfo.queueFamilyIndex = m_queueFamilyIndex; poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - + VkResult result = vkCreateCommandPool(m_device, &poolInfo, nullptr, &m_commandPool); if (result != VK_SUCCESS) { qDebug() << "Failed to create command pool, error code:" << result; return false; } - + m_commandBuffers.resize(MAX_FRAMES_IN_FLIGHT); - + VkCommandBufferAllocateInfo allocInfo = {}; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocInfo.commandPool = m_commandPool; allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; allocInfo.commandBufferCount = static_cast(m_commandBuffers.size()); - + result = vkAllocateCommandBuffers(m_device, &allocInfo, m_commandBuffers.data()); if (result != VK_SUCCESS) { qDebug() << "Failed to allocate command buffers, error code:" << result; return false; } - + qDebug() << "Command objects created successfully"; return true; } @@ -563,18 +563,18 @@ bool VulkanWidget::createCommandObjects() bool VulkanWidget::createSyncObjects() { qDebug() << "Creating synchronization objects..."; - + m_imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT); m_renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT); m_inFlightFences.resize(MAX_FRAMES_IN_FLIGHT); - + VkSemaphoreCreateInfo semaphoreInfo = {}; semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - + VkFenceCreateInfo fenceInfo = {}; fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; - + for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { if (vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &m_imageAvailableSemaphores[i]) != VK_SUCCESS || vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &m_renderFinishedSemaphores[i]) != VK_SUCCESS || @@ -583,7 +583,7 @@ bool VulkanWidget::createSyncObjects() return false; } } - + qDebug() << "Synchronization objects created successfully"; return true; } @@ -591,25 +591,25 @@ bool VulkanWidget::createSyncObjects() bool VulkanWidget::recreateSwapchain() { qDebug() << "Recreating swapchain..."; - + // Wait for device to be idle vkDeviceWaitIdle(m_device); - + // Cleanup old swapchain cleanupSwapchain(); - + // Create new swapchain if (!createSwapchain()) { qDebug() << "Failed to recreate swapchain"; return false; } - + // Update renderer with new surface dimensions if (m_renderer) { qDebug() << "Updating VulkanRenderer to surface size:" << m_surfaceWidth << "x" << m_surfaceHeight; m_renderer->resize(m_surfaceWidth, m_surfaceHeight); } - + qDebug() << "Swapchain recreated successfully"; return true; } @@ -619,16 +619,16 @@ void VulkanWidget::renderFrame() if (!m_initialized || !m_renderingEnabled) { return; } - + // Wait for previous frame vkWaitForFences(m_device, 1, &m_inFlightFences[m_currentFrame], VK_TRUE, UINT64_MAX); - + // Acquire next image uint32_t imageIndex; VkResult result = vkAcquireNextImageKHR(m_device, m_swapchain, UINT64_MAX, m_imageAvailableSemaphores[m_currentFrame], VK_NULL_HANDLE, &imageIndex); - + if (result == VK_ERROR_OUT_OF_DATE_KHR) { recreateSwapchain(); return; @@ -636,18 +636,18 @@ void VulkanWidget::renderFrame() qDebug() << "Failed to acquire swapchain image"; return; } - + // Reset fence vkResetFences(m_device, 1, &m_inFlightFences[m_currentFrame]); - + // Record command buffer vkResetCommandBuffer(m_commandBuffers[m_currentFrame], 0); recordCommandBuffer(m_commandBuffers[m_currentFrame], imageIndex); - + // Submit command buffer VkSubmitInfo submitInfo = {}; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - + VkSemaphore waitSemaphores[] = {m_imageAvailableSemaphores[m_currentFrame]}; VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; submitInfo.waitSemaphoreCount = 1; @@ -655,37 +655,37 @@ void VulkanWidget::renderFrame() submitInfo.pWaitDstStageMask = waitStages; submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &m_commandBuffers[m_currentFrame]; - + VkSemaphore signalSemaphores[] = {m_renderFinishedSemaphores[m_currentFrame]}; submitInfo.signalSemaphoreCount = 1; submitInfo.pSignalSemaphores = signalSemaphores; - + result = vkQueueSubmit(m_queue, 1, &submitInfo, m_inFlightFences[m_currentFrame]); if (result != VK_SUCCESS) { qDebug() << "Failed to submit draw command buffer"; return; } - + // Present VkPresentInfoKHR presentInfo = {}; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; presentInfo.waitSemaphoreCount = 1; presentInfo.pWaitSemaphores = signalSemaphores; - + VkSwapchainKHR swapchains[] = {m_swapchain}; presentInfo.swapchainCount = 1; presentInfo.pSwapchains = swapchains; presentInfo.pImageIndices = &imageIndex; - + result = vkQueuePresentKHR(m_queue, &presentInfo); - + if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || m_needsResize) { m_needsResize = false; recreateSwapchain(); } else if (result != VK_SUCCESS) { qDebug() << "Failed to present swapchain image"; } - + m_currentFrame = (m_currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; m_frameCount++; } @@ -696,7 +696,7 @@ void VulkanWidget::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t i if (!m_renderer && m_surfaceWidth >= 100 && m_surfaceHeight >= 100) { qDebug() << "Creating deferred VulkanRenderer with actual surface size:" << m_surfaceWidth << "x" << m_surfaceHeight; m_renderer = new VulkanRenderer(); - + VkSurfaceFormatKHR surfaceFormat; uint32_t formatCount = 0; vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, nullptr); @@ -705,7 +705,7 @@ void VulkanWidget::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t i vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, formats.data()); surfaceFormat = formats[0]; } - + if (!m_renderer->initialize(m_device, m_physicalDevice, m_queue, m_queueFamilyIndex, static_cast(surfaceFormat.format), @@ -714,48 +714,50 @@ void VulkanWidget::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t i delete m_renderer; m_renderer = nullptr; } else { - qDebug() << "Deferred VulkanRenderer initialized successfully with surface size:" + qDebug() << "Deferred VulkanRenderer initialized successfully with surface size:" << m_surfaceWidth << "x" << m_surfaceHeight; } } - + // Use VulkanRenderer if available if (m_renderer) { if (imageIndex >= m_swapchainImageViews.size()) { qDebug() << "ERROR: imageIndex out of bounds!"; return; } - + VkImageView imageView = reinterpret_cast(m_swapchainImageViews[imageIndex]); - + // Build lock info string QString lockInfo; if (m_lastLockTime.isValid()) { - lockInfo = QString("Last Lock: %1\nDuration: %2s\nLock Count: %3") + lockInfo = QString("Last Lock: %1\nDuration: %2s\nFrame Count at Lock: %3\nFrames During Lock: %4\nLock Count: %5") .arg(m_lastLockTime.toString("hh:mm:ss")) .arg(m_lastLockDuration) + .arg(m_lastLockFrameCount) + .arg(m_lockPaintFrameCount) .arg(m_lockCount); } - + // Debug: Print dimensions occasionally to check for mismatch static int debugCounter = 0; if (debugCounter++ % 300 == 0) { // Every ~5 seconds at 60fps - qDebug() << "Rendering - Widget:" << width() << "x" << height() + qDebug() << "Rendering - Widget:" << width() << "x" << height() << "| Surface:" << m_surfaceWidth << "x" << m_surfaceHeight; } - + m_renderer->recordCommandBuffer(commandBuffer, imageIndex, imageView, m_frameCount, m_rotationAngle, m_wavePhase, m_renderingEnabled, lockInfo.toStdString()); return; } - + // Fallback: Simple clear color pass VkCommandBufferBeginInfo beginInfo = {}; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - + vkBeginCommandBuffer(commandBuffer, &beginInfo); - + VkClearColorValue clearColor; float hue = (m_frameCount % 360) / 360.0f; float r = std::abs(std::sin(hue * 6.28318f)); @@ -765,16 +767,16 @@ void VulkanWidget::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t i clearColor.float32[1] = g * 0.5f + 0.1f; clearColor.float32[2] = b * 0.5f + 0.1f; clearColor.float32[3] = 1.0f; - + VkImageSubresourceRange range = {}; range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; range.baseMipLevel = 0; range.levelCount = 1; range.baseArrayLayer = 0; range.layerCount = 1; - + VkImage image = reinterpret_cast(m_swapchainImages[imageIndex]); - + VkImageMemoryBarrier barrier1 = {}; barrier1.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier1.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; @@ -785,13 +787,13 @@ void VulkanWidget::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t i barrier1.subresourceRange = range; barrier1.srcAccessMask = 0; barrier1.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - - vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier1); - - vkCmdClearColorImage(commandBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + + vkCmdClearColorImage(commandBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1, &range); - + VkImageMemoryBarrier barrier2 = {}; barrier2.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier2.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; @@ -802,10 +804,10 @@ void VulkanWidget::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t i barrier2.subresourceRange = range; barrier2.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier2.dstAccessMask = 0; - + vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier2); - + vkEndCommandBuffer(commandBuffer); } @@ -818,12 +820,12 @@ void VulkanWidget::cleanupSwapchain() } } m_swapchainImageViews.clear(); - + if (m_swapchain != VK_NULL_HANDLE) { vkDestroySwapchainKHR(m_device, m_swapchain, nullptr); m_swapchain = VK_NULL_HANDLE; } - + m_swapchainImages.clear(); } @@ -832,11 +834,11 @@ void VulkanWidget::cleanupVulkan() if (!m_initialized) { return; } - + if (m_device != VK_NULL_HANDLE) { vkDeviceWaitIdle(m_device); } - + // Cleanup sync objects for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { if (m_imageAvailableSemaphores[i] != VK_NULL_HANDLE) { @@ -849,30 +851,30 @@ void VulkanWidget::cleanupVulkan() vkDestroyFence(m_device, m_inFlightFences[i], nullptr); } } - + // Cleanup command pool if (m_commandPool != VK_NULL_HANDLE) { vkDestroyCommandPool(m_device, m_commandPool, nullptr); } - + // Cleanup swapchain cleanupSwapchain(); - + // Cleanup device if (m_device != VK_NULL_HANDLE) { vkDestroyDevice(m_device, nullptr); } - + // Cleanup surface if (m_surface != VK_NULL_HANDLE) { vkDestroySurfaceKHR(m_instance, m_surface, nullptr); } - + // Cleanup instance if (m_instance != VK_NULL_HANDLE) { vkDestroyInstance(m_instance, nullptr); } - + m_initialized = false; qDebug() << "Vulkan cleanup complete"; } @@ -882,13 +884,13 @@ void VulkanWidget::setRenderingEnabled(bool enabled) if (m_renderingEnabled == enabled) { return; } - + m_renderingEnabled = enabled; - + if (m_renderingEnabled) { qDebug() << "Vulkan rendering ENABLED - Resuming animations"; m_renderTimer->start(16); // ~60 FPS - + // Unlocked: calculate lock duration if (m_lastLockTime.isValid()) { QDateTime unlockTime = QDateTime::currentDateTime(); @@ -898,12 +900,12 @@ void VulkanWidget::setRenderingEnabled(bool enabled) qDebug() << "Frames at lock:" << m_lastLockFrameCount << "- Frames painted during lock:" << m_lockPaintFrameCount; } - + m_startTime = QDateTime::currentDateTime(); } else { qDebug() << "Vulkan rendering DISABLED - Stopping animations"; m_renderTimer->stop(); - + // Locked: record lock time m_pauseTime = QDateTime::currentDateTime(); m_lastLockTime = m_pauseTime; @@ -934,7 +936,7 @@ void VulkanWidget::resetFrameCount() void VulkanWidget::showEvent(QShowEvent *event) { QWidget::showEvent(event); - + if (!m_initialized) { initializeVulkan(); } @@ -949,12 +951,12 @@ void VulkanWidget::hideEvent(QHideEvent *event) void VulkanWidget::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); - + if (m_initialized) { m_needsResize = true; - + // Note: Don't update renderer size here - it will be updated after swapchain recreation - // The renderer must use the actual surface dimensions (m_surfaceWidth/Height), + // The renderer must use the actual surface dimensions (m_surfaceWidth/Height), // not the widget dimensions, which may differ on high DPI displays } } @@ -979,13 +981,13 @@ void VulkanWidget::onRenderTimer() if (m_rotationAngle >= 360.0) { m_rotationAngle -= 360.0; } - + m_wavePhase += 0.05; if (m_wavePhase >= 2 * M_PI) { m_wavePhase -= 2 * M_PI; } } - + renderFrame(); } @@ -998,9 +1000,9 @@ void VulkanWidget::setError(const QString &error) std::vector VulkanWidget::getRequiredInstanceExtensions() { std::vector extensions; - + extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME); - + #ifdef _WIN32 extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); #elif defined(__linux__) @@ -1008,7 +1010,7 @@ std::vector VulkanWidget::getRequiredInstanceExtensions() #elif defined(__APPLE__) extensions.push_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME); #endif - + return extensions; } @@ -1017,4 +1019,4 @@ std::vector VulkanWidget::getRequiredDeviceExtensions() std::vector extensions; extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); return extensions; -} \ No newline at end of file +} diff --git a/src/vulkanwidget.h b/src/vulkanwidget.h index 6a7e5aa..fc48090 100644 --- a/src/vulkanwidget.h +++ b/src/vulkanwidget.h @@ -26,7 +26,7 @@ typedef VkFlags VkSurfaceTransformFlagsKHR; /** * @brief Vulkan渲染组件类 - * + * * 使用Qt的native window属性创建Vulkan Surface * 通过volk机制加载Vulkan函数 */ @@ -249,7 +249,7 @@ private: // VulkanRenderer VulkanRenderer *m_renderer; - + // 动画参数 double m_rotationAngle; double m_wavePhase; @@ -265,4 +265,4 @@ private: static const int MAX_FRAMES_IN_FLIGHT = 2; }; -#endif // VULKANWIDGET_H \ No newline at end of file +#endif // VULKANWIDGET_H