Learning Vulkan - Parminder Singh - E-Book

Learning Vulkan E-Book

Parminder Singh

0,0
46,79 €

-100%
Sammeln Sie Punkte in unserem Gutscheinprogramm und kaufen Sie E-Books und Hörbücher mit bis zu 100% Rabatt.

Mehr erfahren.
Beschreibung

Discover how to build impressive 3D graphics with the next-generation graphics API—Vulkan

About This Book

  • Get started with the Vulkan API and its programming techniques using the easy-to-follow examples to create stunning 3D graphics
  • Understand memory management in Vulkan and implement image and buffer resources
  • Get hands-on with the drawing process and synchronization, and render a 3D graphics scene with the Vulkan graphics pipeline

Who This Book Is For

This book is ideal for graphic programmers who want to get up and running with Vulkan. It's also great for programmers who have experience with OpenGL and other graphic APIs who want to take advantage of next generation APIs. A good knowledge of C/C++ is expected.

What You Will Learn

  • Learn fundamentals of Vulkan programing model to harness the power of modern GPU devices.
  • Implement device, command buffer and queues to get connected with the physical hardware.
  • Explore various validation layers and learn how to use it for debugging Vulkan application.
  • Get a grip on memory management to control host and device memory operations.
  • Understand and implement buffer and image resource types in Vulkan.
  • Define drawing operations in the Render pass and implement graphics pipeline.
  • Manage GLSL shader using SPIR-V and update the shader resources with descriptor sets and push constants.
  • Learn the drawing process, manage resources with synchronization objects and render 3D scene output on screen with Swapchain.
  • Bring realism to your rendered 3D scene with textures, and implement linear and optimal textures

In Detail

Vulkan, the next generation graphics and compute API, is the latest offering by Khronos. This API is the successor of OpenGL and unlike OpenGL, it offers great flexibility and high performance capabilities to control modern GPU devices. With this book, you'll get great insights into the workings of Vulkan and how you can make stunning graphics run with minimum hardware requirements.

We begin with a brief introduction to the Vulkan system and show you its distinct features with the successor to the OpenGL API. First, you will see how to establish a connection with hardware devices to query the available queues, memory types, and capabilities offered. Vulkan is verbose, so before diving deep into programing, you'll get to grips with debugging techniques so even first-timers can overcome error traps using Vulkan's layer and extension features.

You'll get a grip on command buffers and acquire the knowledge to record various operation commands into command buffer and submit it to a proper queue for GPU processing. We'll take a detailed look at memory management and demonstrate the use of buffer and image resources to create drawing textures and image views for the presentation engine and vertex buffers to store geometry information.

You'll get a brief overview of SPIR-V, the new way to manage shaders, and you'll define the drawing operations as a single unit of work in the Render pass with the help of attachments and subpasses. You'll also create frame buffers and build a solid graphics pipeline, as well as making use of the synchronizing mechanism to manage GPU and CPU hand-shaking.

By the end, you'll know everything you need to know to get your hands dirty with the coolest Graphics API on the block.

Style and approach

This book takes a practical approach to guide you through the Vulkan API, and you will get to build an application throughout the course of the book. Since you are expected to be familiar with C/C++, there is not much hand-holding throughout the course of the book.

Sie lesen das E-Book in den Legimi-Apps auf:

Android
iOS
von Legimi
zertifizierten E-Readern

Seitenzahl: 521

Veröffentlichungsjahr: 2016

Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Table of Contents

