调整渲染文字内容

This commit is contained in:
ubuntu1804 2025-11-10 21:29:00 +08:00
parent 4b04a1adf7
commit fd9c1c89e6
5 changed files with 179 additions and 177 deletions

View File

@ -20,13 +20,13 @@ void main() {
// Create dynamic gradient based on time // Create dynamic gradient based on time
float t = ubo.time / 360.0; float t = ubo.time / 360.0;
// Calculate color components with sine waves // Calculate color components matching Qt CustomWidget
float r = 0.39 + 0.20 * sin(t * 6.28318); float r = 0.392 + 0.196 * sin(t * 6.28318);
float g = 0.59 + 0.20 * sin(t * 6.28318 + 1.047); float g = 0.588 + 0.196 * sin(t * 6.28318 + 1.047);
float b = 0.78 + 0.22 * sin(t * 6.28318 + 2.094); float b = 0.784 + 0.216 * sin(t * 6.28318 + 2.094);
vec3 color1 = vec3(r, g, b); 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 // Linear gradient from top-left to bottom-right
float gradient = uv.x * 0.5 + uv.y * 0.5; float gradient = uv.x * 0.5 + uv.y * 0.5;

View File

@ -29,13 +29,13 @@
0x00000006u, 0x00000007u, 0x00000006u, 0x00000006u, 0x00040020u, 0x00000015u, 0x00000002u, 0x00000014u, 0x00000006u, 0x00000007u, 0x00000006u, 0x00000006u, 0x00040020u, 0x00000015u, 0x00000002u, 0x00000014u,
0x0004003bu, 0x00000015u, 0x00000016u, 0x00000002u, 0x00040015u, 0x00000017u, 0x00000020u, 0x00000001u, 0x0004003bu, 0x00000015u, 0x00000016u, 0x00000002u, 0x00040015u, 0x00000017u, 0x00000020u, 0x00000001u,
0x0004002bu, 0x00000017u, 0x00000018u, 0x00000000u, 0x00040020u, 0x00000019u, 0x00000002u, 0x00000006u, 0x0004002bu, 0x00000017u, 0x00000018u, 0x00000000u, 0x00040020u, 0x00000019u, 0x00000002u, 0x00000006u,
0x0004002bu, 0x00000006u, 0x0000001cu, 0x43b40000u, 0x0004002bu, 0x00000006u, 0x0000001fu, 0x3ec7ae14u, 0x0004002bu, 0x00000006u, 0x0000001cu, 0x43b40000u, 0x0004002bu, 0x00000006u, 0x0000001fu, 0x3ec8b439u,
0x0004002bu, 0x00000006u, 0x00000020u, 0x3e4ccccdu, 0x0004002bu, 0x00000006u, 0x00000022u, 0x40c90fd0u, 0x0004002bu, 0x00000006u, 0x00000020u, 0x3e48b439u, 0x0004002bu, 0x00000006u, 0x00000022u, 0x40c90fd0u,
0x0004002bu, 0x00000006u, 0x00000028u, 0x3f170a3du, 0x0004002bu, 0x00000006u, 0x0000002bu, 0x3f860419u, 0x0004002bu, 0x00000006u, 0x00000028u, 0x3f16872bu, 0x0004002bu, 0x00000006u, 0x0000002bu, 0x3f860419u,
0x0004002bu, 0x00000006u, 0x00000031u, 0x3f47ae14u, 0x0004002bu, 0x00000006u, 0x00000032u, 0x3e6147aeu, 0x0004002bu, 0x00000006u, 0x00000031u, 0x3f48b439u, 0x0004002bu, 0x00000006u, 0x00000032u, 0x3e5d2f1bu,
0x0004002bu, 0x00000006u, 0x00000035u, 0x40060419u, 0x00040017u, 0x0000003au, 0x00000006u, 0x00000003u, 0x0004002bu, 0x00000006u, 0x00000035u, 0x40060419u, 0x00040017u, 0x0000003au, 0x00000006u, 0x00000003u,
0x00040020u, 0x0000003bu, 0x00000007u, 0x0000003au, 0x0004002bu, 0x00000006u, 0x00000042u, 0x3df5c28fu, 0x00040020u, 0x0000003bu, 0x00000007u, 0x0000003au, 0x0004002bu, 0x00000006u, 0x00000042u, 0x3df1a9fcu,
0x0004002bu, 0x00000006u, 0x00000043u, 0x3e75c28fu, 0x0006002cu, 0x0000003au, 0x00000044u, 0x00000042u, 0x0004002bu, 0x00000006u, 0x00000043u, 0x3e70a3d7u, 0x0006002cu, 0x0000003au, 0x00000044u, 0x00000042u,
0x00000042u, 0x00000043u, 0x00040015u, 0x00000046u, 0x00000020u, 0x00000000u, 0x0004002bu, 0x00000046u, 0x00000042u, 0x00000043u, 0x00040015u, 0x00000046u, 0x00000020u, 0x00000000u, 0x0004002bu, 0x00000046u,
0x00000047u, 0x00000000u, 0x0004002bu, 0x00000046u, 0x0000004bu, 0x00000001u, 0x00040017u, 0x00000056u, 0x00000047u, 0x00000000u, 0x0004002bu, 0x00000046u, 0x0000004bu, 0x00000001u, 0x00040017u, 0x00000056u,
0x00000006u, 0x00000004u, 0x00040020u, 0x00000057u, 0x00000003u, 0x00000056u, 0x0004003bu, 0x00000057u, 0x00000006u, 0x00000004u, 0x00040020u, 0x00000057u, 0x00000003u, 0x00000056u, 0x0004003bu, 0x00000057u,

View File

@ -56,95 +56,95 @@ VulkanWidget::VulkanWidget(QWidget *parent)
setAttribute(Qt::WA_NativeWindow); setAttribute(Qt::WA_NativeWindow);
setAttribute(Qt::WA_PaintOnScreen); setAttribute(Qt::WA_PaintOnScreen);
setAttribute(Qt::WA_OpaquePaintEvent); setAttribute(Qt::WA_OpaquePaintEvent);
// Create render timer // Create render timer
m_renderTimer = new QTimer(this); m_renderTimer = new QTimer(this);
connect(m_renderTimer, &QTimer::timeout, this, &VulkanWidget::onRenderTimer); connect(m_renderTimer, &QTimer::timeout, this, &VulkanWidget::onRenderTimer);
qDebug() << "VulkanWidget created"; qDebug() << "VulkanWidget created";
} }
VulkanWidget::~VulkanWidget() VulkanWidget::~VulkanWidget()
{ {
qDebug() << "VulkanWidget destroying..."; qDebug() << "VulkanWidget destroying...";
if (m_renderTimer) { if (m_renderTimer) {
m_renderTimer->stop(); m_renderTimer->stop();
} }
// Clean up renderer first // Clean up renderer first
if (m_renderer) { if (m_renderer) {
m_renderer->cleanup(); m_renderer->cleanup();
delete m_renderer; delete m_renderer;
m_renderer = nullptr; m_renderer = nullptr;
} }
cleanupVulkan(); cleanupVulkan();
qDebug() << "VulkanWidget destroyed"; qDebug() << "VulkanWidget destroyed";
} }
bool VulkanWidget::initializeVulkan() bool VulkanWidget::initializeVulkan()
{ {
qDebug() << "Initializing Vulkan..."; qDebug() << "Initializing Vulkan...";
if (m_initialized) { if (m_initialized) {
qDebug() << "Vulkan already initialized"; qDebug() << "Vulkan already initialized";
return true; return true;
} }
// Step 1: Initialize volk // Step 1: Initialize volk
if (!initializeVolk()) { if (!initializeVolk()) {
setError("Failed to initialize volk"); setError("Failed to initialize volk");
return false; return false;
} }
// Step 2: Create Vulkan instance // Step 2: Create Vulkan instance
if (!createInstance()) { if (!createInstance()) {
setError("Failed to create Vulkan instance"); setError("Failed to create Vulkan instance");
return false; return false;
} }
// Step 3: Create surface from native window // Step 3: Create surface from native window
if (!createSurface()) { if (!createSurface()) {
setError("Failed to create Vulkan surface"); setError("Failed to create Vulkan surface");
return false; return false;
} }
// Step 4: Select physical device // Step 4: Select physical device
if (!selectPhysicalDevice()) { if (!selectPhysicalDevice()) {
setError("Failed to select physical device"); setError("Failed to select physical device");
return false; return false;
} }
// Step 5: Create logical device // Step 5: Create logical device
if (!createDevice()) { if (!createDevice()) {
setError("Failed to create logical device"); setError("Failed to create logical device");
return false; return false;
} }
// Step 6: Create swapchain // Step 6: Create swapchain
if (!createSwapchain()) { if (!createSwapchain()) {
setError("Failed to create swapchain"); setError("Failed to create swapchain");
return false; return false;
} }
// Step 7: Create command objects // Step 7: Create command objects
if (!createCommandObjects()) { if (!createCommandObjects()) {
setError("Failed to create command objects"); setError("Failed to create command objects");
return false; return false;
} }
// Step 8: Create synchronization objects // Step 8: Create synchronization objects
if (!createSyncObjects()) { if (!createSyncObjects()) {
setError("Failed to create sync objects"); setError("Failed to create sync objects");
return false; return false;
} }
// Step 9: Create VulkanRenderer - but only if we have reasonable dimensions // Step 9: Create VulkanRenderer - but only if we have reasonable dimensions
if (m_surfaceWidth >= 100 && m_surfaceHeight >= 100) { if (m_surfaceWidth >= 100 && m_surfaceHeight >= 100) {
m_renderer = new VulkanRenderer(); m_renderer = new VulkanRenderer();
// Get swapchain format // Get swapchain format
VkSurfaceFormatKHR surfaceFormat; VkSurfaceFormatKHR surfaceFormat;
uint32_t formatCount = 0; uint32_t formatCount = 0;
@ -154,7 +154,7 @@ bool VulkanWidget::initializeVulkan()
vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, formats.data()); vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, formats.data());
surfaceFormat = formats[0]; surfaceFormat = formats[0];
} }
// Initialize renderer // Initialize renderer
if (!m_renderer->initialize(m_device, m_physicalDevice, if (!m_renderer->initialize(m_device, m_physicalDevice,
m_queue, m_queueFamilyIndex, m_queue, m_queueFamilyIndex,
@ -165,14 +165,14 @@ bool VulkanWidget::initializeVulkan()
m_renderer = nullptr; m_renderer = nullptr;
return false; return false;
} }
qDebug() << "VulkanRenderer initialized successfully!"; qDebug() << "VulkanRenderer initialized successfully!";
qDebug() << "Widget size:" << width() << "x" << height() qDebug() << "Widget size:" << width() << "x" << height()
<< "| Surface size:" << m_surfaceWidth << "x" << m_surfaceHeight; << "| Surface size:" << m_surfaceWidth << "x" << m_surfaceHeight;
} else { } else {
qDebug() << "VulkanRenderer initialization deferred - window too small:" << m_surfaceWidth << "x" << m_surfaceHeight; qDebug() << "VulkanRenderer initialization deferred - window too small:" << m_surfaceWidth << "x" << m_surfaceHeight;
} }
m_initialized = true; m_initialized = true;
qDebug() << "Vulkan initialization successful!"; qDebug() << "Vulkan initialization successful!";
return true; return true;
@ -181,13 +181,13 @@ bool VulkanWidget::initializeVulkan()
bool VulkanWidget::initializeVolk() bool VulkanWidget::initializeVolk()
{ {
qDebug() << "Initializing volk..."; qDebug() << "Initializing volk...";
VkResult result = volkInitialize(); VkResult result = volkInitialize();
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
qDebug() << "Failed to initialize volk, error code:" << result; qDebug() << "Failed to initialize volk, error code:" << result;
return false; return false;
} }
qDebug() << "Volk initialized successfully"; qDebug() << "Volk initialized successfully";
return true; return true;
} }
@ -195,7 +195,7 @@ bool VulkanWidget::initializeVolk()
bool VulkanWidget::createInstance() bool VulkanWidget::createInstance()
{ {
qDebug() << "Creating Vulkan instance..."; qDebug() << "Creating Vulkan instance...";
VkApplicationInfo appInfo = {}; VkApplicationInfo appInfo = {};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "VulkanWidget"; appInfo.pApplicationName = "VulkanWidget";
@ -203,25 +203,25 @@ bool VulkanWidget::createInstance()
appInfo.pEngineName = "No Engine"; appInfo.pEngineName = "No Engine";
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.apiVersion = VK_API_VERSION_1_0; appInfo.apiVersion = VK_API_VERSION_1_0;
std::vector<const char*> extensions = getRequiredInstanceExtensions(); std::vector<const char*> extensions = getRequiredInstanceExtensions();
VkInstanceCreateInfo createInfo = {}; VkInstanceCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
createInfo.pApplicationInfo = &appInfo; createInfo.pApplicationInfo = &appInfo;
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size()); createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
createInfo.ppEnabledExtensionNames = extensions.data(); createInfo.ppEnabledExtensionNames = extensions.data();
createInfo.enabledLayerCount = 0; createInfo.enabledLayerCount = 0;
VkResult result = vkCreateInstance(&createInfo, nullptr, &m_instance); VkResult result = vkCreateInstance(&createInfo, nullptr, &m_instance);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
qDebug() << "Failed to create Vulkan instance, error code:" << result; qDebug() << "Failed to create Vulkan instance, error code:" << result;
return false; return false;
} }
// Load instance-level functions // Load instance-level functions
volkLoadInstance(m_instance); volkLoadInstance(m_instance);
qDebug() << "Vulkan instance created successfully"; qDebug() << "Vulkan instance created successfully";
return true; return true;
} }
@ -229,7 +229,7 @@ bool VulkanWidget::createInstance()
bool VulkanWidget::createSurface() bool VulkanWidget::createSurface()
{ {
qDebug() << "Creating Vulkan surface from native window..."; qDebug() << "Creating Vulkan surface from native window...";
if (!windowHandle()) { if (!windowHandle()) {
qDebug() << "Window handle not available, creating window..."; qDebug() << "Window handle not available, creating window...";
create(); create();
@ -238,17 +238,17 @@ bool VulkanWidget::createSurface()
return false; return false;
} }
} }
QWindow *window = windowHandle(); QWindow *window = windowHandle();
#ifdef _WIN32 #ifdef _WIN32
VkWin32SurfaceCreateInfoKHR createInfo = {}; VkWin32SurfaceCreateInfoKHR createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
createInfo.hwnd = reinterpret_cast<HWND>(window->winId()); createInfo.hwnd = reinterpret_cast<HWND>(window->winId());
createInfo.hinstance = GetModuleHandle(nullptr); createInfo.hinstance = GetModuleHandle(nullptr);
VkResult result = vkCreateWin32SurfaceKHR(m_instance, &createInfo, nullptr, &m_surface); VkResult result = vkCreateWin32SurfaceKHR(m_instance, &createInfo, nullptr, &m_surface);
#elif defined(__linux__) #elif defined(__linux__)
VkXlibSurfaceCreateInfoKHR createInfo = {}; VkXlibSurfaceCreateInfoKHR createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR; createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
@ -259,26 +259,26 @@ bool VulkanWidget::createSurface()
return false; return false;
} }
createInfo.window = static_cast<Window>(window->winId()); createInfo.window = static_cast<Window>(window->winId());
VkResult result = vkCreateXlibSurfaceKHR(m_instance, &createInfo, nullptr, &m_surface); VkResult result = vkCreateXlibSurfaceKHR(m_instance, &createInfo, nullptr, &m_surface);
#elif defined(__APPLE__) #elif defined(__APPLE__)
// macOS requires MoltenVK and Metal // macOS requires MoltenVK and Metal
VkMetalSurfaceCreateInfoEXT createInfo = {}; VkMetalSurfaceCreateInfoEXT createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT; createInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
createInfo.pLayer = nullptr; // This needs proper Metal layer setup createInfo.pLayer = nullptr; // This needs proper Metal layer setup
VkResult result = vkCreateMetalSurfaceEXT(m_instance, &createInfo, nullptr, &m_surface); VkResult result = vkCreateMetalSurfaceEXT(m_instance, &createInfo, nullptr, &m_surface);
#else #else
qDebug() << "Unsupported platform for Vulkan surface creation"; qDebug() << "Unsupported platform for Vulkan surface creation";
return false; return false;
#endif #endif
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
qDebug() << "Failed to create Vulkan surface, error code:" << result; qDebug() << "Failed to create Vulkan surface, error code:" << result;
return false; return false;
} }
qDebug() << "Vulkan surface created successfully"; qDebug() << "Vulkan surface created successfully";
return true; return true;
} }
@ -286,28 +286,28 @@ bool VulkanWidget::createSurface()
bool VulkanWidget::selectPhysicalDevice() bool VulkanWidget::selectPhysicalDevice()
{ {
qDebug() << "Selecting physical device..."; qDebug() << "Selecting physical device...";
uint32_t deviceCount = 0; uint32_t deviceCount = 0;
vkEnumeratePhysicalDevices(m_instance, &deviceCount, nullptr); vkEnumeratePhysicalDevices(m_instance, &deviceCount, nullptr);
if (deviceCount == 0) { if (deviceCount == 0) {
qDebug() << "Failed to find GPUs with Vulkan support"; qDebug() << "Failed to find GPUs with Vulkan support";
return false; return false;
} }
std::vector<VkPhysicalDevice> devices(deviceCount); std::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices(m_instance, &deviceCount, devices.data()); vkEnumeratePhysicalDevices(m_instance, &deviceCount, devices.data());
// Select the first suitable device // Select the first suitable device
for (const auto& device : devices) { for (const auto& device : devices) {
VkPhysicalDeviceProperties properties; VkPhysicalDeviceProperties properties;
vkGetPhysicalDeviceProperties(device, &properties); vkGetPhysicalDeviceProperties(device, &properties);
qDebug() << "Found device:" << properties.deviceName; qDebug() << "Found device:" << properties.deviceName;
// Temporarily set physical device to check queue families // Temporarily set physical device to check queue families
m_physicalDevice = device; m_physicalDevice = device;
// Check if device supports our queue family // Check if device supports our queue family
uint32_t queueFamilyIndex; uint32_t queueFamilyIndex;
if (findQueueFamily(queueFamilyIndex)) { if (findQueueFamily(queueFamilyIndex)) {
@ -316,7 +316,7 @@ bool VulkanWidget::selectPhysicalDevice()
return true; return true;
} }
} }
// Reset if no suitable device found // Reset if no suitable device found
m_physicalDevice = VK_NULL_HANDLE; m_physicalDevice = VK_NULL_HANDLE;
qDebug() << "Failed to find suitable physical device"; qDebug() << "Failed to find suitable physical device";
@ -327,42 +327,42 @@ bool VulkanWidget::findQueueFamily(uint32_t &queueFamilyIndex)
{ {
uint32_t queueFamilyCount = 0; uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &queueFamilyCount, nullptr); vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &queueFamilyCount, nullptr);
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount); std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &queueFamilyCount, queueFamilies.data()); vkGetPhysicalDeviceQueueFamilyProperties(m_physicalDevice, &queueFamilyCount, queueFamilies.data());
for (uint32_t i = 0; i < queueFamilyCount; i++) { for (uint32_t i = 0; i < queueFamilyCount; i++) {
// Check if queue family supports graphics // Check if queue family supports graphics
if (queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { if (queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
// Check if queue family supports presentation // Check if queue family supports presentation
VkBool32 presentSupport = false; VkBool32 presentSupport = false;
vkGetPhysicalDeviceSurfaceSupportKHR(m_physicalDevice, i, m_surface, &presentSupport); vkGetPhysicalDeviceSurfaceSupportKHR(m_physicalDevice, i, m_surface, &presentSupport);
if (presentSupport) { if (presentSupport) {
queueFamilyIndex = i; queueFamilyIndex = i;
return true; return true;
} }
} }
} }
return false; return false;
} }
bool VulkanWidget::createDevice() bool VulkanWidget::createDevice()
{ {
qDebug() << "Creating logical device..."; qDebug() << "Creating logical device...";
float queuePriority = 1.0f; float queuePriority = 1.0f;
VkDeviceQueueCreateInfo queueCreateInfo = {}; VkDeviceQueueCreateInfo queueCreateInfo = {};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = m_queueFamilyIndex; queueCreateInfo.queueFamilyIndex = m_queueFamilyIndex;
queueCreateInfo.queueCount = 1; queueCreateInfo.queueCount = 1;
queueCreateInfo.pQueuePriorities = &queuePriority; queueCreateInfo.pQueuePriorities = &queuePriority;
VkPhysicalDeviceFeatures deviceFeatures = {}; VkPhysicalDeviceFeatures deviceFeatures = {};
std::vector<const char*> deviceExtensions = getRequiredDeviceExtensions(); std::vector<const char*> deviceExtensions = getRequiredDeviceExtensions();
VkDeviceCreateInfo createInfo = {}; VkDeviceCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
createInfo.pQueueCreateInfos = &queueCreateInfo; createInfo.pQueueCreateInfos = &queueCreateInfo;
@ -371,19 +371,19 @@ bool VulkanWidget::createDevice()
createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size()); createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
createInfo.ppEnabledExtensionNames = deviceExtensions.data(); createInfo.ppEnabledExtensionNames = deviceExtensions.data();
createInfo.enabledLayerCount = 0; createInfo.enabledLayerCount = 0;
VkResult result = vkCreateDevice(m_physicalDevice, &createInfo, nullptr, &m_device); VkResult result = vkCreateDevice(m_physicalDevice, &createInfo, nullptr, &m_device);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
qDebug() << "Failed to create logical device, error code:" << result; qDebug() << "Failed to create logical device, error code:" << result;
return false; return false;
} }
// Load device-level functions // Load device-level functions
volkLoadDevice(m_device); volkLoadDevice(m_device);
// Get queue handle // Get queue handle
vkGetDeviceQueue(m_device, m_queueFamilyIndex, 0, &m_queue); vkGetDeviceQueue(m_device, m_queueFamilyIndex, 0, &m_queue);
qDebug() << "Logical device created successfully"; qDebug() << "Logical device created successfully";
return true; return true;
} }
@ -393,40 +393,40 @@ bool VulkanWidget::createSwapchain()
qDebug() << "Creating swapchain..."; qDebug() << "Creating swapchain...";
qDebug() << "Widget size:" << width() << "x" << height(); qDebug() << "Widget size:" << width() << "x" << height();
qDebug() << "Device pixel ratio:" << devicePixelRatioF(); qDebug() << "Device pixel ratio:" << devicePixelRatioF();
// Query surface capabilities // Query surface capabilities
VkSurfaceCapabilitiesKHR capabilities; VkSurfaceCapabilitiesKHR capabilities;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_physicalDevice, m_surface, &capabilities); vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_physicalDevice, m_surface, &capabilities);
qDebug() << "Surface capabilities - current extent:" qDebug() << "Surface capabilities - current extent:"
<< capabilities.currentExtent.width << "x" << capabilities.currentExtent.height; << capabilities.currentExtent.width << "x" << capabilities.currentExtent.height;
qDebug() << "Surface capabilities - min extent:" qDebug() << "Surface capabilities - min extent:"
<< capabilities.minImageExtent.width << "x" << capabilities.minImageExtent.height; << capabilities.minImageExtent.width << "x" << capabilities.minImageExtent.height;
qDebug() << "Surface capabilities - max extent:" qDebug() << "Surface capabilities - max extent:"
<< capabilities.maxImageExtent.width << "x" << capabilities.maxImageExtent.height; << capabilities.maxImageExtent.width << "x" << capabilities.maxImageExtent.height;
// Query surface formats // Query surface formats
uint32_t formatCount; uint32_t formatCount;
vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, nullptr); vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, nullptr);
std::vector<VkSurfaceFormatKHR> formats(formatCount); std::vector<VkSurfaceFormatKHR> formats(formatCount);
vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, formats.data()); vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, formats.data());
// Query present modes // Query present modes
uint32_t presentModeCount; uint32_t presentModeCount;
vkGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &presentModeCount, nullptr); vkGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &presentModeCount, nullptr);
std::vector<VkPresentModeKHR> presentModes(presentModeCount); std::vector<VkPresentModeKHR> presentModes(presentModeCount);
vkGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &presentModeCount, presentModes.data()); vkGetPhysicalDeviceSurfacePresentModesKHR(m_physicalDevice, m_surface, &presentModeCount, presentModes.data());
// Select format // Select format
VkSurfaceFormatKHR surfaceFormat = formats[0]; VkSurfaceFormatKHR surfaceFormat = formats[0];
for (const auto& format : formats) { 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) { format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
surfaceFormat = format; surfaceFormat = format;
break; break;
} }
} }
// Select present mode (prefer mailbox, fallback to FIFO) // Select present mode (prefer mailbox, fallback to FIFO)
VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR; VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
for (const auto& mode : presentModes) { for (const auto& mode : presentModes) {
@ -435,7 +435,7 @@ bool VulkanWidget::createSwapchain()
break; break;
} }
} }
// Determine extent // Determine extent
VkExtent2D extent; VkExtent2D extent;
if (capabilities.currentExtent.width != UINT32_MAX) { if (capabilities.currentExtent.width != UINT32_MAX) {
@ -445,27 +445,27 @@ bool VulkanWidget::createSwapchain()
// Calculate extent based on widget size with DPI scaling // Calculate extent based on widget size with DPI scaling
uint32_t pixelWidth = static_cast<uint32_t>(width() * devicePixelRatioF()); uint32_t pixelWidth = static_cast<uint32_t>(width() * devicePixelRatioF());
uint32_t pixelHeight = static_cast<uint32_t>(height() * devicePixelRatioF()); uint32_t pixelHeight = static_cast<uint32_t>(height() * devicePixelRatioF());
extent.width = std::max(capabilities.minImageExtent.width, extent.width = std::max(capabilities.minImageExtent.width,
std::min(capabilities.maxImageExtent.width, pixelWidth)); std::min(capabilities.maxImageExtent.width, pixelWidth));
extent.height = std::max(capabilities.minImageExtent.height, extent.height = std::max(capabilities.minImageExtent.height,
std::min(capabilities.maxImageExtent.height, pixelHeight)); std::min(capabilities.maxImageExtent.height, pixelHeight));
qDebug() << "Calculated extent from widget:" << extent.width << "x" << extent.height qDebug() << "Calculated extent from widget:" << extent.width << "x" << extent.height
<< "(widget:" << width() << "x" << height() << "(widget:" << width() << "x" << height()
<< "* DPR:" << devicePixelRatioF() << ")"; << "* DPR:" << devicePixelRatioF() << ")";
} }
m_surfaceWidth = extent.width; m_surfaceWidth = extent.width;
m_surfaceHeight = extent.height; m_surfaceHeight = extent.height;
qDebug() << "Final swapchain extent:" << m_surfaceWidth << "x" << m_surfaceHeight; qDebug() << "Final swapchain extent:" << m_surfaceWidth << "x" << m_surfaceHeight;
// Determine image count // Determine image count
uint32_t imageCount = capabilities.minImageCount + 1; uint32_t imageCount = capabilities.minImageCount + 1;
if (capabilities.maxImageCount > 0 && imageCount > capabilities.maxImageCount) { if (capabilities.maxImageCount > 0 && imageCount > capabilities.maxImageCount) {
imageCount = capabilities.maxImageCount; imageCount = capabilities.maxImageCount;
} }
VkSwapchainCreateInfoKHR createInfo = {}; VkSwapchainCreateInfoKHR createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
createInfo.surface = m_surface; createInfo.surface = m_surface;
@ -481,19 +481,19 @@ bool VulkanWidget::createSwapchain()
createInfo.presentMode = presentMode; createInfo.presentMode = presentMode;
createInfo.clipped = VK_TRUE; createInfo.clipped = VK_TRUE;
createInfo.oldSwapchain = VK_NULL_HANDLE; createInfo.oldSwapchain = VK_NULL_HANDLE;
VkResult result = vkCreateSwapchainKHR(m_device, &createInfo, nullptr, &m_swapchain); VkResult result = vkCreateSwapchainKHR(m_device, &createInfo, nullptr, &m_swapchain);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
qDebug() << "Failed to create swapchain, error code:" << result; qDebug() << "Failed to create swapchain, error code:" << result;
return false; return false;
} }
// Retrieve swapchain images // Retrieve swapchain images
vkGetSwapchainImagesKHR(m_device, m_swapchain, &imageCount, nullptr); vkGetSwapchainImagesKHR(m_device, m_swapchain, &imageCount, nullptr);
m_swapchainImages.resize(imageCount); m_swapchainImages.resize(imageCount);
vkGetSwapchainImagesKHR(m_device, m_swapchain, &imageCount, vkGetSwapchainImagesKHR(m_device, m_swapchain, &imageCount,
reinterpret_cast<VkImage*>(m_swapchainImages.data())); reinterpret_cast<VkImage*>(m_swapchainImages.data()));
// Create image views for swapchain images // Create image views for swapchain images
m_swapchainImageViews.resize(imageCount); m_swapchainImageViews.resize(imageCount);
for (uint32_t i = 0; i < imageCount; i++) { for (uint32_t i = 0; i < imageCount; i++) {
@ -511,7 +511,7 @@ bool VulkanWidget::createSwapchain()
viewInfo.subresourceRange.levelCount = 1; viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = 0; viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = 1; viewInfo.subresourceRange.layerCount = 1;
VkImageView imageView; VkImageView imageView;
result = vkCreateImageView(m_device, &viewInfo, nullptr, &imageView); result = vkCreateImageView(m_device, &viewInfo, nullptr, &imageView);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
@ -520,42 +520,42 @@ bool VulkanWidget::createSwapchain()
} }
m_swapchainImageViews[i] = reinterpret_cast<void*>(imageView); m_swapchainImageViews[i] = reinterpret_cast<void*>(imageView);
} }
qDebug() << "Swapchain created successfully with" << imageCount << "images, size:" qDebug() << "Swapchain created successfully with" << imageCount << "images, size:"
<< m_surfaceWidth << "x" << m_surfaceHeight; << m_surfaceWidth << "x" << m_surfaceHeight;
return true; return true;
} }
bool VulkanWidget::createCommandObjects() bool VulkanWidget::createCommandObjects()
{ {
qDebug() << "Creating command objects..."; qDebug() << "Creating command objects...";
VkCommandPoolCreateInfo poolInfo = {}; VkCommandPoolCreateInfo poolInfo = {};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.queueFamilyIndex = m_queueFamilyIndex; poolInfo.queueFamilyIndex = m_queueFamilyIndex;
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
VkResult result = vkCreateCommandPool(m_device, &poolInfo, nullptr, &m_commandPool); VkResult result = vkCreateCommandPool(m_device, &poolInfo, nullptr, &m_commandPool);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
qDebug() << "Failed to create command pool, error code:" << result; qDebug() << "Failed to create command pool, error code:" << result;
return false; return false;
} }
m_commandBuffers.resize(MAX_FRAMES_IN_FLIGHT); m_commandBuffers.resize(MAX_FRAMES_IN_FLIGHT);
VkCommandBufferAllocateInfo allocInfo = {}; VkCommandBufferAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.commandPool = m_commandPool; allocInfo.commandPool = m_commandPool;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandBufferCount = static_cast<uint32_t>(m_commandBuffers.size()); allocInfo.commandBufferCount = static_cast<uint32_t>(m_commandBuffers.size());
result = vkAllocateCommandBuffers(m_device, &allocInfo, m_commandBuffers.data()); result = vkAllocateCommandBuffers(m_device, &allocInfo, m_commandBuffers.data());
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
qDebug() << "Failed to allocate command buffers, error code:" << result; qDebug() << "Failed to allocate command buffers, error code:" << result;
return false; return false;
} }
qDebug() << "Command objects created successfully"; qDebug() << "Command objects created successfully";
return true; return true;
} }
@ -563,18 +563,18 @@ bool VulkanWidget::createCommandObjects()
bool VulkanWidget::createSyncObjects() bool VulkanWidget::createSyncObjects()
{ {
qDebug() << "Creating synchronization objects..."; qDebug() << "Creating synchronization objects...";
m_imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT); m_imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
m_renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT); m_renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
m_inFlightFences.resize(MAX_FRAMES_IN_FLIGHT); m_inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
VkSemaphoreCreateInfo semaphoreInfo = {}; VkSemaphoreCreateInfo semaphoreInfo = {};
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
VkFenceCreateInfo fenceInfo = {}; VkFenceCreateInfo fenceInfo = {};
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
if (vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &m_imageAvailableSemaphores[i]) != VK_SUCCESS || if (vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &m_imageAvailableSemaphores[i]) != VK_SUCCESS ||
vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &m_renderFinishedSemaphores[i]) != VK_SUCCESS || vkCreateSemaphore(m_device, &semaphoreInfo, nullptr, &m_renderFinishedSemaphores[i]) != VK_SUCCESS ||
@ -583,7 +583,7 @@ bool VulkanWidget::createSyncObjects()
return false; return false;
} }
} }
qDebug() << "Synchronization objects created successfully"; qDebug() << "Synchronization objects created successfully";
return true; return true;
} }
@ -591,25 +591,25 @@ bool VulkanWidget::createSyncObjects()
bool VulkanWidget::recreateSwapchain() bool VulkanWidget::recreateSwapchain()
{ {
qDebug() << "Recreating swapchain..."; qDebug() << "Recreating swapchain...";
// Wait for device to be idle // Wait for device to be idle
vkDeviceWaitIdle(m_device); vkDeviceWaitIdle(m_device);
// Cleanup old swapchain // Cleanup old swapchain
cleanupSwapchain(); cleanupSwapchain();
// Create new swapchain // Create new swapchain
if (!createSwapchain()) { if (!createSwapchain()) {
qDebug() << "Failed to recreate swapchain"; qDebug() << "Failed to recreate swapchain";
return false; return false;
} }
// Update renderer with new surface dimensions // Update renderer with new surface dimensions
if (m_renderer) { if (m_renderer) {
qDebug() << "Updating VulkanRenderer to surface size:" << m_surfaceWidth << "x" << m_surfaceHeight; qDebug() << "Updating VulkanRenderer to surface size:" << m_surfaceWidth << "x" << m_surfaceHeight;
m_renderer->resize(m_surfaceWidth, m_surfaceHeight); m_renderer->resize(m_surfaceWidth, m_surfaceHeight);
} }
qDebug() << "Swapchain recreated successfully"; qDebug() << "Swapchain recreated successfully";
return true; return true;
} }
@ -619,16 +619,16 @@ void VulkanWidget::renderFrame()
if (!m_initialized || !m_renderingEnabled) { if (!m_initialized || !m_renderingEnabled) {
return; return;
} }
// Wait for previous frame // Wait for previous frame
vkWaitForFences(m_device, 1, &m_inFlightFences[m_currentFrame], VK_TRUE, UINT64_MAX); vkWaitForFences(m_device, 1, &m_inFlightFences[m_currentFrame], VK_TRUE, UINT64_MAX);
// Acquire next image // Acquire next image
uint32_t imageIndex; uint32_t imageIndex;
VkResult result = vkAcquireNextImageKHR(m_device, m_swapchain, UINT64_MAX, VkResult result = vkAcquireNextImageKHR(m_device, m_swapchain, UINT64_MAX,
m_imageAvailableSemaphores[m_currentFrame], m_imageAvailableSemaphores[m_currentFrame],
VK_NULL_HANDLE, &imageIndex); VK_NULL_HANDLE, &imageIndex);
if (result == VK_ERROR_OUT_OF_DATE_KHR) { if (result == VK_ERROR_OUT_OF_DATE_KHR) {
recreateSwapchain(); recreateSwapchain();
return; return;
@ -636,18 +636,18 @@ void VulkanWidget::renderFrame()
qDebug() << "Failed to acquire swapchain image"; qDebug() << "Failed to acquire swapchain image";
return; return;
} }
// Reset fence // Reset fence
vkResetFences(m_device, 1, &m_inFlightFences[m_currentFrame]); vkResetFences(m_device, 1, &m_inFlightFences[m_currentFrame]);
// Record command buffer // Record command buffer
vkResetCommandBuffer(m_commandBuffers[m_currentFrame], 0); vkResetCommandBuffer(m_commandBuffers[m_currentFrame], 0);
recordCommandBuffer(m_commandBuffers[m_currentFrame], imageIndex); recordCommandBuffer(m_commandBuffers[m_currentFrame], imageIndex);
// Submit command buffer // Submit command buffer
VkSubmitInfo submitInfo = {}; VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
VkSemaphore waitSemaphores[] = {m_imageAvailableSemaphores[m_currentFrame]}; VkSemaphore waitSemaphores[] = {m_imageAvailableSemaphores[m_currentFrame]};
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
submitInfo.waitSemaphoreCount = 1; submitInfo.waitSemaphoreCount = 1;
@ -655,37 +655,37 @@ void VulkanWidget::renderFrame()
submitInfo.pWaitDstStageMask = waitStages; submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1; submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &m_commandBuffers[m_currentFrame]; submitInfo.pCommandBuffers = &m_commandBuffers[m_currentFrame];
VkSemaphore signalSemaphores[] = {m_renderFinishedSemaphores[m_currentFrame]}; VkSemaphore signalSemaphores[] = {m_renderFinishedSemaphores[m_currentFrame]};
submitInfo.signalSemaphoreCount = 1; submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores; submitInfo.pSignalSemaphores = signalSemaphores;
result = vkQueueSubmit(m_queue, 1, &submitInfo, m_inFlightFences[m_currentFrame]); result = vkQueueSubmit(m_queue, 1, &submitInfo, m_inFlightFences[m_currentFrame]);
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
qDebug() << "Failed to submit draw command buffer"; qDebug() << "Failed to submit draw command buffer";
return; return;
} }
// Present // Present
VkPresentInfoKHR presentInfo = {}; VkPresentInfoKHR presentInfo = {};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1; presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = signalSemaphores; presentInfo.pWaitSemaphores = signalSemaphores;
VkSwapchainKHR swapchains[] = {m_swapchain}; VkSwapchainKHR swapchains[] = {m_swapchain};
presentInfo.swapchainCount = 1; presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = swapchains; presentInfo.pSwapchains = swapchains;
presentInfo.pImageIndices = &imageIndex; presentInfo.pImageIndices = &imageIndex;
result = vkQueuePresentKHR(m_queue, &presentInfo); result = vkQueuePresentKHR(m_queue, &presentInfo);
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || m_needsResize) { if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || m_needsResize) {
m_needsResize = false; m_needsResize = false;
recreateSwapchain(); recreateSwapchain();
} else if (result != VK_SUCCESS) { } else if (result != VK_SUCCESS) {
qDebug() << "Failed to present swapchain image"; qDebug() << "Failed to present swapchain image";
} }
m_currentFrame = (m_currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; m_currentFrame = (m_currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
m_frameCount++; m_frameCount++;
} }
@ -696,7 +696,7 @@ void VulkanWidget::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t i
if (!m_renderer && m_surfaceWidth >= 100 && m_surfaceHeight >= 100) { if (!m_renderer && m_surfaceWidth >= 100 && m_surfaceHeight >= 100) {
qDebug() << "Creating deferred VulkanRenderer with actual surface size:" << m_surfaceWidth << "x" << m_surfaceHeight; qDebug() << "Creating deferred VulkanRenderer with actual surface size:" << m_surfaceWidth << "x" << m_surfaceHeight;
m_renderer = new VulkanRenderer(); m_renderer = new VulkanRenderer();
VkSurfaceFormatKHR surfaceFormat; VkSurfaceFormatKHR surfaceFormat;
uint32_t formatCount = 0; uint32_t formatCount = 0;
vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, nullptr); 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()); vkGetPhysicalDeviceSurfaceFormatsKHR(m_physicalDevice, m_surface, &formatCount, formats.data());
surfaceFormat = formats[0]; surfaceFormat = formats[0];
} }
if (!m_renderer->initialize(m_device, m_physicalDevice, if (!m_renderer->initialize(m_device, m_physicalDevice,
m_queue, m_queueFamilyIndex, m_queue, m_queueFamilyIndex,
static_cast<uint32_t>(surfaceFormat.format), static_cast<uint32_t>(surfaceFormat.format),
@ -714,48 +714,50 @@ void VulkanWidget::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t i
delete m_renderer; delete m_renderer;
m_renderer = nullptr; m_renderer = nullptr;
} else { } else {
qDebug() << "Deferred VulkanRenderer initialized successfully with surface size:" qDebug() << "Deferred VulkanRenderer initialized successfully with surface size:"
<< m_surfaceWidth << "x" << m_surfaceHeight; << m_surfaceWidth << "x" << m_surfaceHeight;
} }
} }
// Use VulkanRenderer if available // Use VulkanRenderer if available
if (m_renderer) { if (m_renderer) {
if (imageIndex >= m_swapchainImageViews.size()) { if (imageIndex >= m_swapchainImageViews.size()) {
qDebug() << "ERROR: imageIndex out of bounds!"; qDebug() << "ERROR: imageIndex out of bounds!";
return; return;
} }
VkImageView imageView = reinterpret_cast<VkImageView>(m_swapchainImageViews[imageIndex]); VkImageView imageView = reinterpret_cast<VkImageView>(m_swapchainImageViews[imageIndex]);
// Build lock info string // Build lock info string
QString lockInfo; QString lockInfo;
if (m_lastLockTime.isValid()) { 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_lastLockTime.toString("hh:mm:ss"))
.arg(m_lastLockDuration) .arg(m_lastLockDuration)
.arg(m_lastLockFrameCount)
.arg(m_lockPaintFrameCount)
.arg(m_lockCount); .arg(m_lockCount);
} }
// Debug: Print dimensions occasionally to check for mismatch // Debug: Print dimensions occasionally to check for mismatch
static int debugCounter = 0; static int debugCounter = 0;
if (debugCounter++ % 300 == 0) { // Every ~5 seconds at 60fps 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; << "| Surface:" << m_surfaceWidth << "x" << m_surfaceHeight;
} }
m_renderer->recordCommandBuffer(commandBuffer, imageIndex, imageView, m_renderer->recordCommandBuffer(commandBuffer, imageIndex, imageView,
m_frameCount, m_rotationAngle, m_wavePhase, m_frameCount, m_rotationAngle, m_wavePhase,
m_renderingEnabled, lockInfo.toStdString()); m_renderingEnabled, lockInfo.toStdString());
return; return;
} }
// Fallback: Simple clear color pass // Fallback: Simple clear color pass
VkCommandBufferBeginInfo beginInfo = {}; VkCommandBufferBeginInfo beginInfo = {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
vkBeginCommandBuffer(commandBuffer, &beginInfo); vkBeginCommandBuffer(commandBuffer, &beginInfo);
VkClearColorValue clearColor; VkClearColorValue clearColor;
float hue = (m_frameCount % 360) / 360.0f; float hue = (m_frameCount % 360) / 360.0f;
float r = std::abs(std::sin(hue * 6.28318f)); 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[1] = g * 0.5f + 0.1f;
clearColor.float32[2] = b * 0.5f + 0.1f; clearColor.float32[2] = b * 0.5f + 0.1f;
clearColor.float32[3] = 1.0f; clearColor.float32[3] = 1.0f;
VkImageSubresourceRange range = {}; VkImageSubresourceRange range = {};
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
range.baseMipLevel = 0; range.baseMipLevel = 0;
range.levelCount = 1; range.levelCount = 1;
range.baseArrayLayer = 0; range.baseArrayLayer = 0;
range.layerCount = 1; range.layerCount = 1;
VkImage image = reinterpret_cast<VkImage>(m_swapchainImages[imageIndex]); VkImage image = reinterpret_cast<VkImage>(m_swapchainImages[imageIndex]);
VkImageMemoryBarrier barrier1 = {}; VkImageMemoryBarrier barrier1 = {};
barrier1.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier1.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier1.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; barrier1.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
@ -785,13 +787,13 @@ void VulkanWidget::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t i
barrier1.subresourceRange = range; barrier1.subresourceRange = range;
barrier1.srcAccessMask = 0; barrier1.srcAccessMask = 0;
barrier1.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 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); 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); &clearColor, 1, &range);
VkImageMemoryBarrier barrier2 = {}; VkImageMemoryBarrier barrier2 = {};
barrier2.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier2.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier2.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; barrier2.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
@ -802,10 +804,10 @@ void VulkanWidget::recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t i
barrier2.subresourceRange = range; barrier2.subresourceRange = range;
barrier2.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier2.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier2.dstAccessMask = 0; barrier2.dstAccessMask = 0;
vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier2); VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier2);
vkEndCommandBuffer(commandBuffer); vkEndCommandBuffer(commandBuffer);
} }
@ -818,12 +820,12 @@ void VulkanWidget::cleanupSwapchain()
} }
} }
m_swapchainImageViews.clear(); m_swapchainImageViews.clear();
if (m_swapchain != VK_NULL_HANDLE) { if (m_swapchain != VK_NULL_HANDLE) {
vkDestroySwapchainKHR(m_device, m_swapchain, nullptr); vkDestroySwapchainKHR(m_device, m_swapchain, nullptr);
m_swapchain = VK_NULL_HANDLE; m_swapchain = VK_NULL_HANDLE;
} }
m_swapchainImages.clear(); m_swapchainImages.clear();
} }
@ -832,11 +834,11 @@ void VulkanWidget::cleanupVulkan()
if (!m_initialized) { if (!m_initialized) {
return; return;
} }
if (m_device != VK_NULL_HANDLE) { if (m_device != VK_NULL_HANDLE) {
vkDeviceWaitIdle(m_device); vkDeviceWaitIdle(m_device);
} }
// Cleanup sync objects // Cleanup sync objects
for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { for (int i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
if (m_imageAvailableSemaphores[i] != VK_NULL_HANDLE) { if (m_imageAvailableSemaphores[i] != VK_NULL_HANDLE) {
@ -849,30 +851,30 @@ void VulkanWidget::cleanupVulkan()
vkDestroyFence(m_device, m_inFlightFences[i], nullptr); vkDestroyFence(m_device, m_inFlightFences[i], nullptr);
} }
} }
// Cleanup command pool // Cleanup command pool
if (m_commandPool != VK_NULL_HANDLE) { if (m_commandPool != VK_NULL_HANDLE) {
vkDestroyCommandPool(m_device, m_commandPool, nullptr); vkDestroyCommandPool(m_device, m_commandPool, nullptr);
} }
// Cleanup swapchain // Cleanup swapchain
cleanupSwapchain(); cleanupSwapchain();
// Cleanup device // Cleanup device
if (m_device != VK_NULL_HANDLE) { if (m_device != VK_NULL_HANDLE) {
vkDestroyDevice(m_device, nullptr); vkDestroyDevice(m_device, nullptr);
} }
// Cleanup surface // Cleanup surface
if (m_surface != VK_NULL_HANDLE) { if (m_surface != VK_NULL_HANDLE) {
vkDestroySurfaceKHR(m_instance, m_surface, nullptr); vkDestroySurfaceKHR(m_instance, m_surface, nullptr);
} }
// Cleanup instance // Cleanup instance
if (m_instance != VK_NULL_HANDLE) { if (m_instance != VK_NULL_HANDLE) {
vkDestroyInstance(m_instance, nullptr); vkDestroyInstance(m_instance, nullptr);
} }
m_initialized = false; m_initialized = false;
qDebug() << "Vulkan cleanup complete"; qDebug() << "Vulkan cleanup complete";
} }
@ -882,13 +884,13 @@ void VulkanWidget::setRenderingEnabled(bool enabled)
if (m_renderingEnabled == enabled) { if (m_renderingEnabled == enabled) {
return; return;
} }
m_renderingEnabled = enabled; m_renderingEnabled = enabled;
if (m_renderingEnabled) { if (m_renderingEnabled) {
qDebug() << "Vulkan rendering ENABLED - Resuming animations"; qDebug() << "Vulkan rendering ENABLED - Resuming animations";
m_renderTimer->start(16); // ~60 FPS m_renderTimer->start(16); // ~60 FPS
// Unlocked: calculate lock duration // Unlocked: calculate lock duration
if (m_lastLockTime.isValid()) { if (m_lastLockTime.isValid()) {
QDateTime unlockTime = QDateTime::currentDateTime(); QDateTime unlockTime = QDateTime::currentDateTime();
@ -898,12 +900,12 @@ void VulkanWidget::setRenderingEnabled(bool enabled)
qDebug() << "Frames at lock:" << m_lastLockFrameCount qDebug() << "Frames at lock:" << m_lastLockFrameCount
<< "- Frames painted during lock:" << m_lockPaintFrameCount; << "- Frames painted during lock:" << m_lockPaintFrameCount;
} }
m_startTime = QDateTime::currentDateTime(); m_startTime = QDateTime::currentDateTime();
} else { } else {
qDebug() << "Vulkan rendering DISABLED - Stopping animations"; qDebug() << "Vulkan rendering DISABLED - Stopping animations";
m_renderTimer->stop(); m_renderTimer->stop();
// Locked: record lock time // Locked: record lock time
m_pauseTime = QDateTime::currentDateTime(); m_pauseTime = QDateTime::currentDateTime();
m_lastLockTime = m_pauseTime; m_lastLockTime = m_pauseTime;
@ -934,7 +936,7 @@ void VulkanWidget::resetFrameCount()
void VulkanWidget::showEvent(QShowEvent *event) void VulkanWidget::showEvent(QShowEvent *event)
{ {
QWidget::showEvent(event); QWidget::showEvent(event);
if (!m_initialized) { if (!m_initialized) {
initializeVulkan(); initializeVulkan();
} }
@ -949,12 +951,12 @@ void VulkanWidget::hideEvent(QHideEvent *event)
void VulkanWidget::resizeEvent(QResizeEvent *event) void VulkanWidget::resizeEvent(QResizeEvent *event)
{ {
QWidget::resizeEvent(event); QWidget::resizeEvent(event);
if (m_initialized) { if (m_initialized) {
m_needsResize = true; m_needsResize = true;
// Note: Don't update renderer size here - it will be updated after swapchain recreation // 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 // not the widget dimensions, which may differ on high DPI displays
} }
} }
@ -979,13 +981,13 @@ void VulkanWidget::onRenderTimer()
if (m_rotationAngle >= 360.0) { if (m_rotationAngle >= 360.0) {
m_rotationAngle -= 360.0; m_rotationAngle -= 360.0;
} }
m_wavePhase += 0.05; m_wavePhase += 0.05;
if (m_wavePhase >= 2 * M_PI) { if (m_wavePhase >= 2 * M_PI) {
m_wavePhase -= 2 * M_PI; m_wavePhase -= 2 * M_PI;
} }
} }
renderFrame(); renderFrame();
} }
@ -998,9 +1000,9 @@ void VulkanWidget::setError(const QString &error)
std::vector<const char*> VulkanWidget::getRequiredInstanceExtensions() std::vector<const char*> VulkanWidget::getRequiredInstanceExtensions()
{ {
std::vector<const char*> extensions; std::vector<const char*> extensions;
extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME); extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
#ifdef _WIN32 #ifdef _WIN32
extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
#elif defined(__linux__) #elif defined(__linux__)
@ -1008,7 +1010,7 @@ std::vector<const char*> VulkanWidget::getRequiredInstanceExtensions()
#elif defined(__APPLE__) #elif defined(__APPLE__)
extensions.push_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME); extensions.push_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME);
#endif #endif
return extensions; return extensions;
} }
@ -1017,4 +1019,4 @@ std::vector<const char*> VulkanWidget::getRequiredDeviceExtensions()
std::vector<const char*> extensions; std::vector<const char*> extensions;
extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
return extensions; return extensions;
} }

View File

@ -26,7 +26,7 @@ typedef VkFlags VkSurfaceTransformFlagsKHR;
/** /**
* @brief Vulkan渲染组件类 * @brief Vulkan渲染组件类
* *
* 使Qt的native window属性创建Vulkan Surface * 使Qt的native window属性创建Vulkan Surface
* volk机制加载Vulkan函数 * volk机制加载Vulkan函数
*/ */
@ -249,7 +249,7 @@ private:
// VulkanRenderer // VulkanRenderer
VulkanRenderer *m_renderer; VulkanRenderer *m_renderer;
// 动画参数 // 动画参数
double m_rotationAngle; double m_rotationAngle;
double m_wavePhase; double m_wavePhase;
@ -265,4 +265,4 @@ private:
static const int MAX_FRAMES_IN_FLIGHT = 2; static const int MAX_FRAMES_IN_FLIGHT = 2;
}; };
#endif // VULKANWIDGET_H #endif // VULKANWIDGET_H