Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Vulkan Cookbook

You're reading from   Vulkan Cookbook Work through recipes to unlock the full potential of the next generation graphics API—Vulkan

Arrow left icon
Product type Paperback
Published in Apr 2017
Publisher Packt
ISBN-13 9781786468154
Length 700 pages
Edition 1st Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
Pawel Lapinski Pawel Lapinski
Author Profile Icon Pawel Lapinski
Pawel Lapinski
Arrow right icon
View More author details
Toc

Table of Contents (13) Chapters Close

Preface 1. Instance and Devices FREE CHAPTER 2. Image Presentation 3. Command Buffers and Synchronization 4. Resources and Memory 5. Descriptor Sets 6. Render Passes and Framebuffers 7. Shaders 8. Graphics and Compute Pipelines 9. Command Recording and Drawing 10. Helper Recipes 11. Lighting 12. Advanced Rendering Techniques

Checking available queue families and their properties

In Vulkan, when we want to perform operations on hardware, we submit them to queues. The operations within a single queue are processed one after another, in the same order they were submitted--that's why it's called a queue. However, operations submitted to different queues are processed independently (if we need, we can synchronize them):

Different queues may represent different parts of the hardware, and thus may support different kinds of operations. Not all operations may be performed on all queues.

Queues with the same capabilities are grouped into families. A device may expose any number of queue families, and each family may contain one or more queues. To check what operations can be performed on the given hardware, we need to query the properties of all queue families.

How to do it...

  1. Take one of the physical device handles returned by the vkEnumeratePhysicalDevices() function and store it in a variable of type VkPhysicalDevice called physical_device.
  2. Prepare a variable of type uint32_t named queue_families_count.
  3. Call vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, nullptr ). Provide the handle of a physical device in the first parameter; the second parameter should point to the queue_families_count variable, and the final parameter should be set to nullptr.
  4. After the successful call, the queue_families_count variable will contain the number of all queue families exposed by a given physical device.
  5. Prepare a storage for the list of queue families and their properties. A very convenient solution is to use a variable of type std::vector. Its elements must be of type VkQueueFamilyProperties. Call the variable queue_families.
  6. Resize the vector to be able to hold at least the queue_families_count elements.
  7. Call vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, &queue_families[0] ). The first and second argument should be the same as in the previous call; the last parameter should point to the first element of the queue_families vector.
  8. To be sure that everything went okay, check that the queue_families_count variable is greater than zero. If successful, the properties of all queue families will be stored in the queue_families vector.

How it works...

The implementation of the preceding recipe, similarly to other queries, can be divided into two stages: Firstly, we acquire information about the total number of queue families available on a given physical device. This is done by calling a vkGetPhysicalDeviceQueueFamilyProperties() function, with the last argument set to nullptr:

uint32_t queue_families_count = 0; 

vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, nullptr ); 
if( queue_families_count == 0 ) { 
  std::cout << "Could not get the number of queue families." << std::endl; 
  return false; 
}

Secondly, when we know how many queue families there are, we can prepare sufficient memory to be able to store the properties of all of them. In the presented example, we create a variable of type std::vector with VkQueueFamilyProperties elements and resize it to the value returned by the first query. After that, we perform a second vkGetPhysicalDeviceQueueFamilyProperties() function call, with the last parameter pointing to the first element of the created vector. In this vector, the parameters of all available queue families will be stored.

queue_families.resize( queue_families_count ); 
vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, &queue_families[0] ); 
if( queue_families_count == 0 ) { 
  std::cout << "Could not acquire properties of queue families." << std::endl; 
  return false; 
} 

return true;

The most important information we can get from properties is the types of operations that can be performed by the queues in a given family. Types of operations supported by queues are divided into:

  • Graphics: For creating graphics pipelines and drawing
  • Compute: For creating compute pipelines and dispatching compute shaders
  • Transfer: Used for very fast memory-copying operations
  • Sparse: Allows for additional memory management features

Queues from the given family may support more than one type of operation. There may also be a situation where different queue families support exactly the same types of operation.

Family properties also inform us about the number of queues that are available in the given family, about the timestamp support (for time measurements), and the granularity of image transfer operations (how small parts of image can be specified during copy/blit operations).

With the knowledge of the number of queue families, their properties, and the available number of queues in each family, we can prepare for logical device creation. All this information is needed, because we don't create queues by ourselves. We just request them during logical device creation, for which we must specify how many queues are needed and from which families. When a device is created, queues are created automatically along with it. We just need to acquire the handles of all requested queues.

See also

  • The following recipes in this chapter:
    • Selecting index of a queue family with desired capabilities
    • Creating a logical device
    • Getting a device queue
    • Creating a logical device with geometry shaders, graphics, and compute queues
  • The following recipe in Chapter 2, Image Presentation:
    • Selecting a queue family that supports presentation to a given surface
You have been reading a chapter from
Vulkan Cookbook
Published in: Apr 2017
Publisher: Packt
ISBN-13: 9781786468154
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime