April 15, 2024

B&S_1

Linux for developers

Vulkan – Setting up the Environment

The instructions below are intended for Ubuntu users, but you can follow them by changing the apt commands to suit your package manager. You need a C++17 compatible compiler (GCC 7+ or Clang 5+). You will also need a make utility.

Vulkan Packages

The most important Linux components for Vulkan development are the Vulkan loader, validation layers and a few command line utilities to check your computer’s compatibility with Vulkan:

  • sudo apt install vulkan-tools: command line utilities, most notably vulkaninfo and vkcube. Run them to see if your PC supports Vulkan.
  • sudo apt install libvulkan-dev: installs the Vulkan loader. The loader looks for driver methods in rantime (at runtime) in the same way that the GLEW library does for OpenGL.
  • sudo apt install vulkan-validationlayers-dev: installs the standard validation layers that are needed when debugging programs with Vulkan. We’ll talk about them in the next chapter.

Also don’t forget to run vkcube, after which the following should appear on your screen:

GLFW

As already mentioned, Vulkan is a platform-independent API with no tools to create a window to display rendering results. To take advantage of Vulkan’s cross-platform nature and avoid the horrors of X11, we will use the GLFW library for window creation. There are other libraries available, such as SDL, but GLFW is better in that it abstracts not only window creation, but also some other platform-dependent functions.

We will install GLFW using the following command:

sudo apt install libglfw3-dev

GLM

Unlike DirectX 12, Vulkan doesn’t have a library for linear algebra operations, so you’ll have to download it separately. GLM is a nice library designed to be used with graphics APIs and is often used with OpenGL.

The GLM library is a header only library. It can be installed from the libglm-dev package:

sudo apt install libglm-dev

Shader compiler

Now that the setup is almost complete, it remains to install a program to compile shaders from GLSL to bytecode.

The two best known shader compilers are glslangValidator from Khronos Group and glslc from Google. In terms of usage glslc is similar to GCC and Clang, so we will opt for it. Download the binary and copy glslc to /usr/local/bin. Note that, depending on your permissions, you may need to use the sudo command. Run glslc to test, and you should get a warning:

glslc: error: no input files

We will look at glslc in detail in the chapter on shader modules.

Setting up a project for a makefile

After installing all the libraries we can set up the makefile project for Vulkan and write some code to make sure everything works.

Create a new folder in a convenient location and name it VulkanTest. Create a file named main.cpp and paste the code below into it. You don’t have to try to understand it now, it’s important to know if the program will build and run. In the next chapter, we will start with the basics.

#define GLFW_INCLUDE_VULKAN

#include . <GLFW/glfw3.h>

#define GLM_FORCE_RADIANS

#define GLM_FORCE_DEPTH_ZERO_TO_ONE

#include <glm/vec4.hpp>

#include <glm/mat4x4.hpp>

#include <lostream>

int main() {
glfwInit();

glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);

GLFWwindow* window = glfwCreateWindow(800, 600, “Vulkan window”, nullptr, nullptr);

uint32_t extensionCount = 0;

vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);

std::cout << extensionCount << ” extensions supported\n”;

glm::matrix; glm::vec4 vec; auto test = matrix * vec;

while(!glfwWindowShouldClose(window)) {

glfwPollEvents();

}

glfwDestroyWindow(window);

{ glfwTerminate();

return 0;

}

The next step is to write a makefile to compile and run. Create a new empty file named Makefile. It is assumed that you already have initial experience with makefiles. If not, this tutorial will get you up to speed quickly.

First, you need to define a few variables to simplify the rest of the file. Define a variable, CFLAGS, to hold the base flags of the compiler:

CFLAGS = -std=c++17 -O2

We use modern C++ (-std=c++17). We also set the O2 optimization level. You can remove the -O2 level for faster compilation of programs, but you still need to return it for the release build.

Similarly, define the linker base flags in the LDFLAGS variable:

LDFLAGS = -lglfw -lvulkan -ldl -lpthread -lX11 -lXxf86vm -lXrandr -lXi

The -lglfw flag connects the GLFW library, -lvulkan connects the Vulkan loader, and the other flags are low-level libraries and dependencies of GLFW itself.

Now you should have no problem defining a rule to compile VulkanTest. Don’t forget to use tabs instead of spaces for indents.

VulkanTest: main.cpp
g++ $(CFLAGS) -o VulkanTest main.cpp $(LDFLAGS)

Check that the build works. Save the makefile and run make from the folder with main.cpp and Makefile. This should result in an executable VulkanTest.

Now you need to set up two more rules, test and clean. Test launches the executable and clean deletes it.

PHONY: test clean

test: VulkanTest
./VulkanTest

clean:
rm -f VulkanTest

Running the make test command will make sure that the program runs successfully. When you close the empty window, the program should end with a successful return code (0). You should end up with a makefile similar to the one below:

CFLAGS = -std=c++17 -O2
LDFLAGS = -lglfw -lvulkan -ldl -lpthread -lX11 -lXxf86vm -lXrandr -lXi

VulkanTest: main.cpp
g++ $(CFLAGS) -o VulkanTest main.cpp $(LDFLAGS)

.PHONY: test clean

test: VulkanTest
./VulkanTest

clean:
rm -f VulkanTest

You can use this directory structure as a template for Vulkan projects. To do that, copy it, rename it, for example, to HelloTriangle and remove all code from main.cpp.

So, now you’re ready for the real adventure.