This project was mostly for us to set up our development environments. Since I'm trying out Vulkan, that turned
out to be over 1300 lines of code. ;(
Lucky, there's a fantastic guide by Alexander Overvoorde, which I used to setup Vulkan.
More information on that website can be found here
Vulkan Overview
Vulkan is a recent GPU API which is designed from the ground up to take advantage of more recent advances in
GPU hardware.
From Alex's tutorials, Vulkan "reduces driver overhead by allowing programmers to clearly specify their intent
using a more verbose API, and allows multiple threads to create and submit commands in parallel. It reduces
inconsistencies in shader compilation by switching to a standardized byte code format with a single compiler.
Lastly, it acknowledges the general purpose processing capabilities of modern graphics cards by unifying the
graphics and compute functionality in to a single API."
TLDR, it's better, but harder.
Vulkan Setup
What it takes to clear the background color:
Instance and physical device selection
A Vulkan starts by creating a vulkan instance. That instance can be used to choose from a set of physical
devices which can be used for operations. These physical devices have properties, like memory size, device
capabilities, etc, which can be used to select the desired physical device. In this example, I just choose the
first device capable of graphics processing.
Logical device and queue family creation
This is a more granular device selection stage. Although a physical device has many possible features, you
might only want to use a subset of those features. In this stage, we also specify what queue families we'll be
using for this device. These queues are what we'll use to submit work, and different families operate on
different jobs. We create a queue for rendering graphics to an image, and then we create a queue for "presenting"
those images to a surface.
Window surface and swap chain creation
To present images to the screen, more specifically a surface in a window, we need to create that window
surface, as well as a "swap chain". The window surface creation is operating system dependent, but we can use
GLFW to handle that code for us. A swap chain is essentially a set of "render targets" which are presented to a
surface in a particular way. We use that to implement double/triple buffering, V-Sync, etc.
Creation of image views and frame buffers
An image handle acquired from the swap chain must be wrapped before it can be rendered to, and we accomplish
that by creating an "Image view" and a "Frame buffer" for each one. An image view references a specific region in
the image that we'd like to render to, and a frame buffer references image views that should be used for color,
depth, and stencil targets.
Render pass creation
A render pass in Vulkan describes the types of images that will be used for rendering. This is different than a
frame buffer, which actually binds image views to these settings being described by the render pass. A key
component for this project is that the render pass stores what clear color will be used at the beginning of a
frame. So to officially change the background color, I need to recreate this render pass each frame. :S
Command pool and command buffer creation
Many operations in Vulkan need to be submitted to a queue before they're executed. These operations need to be
recorded into a command buffer before being submitted. To allocate command buffers, we create a command pool
that's associated with a particular queue family, and allocate the command buffers from that.
Resources Used
C++, Visual Studio 2017, CMake, Vulkan, GLFW, GLM
Hardware
Intel HD Graphics 620, Intel Core i7 - 8500U CPU @ 4.0GHz, 16GB of memory
Nvidia GTX 1070