a-simple-triangle / Part 19 - Vulkan setup Windows

In this article we will configure our Windows platform to use Vulkan but keep our OpenGL implementation as a fallback at runtime. The Windows setup will be similar to earlier Windows articles where we included and linked against third party libraries such as SDL and GLM.

On a Windows computer a user will typically have graphics card drivers installed to provide the actual Vulkan implementation which we can’t link directly against. Instead we can use the .lib libraries which the Vulkan SDK provides us to give us a way to successfully link against the Vulkan APIs.


Windows Vulkan SDK setup

The first thing we need is the Windows Vulkan SDK itself. Unfortunately (or fortunately?) the Windows variant of the Vulkan SDK only comes as an executable installer rather than a compressed archive like a zip file. This means that we need to manually install the SDK ourselves and we won’t be able to write an automated script to do it.

Navigate to the following site https://vulkan.lunarg.com/sdk/home#windows:

Then scroll down the list within the Windows pane to find the 1.1.92.1 download link. We are choosing this version as it aligns closely with the Mac and Android Vulkan SDK we downloaded in the earlier Vulkan articles. Download the installer (don’t install the WinRT version).

After downloading the installer, run it but change the Destination Folder to your project root\third-party path and append \vulkan-windows to the end, so it sits alongside the other third party libraries we have been using already. You might need to create the vulkan-windows folder yourself. Your path should look similar to the image below - I’ve highlighted what your path should look like:

Note: The installer might try to append a 1.1.92.1 to the Destination Folder input field after you have finished browsing to a folder - for example it might look like root\third-party\vulkan-windows\1.1.92.1. Be sure to delete the 1.1.92.1 part so your path is just root\third-party\vulkan-windows.

Proceed with the installation then check that your folder structure now looks like this:

: root
  + third-party
    + vulkan-windows
      + Bin
      + Bin32
      ...
      + Include
      ...

Of particular interest is the vulkan-windows\Include folder. If you browse into it you will see it contains the Vulkan C/C++ header files we will need to be compile into our Windows target.


Including the Vulkan source

With the Vulkan SDK available to us in our third party folder we can now update our CMakeLists.txt file for the Windows target to include the appropriate Vulkan headers and source files in our build. Edit the windows\CMakeLists.txt file - I would recommend doing this directly in Visual Studio as it will automatically detect the changes and rebuild the CMake configuration cache - and add a new include_directories entry under the existing ones like so:

include_directories(${THIRD_PARTY_DIR}/vulkan-windows/Include)

Save CMakeLists.txt and let Visual Studio regenerate the CMake configuration. Run the application and you’ll encounter the first error:

...\main\src\application\vulkan\vulkan-context.cpp(10): error C2653: 'vk': is not a class or namespace name

Looks like our application doesn’t know what vk is. We’ve bumped into this error before on other platforms - it is because we haven’t added the Vulkan C++ header in the graphics-wrapper.hpp file for the Windows target. Open graphics-wrapper.hpp and update the conditional block for the Windows target:

#elif WIN32
#define GLEW_STATIC
#include <GL/glew.h>
#endif

Becomes:

#elif WIN32
#define GLEW_STATIC
#include <GL/glew.h>
#include <vulkan/vulkan.hpp>
#endif

Save graphics-wrapper.hpp and run the application again, this time you won’t get errors about unknown syntax but you will get errors about unresolved linking like this:

...\vulkan-common.cpp.obj : error LNK2019: unresolved external symbol vkEnumerateInstanceExtensionProperties ...
...\vulkan-context.cpp.obj : error LNK2019: unresolved external symbol vkCreateInstance ...
...\vulkan-context.cpp.obj : error LNK2019: unresolved external symbol vkDestroyInstance ...

This is because we currently have no linked implementation behind the Vulkan header files we are using. As I mentioned earlier we can’t link directly to the video card driver implementation of Vulkan which is installed on the user’s computer - but we can use the bundled .lib files that ship with the Vulkan SDK to form a mediated link.

I’ll only cover how to configure our project to link against the 64 bit Vulkan library - I’ll leave the 32 bit linking as an exercise for those who want or need to get their program running on 32 bit Windows.

The .lib file which we need to link against can be found in the following folder (note that there is also a sibling Lib32 folder if you want to do the 32 bit thing):

: root
  + third-party
    + vulkan-windows
      + Lib
        vulkan-1.lib

We need to register the vulkan-1.lib in our CMakeLists.txt file so it is included as a linked library for our build target. Edit CMakeLists.txt and add the following definition in the same group of other .lib definitions:

set(LIB_VULKAN ${THIRD_PARTY_DIR}/vulkan-windows/Lib/vulkan-1.lib)

This will declare a build property named LIB_VULKAN which we can then attach to our build target by adding ${LIB_VULKAN} to the list of libraries to link against, like so:

target_link_libraries(
    a-simple-triangle
    opengl32
    ${LIB_GLEW}
    ${LIB_SDL2}
    ${LIB_SDL2_MAIN}
    ${LIB_SDL2_IMAGE}
    ${LIB_VULKAN}
)

Save CMakeLists.txt file and run the application again. This time everything should compile and our application will boot itself into Vulkan. If you are on a Windows computer that for some reason has no Vulkan support you would instead see the OpenGL application bootstrap itself.


Summary

Setting up Vulkan for Windows was probably the easiest out of all the platform targets. It was a little unfortunate that we couldn’t automate the setup of the SDK into the third party folder but it still wasn’t too painful.

We now have all of our target platforms running Vulkan successfully or gracefully side stepping it (Emscripten) which means we can now focus on the actual Vulkan programming aspect of the implementation.

The code for this article can be found here.

Continue to Part 20: Vulkan create device.

End of part 19