mirror of
https://github.com/charles-lunarg/vk-bootstrap.git
synced 2024-11-10 02:41:47 +00:00
Add new Queue query API
The original queue query API has shortcomings which cause confusion and make it harder to do the things people want with vk-bootstrap. Design features of the new API: * Choose a queue given a combination of queue types - Instead of only choosing based on a single queue type * Allow picking the first or 'preferred' queue for any given combination of queue types * Allow picking a present queue with a specific surface handle - Instead of only using the surface the PhysicalDevice was selected with * Dont need to update the library to support new queue types over time
This commit is contained in:
parent
be0df09b3a
commit
f290028cb5
@ -151,14 +151,12 @@ No cleanup is required for `vkb::PhysicalDevice`.
|
||||
|
||||
The `vkb::PhysicalDeviceSelector` will look for the first device in the list that satisfied all the specified criteria, and if none is found, will return the first device that partially satisfies the criteria.
|
||||
|
||||
The various "require" and "desire" pairs of functions indicate to `vk-bootstrap` what features and capabilities are necessary for an application and what are simply preferred. A "require" function will fail any `VkPhysicalDevice` that doesn't satisfy the constraint, while any criteria that doesn't satisfy the "desire" functions will make the `VkPhysicalDevice` only 'partially satisfy'.
|
||||
The various "require" functions indicate to `vk-bootstrap` what features and capabilities are necessary for an application. A "require" function will fail any `VkPhysicalDevice` that doesn't satisfy the constraint.
|
||||
|
||||
```c
|
||||
// Application cannot function without this extension
|
||||
phys_device_selector.add_required_extension("VK_KHR_timeline_semaphore");
|
||||
|
||||
// Application can deal with the lack of this extension
|
||||
phys_device_selector.add_desired_extension("VK_KHR_imageless_framebuffer");
|
||||
```
|
||||
|
||||
Note:
|
||||
@ -198,17 +196,30 @@ vkb::destroy_device(vkb_device);
|
||||
|
||||
By default, `vkb::DeviceBuilder` will enable one queue from each queue family available on the `VkPhysicalDevice`. This is done because in practice, most use cases only need a single queue from each family.
|
||||
|
||||
To get a `VkQueue` or the index of a `VkQueue`, use the `get_queue(QueueType type)` and `get_queue_index(QueueType type)` functions of `vkb::Device`. These will return the appropriate `VkQueue` or `uint32_t` if they exist and were enabled, else they will return an error.
|
||||
To get a `VkQueue` and the index of a `VkQueue`, use the `get_preferred_queue_and_index(VkQueueFlags flags)` functions of `vkb::Device`. These will return the appropriate `VkQueue` handle and `uint32_t` index stored in a `vkb::QueueAndIndex` struct if they exist and were enabled, else they will return an error.
|
||||
|
||||
```cpp
|
||||
auto queue_ret = vkb_device.get_queue (vkb::QueueType::graphics);
|
||||
auto queue_ret = vkb_device.get_preferred_queue_and_index (VK_QUEUE_GRAPHICS_BIT);
|
||||
if (!queue_ret) {
|
||||
// handle error
|
||||
}
|
||||
graphics_queue = queue_ret.value ();
|
||||
```
|
||||
|
||||
Queue families represent a set of queues with similar operations, such as graphics, transfer, and compute. Because not all Vulkan hardware has queue families for each operation category, an application should be able to handle the presence or lack of certain queue families. For this reason the `get_dedicated_queue` and `get_dedicated_queue_index` functions of `vkb::Device` exist to allow applications to easily know if there is a queue dedicated to a particular operation, such as compute or transfer operations.
|
||||
To query a queue capable of multiple operations, use multiple `VkQueueFlags` combined with bitwise-or to look for a queue that supports all specified flags, if such a queue exists.
|
||||
|
||||
```cpp
|
||||
vkb_device.get_preferred_queue_and_index(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT);
|
||||
```
|
||||
|
||||
To get a `VkQueue` capable of presentation, use `get_first_presentation_queue_and_index()`.
|
||||
To check if any given queue family index is capable of presentation operations, use `queue_family_index_supports_presentation(VkQueue queue)`.
|
||||
|
||||
`get_preferred_queue_and_index(VkQueueFlags flags)` looks for a queue that supports the given queue flags while minimizing unsupported flags.
|
||||
It does not require that the queue exclusively supports only the given queue flags, which may result in the same queue handle being returns by different queries.
|
||||
Because not all Vulkan hardware has queue families for each operation category, an application needs to be careful that they didn't get the same queue handle multiple times.
|
||||
While it is fine to query the same queue multiple times, it is not fine to use that queue in multiple threads at the same time, or to ignore other synchronization requirements of VkQueue's in the Vulkan API.
|
||||
|
||||
|
||||
#### Custom queue setup
|
||||
|
||||
|
@ -410,6 +410,7 @@ const char* to_string(QueueError err) {
|
||||
CASE_TO_STRING(QueueError, graphics_unavailable)
|
||||
CASE_TO_STRING(QueueError, compute_unavailable)
|
||||
CASE_TO_STRING(QueueError, transfer_unavailable)
|
||||
CASE_TO_STRING(QueueError, queue_type_unavailable)
|
||||
CASE_TO_STRING(QueueError, queue_index_out_of_range)
|
||||
CASE_TO_STRING(QueueError, invalid_queue_family_index)
|
||||
default:
|
||||
@ -932,6 +933,7 @@ bool supports_features(VkPhysicalDeviceFeatures supported,
|
||||
return true;
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
// 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++) {
|
||||
@ -939,21 +941,33 @@ uint32_t get_first_queue_index(std::vector<VkQueueFamilyProperties> const& famil
|
||||
}
|
||||
return 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.
|
||||
|
||||
// Finds the that has the desired flag and the least number of undesired flags.
|
||||
// Any queue family with invalid_flags will be ignored.
|
||||
// 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) {
|
||||
std::vector<VkQueueFamilyProperties> const& families, VkQueueFlags desired_flags, VkQueueFlags undesired_flags, VkQueueFlags invalid_flags) {
|
||||
uint32_t index = QUEUE_INDEX_MAX_VALUE;
|
||||
uint32_t least_undesired_flags_count = QUEUE_INDEX_MAX_VALUE;
|
||||
for (uint32_t i = 0; i < static_cast<uint32_t>(families.size()); i++) {
|
||||
if ((families[i].queueFlags & desired_flags) == desired_flags && ((families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0)) {
|
||||
if ((families[i].queueFlags & undesired_flags) == 0) {
|
||||
return i;
|
||||
} else {
|
||||
if ((invalid_flags != 0) && (families[i].queueFlags & invalid_flags) == invalid_flags) {
|
||||
continue;
|
||||
}
|
||||
if ((families[i].queueFlags & desired_flags) == desired_flags) {
|
||||
uint32_t undesired_flag_count = 0;
|
||||
// Count the number of flags which are supported by the queue family but are undesired
|
||||
for (uint32_t j = VK_QUEUE_FLAG_BITS_MAX_ENUM; j != 0; j >>= 1) {
|
||||
if (families[i].queueFlags & undesired_flags & j) {
|
||||
undesired_flag_count++;
|
||||
}
|
||||
}
|
||||
if (undesired_flag_count < least_undesired_flags_count) {
|
||||
least_undesired_flags_count = undesired_flag_count;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
@ -961,8 +975,7 @@ uint32_t get_separate_queue_index(
|
||||
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 & desired_flags) == desired_flags &&
|
||||
(families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0 && (families[i].queueFlags & undesired_flags) == 0)
|
||||
if ((families[i].queueFlags & desired_flags) == desired_flags && ((families[i].queueFlags & undesired_flags) == 0))
|
||||
return i;
|
||||
}
|
||||
return QUEUE_INDEX_MAX_VALUE;
|
||||
@ -1047,13 +1060,17 @@ PhysicalDevice::Suitable PhysicalDeviceSelector::is_device_suitable(PhysicalDevi
|
||||
if (criteria.required_version > pd.properties.apiVersion) return PhysicalDevice::Suitable::no;
|
||||
if (criteria.desired_version > pd.properties.apiVersion) suitable = PhysicalDevice::Suitable::partial;
|
||||
|
||||
bool dedicated_compute = detail::get_dedicated_queue_index(pd.queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT) !=
|
||||
bool dedicated_compute = detail::get_dedicated_queue_index(pd.queue_families,
|
||||
VK_QUEUE_COMPUTE_BIT,
|
||||
VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
bool dedicated_transfer = detail::get_dedicated_queue_index(pd.queue_families,
|
||||
VK_QUEUE_TRANSFER_BIT,
|
||||
VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
bool separate_compute = detail::get_separate_queue_index(
|
||||
pd.queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT) !=
|
||||
detail::QUEUE_INDEX_MAX_VALUE;
|
||||
bool dedicated_transfer = 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_queue_index(pd.queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT) !=
|
||||
detail::QUEUE_INDEX_MAX_VALUE;
|
||||
bool separate_transfer = detail::get_separate_queue_index(pd.queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT) !=
|
||||
bool separate_transfer = detail::get_separate_queue_index(
|
||||
pd.queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_GRAPHICS_BIT) !=
|
||||
detail::QUEUE_INDEX_MAX_VALUE;
|
||||
|
||||
bool present_queue = detail::get_present_queue_index(pd.physical_device, instance_info.surface, pd.queue_families) !=
|
||||
@ -1356,16 +1373,20 @@ PhysicalDeviceSelector& PhysicalDeviceSelector::select_first_device_unconditiona
|
||||
|
||||
// PhysicalDevice
|
||||
bool PhysicalDevice::has_dedicated_compute_queue() const {
|
||||
return detail::get_dedicated_queue_index(queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
return detail::get_dedicated_queue_index(queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT) !=
|
||||
detail::QUEUE_INDEX_MAX_VALUE;
|
||||
}
|
||||
bool PhysicalDevice::has_separate_compute_queue() const {
|
||||
return detail::get_separate_queue_index(queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
return detail::get_separate_queue_index(queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT) !=
|
||||
detail::QUEUE_INDEX_MAX_VALUE;
|
||||
}
|
||||
bool PhysicalDevice::has_dedicated_transfer_queue() const {
|
||||
return detail::get_dedicated_queue_index(queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
return detail::get_dedicated_queue_index(queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT) !=
|
||||
detail::QUEUE_INDEX_MAX_VALUE;
|
||||
}
|
||||
bool PhysicalDevice::has_separate_transfer_queue() const {
|
||||
return detail::get_separate_queue_index(queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT) != detail::QUEUE_INDEX_MAX_VALUE;
|
||||
return detail::get_separate_queue_index(queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_GRAPHICS_BIT) !=
|
||||
detail::QUEUE_INDEX_MAX_VALUE;
|
||||
}
|
||||
std::vector<VkQueueFamilyProperties> PhysicalDevice::get_queue_families() const { return queue_families; }
|
||||
std::vector<std::string> PhysicalDevice::get_extensions() const { return extensions; }
|
||||
@ -1373,6 +1394,7 @@ PhysicalDevice::operator VkPhysicalDevice() const { return this->physical_device
|
||||
|
||||
// ---- Queues ---- //
|
||||
|
||||
// Legacy queue function
|
||||
Result<uint32_t> Device::get_queue_index(QueueType type) const {
|
||||
uint32_t index = detail::QUEUE_INDEX_MAX_VALUE;
|
||||
switch (type) {
|
||||
@ -1385,27 +1407,11 @@ Result<uint32_t> Device::get_queue_index(QueueType type) const {
|
||||
if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result<uint32_t>{ QueueError::graphics_unavailable };
|
||||
break;
|
||||
case QueueType::compute:
|
||||
index = detail::get_separate_queue_index(queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT);
|
||||
index = detail::get_separate_queue_index(queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT);
|
||||
if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result<uint32_t>{ QueueError::compute_unavailable };
|
||||
break;
|
||||
case QueueType::transfer:
|
||||
index = detail::get_separate_queue_index(queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT);
|
||||
if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result<uint32_t>{ QueueError::transfer_unavailable };
|
||||
break;
|
||||
default:
|
||||
return Result<uint32_t>{ QueueError::invalid_queue_family_index };
|
||||
}
|
||||
return index;
|
||||
}
|
||||
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_queue_index(queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT);
|
||||
if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result<uint32_t>{ QueueError::compute_unavailable };
|
||||
break;
|
||||
case QueueType::transfer:
|
||||
index = detail::get_dedicated_queue_index(queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT);
|
||||
index = detail::get_separate_queue_index(queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_GRAPHICS_BIT);
|
||||
if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result<uint32_t>{ QueueError::transfer_unavailable };
|
||||
break;
|
||||
default:
|
||||
@ -1414,6 +1420,25 @@ Result<uint32_t> Device::get_dedicated_queue_index(QueueType type) const {
|
||||
return index;
|
||||
}
|
||||
|
||||
// Legacy queue function
|
||||
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_queue_index(queue_families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT);
|
||||
if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result<uint32_t>{ QueueError::compute_unavailable };
|
||||
break;
|
||||
case QueueType::transfer:
|
||||
index = detail::get_dedicated_queue_index(queue_families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT);
|
||||
if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result<uint32_t>{ QueueError::transfer_unavailable };
|
||||
break;
|
||||
default:
|
||||
return Result<uint32_t>{ QueueError::invalid_queue_family_index };
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
// Legacy queue function
|
||||
Result<VkQueue> Device::get_queue(QueueType type) const {
|
||||
auto index = get_queue_index(type);
|
||||
if (!index.has_value()) return { index.error() };
|
||||
@ -1421,14 +1446,63 @@ Result<VkQueue> Device::get_queue(QueueType type) const {
|
||||
internal_table.fp_vkGetDeviceQueue(device, index.value(), 0, &out_queue);
|
||||
return out_queue;
|
||||
}
|
||||
|
||||
// Legacy queue function
|
||||
Result<VkQueue> Device::get_dedicated_queue(QueueType type) const {
|
||||
auto index = get_dedicated_queue_index(type);
|
||||
if (!index.has_value()) return { index.error() };
|
||||
VkQueue out_queue;
|
||||
VkQueue out_queue{};
|
||||
internal_table.fp_vkGetDeviceQueue(device, index.value(), 0, &out_queue);
|
||||
return out_queue;
|
||||
}
|
||||
|
||||
|
||||
Result<QueueAndIndex> Device::get_first_queue_and_index(VkQueueFlags queue_flags) const {
|
||||
uint32_t index = detail::get_first_queue_index(queue_families, queue_flags);
|
||||
if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result<QueueAndIndex>{ QueueError::queue_type_unavailable };
|
||||
|
||||
VkQueue out_queue{};
|
||||
internal_table.fp_vkGetDeviceQueue(device, index, 0, &out_queue);
|
||||
return QueueAndIndex{ out_queue, index };
|
||||
}
|
||||
|
||||
Result<QueueAndIndex> Device::get_preferred_queue_and_index(VkQueueFlags queue_flags) const {
|
||||
uint32_t index = detail::get_separate_queue_index(queue_families, queue_flags, ~queue_flags, 0);
|
||||
if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result<QueueAndIndex>{ QueueError::queue_type_unavailable };
|
||||
|
||||
VkQueue out_queue{};
|
||||
internal_table.fp_vkGetDeviceQueue(device, index, 0, &out_queue);
|
||||
return QueueAndIndex{ out_queue, index };
|
||||
}
|
||||
|
||||
Result<QueueAndIndex> Device::get_first_presentation_queue_and_index(VkSurfaceKHR surface_to_check) const {
|
||||
VkSurfaceKHR surface_to_use = surface;
|
||||
if (surface_to_check != VK_NULL_HANDLE) {
|
||||
surface_to_use = surface_to_check;
|
||||
}
|
||||
uint32_t index = detail::get_present_queue_index(physical_device.physical_device, surface_to_use, queue_families);
|
||||
if (index == detail::QUEUE_INDEX_MAX_VALUE) return Result<QueueAndIndex>{ QueueError::present_unavailable };
|
||||
|
||||
VkQueue out_queue{};
|
||||
internal_table.fp_vkGetDeviceQueue(device, index, 0, &out_queue);
|
||||
return QueueAndIndex{ out_queue, index };
|
||||
}
|
||||
|
||||
bool Device::queue_family_index_supports_presentation(uint32_t index, VkSurfaceKHR surface_to_check) const {
|
||||
VkBool32 presentSupport = 0;
|
||||
VkSurfaceKHR surface_to_use = surface;
|
||||
if (surface_to_check != VK_NULL_HANDLE) {
|
||||
surface_to_use = surface_to_check;
|
||||
}
|
||||
if (surface_to_use != VK_NULL_HANDLE) {
|
||||
VkResult res = detail::vulkan_functions().fp_vkGetPhysicalDeviceSurfaceSupportKHR(
|
||||
physical_device, index, surface_to_use, &presentSupport);
|
||||
if (res != VK_SUCCESS) return false;
|
||||
}
|
||||
return presentSupport == 1;
|
||||
}
|
||||
|
||||
|
||||
// ---- Dispatch ---- //
|
||||
|
||||
DispatchTable Device::make_table() const { return { device, fp_vkGetDeviceProcAddr }; }
|
||||
|
@ -200,6 +200,7 @@ enum class QueueError {
|
||||
graphics_unavailable,
|
||||
compute_unavailable,
|
||||
transfer_unavailable,
|
||||
queue_type_unavailable,
|
||||
queue_index_out_of_range,
|
||||
invalid_queue_family_index
|
||||
};
|
||||
@ -675,13 +676,25 @@ class PhysicalDeviceSelector {
|
||||
};
|
||||
|
||||
// ---- Queue ---- //
|
||||
enum class QueueType { present, graphics, compute, transfer };
|
||||
|
||||
enum class QueueType {
|
||||
present,
|
||||
graphics,
|
||||
compute,
|
||||
transfer,
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
// Sentinel value, used in implementation only
|
||||
const uint32_t QUEUE_INDEX_MAX_VALUE = 65536;
|
||||
} // namespace detail
|
||||
|
||||
|
||||
struct QueueAndIndex {
|
||||
VkQueue queue = VK_NULL_HANDLE;
|
||||
uint32_t index = detail::QUEUE_INDEX_MAX_VALUE;
|
||||
};
|
||||
|
||||
// ---- Device ---- //
|
||||
|
||||
struct Device {
|
||||
@ -693,13 +706,34 @@ struct Device {
|
||||
PFN_vkGetDeviceProcAddr fp_vkGetDeviceProcAddr = nullptr;
|
||||
uint32_t instance_version = VKB_VK_API_VERSION_1_0;
|
||||
|
||||
Result<uint32_t> get_queue_index(QueueType type) const;
|
||||
// Only a compute or transfer queue type is valid. All other queue types do not support a 'dedicated' queue index
|
||||
Result<uint32_t> get_dedicated_queue_index(QueueType type) const;
|
||||
// Legacy function - gets the queue which supports queue_type operations using the following rules:
|
||||
// If queue_type is graphics, return the first queue that supports graphics operations
|
||||
// If queue_type is compute, return a queue that supports compute operations but not graphics, if one exists
|
||||
// If queue_type is transfer, return a queue that supports transfer operations but not graphics, if one exists
|
||||
// If queue_type is present, return the first queue that supports presentation with the VkSurfaceKHR given during physical device selection
|
||||
Result<uint32_t> get_queue_index(QueueType queue_type) const;
|
||||
Result<VkQueue> get_queue(QueueType queue_type) const;
|
||||
|
||||
Result<VkQueue> get_queue(QueueType type) const;
|
||||
// Only a compute or transfer queue type is valid. All other queue types do not support a 'dedicated' queue
|
||||
Result<VkQueue> get_dedicated_queue(QueueType type) const;
|
||||
// Legacy function - gets the queue which supports only the queue_type operations using the following rules:
|
||||
// If queue_type is compute, return a queue that supports compute operations but not graphics or transfer, if one
|
||||
// exists If queue_type is transfer, return a queue that supports transfer operations but not graphics or compute,
|
||||
// if one exists If queue_type is any other type, return an error code
|
||||
Result<VkQueue> get_dedicated_queue(QueueType queue_type) const;
|
||||
Result<uint32_t> get_dedicated_queue_index(QueueType queue_type) const;
|
||||
|
||||
// Returns the first queue which supports the operations specified by queue_flags
|
||||
Result<QueueAndIndex> get_first_queue_and_index(VkQueueFlags queue_flags) const;
|
||||
|
||||
// Returns the queue which supports the operations specified by queue_flags and the least number of operations not specified by queue_flags
|
||||
Result<QueueAndIndex> get_preferred_queue_and_index(VkQueueFlags queue_flags) const;
|
||||
|
||||
// Get the first queue which supports presentation. Very unlikely to be unique.
|
||||
// If surface_to_check is not VK_NULL_HANDLE, it will make sure the surface is compatible with the queue
|
||||
// Otherwise if surface_to_check is VK_NULL_HANDLE, it will use the VkSurfaceKHR used duing physical device selection
|
||||
Result<QueueAndIndex> get_first_presentation_queue_and_index(VkSurfaceKHR surface_to_check = VK_NULL_HANDLE) const;
|
||||
|
||||
// Returns true if the given queue family index is capable of supporting presentation operations.
|
||||
bool queue_family_index_supports_presentation(uint32_t index, VkSurfaceKHR surface_to_check = VK_NULL_HANDLE) const;
|
||||
|
||||
// Return a loaded dispatch table
|
||||
DispatchTable make_table() const;
|
||||
|
@ -334,6 +334,9 @@ TEST_CASE("Swapchain", "[VkBootstrap.bootstrap]") {
|
||||
auto graphics_queue_index = device.get_queue_index(vkb::QueueType::graphics).value();
|
||||
auto present_queue_index = device.get_queue_index(vkb::QueueType::present).value();
|
||||
|
||||
REQUIRE(device.get_first_presentation_queue_and_index().has_value());
|
||||
REQUIRE(device.queue_family_index_supports_presentation(present_queue_index));
|
||||
|
||||
THEN("Swapchain can be made") {
|
||||
vkb::SwapchainBuilder swapchain_builder(device);
|
||||
auto swapchain_ret = swapchain_builder.build();
|
||||
@ -727,7 +730,7 @@ TEST_CASE("Querying Required Extension Features in 1.1", "[VkBootstrap.version]"
|
||||
}
|
||||
|
||||
TEST_CASE("Querying Vulkan 1.1 and 1.2 features", "[VkBootstrap.version]") {
|
||||
[[maybe_unused]] VulkanMock& mock = get_and_setup_default();
|
||||
VulkanMock& mock = get_and_setup_default();
|
||||
mock.api_version = VK_API_VERSION_1_2;
|
||||
mock.physical_devices_details[0].properties.apiVersion = VK_API_VERSION_1_2;
|
||||
|
||||
@ -740,7 +743,6 @@ TEST_CASE("Querying Vulkan 1.1 and 1.2 features", "[VkBootstrap.version]") {
|
||||
mock.physical_devices_details[0].add_features_pNext_struct(mock_vulkan_12_features);
|
||||
|
||||
GIVEN("A working instance") {
|
||||
vkb::InstanceBuilder builder;
|
||||
auto instance = get_headless_instance(2); // make sure we use 1.2
|
||||
SECTION("Requires a device that supports multiview and bufferDeviceAddress") {
|
||||
VkPhysicalDeviceVulkan11Features features_11{};
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "VkBootstrap.cpp"
|
||||
|
||||
#include "vulkan_mock.hpp"
|
||||
|
||||
TEST_CASE("Single Queue Device", "[UnitTests.queue_selection_logic]") {
|
||||
std::vector<VkQueueFamilyProperties> families = { VkQueueFamilyProperties{
|
||||
@ -9,9 +10,9 @@ TEST_CASE("Single Queue Device", "[UnitTests.queue_selection_logic]") {
|
||||
|
||||
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));
|
||||
vkb::detail::get_separate_queue_index(families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT));
|
||||
REQUIRE(vkb::detail::QUEUE_INDEX_MAX_VALUE ==
|
||||
vkb::detail::get_separate_queue_index(families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT));
|
||||
vkb::detail::get_separate_queue_index(families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_GRAPHICS_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 ==
|
||||
@ -22,14 +23,16 @@ TEST_CASE("Dedicated Compute Queue, Separate Transfer", "[UnitTests.queue_select
|
||||
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 } },
|
||||
VK_QUEUE_GRAPHICS_BIT | 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 } },
|
||||
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_separate_queue_index(
|
||||
families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT, 0));
|
||||
REQUIRE(2 == vkb::detail::get_separate_queue_index(
|
||||
families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 0));
|
||||
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));
|
||||
@ -37,14 +40,16 @@ TEST_CASE("Dedicated Compute Queue, Separate Transfer", "[UnitTests.queue_select
|
||||
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 } },
|
||||
VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | 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 } },
|
||||
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_separate_queue_index(
|
||||
families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT, 0));
|
||||
REQUIRE(1 == vkb::detail::get_separate_queue_index(
|
||||
families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 0));
|
||||
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));
|
||||
@ -55,14 +60,16 @@ TEST_CASE("Dedicated Transfer Queue, Separate Compute", "[UnitTests.queue_select
|
||||
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 } },
|
||||
VK_QUEUE_GRAPHICS_BIT | 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 } },
|
||||
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(2 == vkb::detail::get_separate_queue_index(
|
||||
families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT, 0));
|
||||
REQUIRE(1 == vkb::detail::get_separate_queue_index(
|
||||
families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 0));
|
||||
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));
|
||||
@ -70,16 +77,208 @@ TEST_CASE("Dedicated Transfer Queue, Separate Compute", "[UnitTests.queue_select
|
||||
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 } },
|
||||
VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | 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 } },
|
||||
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(1 == vkb::detail::get_separate_queue_index(
|
||||
families, VK_QUEUE_COMPUTE_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT, 0));
|
||||
REQUIRE(2 == vkb::detail::get_separate_queue_index(
|
||||
families, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT, 0));
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
vkb::Device setup_mock_for_queue_selection(std::vector<VkQueueFamilyProperties> const& queue_families) {
|
||||
VulkanMock& mock = get_vulkan_mock();
|
||||
VulkanMock::PhysicalDeviceDetails physical_device_details{};
|
||||
physical_device_details.properties.apiVersion = VK_API_VERSION_1_0;
|
||||
physical_device_details.queue_family_properties = queue_families;
|
||||
mock.add_physical_device(std::move(physical_device_details));
|
||||
|
||||
return vkb::DeviceBuilder{
|
||||
vkb::PhysicalDeviceSelector{ vkb::InstanceBuilder{}.set_headless().build().value() }.select().value()
|
||||
}
|
||||
.build()
|
||||
.value();
|
||||
}
|
||||
|
||||
TEST_CASE("Single Uber Queue", "[UnitTests.get_first_queue_and_index]") {
|
||||
vkb::Device d = setup_mock_for_queue_selection(
|
||||
{ VkQueueFamilyProperties{ VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 1 } });
|
||||
|
||||
vkb::QueueAndIndex q0 = d.get_first_queue_and_index(VK_QUEUE_GRAPHICS_BIT).value();
|
||||
CHECK((q0.index == 0 && q0.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q1 = d.get_first_queue_and_index(VK_QUEUE_COMPUTE_BIT).value();
|
||||
CHECK((q1.index == 0 && q1.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q2 = d.get_first_queue_and_index(VK_QUEUE_TRANSFER_BIT).value();
|
||||
CHECK((q2.index == 0 && q2.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q3 =
|
||||
d.get_first_queue_and_index(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT).value();
|
||||
CHECK((q3.index == 0 && q3.queue != nullptr));
|
||||
|
||||
CHECK(d.get_first_queue_and_index(VK_QUEUE_PROTECTED_BIT).matches_error(vkb::QueueError::queue_type_unavailable));
|
||||
CHECK(d.get_first_queue_and_index(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT | VK_QUEUE_PROTECTED_BIT)
|
||||
.matches_error(vkb::QueueError::queue_type_unavailable));
|
||||
}
|
||||
|
||||
TEST_CASE("Uber, Compute + Transfer", "[UnitTests.get_first_queue_and_index]") {
|
||||
vkb::Device d = setup_mock_for_queue_selection(
|
||||
{ VkQueueFamilyProperties{ VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 1 },
|
||||
VkQueueFamilyProperties{ VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 1 } });
|
||||
|
||||
vkb::QueueAndIndex q0 = d.get_first_queue_and_index(VK_QUEUE_GRAPHICS_BIT).value();
|
||||
CHECK((q0.index == 0 && q0.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q1 = d.get_first_queue_and_index(VK_QUEUE_COMPUTE_BIT).value();
|
||||
CHECK((q1.index == 0 && q1.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q2 = d.get_first_queue_and_index(VK_QUEUE_TRANSFER_BIT).value();
|
||||
CHECK((q2.index == 0 && q2.queue != nullptr));
|
||||
}
|
||||
|
||||
TEST_CASE("Single Uber Queue", "[UnitTests.get_preferred_queue_and_index]") {
|
||||
vkb::Device d = setup_mock_for_queue_selection(
|
||||
{ VkQueueFamilyProperties{ VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 1 } });
|
||||
|
||||
vkb::QueueAndIndex q0 = d.get_preferred_queue_and_index(VK_QUEUE_GRAPHICS_BIT).value();
|
||||
CHECK((q0.index == 0 && q0.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q1 = d.get_preferred_queue_and_index(VK_QUEUE_COMPUTE_BIT).value();
|
||||
CHECK((q1.index == 0 && q1.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q2 = d.get_preferred_queue_and_index(VK_QUEUE_TRANSFER_BIT).value();
|
||||
CHECK((q2.index == 0 && q2.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q3 =
|
||||
d.get_preferred_queue_and_index(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT).value();
|
||||
CHECK((q3.index == 0 && q3.queue != nullptr));
|
||||
|
||||
CHECK(d.get_preferred_queue_and_index(VK_QUEUE_PROTECTED_BIT).matches_error(vkb::QueueError::queue_type_unavailable));
|
||||
}
|
||||
|
||||
TEST_CASE("Uber, Compute + Transfer", "[UnitTests.get_preferred_queue_and_index]") {
|
||||
vkb::Device d = setup_mock_for_queue_selection(
|
||||
{ VkQueueFamilyProperties{ VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 1 },
|
||||
VkQueueFamilyProperties{ VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 1 } });
|
||||
|
||||
vkb::QueueAndIndex q0 = d.get_preferred_queue_and_index(VK_QUEUE_GRAPHICS_BIT).value();
|
||||
CHECK((q0.index == 0 && q0.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q1 = d.get_preferred_queue_and_index(VK_QUEUE_COMPUTE_BIT).value();
|
||||
CHECK((q1.index == 1 && q1.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q2 = d.get_preferred_queue_and_index(VK_QUEUE_TRANSFER_BIT).value();
|
||||
CHECK((q2.index == 1 && q2.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q3 =
|
||||
d.get_preferred_queue_and_index(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT).value();
|
||||
CHECK((q3.index == 0 && q3.queue != nullptr));
|
||||
|
||||
CHECK(d.get_preferred_queue_and_index(VK_QUEUE_PROTECTED_BIT).matches_error(vkb::QueueError::queue_type_unavailable));
|
||||
CHECK(d.get_preferred_queue_and_index(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT | VK_QUEUE_PROTECTED_BIT)
|
||||
.matches_error(vkb::QueueError::queue_type_unavailable));
|
||||
}
|
||||
|
||||
TEST_CASE("Uber, Compute + Transfer, Compute", "[UnitTests.get_preferred_queue_and_index]") {
|
||||
vkb::Device d = setup_mock_for_queue_selection(
|
||||
{ VkQueueFamilyProperties{ VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 1 },
|
||||
VkQueueFamilyProperties{ VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 1 },
|
||||
VkQueueFamilyProperties{ VK_QUEUE_COMPUTE_BIT, 1 } });
|
||||
|
||||
vkb::QueueAndIndex q0 = d.get_preferred_queue_and_index(VK_QUEUE_GRAPHICS_BIT).value();
|
||||
CHECK((q0.index == 0 && q0.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q1 = d.get_preferred_queue_and_index(VK_QUEUE_COMPUTE_BIT).value();
|
||||
CHECK((q1.index == 2 && q1.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q2 = d.get_preferred_queue_and_index(VK_QUEUE_TRANSFER_BIT).value();
|
||||
CHECK((q2.index == 1 && q2.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q3 =
|
||||
d.get_preferred_queue_and_index(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT).value();
|
||||
CHECK((q3.index == 0 && q3.queue != nullptr));
|
||||
|
||||
CHECK(d.get_preferred_queue_and_index(VK_QUEUE_PROTECTED_BIT).matches_error(vkb::QueueError::queue_type_unavailable));
|
||||
CHECK(d.get_preferred_queue_and_index(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT | VK_QUEUE_PROTECTED_BIT)
|
||||
.matches_error(vkb::QueueError::queue_type_unavailable));
|
||||
}
|
||||
|
||||
TEST_CASE("Uber, Compute, Compute + Transfer", "[UnitTests.get_preferred_queue_and_index]") {
|
||||
vkb::Device d = setup_mock_for_queue_selection(
|
||||
{ VkQueueFamilyProperties{ VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 1 },
|
||||
VkQueueFamilyProperties{ VK_QUEUE_COMPUTE_BIT, 1 },
|
||||
VkQueueFamilyProperties{ VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 1 } });
|
||||
|
||||
vkb::QueueAndIndex q0 = d.get_preferred_queue_and_index(VK_QUEUE_GRAPHICS_BIT).value();
|
||||
CHECK((q0.index == 0 && q0.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q1 = d.get_preferred_queue_and_index(VK_QUEUE_COMPUTE_BIT).value();
|
||||
CHECK((q1.index == 1 && q1.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q2 = d.get_preferred_queue_and_index(VK_QUEUE_TRANSFER_BIT).value();
|
||||
CHECK((q2.index == 2 && q2.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q3 =
|
||||
d.get_preferred_queue_and_index(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT).value();
|
||||
CHECK((q3.index == 0 && q3.queue != nullptr));
|
||||
|
||||
CHECK(d.get_preferred_queue_and_index(VK_QUEUE_PROTECTED_BIT).matches_error(vkb::QueueError::queue_type_unavailable));
|
||||
CHECK(d.get_preferred_queue_and_index(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT | VK_QUEUE_PROTECTED_BIT)
|
||||
.matches_error(vkb::QueueError::queue_type_unavailable));
|
||||
}
|
||||
|
||||
TEST_CASE("Uber, Transfer, Compute + Transfer", "[UnitTests.get_preferred_queue_and_index]") {
|
||||
vkb::Device d = setup_mock_for_queue_selection(
|
||||
{ VkQueueFamilyProperties{ VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 1 },
|
||||
VkQueueFamilyProperties{ VK_QUEUE_TRANSFER_BIT, 1 },
|
||||
VkQueueFamilyProperties{ VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 1 } });
|
||||
|
||||
vkb::QueueAndIndex q0 = d.get_preferred_queue_and_index(VK_QUEUE_GRAPHICS_BIT).value();
|
||||
CHECK((q0.index == 0 && q0.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q1 = d.get_preferred_queue_and_index(VK_QUEUE_COMPUTE_BIT).value();
|
||||
CHECK((q1.index == 2 && q1.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q2 = d.get_preferred_queue_and_index(VK_QUEUE_TRANSFER_BIT).value();
|
||||
CHECK((q2.index == 1 && q2.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q3 =
|
||||
d.get_preferred_queue_and_index(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT).value();
|
||||
CHECK((q3.index == 0 && q3.queue != nullptr));
|
||||
|
||||
CHECK(d.get_preferred_queue_and_index(VK_QUEUE_PROTECTED_BIT).matches_error(vkb::QueueError::queue_type_unavailable));
|
||||
CHECK(d.get_preferred_queue_and_index(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT | VK_QUEUE_PROTECTED_BIT)
|
||||
.matches_error(vkb::QueueError::queue_type_unavailable));
|
||||
}
|
||||
|
||||
TEST_CASE("Uber, Compute + Transfer, Transfer", "[UnitTests.get_preferred_queue_and_index]") {
|
||||
vkb::Device d = setup_mock_for_queue_selection(
|
||||
{ VkQueueFamilyProperties{ VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 1 },
|
||||
VkQueueFamilyProperties{ VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT, 1 },
|
||||
VkQueueFamilyProperties{ VK_QUEUE_TRANSFER_BIT, 1 } });
|
||||
|
||||
vkb::QueueAndIndex q0 = d.get_preferred_queue_and_index(VK_QUEUE_GRAPHICS_BIT).value();
|
||||
CHECK((q0.index == 0 && q0.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q1 = d.get_preferred_queue_and_index(VK_QUEUE_COMPUTE_BIT).value();
|
||||
CHECK((q1.index == 1 && q1.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q2 = d.get_preferred_queue_and_index(VK_QUEUE_TRANSFER_BIT).value();
|
||||
CHECK((q2.index == 2 && q2.queue != nullptr));
|
||||
|
||||
vkb::QueueAndIndex q3 =
|
||||
d.get_preferred_queue_and_index(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT).value();
|
||||
CHECK((q3.index == 0 && q3.queue != nullptr));
|
||||
|
||||
CHECK(d.get_preferred_queue_and_index(VK_QUEUE_PROTECTED_BIT).matches_error(vkb::QueueError::queue_type_unavailable));
|
||||
CHECK(d.get_preferred_queue_and_index(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT | VK_QUEUE_PROTECTED_BIT)
|
||||
.matches_error(vkb::QueueError::queue_type_unavailable));
|
||||
}
|
||||
|
@ -296,7 +296,9 @@ VKAPI_ATTR VkResult VKAPI_CALL shim_vkGetPhysicalDeviceSurfaceSupportKHR(
|
||||
}
|
||||
}
|
||||
}
|
||||
if (surface && pSupported) *pSupported = true;
|
||||
if (surface && pSupported) {
|
||||
*pSupported = true;
|
||||
}
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
VKAPI_ATTR VkResult VKAPI_CALL shim_vkGetPhysicalDeviceSurfaceFormatsKHR(
|
||||
|
Loading…
Reference in New Issue
Block a user