From c74e0438276c36e0fd9de7c5c80fd78815888668 Mon Sep 17 00:00:00 2001 From: TheLastRar Date: Thu, 11 Dec 2025 11:11:37 +0000 Subject: [PATCH] GS/VK: Use the compute queues for present --- pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp | 141 ++++++++++++++++------- 1 file changed, 100 insertions(+), 41 deletions(-) diff --git a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp index 52a21456eb..1185223576 100644 --- a/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp +++ b/pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp @@ -463,26 +463,72 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer vkGetPhysicalDeviceQueueFamilyProperties(m_physical_device, &queue_family_count, queue_family_properties.data()); DevCon.WriteLn("%u vulkan queue families", queue_family_count); - // Find graphics and present queues. + std::vector queue_family_users(queue_family_count, 0); + m_graphics_queue_family_index = queue_family_count; m_present_queue_family_index = queue_family_count; + u32 present_queue_index = 0; m_spin_queue_family_index = queue_family_count; u32 spin_queue_index = 0; + + // Graphics Queue for (uint32_t i = 0; i < queue_family_count; i++) { - VkBool32 graphics_supported = queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT; - if (graphics_supported) + if (queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { m_graphics_queue_family_index = i; - // Quit now, no need for a present queue. - if (!surface) - { - break; - } + queue_family_users[i]++; + break; } + } - if (surface) + // Spinwait Queue + for (uint32_t i = 0; i < queue_family_count; i++) + { + if (queue_family_properties[i].queueCount == queue_family_users[i]) + continue; + if (!(queue_family_properties[i].queueFlags & VK_QUEUE_COMPUTE_BIT)) + continue; + if (queue_family_properties[i].timestampValidBits == 0) + continue; // We need timing + + if (!(queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)) { + m_spin_queue_family_index = i; + break; + } + else if (m_spin_queue_family_index == queue_family_count) + m_spin_queue_family_index = i; + } + + if (m_spin_queue_family_index != queue_family_count) + { + spin_queue_index = queue_family_users[m_spin_queue_family_index]; + queue_family_users[m_spin_queue_family_index]++; + m_spin_queue_is_graphics_queue = false; + } + else + { + // No spare queue? Try the graphics queue. + if ((queue_family_properties[m_graphics_queue_family_index].queueCount & VK_QUEUE_COMPUTE_BIT) && + (queue_family_properties[m_graphics_queue_family_index].timestampValidBits != 0)) + { + m_spin_queue_family_index = m_graphics_queue_family_index; + spin_queue_index = 0; + m_spin_queue_is_graphics_queue = true; + } + else + m_spin_queue_is_graphics_queue = false; + } + + // Present Queue + if (surface) + { + for (uint32_t i = 0; i < queue_family_count; i++) + { + if (queue_family_properties[i].queueCount == queue_family_users[i]) + continue; + VkBool32 present_supported; VkResult res = vkGetPhysicalDeviceSurfaceSupportKHR(m_physical_device, i, surface, &present_supported); if (res != VK_SUCCESS) @@ -491,35 +537,48 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer return false; } - if (present_supported) + if (!present_supported) + continue; + + // Perfer aync compute queue + if ((queue_family_properties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) && + !(queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)) { m_present_queue_family_index = i; + break; + } + else if (m_present_queue_family_index == queue_family_count) + m_present_queue_family_index = i; + } + + if (m_present_queue_family_index != queue_family_count) + { + present_queue_index = queue_family_users[m_present_queue_family_index]; + queue_family_users[m_present_queue_family_index]++; + } + else + { + // No spare queue? Try the graphics queue. + VkBool32 present_supported; + VkResult res = vkGetPhysicalDeviceSurfaceSupportKHR(m_physical_device, m_graphics_queue_family_index, surface, &present_supported); + if (res != VK_SUCCESS) + { + LOG_VULKAN_ERROR(res, "vkGetPhysicalDeviceSurfaceSupportKHR failed: "); + return false; } - // Prefer one queue family index that does both graphics and present. - if (graphics_supported && present_supported) + if (present_supported) { - break; + m_present_queue_family_index = m_graphics_queue_family_index; + present_queue_index = 0; } } } - for (uint32_t i = 0; i < queue_family_count; i++) - { - // Pick a queue for spinning - if (!(queue_family_properties[i].queueFlags & VK_QUEUE_COMPUTE_BIT)) - continue; // We need compute - if (queue_family_properties[i].timestampValidBits == 0) - continue; // We need timing - const bool queue_is_used = i == m_graphics_queue_family_index || i == m_present_queue_family_index; - if (queue_is_used && m_spin_queue_family_index != queue_family_count) - continue; // Found a non-graphics queue to use - spin_queue_index = 0; - m_spin_queue_family_index = i; - if (queue_is_used && queue_family_properties[i].queueCount > 1) - spin_queue_index = 1; - if (!(queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)) - break; // Async compute queue, definitely pick this one - } + + // Swap spin and present to simplify queue priorities logic. + if (!m_spin_queue_is_graphics_queue && m_present_queue_family_index == m_spin_queue_family_index) + std::swap(spin_queue_index, present_queue_index); + if (m_graphics_queue_family_index == queue_family_count) { Console.Error("VK: Failed to find an acceptable graphics queue."); @@ -537,14 +596,16 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer device_info.flags = 0; device_info.queueCreateInfoCount = 0; - static constexpr float queue_priorities[] = {1.0f, 0.0f}; // Low priority for the spin queue + // Low priority for the spin queue + static constexpr float queue_priorities[] = {1.0f, 1.0f, 0.0f}; + std::array queue_infos; VkDeviceQueueCreateInfo& graphics_queue_info = queue_infos[device_info.queueCreateInfoCount++]; graphics_queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; graphics_queue_info.pNext = nullptr; graphics_queue_info.flags = 0; graphics_queue_info.queueFamilyIndex = m_graphics_queue_family_index; - graphics_queue_info.queueCount = 1; + graphics_queue_info.queueCount = queue_family_users[m_graphics_queue_family_index]; graphics_queue_info.pQueuePriorities = queue_priorities; if (surface != VK_NULL_HANDLE && m_graphics_queue_family_index != m_present_queue_family_index) @@ -554,19 +615,19 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer present_queue_info.pNext = nullptr; present_queue_info.flags = 0; present_queue_info.queueFamilyIndex = m_present_queue_family_index; - present_queue_info.queueCount = 1; + present_queue_info.queueCount = queue_family_users[m_present_queue_family_index]; present_queue_info.pQueuePriorities = queue_priorities; } if (m_spin_queue_family_index == m_graphics_queue_family_index) { - if (spin_queue_index != 0) - graphics_queue_info.queueCount = 2; + if (spin_queue_index == 1) + graphics_queue_info.pQueuePriorities = queue_priorities + 1; } else if (m_spin_queue_family_index == m_present_queue_family_index) { - if (spin_queue_index != 0) - queue_infos[1].queueCount = 2; // present queue + if (spin_queue_index == 1) + queue_infos[1].pQueuePriorities = queue_priorities + 1; } else { @@ -576,7 +637,7 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer spin_queue_info.flags = 0; spin_queue_info.queueFamilyIndex = m_spin_queue_family_index; spin_queue_info.queueCount = 1; - spin_queue_info.pQueuePriorities = queue_priorities + 1; + spin_queue_info.pQueuePriorities = queue_priorities + 2; } device_info.pQueueCreateInfos = queue_infos.data(); @@ -655,13 +716,11 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer vkGetDeviceQueue(m_device, m_graphics_queue_family_index, 0, &m_graphics_queue); if (surface) { - vkGetDeviceQueue(m_device, m_present_queue_family_index, 0, &m_present_queue); + vkGetDeviceQueue(m_device, m_present_queue_family_index, present_queue_index, &m_present_queue); } m_spinning_supported = m_spin_queue_family_index != queue_family_count && queue_family_properties[m_graphics_queue_family_index].timestampValidBits > 0 && m_device_properties.limits.timestampPeriod > 0; - m_spin_queue_is_graphics_queue = - m_spin_queue_family_index == m_graphics_queue_family_index && spin_queue_index == 0; m_gpu_timing_supported = (m_device_properties.limits.timestampComputeAndGraphics != 0 && queue_family_properties[m_graphics_queue_family_index].timestampValidBits > 0 &&