Learning Vulkan
Credits
About the Author
Acknowledgments
About the Reviewer
www.PacktPub.com
Why subscribe?
Preface
What this book covers  
What you need for this book 
Who this book is for 
Conventions
Reader feedback
Customer support
Downloading the example code 
Downloading the color images of this book 
Errata
Piracy
Questions
1. Getting Started with the NextGen 3D Graphics API
Vulkan and its evolution
Vulkan versus OpenGL
Important jargons before we get started
Learning the fundamentals of Vulkan
Vulkan's execution model
Vulkan's queues
The object model
Object lifetime and command syntax
Error checking and validation
Understanding the Vulkan application
Driver
Application
WSI
SPIR-V
LunarG SDK
Getting started with the Vulkan programming model
Hardware initialization
Window presentation surfaces
Resource setup
Pipeline setup
Descriptor sets and descriptor pools
Shaders with SPIR-V
Pipeline management
Recording commands
Queue submission
Summary
2. Your First Vulkan Pseudo Program
Installing Vulkan
The Hello World!!! pseudocode
Initialization - a handshake with the device
Swapchain initialization - querying the WSI extension
Command buffer initialization - allocating command buffers
Resource objects - managing images and buffers
Creating a presentation surface - creating a swapchain
Creating a depth image
Resource allocation - allocating and binding device memory
Supplying shaders - shader compilation into SPIR-V
Building layouts - descriptor and pipeline layouts
Creating a Render Pass - defining a pass attribute
Framebuffer - connect drawing images to the Render Pass
Populating geometry - storing a vertex into GPU memory
Pipeline state management - creating pipelines
Defining states
Creating a graphics pipeline
Executing the Render Pass - drawing Hello World!!!
Acquiring the drawing surface
Preparing the Render Pass control structure
Render Pass execution
Queue submission and synchronization - sending jobs
Displaying with presentation layer - rendering a triangle
Fitting it all together
Summary
3. Shaking Hands with the Device
Getting started with the LunarG SDK
Setting up our first project with CMake
How to build the CMake file
Introduction to extensions
Querying layers and extensions
Creating a Vulkan instance
Enabling layers and extensions
Testing the enabled layers and extensions
Understanding physical and logical devices
Physical devices
Enumerating physical devices
Querying physical device extensions
Getting the properties of a physical device
Interrogating memory properties from the physical device
Logical device
Creating a logical device
Waiting on the host
Losing the device
Understanding queues and queue families
Querying queue families
Storing the graphics queue handle
Creating a queue
Implementing devices and queues all together
Summary
4. Debugging in Vulkan
Peeking into Vulkan debugging
Understanding LunarG validation layers and their features
Implementing debugging in Vulkan
Summary
5. Command Buffer and Memory Management in Vulkan
Getting started with command buffers
Explicit synchronization
Types of command in command buffers
Command buffers and queues
The order of execution
Understanding command pool and buffer APIs
Creating a command pool
Resetting a command pool
Destroying a command pool
Command buffer allocation
Resetting command buffers
Freeing command buffers
Recording command buffers
Queue submission
Queue waiting
Implementing the wrapper class for a command buffer
Implementing the command buffer allocation process
Recording the command buffer allocation process
How to use command buffer recording functions
Submitting the command to the queue
Managing memory in Vulkan
Host memory
Device memory
Allocating device memory
Freeing up device memory
Accessing device memory from the host
Lazily allocated memory
Summary
6. Allocating Image Resources and Building a Swapchain with WSI
Getting started with image resources
Image creation overview
Understanding image resources
Creating images
Destroying the created images
Understanding image layouts
Creating an image view
Destroying the image view
Memory allocation and binding image resources
Gathering memory allocation requirements
Allocating physical memory on the device
Binding the allocated memory to an image object
Introducing swapchains
Understanding the swapchain implementation flow
The swapchain implementation's class block diagram
Renderer - a window management custom class
Creating the presentation window
Initializing the renderer
Creating the command pool
Building swapchain and depth images
Rendering the presentation window
VulkanSwapChain - the swapchain manager
Querying swapchain extensions
Creating the surface with WSI and associating it with the created window
The graphics queue with present support
Querying swapchain image formats
Creating the swapchain
Swapchain surface capabilities and the presentation mode
Managing presentation mode information
Retrieving the swapchain's color images
Creating color image views
Creating a depth image
Introduction to tiling
Creating a depth buffer image object
Getting the depth image's memory requirements
Determining the type of memory
Allocating and binding physical memory to a depth image
Image layout transition
Image layout transition with memory barriers
Creating the image view
Summarizing the application flow
Initialization
Rendering - displaying the output window
Summary
7. Buffer Resource, Render Pass, Framebuffer, and Shaders with SPIR-V
Understanding the Vulkan buffer resource type
Creating the buffer resource object
Destroying the buffer
Creating a buffer view
Destroying the buffer view
Creating geometry with a buffer resource
Preparing geometry data
Creating a vertex buffer
Buffer creation overview
Implementing a buffer resource - creating the vertex buffer for the geometry
Understanding the code flow
Understanding a Render Pass
Attachments
Subpasses
Vulkan APIs for the Render Pass
Implementing the Render Pass
Using the Render Pass and creating the framebuffer
Implementing the framebuffer
Clearing the background color
Setting the background color in the Render Pass instance
Rendering the colored background
Working with a shader in Vulkan
Introduction to SPIR-V
Compiling a GLSL shader into SPIR-V
Offline compilation with the glslangValidator executable
Online compilation with SPIR-V tool libraries
Implementing a shader
Summary
8. Pipelines and Pipeline State Management
Getting started with pipelines
VulkanPipeline - the pipeline implementation class
Caching pipeline objects with a PCO
Creating a pipeline cache object
Merging pipeline caches
Retrieving data from pipeline caches
Implementing the PCO
Creating a graphics pipeline
Implementing a graphics pipeline
Destroying pipelines
Understanding compute pipelines
Pipeline State Objects (PSO) in Vulkan
Dynamic states
Implementing dynamic states
Vertex input states
Implementing vertex input states
Input assembly states
Implementing input assembly states
Primitive restart
Primitive topologies
Primitives topologies with no adjacency
Primitives topologies with adjacency
Rasterization
Rasterization states
Implementing rasterization states
Blending
Color blend states
Implementing color blend states
Viewport management
The viewport state
Implementing the viewport state
Depth and stencil tests
Depth and stencil states
Implementing depth stencil states
Multisample states
Implementing multisample states
Implementing the pipeline
Summary
9. Drawing Objects
Overview of the drawing process in Vulkan
Walking through the header declaration
Preparing the drawing object
Recording Render Pass commands
Beginning Render Pass instance recording
Transitioning to the next subpass
Finishing Render Pass instance recording
Implementation
Binding pipeline object
Implementation
Specifying drawing object geometry information
Implementation
Defining a dynamic viewport
Implementation
Scissoring
Implementation
Draw command
vkCmdDraw command
Implementing drawing object preparation
Rendering the drawing object
Acquiring the swapchain image
Executing the drawing command buffer object
Displaying the output with the presentation engine
Implementing drawing object rendering
Rendering an indexed geometry
Understanding synchronization primitives in Vulkan
Fences
Semaphores
Events
Resizing the display window
Summary
10. Descriptors and Push Constant
Understanding the concept of descriptors
VulkanDescriptor - a user-defined descriptor class
Descriptor set layout
Implementing the descriptor set layout
Destroying the descriptor set layout
Understanding pipeline layouts
Creating a pipeline layout
Implementing the pipeline layout creation
Destroying the pipeline layout
Implementing the pipeline layout destruction process
Descriptor pool
Creating a descriptor pool
Implementing the creation of the descriptor pool
Destroying the descriptor pool
Implementing the destruction of the descriptor pool
Creating the descriptor set resources
Creating the descriptor sets
Allocating the descriptor set object from the descriptor pool
Destroying the allocated descriptor set objects
Associating the resources with the descriptor sets
Implementing descriptor set creation
How to implement Uniforms in Vulkan?
Prerequisites
Execution model overview
Initialization
Shader implementation
Creating descriptors
Rendering
Binding the descriptor set
Update
Updating the transformation
Push constant updates
Defining the push constant resource in the shader
Updating the pipeline layout with the push constant
Updating the resource data
Summary
11. Drawing Textures
Image resource - a quick recap
Prerequisites for texture drawing
Specifying the texture coordinates
Updating the shader program
Loading the image files
Using the GLI library
Local image data structure
Implementing the image resource with linear tiling
Loading the image file
Creating the image object
Memory allocation and binding
Populating the allocated device memory
Creating the command buffer object
Setting the image layout
Submitting the command buffer
Creating an image sampler
Filtering
Wrapping modes
Creating the image view
Implementing the image resource with optimal tiling
Loading the image file
Buffer object memory allocation and binding
Populating the allocated device memory
Creating the image object
Image object memory allocation and binding
Creating a command buffer object
Setting the image layout
Buffer to image copy
Setting the optimal image layout
Submitting the command buffer
Creating an image sampler
Creating the image view
Copying data content between images and buffers
Updating the descriptor set
Summary

Learning Vulkan

Learning Vulkan

Copyright © 2016 Packt Publishing

All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.

Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing, and its dealers and distributors will be held liable for any damages caused or alleged to be caused directly or indirectly by this book.

Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.

First published: December 2016

Production reference: 1121216

Published by Packt Publishing Ltd.

Livery Place

35 Livery Street

Birmingham 

B3 2PB, UK.

ISBN 978-1-78646-980-9

