From 41203627624b3c21c6cc3e134a73927a17b025f0 Mon Sep 17 00:00:00 2001 From: Charles Giessen Date: Thu, 18 Feb 2021 11:25:06 -0700 Subject: [PATCH] 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. --- src/VkBootstrap.cpp | 139 ++++++++++++++++++++++++-------------------- src/VkBootstrap.h | 9 ++- 2 files changed, 82 insertions(+), 66 deletions(-) diff --git a/src/VkBootstrap.cpp b/src/VkBootstrap.cpp index 19392a0..3efaa8a 100644 --- a/src/VkBootstrap.cpp +++ b/src/VkBootstrap.cpp @@ -911,79 +911,80 @@ bool supports_features (VkPhysicalDeviceFeatures supported, VkPhysicalDeviceFeat return true; } -// finds the first queue which supports graphics operations. returns -1 if none is found -int get_graphics_queue_index (std::vector const& families) { - for (size_t i = 0; i < families.size (); i++) { - if (families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) return static_cast (i); +// 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 const& families) { + for (uint32_t i = 0; i < static_cast (families.size ()); 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 -// transfer support returns -1 if none is found -int get_separate_compute_queue_index (std::vector const& families) { - int compute = -1; - for (size_t i = 0; i < families.size (); i++) { +// transfer support returns QUEUE_INDEX_MAX_VALUE if none is found +uint32_t get_separate_compute_queue_index (std::vector const& families) { + uint32_t compute = QUEUE_INDEX_MAX_VALUE; + for (uint32_t i = 0; i < static_cast (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) { - return static_cast (i); + return i; } else { - compute = static_cast (i); + compute = i; } } } return compute; } // 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 -int get_separate_transfer_queue_index (std::vector const& families) { - int transfer = -1; - for (size_t i = 0; i < families.size (); i++) { +// compute support returns QUEUE_INDEX_MAX_VALUE if none is found +uint32_t get_separate_transfer_queue_index (std::vector const& families) { + uint32_t transfer = QUEUE_INDEX_MAX_VALUE; + for (uint32_t i = 0; i < static_cast (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 static_cast (i); + return i; } else { - transfer = static_cast (i); + transfer = i; } } } return transfer; } -// finds the first queue which supports only compute (not graphics or transfer). returns -1 if none is found -int get_dedicated_compute_queue_index (std::vector const& families) { - for (size_t i = 0; i < families.size (); i++) { +// 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 const& families) { + for (uint32_t i = 0; i < static_cast (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 static_cast (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 -int get_dedicated_transfer_queue_index (std::vector const& families) { - for (size_t i = 0; i < families.size (); i++) { +// 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 const& families) { + for (uint32_t i = 0; i < static_cast (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) - return static_cast (i); + return i; } - return -1; + return QUEUE_INDEX_MAX_VALUE; } -// finds the first queue which supports presenting. returns -1 if none is found -int get_present_queue_index (VkPhysicalDevice const phys_device, +// 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, std::vector const& families) { - for (size_t i = 0; i < families.size (); i++) { + for (uint32_t i = 0; i < static_cast (families.size ()); i++) { VkBool32 presentSupport = false; if (surface != VK_NULL_HANDLE) { VkResult res = detail::vulkan_functions ().fp_vkGetPhysicalDeviceSurfaceSupportKHR ( - phys_device, static_cast (i), surface, &presentSupport); - if (res != VK_SUCCESS) return -1; // TODO: determine if this should fail another way + phys_device, i, surface, &presentSupport); + if (res != VK_SUCCESS) + return QUEUE_INDEX_MAX_VALUE; // TODO: determine if this should fail another way } - if (presentSupport == VK_TRUE) return static_cast (i); + if (presentSupport == VK_TRUE) return i; } - return -1; + return QUEUE_INDEX_MAX_VALUE; } } // 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.desired_version > pd.device_properties.apiVersion) suitable = Suitable::partial; - bool dedicated_compute = detail::get_dedicated_compute_queue_index (pd.queue_families) >= 0; - bool dedicated_transfer = detail::get_dedicated_transfer_queue_index (pd.queue_families) >= 0; - bool separate_compute = detail::get_separate_compute_queue_index (pd.queue_families) >= 0; - bool separate_transfer = detail::get_separate_transfer_queue_index (pd.queue_families) >= 0; + bool dedicated_compute = + detail::get_dedicated_compute_queue_index (pd.queue_families) != detail::QUEUE_INDEX_MAX_VALUE; + bool dedicated_transfer = + 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 = - 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_transfer_queue && !dedicated_transfer) return Suitable::no; @@ -1237,16 +1243,16 @@ PhysicalDeviceSelector& PhysicalDeviceSelector::select_first_device_unconditiona } 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 { - 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 { - 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 { - 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 PhysicalDevice::get_queue_families () const { return queue_families; @@ -1255,44 +1261,50 @@ std::vector PhysicalDevice::get_queue_families () const // ---- Queues ---- // detail::Result Device::get_queue_index (QueueType type) const { - int index = -1; + uint32_t index = detail::QUEUE_INDEX_MAX_VALUE; switch (type) { case QueueType::present: index = detail::get_present_queue_index (physical_device.physical_device, surface, queue_families); - if (index < 0) return detail::Result{ QueueError::present_unavailable }; + if (index == detail::QUEUE_INDEX_MAX_VALUE) + return detail::Result{ QueueError::present_unavailable }; break; case QueueType::graphics: index = detail::get_graphics_queue_index (queue_families); - if (index < 0) return detail::Result{ QueueError::graphics_unavailable }; + if (index == detail::QUEUE_INDEX_MAX_VALUE) + return detail::Result{ QueueError::graphics_unavailable }; break; case QueueType::compute: index = detail::get_separate_compute_queue_index (queue_families); - if (index < 0) return detail::Result{ QueueError::compute_unavailable }; + if (index == detail::QUEUE_INDEX_MAX_VALUE) + return detail::Result{ QueueError::compute_unavailable }; break; case QueueType::transfer: index = detail::get_separate_transfer_queue_index (queue_families); - if (index < 0) return detail::Result{ QueueError::transfer_unavailable }; + if (index == detail::QUEUE_INDEX_MAX_VALUE) + return detail::Result{ QueueError::transfer_unavailable }; break; default: return detail::Result{ QueueError::invalid_queue_family_index }; } - return static_cast (index); + return index; } detail::Result Device::get_dedicated_queue_index (QueueType type) const { - int index = -1; + uint32_t index = detail::QUEUE_INDEX_MAX_VALUE; switch (type) { case QueueType::compute: index = detail::get_dedicated_compute_queue_index (queue_families); - if (index < 0) return detail::Result{ QueueError::compute_unavailable }; + if (index == detail::QUEUE_INDEX_MAX_VALUE) + return detail::Result{ QueueError::compute_unavailable }; break; case QueueType::transfer: index = detail::get_dedicated_transfer_queue_index (queue_families); - if (index < 0) return detail::Result{ QueueError::transfer_unavailable }; + if (index == detail::QUEUE_INDEX_MAX_VALUE) + return detail::Result{ QueueError::transfer_unavailable }; break; default: return detail::Result{ QueueError::invalid_queue_family_index }; } - return static_cast (index); + return index; } namespace detail { 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, VkDevice const device, VkSurfaceKHR const surface, - int32_t graphics_queue_index, - int32_t present_queue_index) { + uint32_t graphics_queue_index, + uint32_t present_queue_index) { info.physical_device = physical_device; info.device = device; info.surface = surface; - info.graphics_queue_index = static_cast (graphics_queue_index); - info.present_queue_index = static_cast (present_queue_index); - if (graphics_queue_index < 0 || present_queue_index < 0) { + info.graphics_queue_index = graphics_queue_index; + info.present_queue_index = present_queue_index; + if (graphics_queue_index == detail::QUEUE_INDEX_MAX_VALUE || present_queue_index == detail::QUEUE_INDEX_MAX_VALUE) { auto queue_families = detail::get_vector_noerror ( detail::vulkan_functions ().fp_vkGetPhysicalDeviceQueueFamilyProperties, physical_device); - if (graphics_queue_index < 0) - info.graphics_queue_index = - static_cast (detail::get_graphics_queue_index (queue_families)); - if (present_queue_index < 0) - info.present_queue_index = static_cast ( - detail::get_present_queue_index (physical_device, surface, queue_families)); + if (graphics_queue_index == detail::QUEUE_INDEX_MAX_VALUE) + info.graphics_queue_index = detail::get_graphics_queue_index (queue_families); + if (present_queue_index == detail::QUEUE_INDEX_MAX_VALUE) + info.present_queue_index = + detail::get_present_queue_index (physical_device, surface, queue_families); } } detail::Result SwapchainBuilder::build () const { diff --git a/src/VkBootstrap.h b/src/VkBootstrap.h index 015e226..a1b70ee 100644 --- a/src/VkBootstrap.h +++ b/src/VkBootstrap.h @@ -470,6 +470,11 @@ class PhysicalDeviceSelector { // ---- Queue ---- // enum class QueueType { present, graphics, compute, transfer }; +namespace detail { + // Sentinel value, used in implementation only + const int QUEUE_INDEX_MAX_VALUE = 65536; +} + // ---- Device ---- // struct Device { @@ -561,8 +566,8 @@ class SwapchainBuilder { explicit SwapchainBuilder (VkPhysicalDevice const physical_device, VkDevice const device, VkSurfaceKHR const surface, - int32_t graphics_queue_index = -1, - int32_t present_queue_index = -1); + uint32_t graphics_queue_index = detail::QUEUE_INDEX_MAX_VALUE, + uint32_t present_queue_index = detail::QUEUE_INDEX_MAX_VALUE); detail::Result build () const;