diff --git a/src/dxvk/dxvk_adapter.cpp b/src/dxvk/dxvk_adapter.cpp index b3a71dd0d..f5331bcee 100644 --- a/src/dxvk/dxvk_adapter.cpp +++ b/src/dxvk/dxvk_adapter.cpp @@ -1,4 +1,5 @@ #include +#include #include "dxvk_adapter.h" #include "dxvk_device.h" @@ -88,22 +89,25 @@ namespace dxvk { } - uint32_t DxvkAdapter::graphicsQueueFamily() const { - for (uint32_t i = 0; i < m_queueFamilies.size(); i++) { - if (m_queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) - return i; - } + DxvkAdapterQueueIndices DxvkAdapter::findQueueFamilies() const { + uint32_t graphicsQueue = findQueueFamily( + VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, + VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT); - throw DxvkError("DxvkAdapter: No graphics queue found"); + uint32_t transferQueue = findQueueFamily( + VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, + VK_QUEUE_TRANSFER_BIT); + + if (transferQueue == VK_QUEUE_FAMILY_IGNORED) + transferQueue = graphicsQueue; + + DxvkAdapterQueueIndices queues; + queues.graphics = graphicsQueue; + queues.transfer = transferQueue; + return queues; } - - - uint32_t DxvkAdapter::presentQueueFamily() const { - // TODO Implement properly - return this->graphicsQueueFamily(); - } - - + + bool DxvkAdapter::checkFeatureSupport(const DxvkDeviceFeatures& required) const { return (m_deviceFeatures.core.features.robustBufferAccess || !required.core.features.robustBufferAccess) @@ -324,26 +328,25 @@ namespace dxvk { overallocInfo.pNext = nullptr; overallocInfo.overallocationBehavior = VK_MEMORY_OVERALLOCATION_BEHAVIOR_ALLOWED_AMD; - // Create one single queue for graphics and present + // Create the requested queues float queuePriority = 1.0f; std::vector queueInfos; + + std::unordered_set queueFamiliySet; + + DxvkAdapterQueueIndices queueFamilies = findQueueFamilies(); + queueFamiliySet.insert(queueFamilies.graphics); + queueFamiliySet.insert(queueFamilies.transfer); - uint32_t gIndex = this->graphicsQueueFamily(); - uint32_t pIndex = this->presentQueueFamily(); - - VkDeviceQueueCreateInfo graphicsQueue; - graphicsQueue.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - graphicsQueue.pNext = nullptr; - graphicsQueue.flags = 0; - graphicsQueue.queueFamilyIndex = gIndex; - graphicsQueue.queueCount = 1; - graphicsQueue.pQueuePriorities = &queuePriority; - queueInfos.push_back(graphicsQueue); - - if (pIndex != gIndex) { - VkDeviceQueueCreateInfo presentQueue = graphicsQueue; - presentQueue.queueFamilyIndex = pIndex; - queueInfos.push_back(presentQueue); + for (uint32_t family : queueFamiliySet) { + VkDeviceQueueCreateInfo graphicsQueue; + graphicsQueue.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + graphicsQueue.pNext = nullptr; + graphicsQueue.flags = 0; + graphicsQueue.queueFamilyIndex = family; + graphicsQueue.queueCount = 1; + graphicsQueue.pQueuePriorities = &queuePriority; + queueInfos.push_back(graphicsQueue); } VkDeviceCreateInfo info; @@ -541,6 +544,18 @@ namespace dxvk { m_vki->vkGetPhysicalDeviceQueueFamilyProperties( m_handle, &numQueueFamilies, m_queueFamilies.data()); } + + + uint32_t DxvkAdapter::findQueueFamily( + VkQueueFlags mask, + VkQueueFlags flags) const { + for (uint32_t i = 0; i < m_queueFamilies.size(); i++) { + if ((m_queueFamilies[i].queueFlags & mask) == flags) + return i; + } + + return VK_QUEUE_FAMILY_IGNORED; + } void DxvkAdapter::logNameList(const DxvkNameList& names) { diff --git a/src/dxvk/dxvk_adapter.h b/src/dxvk/dxvk_adapter.h index 4901fbe77..15af2471a 100644 --- a/src/dxvk/dxvk_adapter.h +++ b/src/dxvk/dxvk_adapter.h @@ -41,6 +41,14 @@ namespace dxvk { uint32_t heapCount; DxvkAdapterMemoryHeapInfo heaps[VK_MAX_MEMORY_HEAPS]; }; + + /** + * \brief Retrieves queue indices + */ + struct DxvkAdapterQueueIndices { + uint32_t graphics; + uint32_t transfer; + }; /** * \brief DXVK adapter @@ -162,16 +170,10 @@ namespace dxvk { VkImageFormatProperties& properties) const; /** - * \brief Graphics queue family index - * \returns Graphics queue family index + * \brief Retrieves queue family indices + * \returns Indices for all queue families */ - uint32_t graphicsQueueFamily() const; - - /** - * \brief Presentation queue family index - * \returns Presentation queue family index - */ - uint32_t presentQueueFamily() const; + DxvkAdapterQueueIndices findQueueFamilies() const; /** * \brief Tests whether all required features are supported @@ -273,6 +275,10 @@ namespace dxvk { void queryDeviceInfo(); void queryDeviceFeatures(); void queryDeviceQueues(); + + uint32_t findQueueFamily( + VkQueueFlags mask, + VkQueueFlags flags) const; static void logNameList(const DxvkNameList& names); diff --git a/src/dxvk/dxvk_device.cpp b/src/dxvk/dxvk_device.cpp index db43f9090..f008f826d 100644 --- a/src/dxvk/dxvk_device.cpp +++ b/src/dxvk/dxvk_device.cpp @@ -28,16 +28,9 @@ namespace dxvk { m_metaPackObjects (new DxvkMetaPackObjects (vkd)), m_unboundResources (this), m_submissionQueue (this) { - m_graphicsQueue.queueFamily = m_adapter->graphicsQueueFamily(); - m_presentQueue.queueFamily = m_adapter->presentQueueFamily(); - - m_vkd->vkGetDeviceQueue(m_vkd->device(), - m_graphicsQueue.queueFamily, 0, - &m_graphicsQueue.queueHandle); - - m_vkd->vkGetDeviceQueue(m_vkd->device(), - m_presentQueue.queueFamily, 0, - &m_presentQueue.queueHandle); + auto queueFamilies = m_adapter->findQueueFamilies(); + m_queues.graphics = getQueue(queueFamilies.graphics, 0); + m_queues.transfer = getQueue(queueFamilies.transfer, 0); } @@ -76,10 +69,8 @@ namespace dxvk { Rc DxvkDevice::createCommandList() { Rc cmdList = m_recycledCommandLists.retrieveObject(); - if (cmdList == nullptr) { - cmdList = new DxvkCommandList(this, - m_adapter->graphicsQueueFamily()); - } + if (cmdList == nullptr) + cmdList = new DxvkCommandList(this, m_queues.graphics.queueFamily); return cmdList; } @@ -238,7 +229,7 @@ namespace dxvk { VkSemaphore wakeSync) { DxvkSubmitInfo submitInfo; submitInfo.cmdList = commandList; - submitInfo.queue = m_graphicsQueue.queueHandle; + submitInfo.queue = m_queues.graphics.queueHandle; submitInfo.waitSync = waitSync; submitInfo.wakeSync = wakeSync; m_submissionQueue.submit(submitInfo); @@ -265,5 +256,14 @@ namespace dxvk { void DxvkDevice::recycleDescriptorPool(const Rc& pool) { m_recycledDescriptorPools.returnObject(pool); } + + + DxvkDeviceQueue DxvkDevice::getQueue( + uint32_t family, + uint32_t index) const { + VkQueue queue = VK_NULL_HANDLE; + m_vkd->vkGetDeviceQueue(m_vkd->device(), family, index, &queue); + return DxvkDeviceQueue { queue, family, index }; + } } diff --git a/src/dxvk/dxvk_device.h b/src/dxvk/dxvk_device.h index 962c557dc..235f5e6e5 100644 --- a/src/dxvk/dxvk_device.h +++ b/src/dxvk/dxvk_device.h @@ -42,8 +42,17 @@ namespace dxvk { * queue family that it belongs to. */ struct DxvkDeviceQueue { - uint32_t queueFamily = 0; VkQueue queueHandle = VK_NULL_HANDLE; + uint32_t queueFamily = 0; + uint32_t queueIndex = 0; + }; + + /** + * \brief Device queue infos + */ + struct DxvkDeviceQueueSet { + DxvkDeviceQueue graphics; + DxvkDeviceQueue transfer; }; /** @@ -109,7 +118,7 @@ namespace dxvk { * \returns Graphics queue info */ DxvkDeviceQueue graphicsQueue() const { - return m_graphicsQueue; + return m_queues.graphics; } /** @@ -407,8 +416,7 @@ namespace dxvk { sync::Spinlock m_statLock; DxvkStatCounters m_statCounters; - DxvkDeviceQueue m_graphicsQueue; - DxvkDeviceQueue m_presentQueue; + DxvkDeviceQueueSet m_queues; DxvkRecycler m_recycledCommandLists; DxvkRecycler m_recycledDescriptorPools; @@ -421,6 +429,10 @@ namespace dxvk { void recycleDescriptorPool( const Rc& pool); + DxvkDeviceQueue getQueue( + uint32_t family, + uint32_t index) const; + /** * \brief Dummy buffer handle * \returns Use for unbound vertex buffers.