www.packtpub.com

Credits

Author

Parminder Singh

Copy Editor

Gladson Monteiro

Reviewer

Chris Forbes

Project Coordinator

Ritika Manoj

Commissioning Editor

Ashwin Nair

Proofreader

Safis Editing

Acquisition Editors

Smeet Thakkar

Aaron Lazar

Indexer

Rekha Nair

Content Development Editor

Sachin Karnani

Production Coordinator

Aparna Bhagat

Technical Editor

Murtaza Tinwala

Graphics

Abhinash Sahu

About the Author

Parminder Singh is a computation graphics engineer with Blackmagic Design, Singapore. He has been working and developing graphic applications in the fields of network simulations, geo-modeling, navigation, automotive, infotainment systems, image processing, and post-production for the past decade. His research interests include GPU programming for scalable graphics and compute applications, porting, and performance optimization techniques.

He is a Vulkan, Metal and OpenGL ES trainer and has also authored OpenGL ES 3.0 Cookbook, Packt. His hobbies include traveling, light cooking, and spending quality time with his baby girl.

Feel free to connect Parminder at https://www.linkedin.com/in/parmindersingh18 or you can reach him at http://openglescookbook.com. 

Acknowledgments

I dedicate this to my sweet baby girl, Raskeerat, who was born at the same time as we started this project. With a little baby onboard, it's challenging to write a book; I am grateful to my beloved wife Gurpreet Kaur and my family for helping me deliver this project to the community.

I extend my gratitude to Dr. Ulrich Kabatek and the entire graphics team of Continental Automotive; every member of the team had something to offer me to scale my vision of graphics. I am grateful to Blackmagic Design, who helped me extend my horizon to take GPU programming to a whole new level. I express my regards to Mohit Sindhwani and the whole of Quantum Invention's team. It was a great pleasure to work for them and also was a wonderful learning experience.

I am highly indebted to Chris Forbes from Google; his expertise in the graphics domain has raised the bar of this title. I am highly impressed with his reviews and the quality of work he delivered. Chris reviewed this title inch-by-inch and helped us not only to improve the contents but also our understanding of the concepts with his detailed explanation.

Last but not the least, I am thankful to the entire division of Packt, especially Sachin Karnani, who constantly remained involved during the production of this title. Murtaza Tinwala, who brilliantly exhibited his content management and technical skills during the final stages. I'm really happy to have them work with me on this book.

About the Reviewer

Chris Forbes works as a software developer for Google, working on Vulkan validation support and other ecosystem components. Previously he has been involved in implementing OpenGL 3 and 4 support in open source graphics drivers for Linux (www.mesa3d.org), as well as rebuilding classic strategy games to run on modern systems (www.openra.net).

www.PacktPub.com

For support files and downloads related to your book, please visit www.PacktPub.com.

Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.

At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters and receive exclusive discounts and offers on Packt books and eBooks.

https://www.packtpub.com/mapt

Get the most in-demand software skills with Mapt. Mapt gives you full access to all Packt books and video courses, as well as industry-leading tools to help you plan your personal development and advance your career.

Why subscribe?

Fully searchable across every book published by PacktCopy and paste, print, and bookmark contentOn demand and accessible via a web browser

Preface

This book is all about learning Vulkan from scratch. Vulkan is a next-generation cross-platform graphics and compute API. Despite being a successor of OpenGL API, it is a completely fresh approach to redesigning an API from the base that meets the competitive demand of consumers and works very close with the underlying GPU hardware. Vulkan is a software interface that is capable of controlling GPU hardware settings to harness the power of paralleling computing. The driver layer in Vulkan is really thin and puts more responsibilities on the shoulders of an application programmer to manage the application, its resources, memory management, synchronization, and more; this explicit nature of Vulkan makes it verbose. This book allows the beginner to learn such topics in baby steps, covering each chapter with an easy-to-follow companion example. The chapters are laid out in an incremental fashion; each chapter is built on top of the previous one, exposing the modular difference to our readers.

The Vulkan API certainly requires some level of computer graphics or computing knowledge prior to starting programming on it, as many of the concepts or terminologies are very general and directly used throughout this book.

This book is very practically oriented and prepared with an objective to allow its readers to learn Vulkan theory, concepts, and API specification, and see them in action through companion examples. There are plenty of references throughout the book that help readers to refer to the related concept, helping them to recap the fundamentals as they proceed through.

What this book covers  

Chapter 1, Getting Started with the NextGen 3D Graphics API, will begin with the fundamentals of the Vulkan API and provides an overview of all its distinct features compared to its predecessor OpenGL API. This chapter will cover the basics, concepts, application model, and technical jargon used in Vulkan programming that is extremely helpful for first-time learners. You will also walk through the Vulkan programming model and see an outline of each module and its role.

Chapter 2, Your First Vulkan Pseudo Program, will help you program a simple Hello World program using a pseudocode approach. This will help the beginners to get a flavor of Vulkan programming and learn the step-by-step process to build their first Vulkan application. You will also learn how to install necessary software and the SDK.

Chapter 3, Shaking Hands with the Device, will help you to set up the programming environment to start with building your very first Vulkan example. You will create the Vulkan instance and initialize the program. You will connect with the physical hardware device, explore different types of queues exposed by it, and query various available layers and extensions. This chapter will provide a detailed understanding of the device queue and queue family concept and its relation with logical devices.

Chapter 4, Debugging in Vulkan, will describe how to perform debugging in a Vulkan application. Vulkan allows debugging through validation layers. In this chapter, we will discuss the role of each validation layer and program a simple example to understand the debugging in action. In addition, we will also query the layer extensions to add extra features that may not be a part of the Vulkan specifications.

Chapter 5, Command Buffer and Memory Management in Vulkan, will thoroughly discuss and implement command buffers in Vulkan. You will understand the role of the command pool and will learn how to record command buffers in Vulkan. The second half of the chapter will cover memory management in Vulkan; you will dig through device memory, and learn methods to allocate or deallocate GPU memory and understand the mapping of CPU and GPU memory.

Chapter 6, Allocating Image Resources and Building a Swapchain with WSI, will shed light on image resources and discuss memory management concepts, such as image creation, allocation, binding and mapping. Using this, we will create a depth image for depth testing. This chapter will also introduce the WSI swapchain, which is used for presentation and renders the drawing output onscreen. We will acquire the swapchain color images and create image views that will be used for drawing primitives.

