Merge pull request #6025 from spxtr/present_queue

Vulkan: Use a separate queue for presenting.
This commit is contained in:
Stenzek
2017-09-06 18:32:43 +10:00
committed by GitHub
4 changed files with 79 additions and 34 deletions

View File

@ -352,7 +352,7 @@ void CommandBufferManager::SubmitCommandBuffer(size_t index, VkSemaphore wait_se
&present_image_index, &present_image_index,
nullptr}; nullptr};
res = vkQueuePresentKHR(g_vulkan_context->GetGraphicsQueue(), &present_info); res = vkQueuePresentKHR(g_vulkan_context->GetPresentQueue(), &present_info);
if (res != VK_SUCCESS && res != VK_ERROR_OUT_OF_DATE_KHR && res != VK_SUBOPTIMAL_KHR) if (res != VK_SUCCESS && res != VK_ERROR_OUT_OF_DATE_KHR && res != VK_SUBOPTIMAL_KHR)
LOG_VULKAN_ERROR(res, "vkQueuePresentKHR failed: "); LOG_VULKAN_ERROR(res, "vkQueuePresentKHR failed: ");
} }

View File

@ -327,7 +327,6 @@ bool SwapChain::CreateSwapChain()
VkSwapchainKHR old_swap_chain = m_swap_chain; VkSwapchainKHR old_swap_chain = m_swap_chain;
// Now we can actually create the swap chain // Now we can actually create the swap chain
// TODO: Handle case where the present queue is not the graphics queue.
VkSwapchainCreateInfoKHR swap_chain_info = {VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, VkSwapchainCreateInfoKHR swap_chain_info = {VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
nullptr, nullptr,
0, 0,
@ -346,6 +345,17 @@ bool SwapChain::CreateSwapChain()
m_present_mode, m_present_mode,
VK_TRUE, VK_TRUE,
old_swap_chain}; old_swap_chain};
std::array<uint32_t, 2> indices = {{
g_vulkan_context->GetGraphicsQueueFamilyIndex(),
g_vulkan_context->GetPresentQueueFamilyIndex(),
}};
if (g_vulkan_context->GetGraphicsQueueFamilyIndex() !=
g_vulkan_context->GetPresentQueueFamilyIndex())
{
swap_chain_info.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
swap_chain_info.queueFamilyIndexCount = 2;
swap_chain_info.pQueueFamilyIndices = indices.data();
}
res = res =
vkCreateSwapchainKHR(g_vulkan_context->GetDevice(), &swap_chain_info, nullptr, &m_swap_chain); vkCreateSwapchainKHR(g_vulkan_context->GetDevice(), &swap_chain_info, nullptr, &m_swap_chain);

View File

