Book Image

Vulkan Cookbook

By : Pawel Lapinski
Book Image

Vulkan Cookbook

By: Pawel Lapinski

Overview of this book

Vulkan is the next generation graphics API released by the Khronos group. It is expected to be the successor to OpenGL and OpenGL ES, which it shares some similarities with such as its cross-platform capabilities, programmed pipeline stages, or nomenclature. Vulkan is a low-level API that gives developers much more control over the hardware, but also adds new responsibilities such as explicit memory and resources management. With it, though, Vulkan is expected to be much faster. This book is your guide to understanding Vulkan through a series of recipes. We start off by teaching you how to create instances in Vulkan and choose the device on which operations will be performed. You will then explore more complex topics such as command buffers, resources and memory management, pipelines, GLSL shaders, render passes, and more. Gradually, the book moves on to teach you advanced rendering techniques, how to draw 3D scenes, and how to improve the performance of your applications. By the end of the book, you will be familiar with the latest advanced techniques implemented with the Vulkan API, which can be used on a wide range of platforms.
Table of Contents (13 chapters)

Getting a device queue

In Vulkan, in order to harness the processing power of a given device, we need to submit operations to the device's queues. Queues are not created explicitly by an application. They are requested during device creation: We check what families are available and how many queues each family contains. We can ask only for the subset of available queues from existing queue families, and we can't request more queues than the given family exposes.

Requested queues are created automatically along with the logical device. We don't manage them and create them explicitly. We can't destroy them either; they are also destroyed with a logical device. To use them and to be able to submit any work to the device's queues, we just need to acquire their handles.

How to do it...

  1. Take the handle of a created logical device object. Store it in a variable of type VkDevice named logical_device.
  1. Take the index of one of the queue families that was provided during the logical device creation in a queueFamilyIndex member of a structure of type VkDeviceQueueCreateInfo. Store it in a variable of type uint32_t named queue_family_index.
  2. Take the index of one of the queues requested for a given queue family: The index must be smaller than the total number of queues requested for a given family in a queueCount member of the VkDeviceQueueCreateInfo structure. Store the index in a variable of type uint32_t named queue_index.
  3. Prepare a variable of type VkQueue named queue.
  4. Call vkGetDeviceQueue( logical_device, queue_family_index, queue_index, &queue ). Provide a handle to the created logical device in the first argument; the second argument must be equal to the selected queue family index; the third argument must contain a number of one of the queues requested for a given family; then, in the final parameter, provide a pointer to the queue variable. A handle to the device queue will be stored in this variable.
  5. Repeat steps 2 to 5 for all queues requested from all queue families.

How it works...

Code that acquires the handle of a given queue is very simple:

vkGetDeviceQueue( logical_device, queue_family_index, queue_index, &queue );

We provide a handle to the created logical device, an index of the queue family, and an index of the queue requested for a given family. We must provide one of the family indices that were provided during logical device creation. This means that we can't acquire the handle of a queue from a family that wasn't specified during the logical device creation. Similarly, we can only provide an index of a queue that is smaller than the total number of queues requested from a given family.

Let's imagine the following situation: A given physical device supports five queues in the queue family No. 3. During logical device creation, we request only two queues from this queue family No. 3. So here, when we call the vkGetDeviceQueue() function, we must provide the value 3 as the queue family index. For the queue index, we can provide only values 0 and 1.

The handle of the requested queue is stored in a variable to which we provide a pointer in the final argument of the vkGetDeviceQueue() function call. We can ask for a handle of the same queue multiple times. This call doesn't create queues--they are created implicitly during logical device creation. Here, we just ask for the handle of an existing queue, so we can do it multiple times (although it may not make much sense to do so).

See also

The following recipes in this chapter:

  • Checking available queue families and their properties
  • Selecting the index of a queue family with the desired capabilities
  • Creating a logical device
  • Creating a logical device with geometry shaders, graphics, and compute queues