Chapter 7, Buffer Resource, Render Pass, Frame Buffer, and Shaders with SPIR-V, will discuss the buffer resource and its usage for implementing the vertex buffer containing a drawing object’s geometry information. This chapter will give a detailed introduction to using the Render Pass to define a single unit of work specifying drawing operations using various attachments and subpasses. We will use Render Pass and implement frame buffers in Vulkan and demonstrate simple example to clear the background. As the chapter closes, we will implement our first shader in Vulkan using SPIR-V; we learn about SDK tools that convert GLSL into SPIR-V intermediate representation.

Chapter 8, Pipelines and Pipeline State Management, will introduce Vulkan’s compute and graphics pipeline. This chapter will provide an overview of the graphic pipeline flow and cover the role of various modules from start to end. We will discuss pipeline state objects, pipeline cache objects, and pipeline layouts. This chapter will cover all the pipeline states thoroughly, also covering dynamics states, input assembly with drawing primitives, rasterization, blending, viewport, depth/stencil testing, and multisampling. We will use these states' objects and implement the graphics pipeline.

Chapter 9, Drawing Objects, will thoroughly cover the process of drawing objects in Vulkan. We will record and execute the drawing object command buffers. The recording associates the Render Pass, framebuffer, and pipeline together along with the viewport and geometry data. The command buffer execution involves the submission of the command buffer to the device queue and presenting the drawn swapchain image to the presentation engine. We will also discuss the Vulkan synchronization mechanisms and understand fences, semaphore, and memory barriers. In addition, we will also cover drawing APIs and demonstrate it through some easy-to-follow examples.

Chapter 10, Descriptors and Push Constant, will describe how to update shader resources from a Vulkan application using descriptors and push constants. In descriptors, we will discuss and create descriptor pools and descriptor set layout. You will learn how to use the pipeline layouts and use the descriptors to update the buffer resource residing on the device memory and render the updated geometry on screen. Unlike descriptors, push constant do not use the command buffer and provides an optimized path to update the resources. You will implement a small example to understand push constants in action.

Chapter 11, Drawing Textures, will bring realism to our rendered 3D drawing object by adding textures. You will learn how to create the image resource and apply samplers to it. You will also learn how to apply textures using linear and optimal tiling. In optimal tiling implementation, you will learn to transfer buffer and image memory through staging.

What you need for this book 

Please follow through the hardware and software requirements provided with this book. The reader must have a decent knowledge of C/C++ programming. Coding experience is required.

Who this book is for 

This book caters to those who have an interest in or desire to create cross-platform, high-performance graphics, and compute applications across desktop and embedded domains. The programmer may require some knowledge and experience of graphics and compute domain to better co-relate the Vulkan concepts.

Reader feedback

Feedback from our readers is always welcome. Let us know what you think about this book—what you liked or disliked. Reader feedback is important for us as it helps us develop titles that you will really get the most out of.

To send us general feedback, simply e-mail [email protected], and mention the book's title in the subject of your message.

If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, see our author guide at www.packtpub.com/authors.

Customer support

Now that you are the proud owner of a Packt book, we have a number of things to help you to get the most from your purchase.

Downloading the example code 

You can download the example code files for this book from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

You can download the code files by following these steps:

Log in or register to our website using your e-mail address and password.Hover the mouse pointer on the SUPPORT tab at the top.Click on Code Downloads & Errata.Enter the name of the book in the Search box.Select the book for which you're looking to download the code files.Choose from the drop-down menu where you purchased this book from.Click on Code Download.

You can also download the code files by clicking on the Code Files button on the book's webpage at the Packt Publishing website. This page can be accessed by entering the book's name in the Search box. Please note that you need to be logged in to your Packt account.

Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:

WinRAR / 7-Zip for WindowsZipeg / iZip / UnRarX for Mac7-Zip / PeaZip for Linux

The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Learning-Vulkan. We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!

Downloading the color images of this book 

We also provide you with a PDF file that has color images of the screenshots/diagrams used in this book. The color images will help you better understand the changes in the output. You can download this file from https://www.packtpub.com/sites/default/files/downloads/LearningVulkan_ColorImages.pdf.

Errata

Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you find a mistake in one of our books—maybe a mistake in the text or the code—we would be grateful if you could report this to us. By doing so, you can save other readers from frustration and help us improve subsequent versions of this book. If you find any errata, please report them by visiting http://www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details of your errata. Once your errata are verified, your submission will be accepted and the errata will be uploaded to our website or added to any list of existing errata under the Errata section of that title.

To view the previously submitted errata, go to https://www.packtpub.com/books/content/support and enter the name of the book in the search field. The required information will appear under the Errata section.

Piracy

Piracy of copyrighted material on the Internet is an ongoing problem across all media. At Packt, we take the protection of our copyright and licenses very seriously. If you come across any illegal copies of our works in any form on the Internet, please provide us with the location address or website name immediately so that we can pursue a remedy.

Please contact us at [email protected] with a link to the suspected pirated material.

We appreciate your help in protecting our authors and our ability to bring you valuable content.

Questions

If you have a problem with any aspect of this book, you can contact us at [email protected], and we will do our best to address the problem.

Chapter 1.  Getting Started with the NextGen 3D Graphics API

Vulkan is a revolutionary high-performance 3D graphics and computing API for modern GPU pipeline architectures to meet the demanding requirements of the community. This API provides a brand-new approach to overcome the complexities and gaps in existing traditional APIs. Vulkan is an explicit API that promises predictable behavior and allows you to have smooth rendering frame rates without causing lags or hitches. This chapter will present an overview of the Vulkan API and its distinct features compared to its predecessor: the OpenGL API. We will take a look at Vulkan's ecosystem and understand its graphics system.

So we will cover the following topics:

Vulkan and its evolutionVulkan versus OpenGLImportant jargons before we get startedLearning the fundamentals of VulkanUnderstanding the Vulkan applicationGetting started with the Vulkan programming model

Vulkan and its evolution

It's almost a quarter-century since the famous OpenGL API came into existence, and it is still evolving. Internally, it is a pure state machine that contains several switches working in a binary state (on/off). These states are used to build dependency mapping in the driver to manage resources and control them in an optimal way to yield maximum performance. This state machine automates resource management implicitly, but it is not intelligent enough to capture application logic, which is the driving force behind resource management. As a result, there might be unexpected situations, such as the implementation going off, resulting in recompilation of the shaders even when the application has not requested it. In addition, the OpenGL API might be subject to other factors, such as unpredictable behavior, multithreading scalability, rendering glitches, and so on. Later in this chapter, we will compare OpenGL with the Vulkan API to understand the difference between the two.

