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

Creating a Vulkan Instance

A Vulkan Instance is an object that gathers the state of an application. It encloses information such as an application name, name and version of an engine used to create an application, or enabled instance-level extensions and layers.

Through the Instance, we can also enumerate available physical devices and create logical devices on which typical operations such as image creation or drawing are performed. So, before we proceed with using the Vulkan API, we need to create a new Instance object.

How to do it...

  1. Prepare a variable of type std::vector<char const *> named desired_extensions. Store the names of all extensions you want to enable in the desired_extensions variable.
  2. Create a variable of type std::vector<VkExtensionProperties> named available_extensions. Acquire the list of all available extensions and store it in the available_extensions variable (refer to the Checking available Instance extensions recipe).
  1. Make sure that the name of each extension from the desired_extensions variable is also present in the available_extensions variable.
  2. Prepare a variable of type VkApplicationInfo named application_info. Assign the following values for members of the application_info variable:
    1. VK_STRUCTURE_TYPE_APPLICATION_INFO value for sType.
    2. nullptr value for pNext.
    3. Name of your application for pApplicationName.
    4. Version of your application for the applicationVersion structure member; do that by using VK_MAKE_VERSION macro and specifying major, minor, and patch values in it.
    5. Name of the engine used to create an application for pEngineName.
    6. Version of the engine used to create an application for engineVersion; do that by using VK_MAKE_VERSION macro.
    7. VK_MAKE_VERSION( 1, 0, 0 ) for apiVersion.
  3. Create a variable of type VkInstanceCreateInfo named instance_create_info. Assign the following values for members of the instance_create_info variable:
    1. VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO value for sType.
    2. nullptr value for pNext.
    3. 0 value for flags.
    4. Pointer to the application_info variable in pApplicationInfo.
    5. 0 value for enabledLayerCount.
    6. nullptr value for ppEnabledLayerNames.
    7. Number of elements of the desired_extensions vector for enabledExtensionCount.
    8. Pointer to the first element of the desired_extensions vector (or nullptr if is empty) for ppEnabledExtensionNames.
  4. Create a variable of type VkInstance named instance.
  5. Call the vkCreateInstance( &instance_create_info, nullptr, &instance ) function. Provide a pointer to the instance_create_info variable in the first parameter, a nullptr value in the second, and a pointer to the instance variable in the third parameter.
  6. Make sure the operation was successful by checking whether the value returned by the vkCreateInstance() function call is equal to VK_SUCCESS.

How it works...

To create an Instance, we need to prepare some information. First, we need to create an array of names of instance-level extensions that we would like to enable. Next, we need to check if they are supported on a given hardware. This is done by acquiring the list of all available instance-level extensions and checking if it contains the names of all the extensions we want to enable:

std::vector<VkExtensionProperties> available_extensions; 
if( !CheckAvailableInstanceExtensions( available_extensions ) ) { 
  return false; 
} 

for( auto & extension : desired_extensions ) { 
  if( !IsExtensionSupported( available_extensions, extension ) ) { 
    std::cout << "Extension named '" << extension << "' is not supported." << std::endl; 
    return false; 
  } 
}

Next, we need to create a variable in which we will provide information about our application, such as its name and version, the name and version of an engine used to create an application, and the version of a Vulkan API we want to use (right now only the first version is supported by the API):

VkApplicationInfo application_info = { 
  VK_STRUCTURE_TYPE_APPLICATION_INFO, 
  nullptr, 
  application_name, 
  VK_MAKE_VERSION( 1, 0, 0 ), 
  "Vulkan Cookbook", 
  VK_MAKE_VERSION( 1, 0, 0 ), 
  VK_MAKE_VERSION( 1, 0, 0 ) 
};

The pointer to the application_info variable in the preceding code sample is provided in a second variable with the actual parameters used to create an Instance. In it, apart from the previously mentioned pointer, we provide information about the number and names of extensions we want to enable, and also the number and names of layers we want to enable. Neither extensions nor layers are required to create a valid Instance object and we can skip them. However, there are very important extensions, without which it will be hard to create a fully functional application, so it is recommended to use them. Layers may be safely omitted. Following is the sample code preparing a variable used to define Instance parameters:

VkInstanceCreateInfo instance_create_info = { 
  VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, 
  nullptr, 
  0, 
  &application_info, 
  0, 
  nullptr, 
  static_cast<uint32_t>(desired_extensions.size()), 
  desired_extensions.size() > 0 ? &desired_extensions[0] : nullptr 
};

Finally, when we have prepared the preceding data, we can create an Instance object. This is done with the vkCreateInstance() function. Its first parameter must point to the variable of type VkInstanceCreateInfo. The third parameter must point to a variable of type VkInstance. The created Instance handle will be stored in it. The second parameter is very rarely used: It may point to a variable of type VkAllocationCallbacks, in which allocator callback functions are defined. These functions control the way host memory is allocated and are mainly used for debugging purposes. Most of the time, the second parameter defining allocation callbacks can be set to nullptr:

VkResult result = vkCreateInstance( &instance_create_info, nullptr, &instance ); 
if( (result != VK_SUCCESS) || 
    (instance == VK_NULL_HANDLE) ) { 
  std::cout << "Could not create Vulkan Instance." << std::endl; 
  return false; 
} 

return true;

See also

  • The following recipes in this chapter:
    • Checking available Instance extensions
    • Destroying a Vulkan Instance
  • The following recipe in Chapter 2, Image Presentation:
    • Creating a Vulkan Instance with WSI extensions enabled
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