a-simple-triangle / Part 18 - Vulkan setup Emscripten

In this article we will update our C++ code base and Emscripten platform target configuration to exclude Vulkan as we can only run WebGL code in the browser. At the time of writing these articles there was no way to run Vulkan in the browser - though it appears it is front of mind for the development of next generation standard web standards.


The problem …

To kick off let’s see what will happen when we try to compile our Emscripten app with our code base in its current state:

./build.sh

...

.../main/src/application/vulkan/vulkan-common.cpp:56:43: error: 
      use of undeclared identifier 'vk'
    for (auto const& availableExtension : vk::enumerateInstanceExtensionProperties())
                                          ^
1 error generated.

I guess we had to expect this to happen as we haven’t added any Vulkan source files to our Emscripten CMakeLists.txt, nor any header inclusions for Emscripten to our graphics-wrapper.hpp file.

The problem is that we don’t really have any Emscripten compatible Vulkan source files that would work. To navigate this issue we are going to make a few changes to prevent our Emscripten platform target from compiling any of our Vulkan related code.


Excluding our Vulkan source code

We can exclude all of our code under the main/src/application/vulkan folder so Emscripten doesn’t even compile it in the build. Edit emscripten/CMakeLists.txt file and change the file entries from this:

file(GLOB_RECURSE CPP_HEADERS ${MAIN_SOURCE_DIR}/*.hpp)
file(GLOB_RECURSE CPP_SOURCES ${MAIN_SOURCE_DIR}/*.cpp)

to this:

file(GLOB ALL_CPP_SOURCES
    ${MAIN_SOURCE_DIR}/*.cpp
    ${MAIN_SOURCE_DIR}/application/*.hpp
    ${MAIN_SOURCE_DIR}/application/*.cpp
    ${MAIN_SOURCE_DIR}/application/opengl/*.hpp
    ${MAIN_SOURCE_DIR}/application/opengl/*.cpp
    ${MAIN_SOURCE_DIR}/core/*.hpp
    ${MAIN_SOURCE_DIR}/core/*.cpp
    ${MAIN_SOURCE_DIR}/scene/*.hpp
    ${MAIN_SOURCE_DIR}/scene/*.cpp
)

The key difference is that we will no longer use GLOB_RECURSE so we can electively not include the source files under the application/vulkan folder. The trade off is that any more source folders we create that aren’t in this list - including nested folders - need to be appended to this file entry.

To use this set of source files in our executable we also need to change the add_executable block from this:

add_executable(
    a-simple-triangle
    ${CPP_HEADERS}
    ${CPP_SOURCES}
)

to this:

add_executable(
    a-simple-triangle
    ${ALL_CPP_SOURCES}
)

Save and close CMakeLists.txt.


More macros!

If we run our build script again the compilation will fail with undefined symbol errors. These errors are caused by the parts of our code base which imports Vulkan and our Vulkan application files. Since we just excluded them in our CMake configuration they won’t be part of the build hence the errors.

There are two small adjustments to make to correct this. Edit sdl-wrapper.hpp and change this:

#include <SDL_vulkan.h>

to this:

#ifndef __EMSCRIPTEN__
#include <SDL_vulkan.h>
#endif

This will simply guard against including any other downstream Vulkan related dependencies for SDL.

The other change is to update our main engine.cpp to avoid trying to bootstrap the Vulkan application at all if we are in the Emscripten platform target. Edit engine.cpp and change the following header includes from this:

#include "../application/vulkan/vulkan-application.hpp"
#include "../application/vulkan/vulkan-common.hpp"

to this:

#ifndef __EMSCRIPTEN__
#include "../application/vulkan/vulkan-application.hpp"
#include "../application/vulkan/vulkan-common.hpp"
#endif

Also update the std::unique_ptr<ast::Application> resolveApplication() function to only try and start Vulkan if we are not on Emscripten. Do this by wrapping the Vulkan code with the same #ifndef condition:

std::unique_ptr<ast::Application> resolveApplication()
{
  ...

#ifndef __EMSCRIPTEN__
  if (ast::vulkan::isVulkanAvailable())
  {
    ...
  }
#endif

  ...
}

Save your changes then re-run the Emscripten build script and our good old OpenGL application will bootstrap and run:


Summary

Perhaps one day if (when?) Vulkan becomes the mainstream new standard the web tech will have matured enough to be able to run it in the browser, but for now we have our OpenGL implementation to serve this purpose.

The code for this article can be found here.

Continue to Part 19: Vulkan setup Windows.

End of part 18