Launched by Khronos in 2016, the Vulkan API has a revolutionary architecture that takes full advantage of modern graphics processor units to produce high-performance graphics and compute applications. If you are not aware of Khronos, it's an association of members and organizations that focus on producing open standards for royalty-free APIs. For more information, refer to https://www.khronos.org.

The original concept of Vulkan was designed and developed by AMD, based on their proprietary Mantle API. This API showcased cutting-edge capabilities through several games, thereby proving its revolutionary approach and fulfilling all the competitive demands of the industry. AMD made their Mantle API open source and donated it to Khronos. The Khronos consortium, with the help of many other hardware and software vendors, made collaborative efforts to release Vulkan.

Vulkan is not the only next-gen 3D graphics API; there are competitors, such as Microsoft's Direct-X 12 and Apple's Metal. However, Direct-X is limited to its Windows variants and Metal to Mac (OS X and iOS). Vulkan stands out in that respect. Its cross-platform nature supports almost all the available OS platforms; this list includes Windows (XP, Vista, 7, 8, and 10), Linux, Tizen, SteamOS, and Android.

Vulkan versus OpenGL

Here are the features/improvements in Vulkan that give it an edge over OpenGL:

Reduced driver overhead and CPU usage: Vulkan is designed to be closer to the underlying graphics hardware. Therefore, it provides an application programmer with direct control over computing resources on the host in order to allow the GPU to render as fast as possible. This also allows the software to directly access the graphics processor, allowing better performance.Multithread scalability: Multithread scaling is really poor in OpenGL, and it is very difficult to take advantage of the threading features to better utilize the CPU. However, Vulkan is specially designed to allow end users to fully exploit its multithreading capability in a very transparent manner with no implicit global states. Jobs under different threads remain separated from the moment they are created and submitted for execution.An explicit API: OpenGL is an implicit API, where resource management is the driver's responsibility. The driver takes application hints and tracks resources, which is an unnecessary overhead.
Vulkan is an explicit API; here, the driver is not responsible for tracking resources and their relationships. This task is assigned to the application. This clean approach is more predictable; the driver is not doing gymnastics behind the scenes to manage resources (as in OpenGL). As a result, job processing is streamlined and straightforward, resulting in optimal performance and predictable behavior.
Precompiled intermediate shading language: Unlike OpenGL, which requires shaders to be provided as OpenGL Shading Language (GLSL) source code, the Standard Portable Intermediate Language (SPIR-V) is a standard intermediate language used by Vulkan for parallel computing and graphics.

Note

Compilers for source languages, such as GLSL, HLSL, or LLVM, must target the SPIR-V specification and provide utilities to provide SPIR-V input. Vulkan takes this ready-to-execute binary-intermediate input and uses it at the shader stage.

Driver and Application layer: In OpenGL, the application layer is thinner as compared to the driver layer, as the driver's automation takes into account resource management and state tracking. Vulkan is the opposite of this. It ensures the driver is closer to the hardware with less overhead. It's an application's responsibility to manage logic, resources, and states. The following diagram shows the thickness of the driver and application code base of both the APIs:
Memory controls: Vulkan is capable of exposing various memory types on the system and requires the application developer to choose the appropriate memory type for the intended use of each resource. In contrast, OpenGL drivers decide on the placement of resources according to internal heuristics, which vary between vendors, and it may produce suboptimal placement or unexpected hitches if the driver moves the resource later.Predictable: Vulkan is highly predictable as compared to OpenGL; it does not cause any lags or hitches while rendering. The jobs are submitted upfront as soon as they are given to the driver, whereas the OpenGL job submission process is not upfront and is at the mercy of the driver's scheduler.A single API: OpenGL has separate versions for a desktop-based API (OpenGL) and embedded API (OpenGL ES). Vulkan is clean and consists of only a single API for any number of platforms. Vulkan supports mobile platforms as a first-class citizen, which is not the case in OpenGL. Usually, the OpenGL implementation first appears on desktop-based versions and is later made available to the OpenGL ES APIs.Direct access to the GPU: Vulkan gives a lot of control to the application user by advertising its capabilities and hardware facilities. It exposes various types of available physical devices, memory types, command buffer queues, and extensions. This behavior ensures the software layer is much closer to the real hardware.Error checking and validation: When using OpenGL, well-behaved applications pay a price when it comes to checking for errors, which they will never trigger at the time of execution. In contrast, Vulkan offers these checks and validation as an add-on service, which can be enabled and disabled as and when required. These checks are optional and can be injected into a runtime by enabling error checking and other validation layers. As a result, it causes less CPU overhead by avoiding unnecessary checks. Ideally, these error and validation layers must be turned on during the development phase for the debugging process and turned off during the release process.Supports various GPU hardware: Vulkan supports mobile and desktop rasterizers as an integrated part of the implementation. It supports tile-based or deferred rasterizers for embedded platforms along with native tiling-based feed forward rasterizers.

Important jargons before we get started

Let's check out some of the important technical jargons used in Vulkan before we dive deep into the fundamental details. This book will cover more of these technical terms as we proceed further.

Physical device and device: A system may contain more than one physical Vulkan-capable hardware device. A physical device represents a unique device, whereas a device refers to a logical representation of the physical device in an application.Queues: A queue represents an interface between the execution engine and the application. A physical device always contains one or more queues (graphics, compute, DMA/transfer, and so on). A queue's responsibility is to gather the jobs (command buffers) and dispatch them to the physical device for processing.Memory type: Vulkan exposes various memory types. At a broader level, there are two types of memory: host and device. As we proceed through this chapter, we will cover these.Command: A command is an instruction to do some act. A command can be broadly divided into action, set state, or synchronization.
Action commands: These can be used to draw primitives, clear a surface, copy a buffer, query/timestamp operations, and begin/end subpass operations. These commands are capable of altering framebuffer attachments, reading or writing into the memory (buffer or image), and writing query pools.Set state commands: These help bind the pipelines, descriptor sets, and buffers; they also help set a dynamic state and render a pass/subpass state.Synchronization commands: Synchronization helps in satisfying the requirements of two or more action commands, which may compete for resources or have some memory dependencies. This includes setting or waiting for events, inserting the pipeline barrier, and rendering pass/subpass dependencies.
Command buffer: A command buffer is a collection of commands; it records the commands and submits them to the queues.

In the next section, we will take an overview of Vulkan to help us understand its working model and fundamental basics. We will also understand the command syntax rules get an idea of API commands by simply looking at them.

