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

Preparing for loading Vulkan API functions

When we want to use Vulkan API in our application, we need to acquire procedures specified in the Vulkan documentation. In order to do that, we can add a dependency to the Vulkan Loader library, statically link with it in our project, and use function prototypes defined in the vulkan.h header file. The second approach is to disable the function prototypes defined in the vulkan.h header file and load function pointers dynamically in our application.

The first approach is little bit easier, but it uses functions defined directly in the Vulkan Loader library. When we perform operations on a given device, Vulkan Loader needs to redirect function calls to the proper implementation based on the handle of the device we provide as an argument. This redirection takes some time, and thus impacts performance.

The second option requires more work on the application side, but allows us to skip the preceding redirection (jump) and save some performance. It is performed by loading functions directly from the device we want to use. This way, we can also choose only the subset of Vulkan functions if we don't need them all.

In this book, the second approach is presented, as this gives developers more control over the things that are going in their applications. To dynamically load functions from a Vulkan Loader library, it is convenient to wrap the names of all Vulkan API functions into a set of simple macros and divide declarations, definitions and function loading into multiple files.

How to do it...

  1. Define the VK_NO_PROTOTYPES preprocessor definition in the project: do this in the project properties (when using development environments such as Microsoft Visual Studio or Qt Creator), or by using the #define VK_NO_PROTOTYPES preprocessor directive just before the vulkan.h file is included in the source code of our application.
  2. Create a new file, named ListOfVulkanFunctions.inl.
  3. Type the following contents into the file:
      #ifndef EXPORTED_VULKAN_FUNCTION 
      #define EXPORTED_VULKAN_FUNCTION( function ) 
      #endif 

      #undef EXPORTED_VULKAN_FUNCTION 
      // 
      #ifndef GLOBAL_LEVEL_VULKAN_FUNCTION 
      #define GLOBAL_LEVEL_VULKAN_FUNCTION( function ) 
      #endif 

      #undef GLOBAL_LEVEL_VULKAN_FUNCTION 
      // 
      #ifndef INSTANCE_LEVEL_VULKAN_FUNCTION 
      #define INSTANCE_LEVEL_VULKAN_FUNCTION( function ) 
      #endif 

      #undef INSTANCE_LEVEL_VULKAN_FUNCTION 
      // 
      #ifndef INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION 
      #define INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION( function,       extension ) 
      #endif 

      #undef INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION 
      // 
      #ifndef DEVICE_LEVEL_VULKAN_FUNCTION 
      #define DEVICE_LEVEL_VULKAN_FUNCTION( function ) 
      #endif 

      #undef DEVICE_LEVEL_VULKAN_FUNCTION 
      // 
      #ifndef DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION 
      #define DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION( function,
      extension ) 
      #endif 
       
      #undef DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION
  1. Create a new header file, named VulkanFunctions.h.
  2. Insert the following contents into the file:
      #include "vulkan.h" 

      namespace VulkanCookbook { 

      #define EXPORTED_VULKAN_FUNCTION( name ) extern PFN_##name name; 
      #define GLOBAL_LEVEL_VULKAN_FUNCTION( name ) extern PFN_##name 
      name; 
      #define INSTANCE_LEVEL_VULKAN_FUNCTION( name ) extern PFN_##name 
      name; 
      #define INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION( name,
      extension ) extern PFN_##name name; 
      #define DEVICE_LEVEL_VULKAN_FUNCTION( name ) extern PFN_##name 
      name; 
      #define DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION( name, 
      extension ) extern PFN_##name name; 

      #include "ListOfVulkanFunctions.inl" 

      } // namespace VulkanCookbook
  1. Create a new file with a source code named VulkanFunctions.cpp.
  2. Insert the following contents into the file:
      #include "VulkanFunctions.h" 

      namespace VulkanCookbook { 

      #define EXPORTED_VULKAN_FUNCTION( name ) PFN_##name name; 
      #define GLOBAL_LEVEL_VULKAN_FUNCTION( name ) PFN_##name name; 
      #define INSTANCE_LEVEL_VULKAN_FUNCTION( name ) PFN_##name name; 
      #define INSTANCE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION( name, 
      extension ) PFN_##name name; 
      #define DEVICE_LEVEL_VULKAN_FUNCTION( name ) PFN_##name name; 
      #define DEVICE_LEVEL_VULKAN_FUNCTION_FROM_EXTENSION( name, 
      extension ) PFN_##name name; 

      #include "ListOfVulkanFunctions.inl" 

      } // namespace VulkanCookbook

How it works...

The preceding set of files may seem unnecessary, or even overwhelming, at first. VulkanFunctions.h and VulkanFunctions.cpp files are used to declare and define variables in which we will store pointers to Vulkan API functions. Declarations and definitions are done through a convenient macro definition and an inclusion of a ListOfVulkanFunctions.inl file. We will update this file and add the names of many Vulkan functions, from various levels. This way, we don't need to repeat the names of functions multiple times, in multiple places, which helps us avoid making mistakes and typos. We can just write the required names of Vulkan functions only once, in the ListOfVulkanFunctions.inl file, and include it when it's needed.

How do we know the types of variables for storing pointers to Vulkan API functions? It's quite simple. The type of each function's prototype is derived directly from the function's name. When a function is named <name>, its type is PFN_<name>. For example, a function that creates an image is called vkCreateImage(), so the type of this function is PFN_vkCreateImage. That's why macros defined in the presented set of files have just one parameter for function name, from which the type can be easily derived.

Last, but not least, remember that declarations and definitions of variables, in which we will store addresses of the Vulkan functions, should be placed inside a namespace, a class, or a structure. This is because, if they are made global, this could lead to problems on some operating systems. It's better to remember about namespaces and increase the portability of our code.

Place declarations and definitions of variables containing Vulkan API function pointers inside a structure, class, or namespace.

Now that we are prepared, we can start loading Vulkan functions.

See also

The following recipes in this chapter:

  • Loading function exported from a Vulkan Loader library
  • Loading global-level functions
  • Loading instance-level functions
  • Loading device-level functions
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