@ -494,36 +494,41 @@ bool VulkanContext::CreateDevice(VkSurfaceKHR surface, bool enable_validation_la
queue_family_properties.data()); queue_family_properties.data());
INFO_LOG(VIDEO, "%u vulkan queue families", queue_family_count); INFO_LOG(VIDEO, "%u vulkan queue families", queue_family_count);
// Find a graphics queue // Find graphics and present queues.
// Currently we only use a single queue for both graphics and presenting.
// TODO: In the future we could do post-processing and presenting on a different queue.
m_graphics_queue_family_index = queue_family_count; m_graphics_queue_family_index = queue_family_count;
m_present_queue_family_index = queue_family_count;
for (uint32_t i = 0; i < queue_family_count; i++) for (uint32_t i = 0; i < queue_family_count; i++)
{ {
if (queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) VkBool32 graphics_supported = queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT;
if (graphics_supported)
{ {
// Check that it can present to our surface from this queue m_graphics_queue_family_index = i;
if (surface) // Quit now, no need for a present queue.
if (!surface)
{ {
VkBool32 present_supported; break;
VkResult res =
vkGetPhysicalDeviceSurfaceSupportKHR(m_physical_device, i, surface, &present_supported);
if (res != VK_SUCCESS)
{
LOG_VULKAN_ERROR(res, "vkGetPhysicalDeviceSurfaceSupportKHR failed: ");
return false;
}
if (present_supported)
{
m_graphics_queue_family_index = i;
break;
}
} }
else }
if (surface)
{
VkBool32 present_supported;
VkResult res =
vkGetPhysicalDeviceSurfaceSupportKHR(m_physical_device, i, surface, &present_supported);
if (res != VK_SUCCESS)
{
LOG_VULKAN_ERROR(res, "vkGetPhysicalDeviceSurfaceSupportKHR failed: ");
return false;
}
if (present_supported)
{
m_present_queue_family_index = i;
}
// Prefer one queue family index that does both graphics and present.
if (graphics_supported && present_supported)
{ {
// We don't need present, so any graphics queue will do.
m_graphics_queue_family_index = i;
break; break;
} }
} }
@ -533,6 +538,11 @@ bool VulkanContext::CreateDevice(VkSurfaceKHR surface, bool enable_validation_la
ERROR_LOG(VIDEO, "Vulkan: Failed to find an acceptable graphics queue."); ERROR_LOG(VIDEO, "Vulkan: Failed to find an acceptable graphics queue.");
return false; return false;
} }
if (surface && m_present_queue_family_index == queue_family_count)
{
ERROR_LOG(VIDEO, "Vulkan: Failed to find an acceptable present queue.");
return false;
}
VkDeviceCreateInfo device_info = {}; VkDeviceCreateInfo device_info = {};
device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
@ -540,15 +550,32 @@ bool VulkanContext::CreateDevice(VkSurfaceKHR surface, bool enable_validation_la
device_info.flags = 0; device_info.flags = 0;
static constexpr float queue_priorities[] = {1.0f}; static constexpr float queue_priorities[] = {1.0f};
VkDeviceQueueCreateInfo queue_info = {}; VkDeviceQueueCreateInfo graphics_queue_info = {};
queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; graphics_queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queue_info.pNext = nullptr; graphics_queue_info.pNext = nullptr;
queue_info.flags = 0; graphics_queue_info.flags = 0;
queue_info.queueFamilyIndex = m_graphics_queue_family_index; graphics_queue_info.queueFamilyIndex = m_graphics_queue_family_index;
queue_info.queueCount = 1; graphics_queue_info.queueCount = 1;
queue_info.pQueuePriorities = queue_priorities; graphics_queue_info.pQueuePriorities = queue_priorities;
VkDeviceQueueCreateInfo present_queue_info = {};
present_queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
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.pQueuePriorities = queue_priorities;
std::array<VkDeviceQueueCreateInfo, 2> queue_infos = {{
graphics_queue_info, present_queue_info,
}};
device_info.queueCreateInfoCount = 1; device_info.queueCreateInfoCount = 1;
device_info.pQueueCreateInfos = &queue_info; if (m_graphics_queue_family_index != m_present_queue_family_index)
{
device_info.queueCreateInfoCount = 2;
}
device_info.pQueueCreateInfos = queue_infos.data();
ExtensionList enabled_extensions; ExtensionList enabled_extensions;
if (!SelectDeviceExtensions(&enabled_extensions, surface != VK_NULL_HANDLE)) if (!SelectDeviceExtensions(&enabled_extensions, surface != VK_NULL_HANDLE))
@ -584,8 +611,12 @@ bool VulkanContext::CreateDevice(VkSurfaceKHR surface, bool enable_validation_la
if (!LoadVulkanDeviceFunctions(m_device)) if (!LoadVulkanDeviceFunctions(m_device))
return false; return false;
// Grab the graphics queue (only one we're using at this point). // Grab the graphics and present queues.
vkGetDeviceQueue(m_device, m_graphics_queue_family_index, 0, &m_graphics_queue); 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);
}
return true; return true;
} }

View File

@ -57,6 +57,8 @@ public:
VkDevice GetDevice() const { return m_device; } VkDevice GetDevice() const { return m_device; }
VkQueue GetGraphicsQueue() const { return m_graphics_queue; } VkQueue GetGraphicsQueue() const { return m_graphics_queue; }
u32 GetGraphicsQueueFamilyIndex() const { return m_graphics_queue_family_index; } u32 GetGraphicsQueueFamilyIndex() const { return m_graphics_queue_family_index; }
VkQueue GetPresentQueue() const { return m_present_queue; }
u32 GetPresentQueueFamilyIndex() const { return m_present_queue_family_index; }
const VkQueueFamilyProperties& GetGraphicsQueueProperties() const const VkQueueFamilyProperties& GetGraphicsQueueProperties() const
{ {
return m_graphics_queue_properties; return m_graphics_queue_properties;
@ -119,6 +121,8 @@ private:
VkQueue m_graphics_queue = VK_NULL_HANDLE; VkQueue m_graphics_queue = VK_NULL_HANDLE;
u32 m_graphics_queue_family_index = 0; u32 m_graphics_queue_family_index = 0;
VkQueue m_present_queue = VK_NULL_HANDLE;
u32 m_present_queue_family_index = 0;
VkQueueFamilyProperties m_graphics_queue_properties = {}; VkQueueFamilyProperties m_graphics_queue_properties = {};
VkDebugReportCallbackEXT m_debug_report_callback = VK_NULL_HANDLE; VkDebugReportCallbackEXT m_debug_report_callback = VK_NULL_HANDLE;