Learning the fundamentals of Vulkan

This section will cover the basics of Vulkan. Here we will discuss the following:

Vulkan's execution modelVulkan's queueThe object modelObject life-time and command syntaxError checking and validation

Vulkan's execution model

A Vulkan-capable system is able to query the system and expose the number of physical devices available on it. Each of the physical devices advertises one or more queues. These queues are categorized into different families, where each family has very specific functionalities. For example, these functionalities could include graphics, compute, data transfer, and sparse memory management. Each member of the queue family may contain one or more similar queues, making them compatible with each other. For example, a given implementation may support data transfer and graphics operations on the same queue.

Vulkan allows you to explicitly manage memory control via the application. It exposes the various types of heap available on the device, where each heap belongs to a different memory region. Vulkan's execution model is fairly simple and straightforward. Here, command buffers are submitted into queues, which are then consumed by the physical device in order to be processed.

A Vulkan application is responsible for controlling a set of Vulkan-capable devices by recording a number of commands into command buffers and submitting them into a queue. This queue is read by the driver that executes the jobs upfront in the submitted order. The command buffer construction is expensive; therefore, once constructed, it can be cached and submitted to the queue for execution as many times as required. Further, several command buffers can be built simultaneously in parallel using multiple threads in an application.

The following diagram shows a simplified pictorial representation of the execution model:

In this, the application records two command buffers containing several commands. These commands are then given to one or more queues depending upon the job nature. The queues submit these command buffer jobs to the device for processing. Finally, the device processes the results and either displays them on the output display or returns them to the application for further processing.

In Vulkan, the application is responsible for the following:

Producing all the necessary prerequisites for the successful execution of commands:
This may include preparing resources, precompiling a shader, and attaching the resources to the shader; specifying the render states; building a pipeline; and drawing calls
Memory managementSynchronization
Between the host and deviceBetween the different queues available on the device
Hazard management

Vulkan's queues

Queues are the medium in Vulkan through which command buffers are fed into the device. The command buffers record one or more commands and submit them to the required queue. The device may expose multiple queues; therefore, it is the application's responsibility to submit the command buffer to the correct queue.

The command buffers can be submitted to the following:

Single queue:
The order of the submission of the command buffer and execution or playback are maintainedCommand buffers are executed in a serial fashion
Multiple queues:
Allows the execution of the command buffer in parallel in two or more queues.The order of the submission and execution of command buffers are not guaranteed unless specified explicitly. It is the application's responsibility to synchronize this; in its absence, the execution may be completely out of order with respect.

Vulkan provides various synchronization primitives to allow you to have relative control of the work execution within a single queue or across queues. These are as follows:

Semaphore: This synchronizes work across multiple queues or a coarse-grained command buffer submission in a single queue.Events: Events controls fine-grained synchronization and are applied on a single queue, allowing us to synchronize work within a single command buffer or sequence of command buffers submitted to a single queue. The host can also participate in event-based synchronization.Fences: These allow synchronization between the host and device.Pipeline barriers: A pipeline barrier is an inserted instruction that ensures that commands prior to it must be executed before commands specified after it in the command buffer.

The object model

At the application level, all the entities, including devices, queues, command buffers, framebuffers, pipelines, and so on, are called Vulkan objects. Internally, at the API level, these Vulkan objects are recognized with handles. These handles can be of two types: dispatchable and non-dispatchable.

A dispatchable handle: This is a pointer that refers to an opaque-shaped entity inside. Opaque types do not allow you to have direct access to the structure's field. The fields can only be accessed using API routines. Each dispatchable handle has an associated dispatchable type that is used to pass as a parameter in the API command. Here's an example of this:

VkInstance

VkCommandBuffer

VkPhysicalDevice

VkDevice

VkQueue

Non-dispatchable handles: These are 64-bit integer-type handles that may contain the object information itself, rather than a pointer to the structure. Here's an example of this:

VkSemaphore

VkFence

VkQueryPool

VkBufferView

VkDeviceMemory

VkBuffer

VkImage

VkPipeline

VkShaderModule

VkSampler

VkRenderPass

VkDescriptorPool

VkDescriptorSetLayout

VkFramebuffer

VkPipelineCache

VkCommandPool

VkDescriptorSet

VkEvent

VkPipelineLayout

VkImageView

Object lifetime and command syntax

In Vulkan, objects are created and destroyed explicitly as per application logic, and it is the responsibility of an application to manage this.

Objects in Vulkan are created using Create and destroyed using the Destroy command:

Create syntax: Objects are created using the vkCreate* command; this accepts a Vk*CreateInfo structure as a parameter inputDestroy syntax: The objects produced using the Create command are destroyed using vkDestroy*

Objects created as part of the existing object pool or heap are created using the Allocate command and released from the pool or heap with Free.

Allocate syntax: Objects that are created as part of an object pool use vkAllocate* along with Vk*AllocateInfo as an argument input.Freeing syntax: Objects are released back to the pool or memory using the vkFree* command.

Any given implementation information can be easily accessed using the vkGet* command. The API implementation of the form vkCmd* is used to record commands in the command buffer.

Error checking and validation

Vulkan is specially designed to offer maximum performance by keeping error checks and validations optional. At runtime, the error checks and validations are really minimal, making the building of a command buffer and submission highly efficient. These optional capabilities can be enabled using Vulkan's layered architecture, which allows the dynamic injection of various layers (debugging and validation) into the running system.

Understanding the Vulkan application

This section will provide you with an overview of the various components that contribute to, and are helpful in building a Vulkan application.

The following block diagram shows the different component blocks and respective interconnections within the system:

Driver

A Vulkan-capable system comprises a minimum of one CPU and GPU. IHV's vendor supplies the driver of a given Vulkan specification implementation for their dedicated GPU architecture. The driver acts as an interface between the application and the device itself. It provides high-level facilities to the application so it can communicate with the device. For example, it advertises the number of devices available on the system, their queues and queue capabilities, available heaps and their related properties, and so on.

Application

An application refers to a user-written program that is intended to make use of Vulkan APIs to perform graphics or compute jobs. The application starts with the initialization of the hardware and software; it detects the driver and loads all the Vulkan APIs. The presentation layer is initialized with Vulkan's Window System Integration (WSI) APIs; WSI will be helpful in rendering the drawing image on the display surface. The application creates resources and binds them to the shader stage using descriptors. The descriptor set layout helps bind the created resources to the underlying pipeline object that is created (of the graphics or compute type). Finally, command buffers are recorded and submitted to the queue for processing.

