mirror of
https://github.com/charles-lunarg/vk-bootstrap.git
synced 2024-11-22 07:24:34 +00:00
Add queue selection tests and refactor internal code a bit
This commit is contained in:
parent
36eff8fa42
commit
045b1e7b0f
@ -927,65 +927,44 @@ bool supports_features(VkPhysicalDeviceFeatures supported,
|
||||
return true;
|
||||
}
|
||||
// clang-format on
|
||||
// finds the first queue which supports graphics operations. returns QUEUE_INDEX_MAX_VALUE if none is found
|
||||
uint32_t get_graphics_queue_index(std::vector<VkQueueFamilyProperties> const& families) {
|
||||
// Finds the first queue which supports the desired operations. Returns QUEUE_INDEX_MAX_VALUE if none is found
|
||||
uint32_t get_first_queue_index(std::vector<VkQueueFamilyProperties> const& families, VkQueueFlags desired_flags) {
|
||||
for (uint32_t i = 0; i < static_cast<uint32_t>(families.size()); i++) {
|
||||
if (families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) return i;
|
||||
if (families[i].queueFlags & desired_flags) return i;
|
||||
}
|
||||
return QUEUE_INDEX_MAX_VALUE;
|
||||
}
|
||||
// finds a compute queue which is separate from the graphics queue and tries to find one without
|
||||
// transfer support returns QUEUE_INDEX_MAX_VALUE if none is found
|
||||
uint32_t get_separate_compute_queue_index(std::vector<VkQueueFamilyProperties> const& families) {
|
||||
uint32_t compute = QUEUE_INDEX_MAX_VALUE;
|
||||
// Finds the queue which is separate from the graphics queue and has the desired flag and not the
|
||||
// undesired flag, but will select it if no better options are available compute support. Returns
|
||||
// QUEUE_INDEX_MAX_VALUE if none is found.
|
||||
uint32_t get_separate_queue_index(std::vector<VkQueueFamilyProperties> const& families,
|
||||
VkQueueFlags desired_flags,
|
||||
VkQueueFlags undesired_flags) {
|
||||
uint32_t index = QUEUE_INDEX_MAX_VALUE;
|
||||
for (uint32_t i = 0; i < static_cast<uint32_t>(families.size()); i++) {
|
||||
if ((families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) &&
|
||||
((families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0)) {
|
||||
if ((families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) == 0) {
|
||||
if ((families[i].queueFlags & desired_flags) && ((families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0)) {
|
||||
if ((families[i].queueFlags & undesired_flags) == 0) {
|
||||
return i;
|
||||
} else {
|
||||
compute = i;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return compute;
|
||||
return index;
|
||||
}
|
||||
// finds a transfer queue which is separate from the graphics queue and tries to find one without
|
||||
// compute support returns QUEUE_INDEX_MAX_VALUE if none is found
|
||||
uint32_t get_separate_transfer_queue_index(std::vector<VkQueueFamilyProperties> const& families) {
|
||||
uint32_t transfer = QUEUE_INDEX_MAX_VALUE;
|
||||
|
||||
// finds the first queue which supports only the desired flag (not graphics or transfer). Returns QUEUE_INDEX_MAX_VALUE if none is found.
|
||||
uint32_t get_dedicated_queue_index(std::vector<VkQueueFamilyProperties> const& families,
|
||||
VkQueueFlags desired_flags,
|
||||
VkQueueFlags undesired_flags) {
|
||||
for (uint32_t i = 0; i < static_cast<uint32_t>(families.size()); i++) {
|
||||
if ((families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) &&
|
||||
((families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0)) {
|
||||
if ((families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) == 0) {
|
||||
return i;
|
||||
} else {
|
||||
transfer = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return transfer;
|
||||
}
|
||||
// finds the first queue which supports only compute (not graphics or transfer). returns QUEUE_INDEX_MAX_VALUE if none is found
|
||||
uint32_t get_dedicated_compute_queue_index(std::vector<VkQueueFamilyProperties> const& families) {
|
||||
for (uint32_t i = 0; i < static_cast<uint32_t>(families.size()); i++) {
|
||||
if ((families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) &&
|
||||
(families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0 &&
|
||||
(families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) == 0)
|
||||
return i;
|
||||
}
|
||||
return QUEUE_INDEX_MAX_VALUE;
|
||||
}
|
||||
// finds the first queue which supports only transfer (not graphics or compute). returns QUEUE_INDEX_MAX_VALUE if none is found
|
||||
uint32_t get_dedicated_transfer_queue_index(std::vector<VkQueueFamilyProperties> const& families) {
|
||||
for (uint32_t i = 0; i < static_cast<uint32_t>(families.size()); i++) {
|
||||
if ((families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) &&
|
||||
(families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0 &&
|
||||
(families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) == 0)
|
||||
if ((families[i].queueFlags & desired_flags) && (families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0 &&
|
||||
(families[i].queueFlags & undesired_flags) == 0)
|
||||
return i;
|
||||
}
|
||||
return QUEUE_INDEX_MAX_VALUE;
|
||||
}
|
||||
|
||||
// finds the first queue which supports presenting. returns QUEUE_INDEX_MAX_VALUE if none is found
|
||||
uint32_t get_present_queue_index(VkPhysicalDevice const phys_device,
|
||||
VkSurfaceKHR const surface,
|
||||
@ -1052,13 +1031,13 @@ PhysicalDeviceSelector::Suitable PhysicalDeviceSelector::is_device_suitable(Phys
|
||||
if (criteria.desired_version > pd.device_properties.apiVersion) suitable = Suitable::partial;
|
||||
|
||||
bool dedicated_compute =
|
||||
detail::get_dedicated_compute_queue_index(pd.queue_families) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
detail::get_dedicated_queue_index(pd.queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
bool dedicated_transfer =
|
||||
detail::get_dedicated_transfer_queue_index(pd.queue_families) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
detail::get_dedicated_queue_index(pd.queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
bool separate_compute =
|
||||
detail::get_separate_compute_queue_index(pd.queue_families) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
detail::get_separate_queue_index(pd.queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
bool separate_transfer =
|
||||
detail::get_separate_transfer_queue_index(pd.queue_families) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
detail::get_separate_queue_index(pd.queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
|
||||
bool present_queue =
|
||||
detail::get_present_queue_index(pd.phys_device, instance_info.surface, pd.queue_families) !=
|
||||
@ -1303,16 +1282,16 @@ PhysicalDeviceSelector& PhysicalDeviceSelector::select_first_device_unconditiona
|
||||
}
|
||||
|
||||
bool PhysicalDevice::has_dedicated_compute_queue() const {
|
||||
return detail::get_dedicated_compute_queue_index(queue_families) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
return detail::get_dedicated_queue_index(queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
}
|
||||
bool PhysicalDevice::has_separate_compute_queue() const {
|
||||
return detail::get_separate_compute_queue_index(queue_families) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
return detail::get_separate_queue_index(queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
}
|
||||
bool PhysicalDevice::has_dedicated_transfer_queue() const {
|
||||
return detail::get_dedicated_transfer_queue_index(queue_families) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
return detail::get_dedicated_queue_index(queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
}
|
||||
bool PhysicalDevice::has_separate_transfer_queue() const {
|
||||
return detail::get_separate_transfer_queue_index(queue_families) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
return detail::get_separate_queue_index(queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
}
|
||||
std::vector<VkQueueFamilyProperties> PhysicalDevice::get_queue_families() const {
|
||||
return queue_families;
|
||||
@ -1329,17 +1308,17 @@ detail::Result<uint32_t> Device::get_queue_index(QueueType type) const {
|
||||
return detail::Result<uint32_t>{ QueueError::present_unavailable };
|
||||
break;
|
||||
case QueueType::graphics:
|
||||
index = detail::get_graphics_queue_index(queue_families);
|
||||
index = detail::get_first_queue_index(queue_families, VK_QUEUE_GRAPHICS_BIT);
|
||||
if (index == detail::QUEUE_INDEX_MAX_VALUE)
|
||||
return detail::Result<uint32_t>{ QueueError::graphics_unavailable };
|
||||
break;
|
||||
case QueueType::compute:
|
||||
index = detail::get_separate_compute_queue_index(queue_families);
|
||||
index = detail::get_separate_queue_index(queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT);
|
||||
if (index == detail::QUEUE_INDEX_MAX_VALUE)
|
||||
return detail::Result<uint32_t>{ QueueError::compute_unavailable };
|
||||
break;
|
||||
case QueueType::transfer:
|
||||
index = detail::get_separate_transfer_queue_index(queue_families);
|
||||
index = detail::get_separate_queue_index(queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT);
|
||||
if (index == detail::QUEUE_INDEX_MAX_VALUE)
|
||||
return detail::Result<uint32_t>{ QueueError::transfer_unavailable };
|
||||
break;
|
||||
@ -1352,12 +1331,12 @@ detail::Result<uint32_t> Device::get_dedicated_queue_index(QueueType type) const
|
||||
uint32_t index = detail::QUEUE_INDEX_MAX_VALUE;
|
||||
switch (type) {
|
||||
case QueueType::compute:
|
||||
index = detail::get_dedicated_compute_queue_index(queue_families);
|
||||
index = detail::get_dedicated_queue_index(queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT);
|
||||
if (index == detail::QUEUE_INDEX_MAX_VALUE)
|
||||
return detail::Result<uint32_t>{ QueueError::compute_unavailable };
|
||||
break;
|
||||
case QueueType::transfer:
|
||||
index = detail::get_dedicated_transfer_queue_index(queue_families);
|
||||
index = detail::get_dedicated_queue_index(queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT);
|
||||
if (index == detail::QUEUE_INDEX_MAX_VALUE)
|
||||
return detail::Result<uint32_t>{ QueueError::transfer_unavailable };
|
||||
break;
|
||||
@ -1660,7 +1639,7 @@ SwapchainBuilder::SwapchainBuilder(VkPhysicalDevice const physical_device,
|
||||
auto queue_families = detail::get_vector_noerror<VkQueueFamilyProperties>(
|
||||
detail::vulkan_functions().fp_vkGetPhysicalDeviceQueueFamilyProperties, physical_device);
|
||||
if (graphics_queue_index == detail::QUEUE_INDEX_MAX_VALUE)
|
||||
info.graphics_queue_index = detail::get_graphics_queue_index(queue_families);
|
||||
info.graphics_queue_index = detail::get_first_queue_index(queue_families, VK_QUEUE_GRAPHICS_BIT);
|
||||
if (present_queue_index == detail::QUEUE_INDEX_MAX_VALUE)
|
||||
info.present_queue_index = detail::get_present_queue_index(physical_device, surface, queue_families);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
add_executable(vk-bootstrap-test main.cpp bootstrap_tests.cpp error_code_tests.cpp)
|
||||
add_executable(vk-bootstrap-test main.cpp bootstrap_tests.cpp error_code_tests.cpp unit_tests.cpp)
|
||||
target_link_libraries(vk-bootstrap-test
|
||||
PRIVATE
|
||||
vk-bootstrap
|
||||
|
94
tests/unit_tests.cpp
Normal file
94
tests/unit_tests.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
#include "VkBootstrap.cpp"
|
||||
|
||||
|
||||
TEST_CASE("Single Queue Device", "[UnitTests.queue_selection_logic]") {
|
||||
std::vector<VkQueueFamilyProperties> families = { VkQueueFamilyProperties{
|
||||
VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 1, 0, VkExtent3D{ 1, 1, 1 } } };
|
||||
|
||||
REQUIRE(0 == vkb::detail::get_first_queue_index(families, VK_QUEUE_GRAPHICS_BIT));
|
||||
REQUIRE(vkb::detail::QUEUE_INDEX_MAX_VALUE ==
|
||||
vkb::detail::get_separate_queue_index(families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT));
|
||||
REQUIRE(vkb::detail::QUEUE_INDEX_MAX_VALUE ==
|
||||
vkb::detail::get_separate_queue_index(families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT));
|
||||
REQUIRE(vkb::detail::QUEUE_INDEX_MAX_VALUE ==
|
||||
vkb::detail::get_dedicated_queue_index(families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT));
|
||||
REQUIRE(vkb::detail::QUEUE_INDEX_MAX_VALUE ==
|
||||
vkb::detail::get_dedicated_queue_index(families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT));
|
||||
}
|
||||
|
||||
TEST_CASE("Dedicated Compute Queue, Separate Transfer", "[UnitTests.queue_selection_logic]") {
|
||||
SECTION("Dedicated Queue First") {
|
||||
std::vector<VkQueueFamilyProperties> families = {
|
||||
VkQueueFamilyProperties{
|
||||
VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT, 1, 0, VkExtent3D{ 1, 1, 1 } },
|
||||
VkQueueFamilyProperties{ VK_QUEUE_COMPUTE_BIT, 1, 0, VkExtent3D{ 1, 1, 1 } },
|
||||
VkQueueFamilyProperties{ VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 1, 0, VkExtent3D{ 1, 1, 1 } }
|
||||
};
|
||||
|
||||
REQUIRE(0 == vkb::detail::get_first_queue_index(families, VK_QUEUE_GRAPHICS_BIT));
|
||||
REQUIRE(1 == vkb::detail::get_separate_queue_index(families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT));
|
||||
REQUIRE(2 == vkb::detail::get_separate_queue_index(families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT));
|
||||
REQUIRE(1 == vkb::detail::get_dedicated_queue_index(families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT));
|
||||
REQUIRE(vkb::detail::QUEUE_INDEX_MAX_VALUE ==
|
||||
vkb::detail::get_dedicated_queue_index(families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT));
|
||||
}
|
||||
SECTION("Dedicated Queue Last") {
|
||||
std::vector<VkQueueFamilyProperties> families = {
|
||||
VkQueueFamilyProperties{
|
||||
VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT, 1, 0, VkExtent3D{ 1, 1, 1 } },
|
||||
VkQueueFamilyProperties{ VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 1, 0, VkExtent3D{ 1, 1, 1 } },
|
||||
VkQueueFamilyProperties{ VK_QUEUE_COMPUTE_BIT, 1, 0, VkExtent3D{ 1, 1, 1 } }
|
||||
};
|
||||
|
||||
REQUIRE(0 == vkb::detail::get_first_queue_index(families, VK_QUEUE_GRAPHICS_BIT));
|
||||
REQUIRE(2 == vkb::detail::get_separate_queue_index(families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT));
|
||||
REQUIRE(1 == vkb::detail::get_separate_queue_index(families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT));
|
||||
REQUIRE(2 == vkb::detail::get_dedicated_queue_index(families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT));
|
||||
REQUIRE(vkb::detail::QUEUE_INDEX_MAX_VALUE ==
|
||||
vkb::detail::get_dedicated_queue_index(families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Dedicated Transfer Queue, Separate Compute", "[UnitTests.queue_selection_logic]") {
|
||||
SECTION("Dedicated Queue First") {
|
||||
std::vector<VkQueueFamilyProperties> families = {
|
||||
VkQueueFamilyProperties{
|
||||
VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT, 1, 0, VkExtent3D{ 1, 1, 1 } },
|
||||
VkQueueFamilyProperties{ VK_QUEUE_TRANSFER_BIT, 1, 0, VkExtent3D{ 1, 1, 1 } },
|
||||
VkQueueFamilyProperties{ VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 1, 0, VkExtent3D{ 1, 1, 1 } }
|
||||
};
|
||||
|
||||
REQUIRE(0 == vkb::detail::get_first_queue_index(families, VK_QUEUE_GRAPHICS_BIT));
|
||||
REQUIRE(2 == vkb::detail::get_separate_queue_index(families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT));
|
||||
REQUIRE(1 == vkb::detail::get_separate_queue_index(families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT));
|
||||
REQUIRE(vkb::detail::QUEUE_INDEX_MAX_VALUE ==
|
||||
vkb::detail::get_dedicated_queue_index(families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT));
|
||||
REQUIRE(1 == vkb::detail::get_dedicated_queue_index(families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT));
|
||||
}
|
||||
SECTION("Dedicated Queue Last") {
|
||||
std::vector<VkQueueFamilyProperties> families = {
|
||||
VkQueueFamilyProperties{
|
||||
VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT, 1, 0, VkExtent3D{ 1, 1, 1 } },
|
||||
VkQueueFamilyProperties{ VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 1, 0, VkExtent3D{ 1, 1, 1 } },
|
||||
VkQueueFamilyProperties{ VK_QUEUE_TRANSFER_BIT, 1, 0, VkExtent3D{ 1, 1, 1 } }
|
||||
};
|
||||
|
||||
REQUIRE(0 == vkb::detail::get_first_queue_index(families, VK_QUEUE_GRAPHICS_BIT));
|
||||
REQUIRE(1 == vkb::detail::get_separate_queue_index(families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT));
|
||||
REQUIRE(2 == vkb::detail::get_separate_queue_index(families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT));
|
||||
REQUIRE(vkb::detail::QUEUE_INDEX_MAX_VALUE ==
|
||||
vkb::detail::get_dedicated_queue_index(families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT));
|
||||
REQUIRE(2 == vkb::detail::get_dedicated_queue_index(families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Queue Selection logic", "[VkBootstrap.queue_logic]") {
|
||||
vkb::InstanceBuilder builder;
|
||||
|
||||
auto instance_ret = builder.request_validation_layers().build();
|
||||
REQUIRE(instance_ret.has_value());
|
||||
|
||||
vkb::destroy_instance(instance_ret.value());
|
||||
}
|
Loading…
Reference in New Issue
Block a user