Skip to content
Snippets Groups Projects
Commit c7a829b0 authored by Vanessa Karolek's avatar Vanessa Karolek
Browse files

[#16][Fix] compute valid queues and queue handles

When creating queues, we need information about which queues were created and at which queue family index. This information is lost when our previous getQueueCreateInfos function terminated. The actual idea is to save this information for each queue type and compute valid handles for them.

The code might look uglier than before... but maybe we can improve this. :D We also need to clean up the unnecessary print outs later on.
parent 77b80bea
No related branches found
No related tags found
4 merge requests!12Resolve "Swapchain Class",!7Resolve "Shader Program Class",!5Resolve "Pipeline State Object",!4Resolve "Renderpass Class"
Pipeline #24758 failed
...@@ -86,14 +86,27 @@ namespace vkcv ...@@ -86,14 +86,27 @@ namespace vkcv
* @param queueFlags The abilities which have to be supported by any created queue * @param queueFlags The abilities which have to be supported by any created queue
* @return * @return
*/ */
std::vector<vk::DeviceQueueCreateInfo> getQueueCreateInfos(vk::PhysicalDevice& physicalDevice, void queueCreateInfosQueueHandles(vk::PhysicalDevice& physicalDevice,
std::vector<float> &qPriorities, std::vector<float> &qPriorities,
std::vector<vk::QueueFlagBits>& queueFlags) std::vector<vk::QueueFlagBits>& queueFlags,
std::vector<vk::DeviceQueueCreateInfo> &queueCreateInfos,
std::vector<std::pair<int, int>> &queuePairsGraphics,
std::vector<std::pair<int, int>> &queuePairsCompute,
std::vector<std::pair<int, int>> &queuePairsTransfer)
{ {
std::vector<vk::DeviceQueueCreateInfo> queueCreateInfos; queueCreateInfos = {};
queuePairsGraphics = {};
queuePairsCompute = {};
queuePairsTransfer = {};
std::vector<vk::QueueFamilyProperties> qFamilyProperties = physicalDevice.getQueueFamilyProperties(); std::vector<vk::QueueFamilyProperties> qFamilyProperties = physicalDevice.getQueueFamilyProperties();
//check priorities of flags // DEBUG
std::cout << "Input queue flags:" << std::endl;
for (auto qFlag : queueFlags) {
std::cout << "\t" << to_string(qFlag) << std::endl;
}
//check priorities of flags -> the lower prioCount the higher the priority
std::vector<int> prios; std::vector<int> prios;
for(auto flag: queueFlags){ for(auto flag: queueFlags){
int prioCount = 0; int prioCount = 0;
...@@ -113,30 +126,112 @@ namespace vkcv ...@@ -113,30 +126,112 @@ namespace vkcv
prios[index] = INT_MAX; prios[index] = INT_MAX;
} }
std::cout << "Sorted queue flags:" << std::endl;
for (auto qFlag : newFlags) {
std::cout << "\t" << to_string(qFlag) << std::endl;
}
// create requested queues and check if more requested queues are supported
// herefore: create vector that updates available queues in each queue family
// structure: [qFamily_0, ..., qFamily_n] where
// - qFamily_i = [GraphicsCount, ComputeCount, TransferCount], 0 <= i <= n
std::vector<std::vector<int>> queueFamilyStatus, initialQueueFamilyStatus;
for (auto qFamily : qFamilyProperties) {
int graphicsCount = int(static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eGraphics) != 0) * qFamily.queueCount;
int computeCount = int(static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eCompute) != 0) * qFamily.queueCount;;
int transferCount = int(static_cast<uint32_t>(qFamily.queueFlags & vk::QueueFlagBits::eTransfer) != 0) * qFamily.queueCount;;
queueFamilyStatus.push_back({graphicsCount, computeCount, transferCount});
}
// search for queue families which support the desired queue flag bits initialQueueFamilyStatus = queueFamilyStatus;
uint32_t create = newFlags.size();
for (int i = 0; i < qFamilyProperties.size(); i++) { // check if every queue with the specified queue flag can be created
bool supported = true; // this automatically checks for queue flag support!
for (auto qFlag : newFlags) { for (auto qFlag : newFlags) {
supported = supported && (static_cast<uint32_t>(qFlag & qFamilyProperties[i].queueFlags) != 0); bool found;
switch (qFlag) {
case vk::QueueFlagBits::eGraphics:
found = false;
for (int i = 0; i < queueFamilyStatus.size() && !found; i++) {
if (queueFamilyStatus[i][0] > 0) {
queuePairsGraphics.push_back(std::pair(i, initialQueueFamilyStatus[i][0] - queueFamilyStatus[i][0]));
queueFamilyStatus[i][0]--;
queueFamilyStatus[i][1]--;
queueFamilyStatus[i][2]--;
std::cout << "Graphics queue available at queue family #" << i << std::endl;
found = true;
}
}
if (!found) {
throw std::runtime_error("Too many graphics queues were requested than being available!");
}
break;
case vk::QueueFlagBits::eCompute:
found = false;
for (int i = 0; i < queueFamilyStatus.size() && !found; i++) {
if (queueFamilyStatus[i][1] > 0) {
queuePairsCompute.push_back(std::pair(i, initialQueueFamilyStatus[i][1] - queueFamilyStatus[i][1]));
queueFamilyStatus[i][0]--;
queueFamilyStatus[i][1]--;
queueFamilyStatus[i][2]--;
std::cout << "Compute queue available at queue family #" << i << std::endl;
found = true;
}
}
if (!found) {
throw std::runtime_error("Too many compute queues were requested than being available!");
}
break;
case vk::QueueFlagBits::eTransfer:
found = false;
for (int i = 0; i < queueFamilyStatus.size() && !found; i++) {
if (queueFamilyStatus[i][2] > 0) {
queuePairsTransfer.push_back(std::pair(i, initialQueueFamilyStatus[i][2] - queueFamilyStatus[i][2]));
queueFamilyStatus[i][0]--;
queueFamilyStatus[i][1]--;
queueFamilyStatus[i][2]--;
std::cout << "Transfer queue available at queue family #" << i << std::endl;
found = true;
}
}
if (!found) {
throw std::runtime_error("Too many transfer queues were requested than being available!");
}
break;
default:
throw std::runtime_error("Invalid input for queue flag bits. Valid inputs are 'vk::QueueFlagBits::eGraphics', 'vk::QueueFlagBits::eCompute' and 'vk::QueueFlagBits::eTransfer'.");
} }
// if queue family supports all desired queue flag bits, create as many queues available for the actual queue family }
// search for another queue family, if more queues should be created
if (supported && create > 0) { std::cout << "Initial queue status:" << std::endl;
const uint32_t maxCreatableQueues = std::min(create, qFamilyProperties[i].queueCount); int x = 0;
for (std::vector<int> e : initialQueueFamilyStatus) {
std::cout << "#" << x << ":\t[" << e[0] << ", " << e[1] << ", " << e[2] << "]" << std::endl;
x++;
}
std::cout << "Actual queue status:" << std::endl;
x = 0;
for (std::vector<int> e : queueFamilyStatus) {
std::cout << "#" << x << ":\t[" << e[0] << ", " << e[1] << ", " << e[2] << "]" << std::endl;
x++;
}
// create all requested queues
for (int i = 0; i < qFamilyProperties.size(); i++) {
uint32_t create = std::abs(initialQueueFamilyStatus[i][0] - queueFamilyStatus[i][0]);
std::cout << "For Queue Family #" << i << " create " << create << " queues" << std::endl;
if (create > 0) {
vk::DeviceQueueCreateInfo qCreateInfo( vk::DeviceQueueCreateInfo qCreateInfo(
vk::DeviceQueueCreateFlags(), vk::DeviceQueueCreateFlagBits(),
i, i,
maxCreatableQueues, create,
qPriorities.data() qPriorities.data()
); );
queueCreateInfos.push_back(qCreateInfo); queueCreateInfos.push_back(qCreateInfo);
create -= maxCreatableQueues;
} }
} }
return queueCreateInfos;
} }
/** /**
...@@ -176,22 +271,19 @@ namespace vkcv ...@@ -176,22 +271,19 @@ namespace vkcv
} }
/** /**
* @brief finds an queue family index that fits with the given queue flags to create a queue handle * Computes the queue handles from @p queuePairs
* @param flag The given flag that specifies as which queue type the accessed queue should be treated * @param queuePairs The queuePairs that were created separately for each queue type (e.g., vk::QueueFlagBits::eGraphics)
* @param createInfos The createInfos of the created queues depending on the logical device * @param device The device
* @param device The physical with which the queue families can be accessed * @return An array of queue handles based on the @p queuePairs
* @return a fitting queue family index
*/ */
int findQueueFamilyIndex(vk::QueueFlagBits flag, std::vector<vk::DeviceQueueCreateInfo> &createInfos, vk::PhysicalDevice &device){ std::vector<vk::Queue> getQueueHandles(const std::vector<std::pair<int, int>> queuePairs, const vk::Device device) {
std::vector<vk::QueueFamilyProperties> queueFamilyProperties = device.getQueueFamilyProperties(); std::vector<vk::Queue> queueHandles;
for (auto i = createInfos.begin(); i != createInfos.end(); ++i ) { for (auto q : queuePairs) {
auto createInfo = *i; int queueFamilyIndex = q.first; // the queueIndex of the queue family
int index = createInfo.queueFamilyIndex; int queueIndex = q.second; // the queueIndex within a queue family
if(static_cast<uint32_t>(queueFamilyProperties[index].queueFlags & flag) != 0){ queueHandles.push_back(device.getQueue(queueFamilyIndex, queueIndex));
return index;
}
} }
return -1; return queueHandles;
} }
Core Core::create(const Window &window, Core Core::create(const Window &window,
...@@ -283,7 +375,9 @@ namespace vkcv ...@@ -283,7 +375,9 @@ namespace vkcv
qPriorities.resize(queueFlags.size(), 1.f); // all queues have the same priorities qPriorities.resize(queueFlags.size(), 1.f); // all queues have the same priorities
// create required queues // create required queues
std::vector<vk::DeviceQueueCreateInfo> qCreateInfos = getQueueCreateInfos(physicalDevice, qPriorities,queueFlags); std::vector<vk::DeviceQueueCreateInfo> qCreateInfos;
std::vector<std::pair<int, int>> queuePairsGraphics, queuePairsCompute, queuePairsTransfer;
queueCreateInfosQueueHandles(physicalDevice, qPriorities, queueFlags, qCreateInfos, queuePairsGraphics, queuePairsCompute, queuePairsTransfer);
vk::DeviceCreateInfo deviceCreateInfo( vk::DeviceCreateInfo deviceCreateInfo(
vk::DeviceCreateFlags(), vk::DeviceCreateFlags(),
...@@ -304,21 +398,15 @@ namespace vkcv ...@@ -304,21 +398,15 @@ namespace vkcv
vk::Device device = physicalDevice.createDevice(deviceCreateInfo); vk::Device device = physicalDevice.createDevice(deviceCreateInfo);
uint32_t graphicsQueueFamilyIndex = findQueueFamilyIndex({vk::QueueFlagBits::eGraphics}, qCreateInfos, physicalDevice); // maybe it can be useful to store these lists as member variable of Core
if(graphicsQueueFamilyIndex == -1){ std::vector<vk::Queue> graphicsQueues = getQueueHandles(queuePairsGraphics, device);
throw std::runtime_error("It is not possible to access another queue as a graphics queue."); std::vector<vk::Queue> computeQueues = getQueueHandles(queuePairsCompute, device);
} std::vector<vk::Queue> transferQueues = getQueueHandles(queuePairsTransfer, device);
uint32_t computeQueueFamilyIndex = findQueueFamilyIndex({vk::QueueFlagBits::eCompute}, qCreateInfos, physicalDevice);
if(computeQueueFamilyIndex == -1){ // examples for accessing queues
throw std::runtime_error("It is not possible to access another queue as a compute queue."); vk::Queue graphicsQueue = graphicsQueues[0];
} vk::Queue computeQueue = computeQueues[0];
uint32_t transferQueueFamilyIndex = findQueueFamilyIndex({vk::QueueFlagBits::eTransfer}, qCreateInfos, physicalDevice); vk::Queue transferQueue = transferQueues[0];
if(transferQueueFamilyIndex == -1){
throw std::runtime_error("It is not possible to access another queue as a transfer queue.");
}
vk::Queue graphicsQueue = device.getQueue(graphicsQueueFamilyIndex, 0);
vk::Queue computeQueue = device.getQueue(computeQueueFamilyIndex, 1);
vk::Queue transferQueue = device.getQueue(transferQueueFamilyIndex, 2);
Context context(instance, physicalDevice, device); Context context(instance, physicalDevice, device);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment