Skip to content

Building

This page covers building Daxa itself from source - useful if you want to contribute to Daxa, run its test suite, or try out unreleased code.

If you’re starting a new project that uses Daxa, you don’t need to follow this page at all: the Development Environment tutorial sets you up with the app template, which pulls in Daxa automatically via CMake’s FetchContent and builds it as part of your project.

Either way, first work through Installing Dependencies - you’ll need CMake, Ninja, a C++20 compiler, and the Vulkan SDK.

Daxa’s CMakePresets.json provides a configure preset per supported compiler/platform combination - cl-x86_64-windows-msvc, clang-x86_64-windows-msvc, gcc-x86_64-linux-gnu, and clang-x86_64-linux-gnu - each with matching -debug, -relwithdebinfo, and -release build presets.

Terminal window
cmake --preset=cl-x86_64-windows-msvc
cmake --build --preset=cl-x86_64-windows-msvc-debug
Terminal window
cmake --preset=gcc-x86_64-linux-gnu
cmake --build --preset=gcc-x86_64-linux-gnu-debug

Swap -debug for -relwithdebinfo or -release to build an optimized binary instead.

The presets above enable DAXA_ENABLE_TESTS, which also builds the sample/test executables under tests/.

Terminal window
./build/cl-x86_64-windows-msvc/tests/Debug/daxa_test_2_daxa_api_5_swapchain
Terminal window
./build/gcc-x86_64-linux-gnu/tests/Debug/daxa_test_2_daxa_api_5_swapchain

