diff --git a/CMakeLists.txt b/CMakeLists.txt index c50b40ea0a97251527caaa721a1053f8e32d7288..09a842443f7417d181f3b72a831c3531fe026b7d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -164,6 +164,8 @@ add_library(lava.base STATIC ${LIBLAVA_DIR}/base/memory.hpp ${LIBLAVA_DIR}/base/physical_device.cpp ${LIBLAVA_DIR}/base/physical_device.hpp + ${LIBLAVA_DIR}/base/queue.cpp + ${LIBLAVA_DIR}/base/queue.hpp ${LIBLAVA_EXT_DIR}/volk/volk.c ) @@ -357,14 +359,10 @@ if(LIBLAVA_TESTS) RUNTIME DESTINATION bin ) - message(">> lava-unit") - - message(">>> Catch2") + message(">> lava-unit (Catch2)") add_subdirectory(${LIBLAVA_EXT_DIR}/Catch2 Catch2 EXCLUDE_FROM_ALL) - message("<<< Catch2") - add_executable(lava-unit ${LIBLAVA_TESTS_DIR}/unit.cpp ) diff --git a/DOCS.md b/DOCS.md index a297d31d66a7a51c06cb70508a0d17033cac2262..946003921177cb7b704c921016f0a67cd45c5377 100644 --- a/DOCS.md +++ b/DOCS.md @@ -398,7 +398,7 @@ int main(int argc, char* argv[]) { #### lava [base](https://github.com/liblava/liblava/tree/master/liblava/base) -[](https://github.com/liblava/liblava/tree/master/liblava/base/base.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/base/device.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/base/instance.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/base/memory.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/base/physical_device.hpp) +[](https://github.com/liblava/liblava/tree/master/liblava/base/base.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/base/device.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/base/instance.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/base/memory.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/base/physical_device.hpp) [](https://github.com/liblava/liblava/tree/master/liblava/base/queue.hpp) #### lava [file](https://github.com/liblava/liblava/tree/master/liblava/file) diff --git a/liblava/base.hpp b/liblava/base.hpp index 32eb8d6187f3408ba71b571ecbb5e1d5eaef1446..659e8261c5cc839a66b2bd691052a43cb4457ad4 100644 --- a/liblava/base.hpp +++ b/liblava/base.hpp @@ -11,3 +11,4 @@ #include <liblava/base/instance.hpp> #include <liblava/base/memory.hpp> #include <liblava/base/physical_device.hpp> +#include <liblava/base/queue.hpp> diff --git a/liblava/base/device.cpp b/liblava/base/device.cpp index 8b39724a5c9ff84578a83ba9e8f83821f004b384..1e37a26e2bb283b60c7db2711b0228ce0aae7de7 100644 --- a/liblava/base/device.cpp +++ b/liblava/base/device.cpp @@ -8,25 +8,79 @@ namespace lava { + void device::create_param::set_all_queues() { + lava::set_all_queues(queue_family_infos, physical_device->get_queue_family_properties()); + } + + bool device::create_param::add_queues(VkQueueFlags flags, ui32 count, r32 priority) { + return lava::add_queues(queue_family_infos, physical_device->get_queue_family_properties(), flags, count, priority); + } + + bool device::create_param::add_dedicated_queues(r32 priority) { + return lava::add_dedicated_queues(queue_family_infos, physical_device->get_queue_family_properties(), priority); + } + + queue_verify_result device::create_param::verify_queues() const { + return lava::verify_queues(queue_family_infos, physical_device->get_queue_family_properties()); + } + bool device::create(create_param::ref param) { physical_device = param.physical_device; if (!physical_device) return false; - std::vector<VkDeviceQueueCreateInfo> queue_create_info_list(param.queue_info_list.size()); + auto verify_result = param.verify_queues(); + if (verify_result != queue_verify_result::ok) { + switch (verify_result) { + case queue_verify_result::empty_list: { + log()->error("create device - verify queues - param with empty list"); + break; + } + case queue_verify_result::no_properties: { + log()->error("create device - verify queues - no device family properties"); + break; + } + case queue_verify_result::duplicate_family_index: { + log()->error("create device - verify queues - duplicate family index"); + break; + } + case queue_verify_result::no_family_index: { + log()->error("create device - verify queues - family index is not available"); + break; + } + case queue_verify_result::no_queues: { + log()->error("create device - verify queues - undefined queues in family"); + break; + } + case queue_verify_result::too_many_queues: { + log()->error("create device - verify queues - number of queues is incorrect"); + break; + } + case queue_verify_result::no_compatible_flags: { + log()->error("create device - verify queues - no compatible flags in queue"); + break; + } + default: + log()->error("create device - verify queues"); + } + + return false; + } + + std::vector<VkDeviceQueueCreateInfo> queue_create_info_list(param.queue_family_infos.size()); - for (size_t i = 0, e = param.queue_info_list.size(); i != e; ++i) { + std::vector<std::vector<r32>> priorities; + priorities.resize(param.queue_family_infos.size()); + + for (auto i = 0u; i < param.queue_family_infos.size(); ++i) { queue_create_info_list[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queue_create_info_list[i].queueFamilyIndex = param.queue_family_infos[i].family_index; + queue_create_info_list[i].queueCount = param.queue_family_infos[i].queues.size(); - auto index = 0u; - if (!physical_device->get_queue_family(index, param.queue_info_list[i].flags)) { - log()->error("create device queue family"); - return false; - } + for (auto j = 0u; j < param.queue_family_infos[i].queues.size(); ++j) + priorities.at(i).push_back(param.queue_family_infos[i].queues.at(j).priority); - queue_create_info_list[i].queueFamilyIndex = index; - queue_create_info_list[i].queueCount = param.queue_info_list[i].count(); - queue_create_info_list[i].pQueuePriorities = param.queue_info_list[i].priorities.data(); + queue_create_info_list[i].pQueuePriorities = priorities.at(i).data(); } VkDeviceCreateInfo create_info{ @@ -55,27 +109,29 @@ namespace lava { transfer_queue_list.clear(); queue_list.clear(); - index_map queue_family_map; + for (auto i = 0u; i != queue_create_info_list.size(); ++i) { + auto queue_family_index = queue_create_info_list[i].queueFamilyIndex; + auto queue_family_flags = physical_device->get_queue_family_properties().at(queue_family_index).queueFlags; - for (size_t i = 0, ei = queue_create_info_list.size(); i != ei; ++i) { - if (!queue_family_map.count(queue_create_info_list[i].queueFamilyIndex)) - queue_family_map.emplace(queue_create_info_list[i].queueFamilyIndex, 0); + for (auto queue_index = 0u; queue_index != queue_create_info_list[i].queueCount; ++queue_index) { + VkQueue vk_queue = nullptr; + call().vkGetDeviceQueue(vk_device, queue_family_index, queue_index, &vk_queue); - for (size_t j = 0, ej = queue_create_info_list[i].queueCount; j != ej; ++j) { - auto counter = queue_family_map[queue_create_info_list[i].queueFamilyIndex]; - queue_family_map[queue_create_info_list[i].queueFamilyIndex]++; + auto flags = param.queue_family_infos[i].queues.at(queue_index).flags; + auto priority = queue_create_info_list[i].pQueuePriorities[queue_index]; - VkQueue queue = nullptr; - call().vkGetDeviceQueue(vk_device, queue_create_info_list[i].queueFamilyIndex, counter, &queue); + queue queue{ + vk_queue, queue_family_flags, queue_family_index, priority + }; - if (param.queue_info_list[i].flags & VK_QUEUE_GRAPHICS_BIT) - graphics_queue_list.push_back({ queue, queue_create_info_list[i].queueFamilyIndex }); - if (param.queue_info_list[i].flags & VK_QUEUE_COMPUTE_BIT) - compute_queue_list.push_back({ queue, queue_create_info_list[i].queueFamilyIndex }); - if (param.queue_info_list[i].flags & VK_QUEUE_TRANSFER_BIT) - transfer_queue_list.push_back({ queue, queue_create_info_list[i].queueFamilyIndex }); + if (flags & VK_QUEUE_GRAPHICS_BIT) + graphics_queue_list.push_front(queue); + if (flags & VK_QUEUE_COMPUTE_BIT) + compute_queue_list.push_front(queue); + if (flags & VK_QUEUE_TRANSFER_BIT) + transfer_queue_list.push_front(queue); - queue_list.push_back({ queue, queue_create_info_list[i].queueFamilyIndex }); + queue_list.push_back(queue); } } diff --git a/liblava/base/device.hpp b/liblava/base/device.hpp index 9da9193d68b963a87d4d15dccbfe79d5362788cb..abc96daee5f5886b76bbdc44f24579ebcfa78b78 100644 --- a/liblava/base/device.hpp +++ b/liblava/base/device.hpp @@ -5,6 +5,7 @@ #pragma once #include <liblava/base/device_table.hpp> +#include <liblava/base/queue.hpp> #include <liblava/core/data.hpp> namespace lava { @@ -22,34 +23,30 @@ namespace lava { physical_device_cptr physical_device = nullptr; - struct queue_info { - using list = std::vector<queue_info>; + names extensions; + VkPhysicalDeviceFeatures features{}; + void const* next = nullptr; // pNext - VkQueueFlags flags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT; + queue_family_info::list queue_family_infos; - using priority_list = std::vector<float>; - priority_list priorities; + void add_swapchain_extension() { + extensions.push_back("VK_KHR_swapchain"); + } - ui32 count() const { - return to_ui32(priorities.size()); - } + void set_default_queues() { + lava::set_default_queues(queue_family_infos); + } - explicit queue_info(ui32 count = 1) { - for (auto i = 0u; i < count; ++i) - priorities.push_back(1.f); - } - }; + void set_all_queues(); - queue_info::list queue_info_list; + bool add_queue(VkQueueFlags flags, r32 priority = 1.f) { + return add_queues(flags, 1, priority); + } + bool add_queues(VkQueueFlags flags, ui32 count, r32 priority = 1.f); - names extensions; - VkPhysicalDeviceFeatures features{}; - void const* next = nullptr; // pNext + bool add_dedicated_queues(r32 priority = 1.f); - void set_default_queues() { - extensions.push_back("VK_KHR_swapchain"); - queue_info_list.resize(1); - } + queue_verify_result verify_queues() const; }; ~device() { @@ -59,14 +56,6 @@ namespace lava { bool create(create_param::ref param); void destroy(); - struct queue { - using list = std::vector<queue>; - using ref = queue const&; - - VkQueue vk_queue = nullptr; - index family = 0; - }; - queue::ref get_graphics_queue(index index = 0) const { return get_graphics_queues().at(index); } @@ -160,10 +149,10 @@ namespace lava { VkDescriptorPool descriptor_pool = 0; - device::queue::list graphics_queue_list; - device::queue::list compute_queue_list; - device::queue::list transfer_queue_list; - device::queue::list queue_list; + queue::list graphics_queue_list; + queue::list compute_queue_list; + queue::list transfer_queue_list; + queue::list queue_list; VkPhysicalDeviceFeatures features; diff --git a/liblava/base/physical_device.cpp b/liblava/base/physical_device.cpp index 1b42f9f1c358e04f74b53f612eadd184fd597e20..e6f4a22b3044eab7c778281a6e4fcd3316753d5b 100644 --- a/liblava/base/physical_device.cpp +++ b/liblava/base/physical_device.cpp @@ -51,6 +51,7 @@ namespace lava { device::create_param physical_device::create_default_device_param() const { device::create_param create_param; create_param.physical_device = this; + create_param.add_swapchain_extension(); create_param.set_default_queues(); return create_param; diff --git a/liblava/base/queue.cpp b/liblava/base/queue.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7fc13314f512cce59ded73ec01de95fcd4c4dd58 --- /dev/null +++ b/liblava/base/queue.cpp @@ -0,0 +1,129 @@ +// file : liblava/base/queue.cpp +// copyright : Copyright (c) 2018-present, Lava Block OÜ and contributors +// license : MIT; see accompanying LICENSE file + +#include <liblava/base/queue.hpp> + +namespace lava { + + void set_default_queues(queue_family_info::list& list) { + list.clear(); + + list.resize(1); + list.at(0).queues.resize(1); + } + + void set_all_queues(queue_family_info::list& list, VkQueueFamilyPropertiesList const& properties) { + list.clear(); + + for (auto& queue_family : properties) { + queue_family_info info; + info.family_index = list.size(); + for (auto queue_count = 0; queue_count < queue_family.queueCount; ++queue_count) + info.queues.emplace_back(queue_family.queueFlags, 1.f); + list.push_back(info); + } + } + + void add_queues(queue_family_info::list& list, index family_index, VkQueueFlags flags, ui32 count, r32 priority) { + for (auto& family_info : list) { + if (family_info.family_index == family_index) { + family_info.add(flags, count, priority); + return; + } + } + + queue_family_info family_info; + family_info.family_index = family_index; + family_info.add(flags, count, priority); + list.emplace_back(family_info); + } + + bool add_queues(queue_family_info::list& list, VkQueueFamilyPropertiesList const& properties, VkQueueFlags flags, ui32 count, r32 priority) { + VkQueueFamilyPropertiesList free_properties; + for (auto family_index = 0u; family_index < properties.size(); ++family_index) { + auto family_properties = properties.at(family_index); + for (auto& family_info : list) { + if (family_info.family_index == family_index) { + family_properties.queueCount = properties.at(family_index).queueCount - family_info.count(); + break; + } + } + + free_properties.push_back(family_properties); + } + + // first look for a free family with the same flags (in reverse order) + i32 family_index_count = free_properties.size(); + for (auto family_index = family_index_count - 1; family_index >= 0; --family_index) { + auto const& queue_family = free_properties.at(family_index); + + auto queue_family_flags = queue_family.queueFlags & ~VK_QUEUE_SPARSE_BINDING_BIT; // ignore + if ((queue_family_flags == flags) && (queue_family.queueCount >= count)) { + add_queues(list, family_index, flags, count, priority); + return true; + } + } + + // fallback: search again if the flags exists within a free family + for (auto family_index = 0u; family_index < free_properties.size(); ++family_index) { + auto const& queue_family = free_properties.at(family_index); + + auto queue_family_flags = queue_family.queueFlags & ~VK_QUEUE_SPARSE_BINDING_BIT; // ignore + if (((queue_family_flags & flags) == flags) && (queue_family.queueCount >= count)) { + add_queues(list, family_index, flags, count, priority); + return true; + } + } + + return false; + } + + bool add_dedicated_queues(queue_family_info::list& list, VkQueueFamilyPropertiesList const& properties, r32 priority) { + if (properties.size() < 2) + return false; + + for (auto family_index = 1u; family_index < properties.size(); ++family_index) { + queue_family_info info; + info.family_index = family_index; + for (auto queue_count = 0; queue_count < properties.at(family_index).queueCount; ++queue_count) + info.queues.emplace_back(properties.at(family_index).queueFlags, priority); + list.push_back(info); + } + + return true; + } + + queue_verify_result verify_queues(queue_family_info::list const& list, VkQueueFamilyPropertiesList const& properties) { + if (list.empty()) + return queue_verify_result::empty_list; + + if (properties.empty()) + return queue_verify_result::no_properties; + + index_list families; + for (auto& info : list) { + if (contains(families, info.family_index)) + return queue_verify_result::duplicate_family_index; + + families.push_back(info.family_index); + + if (info.family_index > properties.size() - 1) + return queue_verify_result::no_family_index; + + if (info.queues.empty()) + return queue_verify_result::no_queues; + + if (info.count() > properties[info.family_index].queueCount) + return queue_verify_result::too_many_queues; + + for (auto& queue : info.queues) { + if ((properties[info.family_index].queueFlags & queue.flags) != queue.flags) + return queue_verify_result::no_compatible_flags; + } + } + + return queue_verify_result::ok; + } + +} // namespace lava diff --git a/liblava/base/queue.hpp b/liblava/base/queue.hpp new file mode 100644 index 0000000000000000000000000000000000000000..385304d619f80f2c061729e0665817ae17460500 --- /dev/null +++ b/liblava/base/queue.hpp @@ -0,0 +1,78 @@ +// file : liblava/base/queue.hpp +// copyright : Copyright (c) 2018-present, Lava Block OÜ and contributors +// license : MIT; see accompanying LICENSE file + +#pragma once + +#include <liblava/base/base.hpp> + +namespace lava { + + struct queue { + using list = std::deque<queue>; + using ref = queue const&; + + VkQueue vk_queue = nullptr; + VkQueueFlags flags = 0; + + index family = 0; + r32 priority = 1.f; + + bool operator<(queue const& other) const { + return priority < other.priority; + } + }; + + constexpr VkQueueFlags const default_queue_flags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT; + + struct queue_info { + using list = std::deque<queue_info>; + + VkQueueFlags flags = default_queue_flags; + r32 priority = 1.f; + }; + + struct queue_family_info { + using list = std::deque<queue_family_info>; + + index family_index = 0; + queue_info::list queues; + + void add(VkQueueFlags flags, ui32 count = 1, r32 priority = 1.f) { + for (auto i = 0u; i < count; ++i) + queues.emplace_back(flags, priority); + } + + ui32 count() const { + return to_ui32(queues.size()); + } + + void clear() { + queues.clear(); + } + }; + + void set_default_queues(queue_family_info::list& list); + void set_all_queues(queue_family_info::list& list, VkQueueFamilyPropertiesList const& properties); + + bool add_queues(queue_family_info::list& list, + VkQueueFamilyPropertiesList const& properties, + VkQueueFlags flags, ui32 count, r32 priority = 1.f); + + bool add_dedicated_queues(queue_family_info::list& list, + VkQueueFamilyPropertiesList const& properties, + r32 priority = 1.f); + + enum class queue_verify_result : type { + ok = 0, + empty_list, + no_properties, + duplicate_family_index, + no_family_index, + no_queues, + too_many_queues, + no_compatible_flags + }; + queue_verify_result verify_queues(queue_family_info::list const& list, VkQueueFamilyPropertiesList const& properties); + +} // namespace lava diff --git a/liblava/frame/renderer.cpp b/liblava/frame/renderer.cpp index 823aaf815ddb6bc5716468eb56b1d845a5acc8d9..5277313b37a66be0d7c29ff3202d226b3bcec3fc 100644 --- a/liblava/frame/renderer.cpp +++ b/liblava/frame/renderer.cpp @@ -11,7 +11,7 @@ namespace lava { target = t; device = target->get_device(); - queue = device->get_graphics_queue(); + graphics_queue = device->get_graphics_queue(); queued_frames = target->get_backbuffer_count(); fences.resize(queued_frames); @@ -141,7 +141,7 @@ namespace lava { std::array<VkSubmitInfo, 1> const submit_infos = { submit_info }; VkFence current_fence = fences[current_sync]; - if (!device->vkQueueSubmit(queue.vk_queue, to_ui32(submit_infos.size()), submit_infos.data(), current_fence)) + if (!device->vkQueueSubmit(graphics_queue.vk_queue, to_ui32(submit_infos.size()), submit_infos.data(), current_fence)) return false; std::array<VkSwapchainKHR, 1> const swapchains = { target->get() }; @@ -156,7 +156,7 @@ namespace lava { .pImageIndices = indices.data(), }; - auto result = device->vkQueuePresentKHR(queue.vk_queue, &present_info); + auto result = device->vkQueuePresentKHR(graphics_queue.vk_queue, &present_info); if (result.value == VK_ERROR_OUT_OF_DATE_KHR) { target->request_reload(); return true; diff --git a/liblava/frame/renderer.hpp b/liblava/frame/renderer.hpp index b09f15dc2ac15569cb645854332a6adbfc172f3f..621d3ff7f3971525c38ff48b84ba83e2915cfe1c 100644 --- a/liblava/frame/renderer.hpp +++ b/liblava/frame/renderer.hpp @@ -34,7 +34,7 @@ namespace lava { private: device_ptr device = nullptr; - device::queue queue; + queue graphics_queue; swapchain* target = nullptr; diff --git a/tests/unit.cpp b/tests/unit.cpp index 4dfc7ee50141861f1b8b15f56e298c8fbcedf79f..dbae9908505f20409c30c45888709b9c9f920952 100644 --- a/tests/unit.cpp +++ b/tests/unit.cpp @@ -1,5 +1,5 @@ // file : tests/unit.cpp -// copyright : Copyright (c) 2018-present, Lava Block O� and contributors +// copyright : Copyright (c) 2018-present, Lava Block OÜ and contributors // license : MIT; see accompanying LICENSE file #include <catch2/catch_test_macros.hpp> @@ -7,13 +7,108 @@ using namespace lava; -unsigned int Factorial(unsigned int number) { - return number <= 1 ? number : Factorial(number - 1) * number; +TEST_CASE("queue setup - GeForce GTX 1060", "[queue]") { + // http://vulkan.gpuinfo.org/listreports.php?devicename=GeForce+GTX+1060 + + VkQueueFamilyPropertiesList properties{ + { VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 16 }, + { VK_QUEUE_TRANSFER_BIT, 2 }, + { VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 8 } + }; + + queue_family_info::list list; + + SECTION("set default queues") { + set_default_queues(list); + + REQUIRE(list.at(0).count() == 1); + REQUIRE(list.at(0).queues.at(0).flags == (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT)); + } + + SECTION("set all queues") { + set_all_queues(list, properties); + + REQUIRE(list.at(0).count() == 16); + for (auto& queue : list.at(0).queues) + REQUIRE(queue.flags == (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT)); + + REQUIRE(list.at(1).count() == 2); + for (auto& queue : list.at(1).queues) + REQUIRE(queue.flags == (VK_QUEUE_TRANSFER_BIT)); + + REQUIRE(list.at(2).count() == 8); + for (auto& queue : list.at(2).queues) + REQUIRE(queue.flags == (VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT)); + } + + SECTION("add default + each dedicated queues") { + set_default_queues(list); + + REQUIRE(add_queues(list, properties, VK_QUEUE_COMPUTE_BIT, 1)); + REQUIRE(add_queues(list, properties, VK_QUEUE_TRANSFER_BIT, 1)); + } + + REQUIRE(verify_queues(list, properties) == queue_verify_result::ok); +} + +TEST_CASE("queue setup - Radeon RX 580 Series", "[queue]") { + // http://vulkan.gpuinfo.org/listreports.php?devicename=Radeon+RX+580+Series + + VkQueueFamilyPropertiesList properties{ + { VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 1 }, + { VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 2 }, + { VK_QUEUE_TRANSFER_BIT, 2 } + }; + + queue_family_info::list list; + + SECTION("add all dedicated queues") { + SECTION("with default queues") { + set_default_queues(list); + REQUIRE(list.size() == 1); + REQUIRE(add_dedicated_queues(list, properties)); + REQUIRE(list.size() == 3); + } + + SECTION("without default queues") { + REQUIRE(list.empty()); + REQUIRE(add_dedicated_queues(list, properties)); + REQUIRE(list.size() == 2); + } + } + + SECTION("add more queues + fallback") { + REQUIRE(add_queues(list, properties, VK_QUEUE_TRANSFER_BIT, 2)); + REQUIRE(add_queues(list, properties, VK_QUEUE_TRANSFER_BIT | VK_QUEUE_COMPUTE_BIT, 1)); + REQUIRE(add_queues(list, properties, VK_QUEUE_TRANSFER_BIT | VK_QUEUE_COMPUTE_BIT, 1)); + + // fallback + REQUIRE(add_queues(list, properties, VK_QUEUE_TRANSFER_BIT, 1)); + REQUIRE_FALSE(add_queues(list, properties, VK_QUEUE_COMPUTE_BIT, 1)); + } + + REQUIRE(verify_queues(list, properties) == queue_verify_result::ok); } -TEST_CASE("Factorials are computed", "[factorial]") { - REQUIRE(Factorial(1) == 1); - REQUIRE(Factorial(2) == 2); - REQUIRE(Factorial(3) == 6); - REQUIRE(Factorial(10) == 3628800); +TEST_CASE("queue setup - Intel(R) HD Graphics 620", "[queue]") { + // http://vulkan.gpuinfo.org/listreports.php?devicename=Intel%28R%29+HD+Graphics+620 + + VkQueueFamilyPropertiesList properties{ + { VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 1 } + }; + + queue_family_info::list list; + + SECTION("no dedicated queues available") { + REQUIRE_FALSE(add_dedicated_queues(list, properties)); + + REQUIRE(verify_queues(list, properties) == queue_verify_result::empty_list); + } + + SECTION("no more queues available") { + REQUIRE(add_queues(list, properties, VK_QUEUE_GRAPHICS_BIT, 1)); + REQUIRE_FALSE(add_queues(list, properties, VK_QUEUE_COMPUTE_BIT, 1)); + + REQUIRE(verify_queues(list, properties) == queue_verify_result::ok); + } }