WSI

Windows System Integration is a set of extensions from Khronos for the unification of the presentation layer across different platforms, such as Linux, Windows, and Android.

SPIR-V

SPIR-V provides a precompiled binary format for specifying shaders to Vulkan. Compilers are available for various shader source languages, including variants of GLSL and HLSL, which produce SPIR-V.

LunarG SDK

The Vulkan SDK from LunarG comprises a variety of tools and resources to aid Vulkan application development. These tools and resources include the Vulkan loader, validation layers, trace and replay tools, SPIR-V tools, Vulkan runtime installer, documentation, samples, and demos, see Chapter 3, Shaking Hands with the Device to see detailed description to get started with LunarG SDK. You can read more about it at http://lunarg.com/vulkan-sdk.

Getting started with the Vulkan programming model

Let's discuss the Vulkan programming model in detail. Here, the end user, considering he or she is a total beginner, will be able to understand the following concepts:

The Vulkan programming modelThe rendering execution model, which will be described using a pseudo step-by-step approachHow Vulkan works

The following diagram shows a top-down approach of the Vulkan application programming model; we will understand this process in detail and also delve into the sublevel components and their functionalities:

Hardware initialization

When a Vulkan application starts, its very first job is the initialization of the hardware. Here, the application activates the Vulkan drivers by communicating with the loader. The following diagram represents a block diagram of a Loader with its subcomponents:

Loader: A loader is a piece of code used in the application start-up to locate the Vulkan drivers in a system in a unified way across platforms. The following are the responsibilities of a loader:

Locating drivers: As its primary job, a loader knows where to search for drivers in the given system. It finds the correct driver and loads it.Platform-independent: Initializing Vulkan is consistent across all platforms. Unlike OpenGL, where creating a context requires working with a different window system API for each environment, EGL, GLX, and WGL. Platform differences in Vulkan are expressed as extensions.Injectable layers: A loader supports a layered architecture and provides the capability to inject various layers at runtime. The big improvement is that the driver need not do any of the work (or retain any of the states it would need to do the work) in determining whether the application's use of the API is valid. Therefore, it's advisable to turn on the selected injectable layers, as per application requirements, during the development stage and turn them off at the deployment stage. For example, injectable layers can offer the following:
Tracing the Vulkan API commandsCapturing rendered scenes and executing them laterError and validation for debugging purposes

The Vulkan application first performs a handshake with the loader library and initializes the Vulkan implementation driver. The loader library loads Vulkan APIs dynamically. The loader also offers a mechanism that allows the automatic loading of specific layers into all Vulkan applications; this is called an Implicit-Enabled layer.

Once the loader locates the drivers and successfully links with the APIs, the application is responsible for the following:

Creating a Vulkan instanceQuerying the physical device for the available queuesQuerying extensions and storing them as function pointers, such as WSI or special feature APIsEnabling an injectable layer for error checking, debugging, or the validation process

Window presentation surfaces

Once the Vulkan implementation driver is located by the loader, we are good to draw something using the Vulkan APIs. For this, we need an image to perform the drawing task and put it on the presentation window to display it:

Building a presentation image and creating windows are very platform-specific jobs. In OpenGL, windowing is intimately linked; the window system framebuffer is created along with context/device. The big difference from GL here is that context/device creation in Vulkan needn't involve the window system at all; it is managed through Window System Integration (WSI).

WSI contains a set of cross-platform windowing management extensions:

A unique cross-platform implementation for the majority of platforms, such as Windows, Linux, Android, and other OSesA consistent API standard to easily create surfaces and display them without getting into the details

WSI supports multiple windowing systems, such as Wayland, X, and Windows, and it also manages the ownership of images via a swapchain.

WSI provides a swapchain mechanism; this allows the use of multiple images in such a way that, while the window system is displaying one image, the application can prepare the next.

The following screenshot shows the double-buffering swap image process. It contains two images named First Image and Second Image. These images are swapped between Application and Display with the help of WSI:

WSI works as an interface between Display and Application. It makes sure that both images are acquired by Display and Application in a mutually exclusive way. Therefore, when an Application works on First Image, WSI hands over Second Image to Display in order to render its contents. Once the Application finishes the painting First image, it submits it to the WSI and in return acquires Second Image to work with and vice-versa.

At this point, perform the following tasks:

Create a native window (like the CreateWindow method in the Windows OS)Create a WSI surface attached to the windowCreate the swapchain to present to the surfaceRequest the drawing images from the created swapchain

Resource setup

Setting up resources means storing data into memory regions. It could be any type of data, for example, vertex attributes, such as position, color, or image type/name. Certainly, the data has resided somewhere in the memory for Vulkan to access it.

Unlike OpenGL, which manages the memory behind the scenes using hints, Vulkan provides full low-level access and control of the memory. Vulkan advertises the various types of available memory on the physical device, providing the application with a fine opportunity to manage these different types of memory explicitly.

Memory heaps can be categorized into two types, based upon their performance:

Host local: This is a slower type of memoryDevice local: This is a type of memory with high bandwidth; it is faster

Memory heaps can be further divided based upon their memory type configurations:

Device local: This type of memory is physically attached to the physical device:
Visible to the deviceNot visible to the host
Device local, host visible: This type of memory is also physically attached to the device:
Visible to the deviceVisible to the host
Host local, host visible: This refers to the local memory of the host, but it is slower than the local device:
Visible to the deviceVisible to the host

In Vulkan, resources are explicitly taken care of by the application with exclusive control of memory management. The following is the process of resource management:

Resource objects: For resource setup, an application is responsible for allocating memory for resources; these resources could be either images or buffer objects.Allocation and suballocations: When resource objects are created, only logical addresses are associated with them; there is no physical backing available. The application allocates physical memory and binds these logical addresses to it. As allocation is an expensive process, suballocation is an efficient way to manage the memory; it allocates a big chunk of physical memory at once and puts different resource objects into it. Suballocation is the responsibility of an application. The following diagram shows the suballocated object from the big allocated piece of physical memory:
Sparse memory: For very large image objects, Vulkan fully supports sparse memory with all its features. Sparse memory is a special feature that allows you to store large image resources; which are much larger than the actual memory capacity, in the memory. This technique breaks the image into tiles and loads only those tiles that fit the application logic.Staging buffers: The population of the object and image buffers is done using staging, where two different memory regions are used for the physical allocation. The ideal memory placement for a resource may not be visible to the host. In this case, the application must first populate the resource in a staging buffer that is host-visible and then transfer it to the ideal location.Asynchronous transfer: The data is transferred asynchronously using asynchronous commands with any of the graphics or DMA/transfer queues.