Most of Daxa’s daxa/utils/* headers are optional utilities that have to be explicitly enabled via CMake cache variables before Daxa is configured. If a util’s header is included without its option enabled, it fails fast with a clear compile-time error:

#error "[build error] You must build Daxa with the DAXA_ENABLE_UTILS_TASK_GRAPH CMake option enabled"

This is the same mechanism for every util: the CMake option (e.g. DAXA_ENABLE_UTILS_TASK_GRAPH) controls whether Daxa is built with that util’s source files and dependencies, and a matching DAXA_BUILT_WITH_UTILS_* compile definition is propagated to anything linking against daxa::daxa so the header can check it.

CMake optionEnablesSee also
DAXA_ENABLE_UTILS_TASK_GRAPHdaxa/utils/task_graph.hpp - automatic synchronization, transient resource aliasing. Implies DAXA_ENABLE_UTILS_MEM.TaskGraph
DAXA_ENABLE_UTILS_MEMdaxa/utils/mem.hpp - ring buffer / TransferMemoryPool staging allocators.TransferMemoryPool
DAXA_ENABLE_UTILS_PIPELINE_MANAGER_GLSLANGGLSL shader compilation in the Pipeline Manager, via glslang.Pipeline Manager
DAXA_ENABLE_UTILS_PIPELINE_MANAGER_SLANGSlang shader compilation in the Pipeline Manager, via a prebuilt Slang release.Pipeline Manager
DAXA_ENABLE_UTILS_PIPELINE_MANAGER_SPIRV_VALIDATIONValidates pipeline manager output with SPIRV-Tools (must be findable via find_package).-
DAXA_ENABLE_UTILS_IMGUIdaxa/utils/imgui.hpp - Dear ImGui + implot renderer integration.-
DAXA_ENABLE_UTILS_FSR2daxa/utils/fsr2.hpp - AMD FSR2 upscaling.-
DAXA_ENABLE_TESTSBuilds the sample/test executables under tests/ (also fetches GLFW).-
DAXA_ENABLE_TOOLSBuilds the daxa_tools_compile_* shader-precompilation helper executables.-
DAXA_ENABLE_STATIC_ANALYSISRuns cppcheck/clang-tidy over Daxa’s sources during the build, if installed.-
DAXA_USE_STATIC_CRT(MSVC only) Links Daxa against the static CRT (/MT//MTd) instead of the default dynamic CRT.-

All of these are plain CMake cache variables and default to OFF unless set. They must be set before Daxa’s CMakeLists.txt runs - i.e. before add_subdirectory(...) or FetchContent_MakeAvailable(daxa) - since they decide both what gets compiled into the daxa library and which extra dependencies cmake/deps.cmake fetches.

cmake/deps.cmake uses CMake’s FetchContent to fetch exactly the dependencies needed by whichever utils are enabled:

Each FetchContent_Declare/FetchContent_MakeAvailable call is guarded with if (... AND NOT TARGET ...), so if your own project already provides one of these targets (e.g. you fetch your own GLFW for windowing), Daxa reuses your target instead of fetching a second copy.

The app template used in the tutorial already sets this up for you, but the pattern is simple enough to add to any CMake project:

# cmake/deps.cmake (or directly in CMakeLists.txt)
include(FetchContent)
# Enable exactly the Daxa utils your project needs *before* fetching Daxa.
set(DAXA_ENABLE_UTILS_TASK_GRAPH ON)
set(DAXA_ENABLE_UTILS_PIPELINE_MANAGER_GLSLANG ON)
set(DAXA_ENABLE_UTILS_IMGUI ON)
FetchContent_Declare(
daxa
GIT_REPOSITORY https://github.com/Ipotrick/Daxa
GIT_TAG v3.0.2 # or a commit/branch
)
FetchContent_MakeAvailable(daxa)
# CMakeLists.txt
target_link_libraries(my_app PRIVATE daxa::daxa)
target_compile_features(my_app PRIVATE cxx_std_20)

A git submodule pointing at the Daxa repo plus add_subdirectory(deps/daxa) works just as well - either way, the important part is that the DAXA_ENABLE_UTILS_* variables from the table above are set before Daxa’s CMakeLists.txt is processed, since that’s what cmake/deps.cmake and the #if DAXA_BUILT_WITH_UTILS_* checks key off of.

A Larger Example: Submodule + cmake/deps.cmake

Section titled “A Larger Example: Submodule + cmake/deps.cmake”

Larger Daxa-based projects (e.g. Timberdoodle) tend to vendor Daxa as a git submodule under deps/daxa and collect every other dependency in a single cmake/deps.cmake, mirroring the same if (NOT TARGET ...) + FetchContent pattern Daxa’s own cmake/deps.cmake uses:

# cmake/deps.cmake
find_package(Vulkan REQUIRED)
include(FetchContent)
# Daxa is vendored as a git submodule under deps/daxa - clone it if missing.
if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/deps/daxa/CMakeLists.txt")
find_package(Git REQUIRED)
execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init
WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}"
COMMAND_ERROR_IS_FATAL ANY)
endif()
# Any further project dependencies go here, following the same
# `if (NOT TARGET ...)` + FetchContent_Declare/FetchContent_MakeAvailable
# guard pattern Daxa's own cmake/deps.cmake uses.

The top-level CMakeLists.txt includes deps.cmake, configures Daxa’s utils, then adds Daxa and your own executable:

# CMakeLists.txt
cmake_minimum_required(VERSION 3.21)
project(MyApp)
include(cmake/deps.cmake)
# Configure Daxa's optional utilities *before* pulling it in.
set(DAXA_ENABLE_UTILS_IMGUI true)
set(DAXA_ENABLE_UTILS_MEM true)
set(DAXA_ENABLE_UTILS_TASK_GRAPH true)
set(DAXA_ENABLE_UTILS_PIPELINE_MANAGER_GLSLANG true)
set(DAXA_ENABLE_UTILS_PIPELINE_MANAGER_SLANG true)
set(DAXA_ENABLE_TESTS false)
add_subdirectory(${PROJECT_SOURCE_DIR}/deps/daxa)
add_executable(${PROJECT_NAME}
"src/main.cpp"
)
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20)
target_link_libraries(${PROJECT_NAME} PRIVATE
daxa::daxa
)

A few things worth noting about this structure:

  • Setting DAXA_ENABLE_TESTS false skips building Daxa’s own tests/ executables (and the GLFW fetch they pull in) as part of your build.
  • EXCLUDE_FROM_ALL on a FetchContent_Declare keeps a dependency’s targets out of the default build/install set until something actually links against them - use it for anything you add to deps.cmake.
  • Because both your deps.cmake and Daxa’s cmake/deps.cmake guard every FetchContent_Declare with if (NOT TARGET ...), declaring a dependency Daxa also fetches (e.g. glfw, imgui::imgui) in your own deps.cmake before add_subdirectory(deps/daxa) makes Daxa reuse your version instead of fetching its own - useful for pinning a specific version or build configuration.

Note: The following steps are only meant for Daxa maintainers. They are not needed if you simply want to use Daxa in a project.

You must build this repo (Debug is fine; you get symbols)

Terminal window
git clone https://github.com/KhronosGroup/Vulkan-ValidationLayers

Open up Vulkan Configurator and add a new layer profile: Screenshot 2022-10-02 110620

Add a user-defined path: Screenshot 2022-10-02 110800

For me, it’s at C:/dev/projects/cpp/Vulkan-ValidationLayers/build/debug-windows/layers Screenshot 2022-10-02 110934

And then override the validation layer: Screenshot 2022-10-02 111055

And that should be it!