Use uint32_t in Queues everywhere, add QUEUE_INDEX_MAX_VALUE as sentinel

This commit removes the many casts from int to uint and back, as -1 was used
as a sentinel value. Because thats confusing and leads to many casts
everywhere it was decided to add a sentinel value and compare everything
to that to determine if a queue index is valid or not.
This commit is contained in:
Charles Giessen 2021-02-18 11:25:06 -07:00 committed by Charles Giessen
parent daf244d180
commit 4120362762
2 changed files with 82 additions and 66 deletions

View File

@ -911,79 +911,80 @@ bool supports_features (VkPhysicalDeviceFeatures supported, VkPhysicalDeviceFeat
return true; return true;
} }
// finds the first queue which supports graphics operations. returns -1 if none is found // finds the first queue which supports graphics operations. returns QUEUE_INDEX_MAX_VALUE if none is found
int get_graphics_queue_index (std::vector<VkQueueFamilyProperties> const& families) { uint32_t get_graphics_queue_index (std::vector<VkQueueFamilyProperties> const& families) {
for (size_t i = 0; i < families.size (); i++) { for (uint32_t i = 0; i < static_cast<uint32_t> (families.size ()); i++) {
if (families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) return static_cast<int> (i); if (families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) return i;
} }
return -1; return QUEUE_INDEX_MAX_VALUE;
} }
// finds a compute queue which is separate from the graphics queue and tries to find one without // finds a compute queue which is separate from the graphics queue and tries to find one without
// transfer support returns -1 if none is found // transfer support returns QUEUE_INDEX_MAX_VALUE if none is found
int get_separate_compute_queue_index (std::vector<VkQueueFamilyProperties> const& families) { uint32_t get_separate_compute_queue_index (std::vector<VkQueueFamilyProperties> const& families) {
int compute = -1; uint32_t compute = QUEUE_INDEX_MAX_VALUE;
for (size_t i = 0; i < families.size (); i++) { for (uint32_t i = 0; i < static_cast<uint32_t> (families.size ()); i++) {
if ((families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) && if ((families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) &&
((families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0)) { ((families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0)) {
if ((families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) == 0) { if ((families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) == 0) {
return static_cast<int> (i); return i;
} else { } else {
compute = static_cast<int> (i); compute = i;
} }
} }
} }
return compute; return compute;
} }
// finds a transfer queue which is separate from the graphics queue and tries to find one without // finds a transfer queue which is separate from the graphics queue and tries to find one without
// compute support returns -1 if none is found // compute support returns QUEUE_INDEX_MAX_VALUE if none is found
int get_separate_transfer_queue_index (std::vector<VkQueueFamilyProperties> const& families) { uint32_t get_separate_transfer_queue_index (std::vector<VkQueueFamilyProperties> const& families) {
int transfer = -1; uint32_t transfer = QUEUE_INDEX_MAX_VALUE;
for (size_t i = 0; i < families.size (); i++) { for (uint32_t i = 0; i < static_cast<uint32_t> (families.size ()); i++) {
if ((families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) && if ((families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) &&
((families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0)) { ((families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0)) {
if ((families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) == 0) { if ((families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) == 0) {
return static_cast<int> (i); return i;
} else { } else {
transfer = static_cast<int> (i); transfer = i;
} }
} }
} }
return transfer; return transfer;
} }
// finds the first queue which supports only compute (not graphics or transfer). returns -1 if none is found // finds the first queue which supports only compute (not graphics or transfer). returns QUEUE_INDEX_MAX_VALUE if none is found
int get_dedicated_compute_queue_index (std::vector<VkQueueFamilyProperties> const& families) { uint32_t get_dedicated_compute_queue_index (std::vector<VkQueueFamilyProperties> const& families) {
for (size_t i = 0; i < families.size (); i++) { for (uint32_t i = 0; i < static_cast<uint32_t> (families.size ()); i++) {
if ((families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) && if ((families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) &&
(families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0 && (families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0 &&
(families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) == 0) (families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) == 0)
return static_cast<int> (i); return i;
} }
return -1; return QUEUE_INDEX_MAX_VALUE;
} }
// finds the first queue which supports only transfer (not graphics or compute). returns -1 if none is found // finds the first queue which supports only transfer (not graphics or compute). returns QUEUE_INDEX_MAX_VALUE if none is found
int get_dedicated_transfer_queue_index (std::vector<VkQueueFamilyProperties> const& families) { uint32_t get_dedicated_transfer_queue_index (std::vector<VkQueueFamilyProperties> const& families) {
for (size_t i = 0; i < families.size (); i++) { for (uint32_t i = 0; i < static_cast<uint32_t> (families.size ()); i++) {
if ((families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) && if ((families[i].queueFlags & VK_QUEUE_TRANSFER_BIT) &&
(families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0 && (families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0 &&
(families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) == 0) (families[i].queueFlags & VK_QUEUE_COMPUTE_BIT) == 0)
return static_cast<int> (i); return i;
} }
return -1; return QUEUE_INDEX_MAX_VALUE;
} }
// finds the first queue which supports presenting. returns -1 if none is found // finds the first queue which supports presenting. returns QUEUE_INDEX_MAX_VALUE if none is found
int get_present_queue_index (VkPhysicalDevice const phys_device, uint32_t get_present_queue_index (VkPhysicalDevice const phys_device,
VkSurfaceKHR const surface, VkSurfaceKHR const surface,
std::vector<VkQueueFamilyProperties> const& families) { std::vector<VkQueueFamilyProperties> const& families) {
for (size_t i = 0; i < families.size (); i++) { for (uint32_t i = 0; i < static_cast<uint32_t> (families.size ()); i++) {
VkBool32 presentSupport = false; VkBool32 presentSupport = false;
if (surface != VK_NULL_HANDLE) { if (surface != VK_NULL_HANDLE) {
VkResult res = detail::vulkan_functions ().fp_vkGetPhysicalDeviceSurfaceSupportKHR ( VkResult res = detail::vulkan_functions ().fp_vkGetPhysicalDeviceSurfaceSupportKHR (
phys_device, static_cast<uint32_t> (i), surface, &presentSupport); phys_device, i, surface, &presentSupport);
if (res != VK_SUCCESS) return -1; // TODO: determine if this should fail another way if (res != VK_SUCCESS)
return QUEUE_INDEX_MAX_VALUE; // TODO: determine if this should fail another way
} }
if (presentSupport == VK_TRUE) return static_cast<int> (i); if (presentSupport == VK_TRUE) return i;
} }
return -1; return QUEUE_INDEX_MAX_VALUE;
} }
} // namespace detail } // namespace detail
@ -1008,13 +1009,18 @@ PhysicalDeviceSelector::Suitable PhysicalDeviceSelector::is_device_suitable (Phy
if (criteria.required_version > pd.device_properties.apiVersion) return Suitable::no; if (criteria.required_version > pd.device_properties.apiVersion) return Suitable::no;
if (criteria.desired_version > pd.device_properties.apiVersion) suitable = Suitable::partial; if (criteria.desired_version > pd.device_properties.apiVersion) suitable = Suitable::partial;
bool dedicated_compute = detail::get_dedicated_compute_queue_index (pd.queue_families) >= 0; bool dedicated_compute =
bool dedicated_transfer = detail::get_dedicated_transfer_queue_index (pd.queue_families) >= 0; detail::get_dedicated_compute_queue_index (pd.queue_families) != detail::QUEUE_INDEX_MAX_VALUE;
bool separate_compute = detail::get_separate_compute_queue_index (pd.queue_families) >= 0; bool dedicated_transfer =
bool separate_transfer = detail::get_separate_transfer_queue_index (pd.queue_families) >= 0; detail::get_dedicated_transfer_queue_index (pd.queue_families) != detail::QUEUE_INDEX_MAX_VALUE;
bool separate_compute =
detail::get_separate_compute_queue_index (pd.queue_families) != detail::QUEUE_INDEX_MAX_VALUE;
bool separate_transfer =
detail::get_separate_transfer_queue_index (pd.queue_families) != detail::QUEUE_INDEX_MAX_VALUE;
bool present_queue = bool present_queue =
detail::get_present_queue_index (pd.phys_device, system_info.surface, pd.queue_families) >= 0; detail::get_present_queue_index (pd.phys_device, system_info.surface, pd.queue_families) !=
detail::QUEUE_INDEX_MAX_VALUE;
if (criteria.require_dedicated_compute_queue && !dedicated_compute) return Suitable::no; if (criteria.require_dedicated_compute_queue && !dedicated_compute) return Suitable::no;
if (criteria.require_dedicated_transfer_queue && !dedicated_transfer) return Suitable::no; if (criteria.require_dedicated_transfer_queue && !dedicated_transfer) return Suitable::no;
@ -1237,16 +1243,16 @@ PhysicalDeviceSelector& PhysicalDeviceSelector::select_first_device_unconditiona
} }
bool PhysicalDevice::has_dedicated_compute_queue () const { bool PhysicalDevice::has_dedicated_compute_queue () const {
return detail::get_dedicated_compute_queue_index (queue_families) >= 0; return detail::get_dedicated_compute_queue_index (queue_families) != detail::QUEUE_INDEX_MAX_VALUE;
} }
bool PhysicalDevice::has_separate_compute_queue () const { bool PhysicalDevice::has_separate_compute_queue () const {
return detail::get_separate_compute_queue_index (queue_families) >= 0; return detail::get_separate_compute_queue_index (queue_families) != detail::QUEUE_INDEX_MAX_VALUE;
} }
bool PhysicalDevice::has_dedicated_transfer_queue () const { bool PhysicalDevice::has_dedicated_transfer_queue () const {
return detail::get_dedicated_transfer_queue_index (queue_families) >= 0; return detail::get_dedicated_transfer_queue_index (queue_families) != detail::QUEUE_INDEX_MAX_VALUE;
} }
bool PhysicalDevice::has_separate_transfer_queue () const { bool PhysicalDevice::has_separate_transfer_queue () const {
return detail::get_separate_transfer_queue_index (queue_families) >= 0; return detail::get_separate_transfer_queue_index (queue_families) != detail::QUEUE_INDEX_MAX_VALUE;
} }
std::vector<VkQueueFamilyProperties> PhysicalDevice::get_queue_families () const { std::vector<VkQueueFamilyProperties> PhysicalDevice::get_queue_families () const {
return queue_families; return queue_families;
@ -1255,44 +1261,50 @@ std::vector<VkQueueFamilyProperties> PhysicalDevice::get_queue_families () const
// ---- Queues ---- // // ---- Queues ---- //
detail::Result<uint32_t> Device::get_queue_index (QueueType type) const { detail::Result<uint32_t> Device::get_queue_index (QueueType type) const {
int index = -1; uint32_t index = detail::QUEUE_INDEX_MAX_VALUE;
switch (type) { switch (type) {
case QueueType::present: case QueueType::present:
index = detail::get_present_queue_index (physical_device.physical_device, surface, queue_families); index = detail::get_present_queue_index (physical_device.physical_device, surface, queue_families);
if (index < 0) return detail::Result<uint32_t>{ QueueError::present_unavailable }; if (index == detail::QUEUE_INDEX_MAX_VALUE)
return detail::Result<uint32_t>{ QueueError::present_unavailable };
break; break;
case QueueType::graphics: case QueueType::graphics:
index = detail::get_graphics_queue_index (queue_families); index = detail::get_graphics_queue_index (queue_families);
if (index < 0) return detail::Result<uint32_t>{ QueueError::graphics_unavailable }; if (index == detail::QUEUE_INDEX_MAX_VALUE)
return detail::Result<uint32_t>{ QueueError::graphics_unavailable };
break; break;
case QueueType::compute: case QueueType::compute:
index = detail::get_separate_compute_queue_index (queue_families); index = detail::get_separate_compute_queue_index (queue_families);
if (index < 0) return detail::Result<uint32_t>{ QueueError::compute_unavailable }; if (index == detail::QUEUE_INDEX_MAX_VALUE)
return detail::Result<uint32_t>{ QueueError::compute_unavailable };
break; break;
case QueueType::transfer: case QueueType::transfer:
index = detail::get_separate_transfer_queue_index (queue_families); index = detail::get_separate_transfer_queue_index (queue_families);
if (index < 0) return detail::Result<uint32_t>{ QueueError::transfer_unavailable }; if (index == detail::QUEUE_INDEX_MAX_VALUE)
return detail::Result<uint32_t>{ QueueError::transfer_unavailable };
break; break;
default: default:
return detail::Result<uint32_t>{ QueueError::invalid_queue_family_index }; return detail::Result<uint32_t>{ QueueError::invalid_queue_family_index };
} }
return static_cast<uint32_t> (index); return index;
} }
detail::Result<uint32_t> Device::get_dedicated_queue_index (QueueType type) const { detail::Result<uint32_t> Device::get_dedicated_queue_index (QueueType type) const {
int index = -1; uint32_t index = detail::QUEUE_INDEX_MAX_VALUE;
switch (type) { switch (type) {
case QueueType::compute: case QueueType::compute:
index = detail::get_dedicated_compute_queue_index (queue_families); index = detail::get_dedicated_compute_queue_index (queue_families);
if (index < 0) return detail::Result<uint32_t>{ QueueError::compute_unavailable }; if (index == detail::QUEUE_INDEX_MAX_VALUE)
return detail::Result<uint32_t>{ QueueError::compute_unavailable };
break; break;
case QueueType::transfer: case QueueType::transfer:
index = detail::get_dedicated_transfer_queue_index (queue_families); index = detail::get_dedicated_transfer_queue_index (queue_families);
if (index < 0) return detail::Result<uint32_t>{ QueueError::transfer_unavailable }; if (index == detail::QUEUE_INDEX_MAX_VALUE)
return detail::Result<uint32_t>{ QueueError::transfer_unavailable };
break; break;
default: default:
return detail::Result<uint32_t>{ QueueError::invalid_queue_family_index }; return detail::Result<uint32_t>{ QueueError::invalid_queue_family_index };
} }
return static_cast<uint32_t> (index); return index;
} }
namespace detail { namespace detail {
VkQueue get_queue (VkDevice device, uint32_t family) { VkQueue get_queue (VkDevice device, uint32_t family) {
@ -1548,22 +1560,21 @@ SwapchainBuilder::SwapchainBuilder (Device const& device, VkSurfaceKHR const sur
SwapchainBuilder::SwapchainBuilder (VkPhysicalDevice const physical_device, SwapchainBuilder::SwapchainBuilder (VkPhysicalDevice const physical_device,
VkDevice const device, VkDevice const device,
VkSurfaceKHR const surface, VkSurfaceKHR const surface,
int32_t graphics_queue_index, uint32_t graphics_queue_index,
int32_t present_queue_index) { uint32_t present_queue_index) {
info.physical_device = physical_device; info.physical_device = physical_device;
info.device = device; info.device = device;
info.surface = surface; info.surface = surface;
info.graphics_queue_index = static_cast<uint32_t> (graphics_queue_index); info.graphics_queue_index = graphics_queue_index;
info.present_queue_index = static_cast<uint32_t> (present_queue_index); info.present_queue_index = present_queue_index;
if (graphics_queue_index < 0 || present_queue_index < 0) { if (graphics_queue_index == detail::QUEUE_INDEX_MAX_VALUE || present_queue_index == detail::QUEUE_INDEX_MAX_VALUE) {
auto queue_families = detail::get_vector_noerror<VkQueueFamilyProperties> ( auto queue_families = detail::get_vector_noerror<VkQueueFamilyProperties> (
detail::vulkan_functions ().fp_vkGetPhysicalDeviceQueueFamilyProperties, physical_device); detail::vulkan_functions ().fp_vkGetPhysicalDeviceQueueFamilyProperties, physical_device);
if (graphics_queue_index < 0) if (graphics_queue_index == detail::QUEUE_INDEX_MAX_VALUE)
info.graphics_queue_index = info.graphics_queue_index = detail::get_graphics_queue_index (queue_families);
static_cast<uint32_t> (detail::get_graphics_queue_index (queue_families)); if (present_queue_index == detail::QUEUE_INDEX_MAX_VALUE)
if (present_queue_index < 0) info.present_queue_index =
info.present_queue_index = static_cast<uint32_t> ( detail::get_present_queue_index (physical_device, surface, queue_families);
detail::get_present_queue_index (physical_device, surface, queue_families));
} }
} }
detail::Result<Swapchain> SwapchainBuilder::build () const { detail::Result<Swapchain> SwapchainBuilder::build () const {

View File

@ -470,6 +470,11 @@ class PhysicalDeviceSelector {
// ---- Queue ---- // // ---- Queue ---- //
enum class QueueType { present, graphics, compute, transfer }; enum class QueueType { present, graphics, compute, transfer };
namespace detail {
// Sentinel value, used in implementation only
const int QUEUE_INDEX_MAX_VALUE = 65536;
}
// ---- Device ---- // // ---- Device ---- //
struct Device { struct Device {
@ -561,8 +566,8 @@ class SwapchainBuilder {
explicit SwapchainBuilder (VkPhysicalDevice const physical_device, explicit SwapchainBuilder (VkPhysicalDevice const physical_device,
VkDevice const device, VkDevice const device,
VkSurfaceKHR const surface, VkSurfaceKHR const surface,
int32_t graphics_queue_index = -1, uint32_t graphics_queue_index = detail::QUEUE_INDEX_MAX_VALUE,
int32_t present_queue_index = -1); uint32_t present_queue_index = detail::QUEUE_INDEX_MAX_VALUE);
detail::Result<Swapchain> build () const; detail::Result<Swapchain> build () const;