Tip

Physical memory allocation is expensive; therefore, a good practice is to allocate a large physical memory and then suballocate objects.

In contrast, OpenGL resource management does not offer granular control over the memory. There is no conception of host and device memory; the driver secretly does all of the allocation in the background. Also, these allocation and suballocation processes are not fully transparent and might change from one driver to another. This lack of consistency and hidden memory management cause unpredictable behavior. Vulkan, on the other hand, allocates the object right there in the chosen memory, making it highly predictable.

Therefore, during the resource setup stage, you need to perform the following tasks:

Create a resource object.Query the appropriate memory instance and create a memory object like buffer and images.Get the memory requirements for the allocation.Allocate space and store data in it.Bind the memory with the resource object that we created.

Pipeline setup

A pipeline is a set of events that occur in a fixed sequence defined by the application logic. These events consist of the following: supplying the shaders, binding them to the resource, and managing the state:

Descriptor sets and descriptor pools

A descriptor set is an interface between resources and shaders. It is a simple structure that binds the shader to the resource information, such as images or buffers. It associates or binds a resource memory that the shader is going to use. The following are the characteristics associated with descriptor sets:

Frequent change: By nature, a descriptor set changes frequently; generally, it contains attributes such as material, texture, and so on.Descriptor pool: Considering the nature of descriptor sets, they are allocated from a descriptor pool without introducing global synchronizationMultithread scalability: This allows multiple threads to update the descriptor set simultaneously

Tip

Updating or changing a descriptor set is one of the most performance-critical paths in rendering Vulkan. Therefore, the design of a descriptor set is an important aspect in achieving maximum performance. Vulkan supports logical partitioning of multiple descriptor sets at the scene (low frequency updates), model (medium frequency updates), and draw level (high frequency updates). This ensures that the high frequency update descriptor does not affect low frequency descriptor resources.

Shaders with SPIR-V

The only way to specify shaders or compute kernels in Vulkan is through SPIR-V. The following are some characteristics associated with it:

Multiple inputs: SPIR-V producing compilers exist for various source languages, including GLSL and HLSL. These can be used to convert a human-readable shader into a SPIR-V intermediate representation.Offline compilation: Shaders/kernels are compiled offline and injected upfront.glslangValidator: LunarG SDK provides the glslangValidator compiler, which can be used to create SPIR-V shaders from equivalent GLSL shaders.Multiple entry points: The shader object provides multiple entry points. This is very beneficial for reducing the shipment size (and the loaded size) of the SPIR-V shaders. Variants of a shader can be packaged into a single module.

Pipeline management

A physical device contains a range of hardware settings that determine how the submitted input data of a given geometry needs to be interpreted and drawn. These settings are collectively called pipeline states. These include the rasterizer state, blend state, and depth stencil state; they also include the primitive topology type (point/line/triangle) of the submitted geometry and the shaders that will be used for rendering. There are two types of states: dynamic and static. The pipeline states are used to create the pipeline object (graphics or compute), which is a performance-critical path. Therefore, we don't want to create them again and again; we want to create them once and reuse them.

Vulkan allows you to control states using pipeline objects in conjunction with Pipeline Cache Object (PCO) and the pipeline layout:

Pipeline objects: Pipeline creation is expensive. It includes shader recompilation, resource binding, Render Pass, framebuffer management, and other related operations. Pipeline objects could be numbered in hundreds and thousands; therefore, each different state combination is stored as a separate pipeline object.PCO: The creation of pipelines is expensive; therefore once created, a pipeline can be cached. When a new pipeline is requested, the driver can look for a closer match and create the new pipeline using the base pipeline.

Pipeline caches are opaque, and the details of their use by the driver are unspecified. The application is responsible for persisting the cache if it wishes to reuse it across runs and for providing a suitable cache at the time of pipeline creation if it wishes to reap potential benefits.

Pipeline layout: Pipeline layouts describe the descriptor sets that will be used with the pipeline, indicating what kind of resource is attached to each binding slot in the shader. Different pipeline objects can use the same pipeline layout.

In the pipeline management stage, this is what happens:

The application compiles the shader into SPIR-V form and specifies it in the pipeline shader state.The descriptor helps us connect these resources to the shader itself. The application allocates the descriptor set from the descriptor pool and connects the incoming or outgoing resources to the binding slots in the shader.The application creates pipeline objects, which contain the static and dynamic state configuration to control the hardware settings. The pipeline should be created from a pipeline cache pool for better performance.

Recording commands

Recording commands is the process of command buffer formation. Command buffers are allocated from the command pool memory. Command pools can also be used for multiple allocations. A command buffer is recorded by supplying commands within a given start and end scope defined by the application. The following diagram illustrates the recording of a drawing command buffer, and as you can see, it comprises many commands recorded in the top-down order responsible for object painting.

Note

Note that the commands in the command buffer may vary with the job requirement. This diagram is just an illustration that covers the most common steps performed while drawing primitives.

The major parts of drawing the are covered here:

Scope: The scope defines the start and end of the command buffer recording.Render Pass: This defines the execution process of a job that might affect the framebuffer cache. It may comprise attachments, subpasses, and dependencies between those subpasses. The attachment refers to images on which the drawing is performed. In a subpass, an attachment-like image can be subpassed for multisampling resolve. Render Pass also controls how the framebuffer will be treated at the beginning of the pass: it will either retain the last information on it or clear it with the given color. Similarly, at the end of the Render Pass, the results are going to be either discarded or stored.Pipeline: This contains the states' (static/dynamic) information represented by a pipeline object.Descriptor: This binds the resource information to the pipeline.Bind resource: This specifies the vertex buffer, image, or other geometry-related information.Viewport: This determines the portion of the drawing surface on which the rendering of the primitives will be performed.Scissor: This defines a rectangular space region beyond which nothing will be drawn.Drawing: The draw command specifies geometry buffer attributes, such as the start index, total count, and so on.

Tip

The creation of a command buffer is an expensive job; it considers the most performance-critical path. It can be reused numerous times if the same work needs to happen on many frames. It can be resubmitted without needing to re-record it. Also, multiple command buffers can be produced simultaneously using multiple threads. Vulkan is specially designed to exploit multithreaded scalability. Command pools ensure there is no lock contention if used in a multithreaded environment.

The following diagram shows a scalable command buffer creation model with a multicore and multithreading approach. This model provides true parallelism with multicore processors.