Changes to device queue creation info (Fixes #216), try to get a separate compute queue if possible
This commit is contained in:
parent
6b9a8f6051
commit
e94a762684
1 changed files with 72 additions and 56 deletions
|
|
@ -30,6 +30,8 @@ namespace vk
|
||||||
VkPhysicalDeviceFeatures features;
|
VkPhysicalDeviceFeatures features;
|
||||||
/** @brief Memory types and heaps of the physical device */
|
/** @brief Memory types and heaps of the physical device */
|
||||||
VkPhysicalDeviceMemoryProperties memoryProperties;
|
VkPhysicalDeviceMemoryProperties memoryProperties;
|
||||||
|
/** @brief Queue family properties of the physical device */
|
||||||
|
std::vector<VkQueueFamilyProperties> queueFamilyProperties;
|
||||||
|
|
||||||
/** @brief Default command pool for the graphics queue family index */
|
/** @brief Default command pool for the graphics queue family index */
|
||||||
VkCommandPool commandPool = VK_NULL_HANDLE;
|
VkCommandPool commandPool = VK_NULL_HANDLE;
|
||||||
|
|
@ -37,11 +39,11 @@ namespace vk
|
||||||
/** @brief Set to true when the debug marker extension is detected */
|
/** @brief Set to true when the debug marker extension is detected */
|
||||||
bool enableDebugMarkers = false;
|
bool enableDebugMarkers = false;
|
||||||
|
|
||||||
/** @brief Contains queue family indices */
|
/** @brief Contains queue family indices */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint32_t graphics = 0;
|
uint32_t graphics;
|
||||||
uint32_t compute = 0;
|
uint32_t compute;
|
||||||
} queueFamilyIndices;
|
} queueFamilyIndices;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -61,6 +63,12 @@ namespace vk
|
||||||
vkGetPhysicalDeviceFeatures(physicalDevice, &features);
|
vkGetPhysicalDeviceFeatures(physicalDevice, &features);
|
||||||
// Memory properties are used regularly for creating all kinds of buffer
|
// Memory properties are used regularly for creating all kinds of buffer
|
||||||
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties);
|
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties);
|
||||||
|
// Queue family properties, used for setting up requested queues upon device creation
|
||||||
|
uint32_t queueFamilyCount;
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, nullptr);
|
||||||
|
assert(queueFamilyCount > 0);
|
||||||
|
queueFamilyProperties.resize(queueFamilyCount);
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyCount, queueFamilyProperties.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -140,31 +148,29 @@ namespace vk
|
||||||
*/
|
*/
|
||||||
uint32_t getQueueFamiliyIndex(VkQueueFlagBits queueFlags)
|
uint32_t getQueueFamiliyIndex(VkQueueFlagBits queueFlags)
|
||||||
{
|
{
|
||||||
uint32_t queueCount;
|
// If a compute queue is requested, try to find a separate compute queue family from graphics first
|
||||||
|
if (queueFlags & VK_QUEUE_COMPUTE_BIT)
|
||||||
// Get number of available queue families on this device
|
|
||||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, NULL);
|
|
||||||
assert(queueCount >= 1);
|
|
||||||
|
|
||||||
// Get available queue families
|
|
||||||
std::vector<VkQueueFamilyProperties> queueProps;
|
|
||||||
queueProps.resize(queueCount);
|
|
||||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, queueProps.data());
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < queueCount; i++)
|
|
||||||
{
|
{
|
||||||
if (queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
for (uint32_t i = 0; i < static_cast<uint32_t>(queueFamilyProperties.size()); i++)
|
||||||
|
{
|
||||||
|
if ((queueFamilyProperties[i].queueFlags & queueFlags) && ((queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0))
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For other queue types or if no separate compute queue is present, return the first one to support the requested flags
|
||||||
|
for (uint32_t i = 0; i < static_cast<uint32_t>(queueFamilyProperties.size()); i++)
|
||||||
|
{
|
||||||
|
if (queueFamilyProperties[i].queueFlags & queueFlags)
|
||||||
{
|
{
|
||||||
return i;
|
return i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: Advanced search for devices that have dedicated queues for compute and transfer
|
|
||||||
// Try to find queues with only the requested flags or (if not present) with as few
|
|
||||||
// other flags set as possible (example: http://vulkan.gpuinfo.org/displayreport.php?id=509#queuefamilies)
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
//todo : Exceptions are disabled by default on Android (need to add LOCAL_CPP_FEATURES += exceptions to Android.mk), so for now just return zero
|
//todo : Exceptions are disabled by default on Android (need to add LOCAL_CPP_FEATURES += exceptions to Android.mk), so for now just return zero
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -178,55 +184,65 @@ namespace vk
|
||||||
*
|
*
|
||||||
* @param enabledFeatures Can be used to enable certain features upon device creation
|
* @param enabledFeatures Can be used to enable certain features upon device creation
|
||||||
* @param useSwapChain Set to false for headless rendering to omit the swapchain device extensions
|
* @param useSwapChain Set to false for headless rendering to omit the swapchain device extensions
|
||||||
|
* @param requestedQueueTypes Bit flags specifying the queue types to be requested from the device
|
||||||
*
|
*
|
||||||
* @return VkResult of the device creation call
|
* @return VkResult of the device creation call
|
||||||
*/
|
*/
|
||||||
VkResult createLogicalDevice(VkPhysicalDeviceFeatures enabledFeatures, bool useSwapChain = true)
|
VkResult createLogicalDevice(VkPhysicalDeviceFeatures enabledFeatures, bool useSwapChain = true, VkQueueFlags requestedQueueTypes = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT)
|
||||||
{
|
{
|
||||||
// Get queue family indices for graphics and compute
|
// Desired queues need to be requested upon logical device creation
|
||||||
// Note that the indices may overlap depending on the implementation
|
// Due to differing queue family configurations of Vulkan implementations this can be a bit tricky, especially if the application
|
||||||
queueFamilyIndices.graphics = getQueueFamiliyIndex(VK_QUEUE_GRAPHICS_BIT);
|
// requests different queue types
|
||||||
queueFamilyIndices.compute = getQueueFamiliyIndex(VK_QUEUE_COMPUTE_BIT);
|
|
||||||
//todo: Transfer?
|
|
||||||
|
|
||||||
// Pass queue information for graphics and compute, so examples can later on request queues from both
|
|
||||||
std::vector<float> queuePriorities;
|
|
||||||
|
|
||||||
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos{};
|
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos{};
|
||||||
// We need one queue create info per queue family index
|
|
||||||
// If graphics and compute share the same queue family index we only need one queue create info but
|
// Get queue family indices for graphics and compute
|
||||||
// with two queues to request
|
// Note that the indices may overlap depending on the implementation
|
||||||
queueCreateInfos.resize(1);
|
|
||||||
// Graphics
|
// Graphics queue
|
||||||
queuePriorities.push_back(0.0f);
|
if (requestedQueueTypes & VK_QUEUE_GRAPHICS_BIT)
|
||||||
queueCreateInfos[0] = {};
|
|
||||||
queueCreateInfos[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
|
||||||
queueCreateInfos[0].queueFamilyIndex = queueFamilyIndices.graphics;
|
|
||||||
queueCreateInfos[0].queueCount = 1;
|
|
||||||
// Compute
|
|
||||||
// If compute has a different queue family index, add another create info, else just add
|
|
||||||
if (queueFamilyIndices.graphics != queueFamilyIndices.compute)
|
|
||||||
{
|
{
|
||||||
queueCreateInfos.resize(2);
|
queueFamilyIndices.graphics = getQueueFamiliyIndex(VK_QUEUE_GRAPHICS_BIT);
|
||||||
queueCreateInfos[1] = {};
|
float queuePriority(0.0f);
|
||||||
queueCreateInfos[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
VkDeviceQueueCreateInfo queueInfo{};
|
||||||
queueCreateInfos[1].queueFamilyIndex = queueFamilyIndices.compute;
|
queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||||
queueCreateInfos[1].queueCount = 1;
|
queueInfo.queueFamilyIndex = queueFamilyIndices.graphics;
|
||||||
queueCreateInfos[1].pQueuePriorities = queuePriorities.data();
|
queueInfo.queueCount = 1;
|
||||||
|
queueInfo.pQueuePriorities = &queuePriority;
|
||||||
|
queueCreateInfos.push_back(queueInfo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
queueCreateInfos[0].queueCount++;
|
queueFamilyIndices.graphics = VK_NULL_HANDLE;
|
||||||
queuePriorities.push_back(0.0f);
|
}
|
||||||
|
|
||||||
|
// Compute queue
|
||||||
|
if (requestedQueueTypes & VK_QUEUE_COMPUTE_BIT)
|
||||||
|
{
|
||||||
|
queueFamilyIndices.compute = getQueueFamiliyIndex(VK_QUEUE_COMPUTE_BIT);
|
||||||
|
if (queueFamilyIndices.compute != queueFamilyIndices.graphics)
|
||||||
|
{
|
||||||
|
// If compute family index differs, we need an additional queue create info for the compute queue
|
||||||
|
float queuePriority(0.0f);
|
||||||
|
VkDeviceQueueCreateInfo queueInfo{};
|
||||||
|
queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||||
|
queueInfo.queueFamilyIndex = queueFamilyIndices.compute;
|
||||||
|
queueInfo.queueCount = 1;
|
||||||
|
queueInfo.pQueuePriorities = &queuePriority;
|
||||||
|
queueCreateInfos.push_back(queueInfo);
|
||||||
|
}
|
||||||
|
// Else we use the same queue
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
queueFamilyIndices.compute = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
queueCreateInfos[0].pQueuePriorities = queuePriorities.data();
|
|
||||||
|
|
||||||
// Create the logical device representation
|
// Create the logical device representation
|
||||||
std::vector<const char*> deviceExtensions;
|
std::vector<const char*> deviceExtensions;
|
||||||
if (useSwapChain)
|
if (useSwapChain)
|
||||||
{
|
{
|
||||||
// If the device will be used for presenting to a display via a swapchain
|
// If the device will be used for presenting to a display via a swapchain we need to request the swapchain extension
|
||||||
// we need to request the swapchain extension
|
|
||||||
deviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
deviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -236,7 +252,7 @@ namespace vk
|
||||||
deviceCreateInfo.pQueueCreateInfos = queueCreateInfos.data();
|
deviceCreateInfo.pQueueCreateInfos = queueCreateInfos.data();
|
||||||
deviceCreateInfo.pEnabledFeatures = &enabledFeatures;
|
deviceCreateInfo.pEnabledFeatures = &enabledFeatures;
|
||||||
|
|
||||||
// Cnable the debug marker extension if it is present (likely meaning a debugging tool is present)
|
// Enable the debug marker extension if it is present (likely meaning a debugging tool is present)
|
||||||
if (vkTools::checkDeviceExtensionPresent(physicalDevice, VK_EXT_DEBUG_MARKER_EXTENSION_NAME))
|
if (vkTools::checkDeviceExtensionPresent(physicalDevice, VK_EXT_DEBUG_MARKER_EXTENSION_NAME))
|
||||||
{
|
{
|
||||||
deviceExtensions.push_back(VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
|
deviceExtensions.push_back(VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue