Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ ebook/*.epub

convert.py

**/[B,b]uild/*

attachments/build/**
attachments/android/.gradle/**
attachments/android/.idea
Expand Down
18 changes: 18 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
cmake_minimum_required (VERSION 3.29)

project (VulkanTutorialRoot)
# This is to allow the CMakeLists.txt files in attachments/ to be accessed from root level
# Use command: cmake -S . -B build to configure from root level
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't you just be able to cmake -S attachments -B build from the root level and achieve the same thing?

Copy link
Author

@euclid-skyline euclid-skyline Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi gpx1000
Yes, you can do that too. The idea here is to be able to cmake from root and from attachments directory or any decent directory if it is having CMakeLists.txt. But if you select to cmake from root it will be going into massive configuration stage for all projects under the root. But in cmake build stage I think I will go with selecting the target more than cmake all targets for time saving. Anyway, my recommendation will not break anything except just the notes I provided below.
Here is commands from the root directory
cmake -S attachments -B attachments/build/msvc -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake"

OR from attachments directory cmake -S . -B build/msvc -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" -DVCPKG_MANIFEST_DIR="../"

Also if you want to use root CMakeLists.txt
cmake -S . -B build/msvc -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake"

# Then use command: cmake --build build to build from root level
# This will generate the build files in the build/ directory
# The build files will reference the source files in the attachments/ directory
# No need to change or delete any lines in attachments/ CMakeLists.txt files
# You can still build from attachments/ directory if needed
# Just navigate to attachments/ and run cmake and build commands as usual
add_subdirectory(attachments)

# Any other subdirectories can be added here
# Need to be carefull using CMAKE_SOURCE_DIR is points to the root level CMakeLists.txt
# Use CMAKE_CURRENT_SOURCE_DIR to point to the current directory instead
# For Simple Vulkan Engine project please uncomment the following line
# add_subdirectory(attachments/simple_engine)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm... I didn't test having both projects setup like this. One that builds the main tutorial and the other that builds the engine. I can't think why it wouldn't work. However, the "working directory" for when you "run" the engine or the tutorial might feel a bit odd.
I see below that the idea is to copy the assets to the directory local to the build folder. That does lead me to believe that it would make the tutorial chapters able to be run from the build directory. I don't think we sanitized the code in the tutorial to allow running from any directory; so I think the build process would be:
cmake -S . -B build
make
cd build
./run.exe

I think for the game engine, that pattern might not be pleasant as the map and assets are quite large. We do provide a script to download the project. Maybe a pattern to enable the game engine to work with this is to include the packaging phase of CMake. Thus, this constraint would have a side benefit of demonstrating how to create an install for a non-trivial Vulkan project. That might feel a bit beyond the scope for the game engine so will ask for feedback on if that's a wise idea.
We'll have to think that through for other Tutorials currently in the works.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Honestly, I did not test to cmake the engine from the root directory. But my setup work with main tutorial at the attachments directory smoothly. For time being I do not suggest doing cmake from root directory for engine because I do not know what is there and what it will be break. But the suggestion in comment is valid and could be implanted very easily any time if you be carefully following the suggestion I put in the comment. Meanwhile I'm trying to make live easy for tutorial part.
If I don't answer your comment correctly let me know in comment what is exactly your question.

91 changes: 71 additions & 20 deletions attachments/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ if(ENABLE_CPP20_MODULE)
endif()

target_sources(VulkanCppModule
PUBLIC
FILE_SET cxx_modules TYPE CXX_MODULES
BASE_DIRS
"${Vulkan_INCLUDE_DIR}"
FILES
"${Vulkan_INCLUDE_DIR}/vulkan/vulkan.cppm"
PUBLIC
FILE_SET cxx_modules TYPE CXX_MODULES
BASE_DIRS
"${Vulkan_INCLUDE_DIR}"
FILES
"${Vulkan_INCLUDE_DIR}/vulkan/vulkan.cppm"
)


Expand Down Expand Up @@ -85,7 +85,7 @@ find_program(SLANGC_EXECUTABLE slangc HINTS $ENV{VULKAN_SDK}/bin REQUIRED)

function (add_shaders_target TARGET)
cmake_parse_arguments ("SHADER" "" "CHAPTER_NAME" "SOURCES" ${ARGN})
set (SHADERS_DIR ${SHADER_CHAPTER_NAME}/shaders)
set (SHADERS_DIR ${CMAKE_BINARY_DIR}/${SHADER_CHAPTER_NAME}/shaders)
add_custom_command (
OUTPUT ${SHADERS_DIR}
COMMAND ${CMAKE_COMMAND} -E make_directory ${SHADERS_DIR}
Expand All @@ -95,32 +95,32 @@ function (add_shaders_target TARGET)
COMMAND glslang::validator
ARGS --target-env vulkan1.0 ${SHADER_SOURCES} --quiet
WORKING_DIRECTORY ${SHADERS_DIR}
DEPENDS ${SHADERS_DIR} ${SHADER_SOURCES}
COMMENT "Compiling Shaders"
DEPENDS ${SHADER_SOURCES}
COMMENT "Compiling Shaders for ${TARGET}"
VERBATIM
)
add_custom_target (${TARGET} DEPENDS ${SHADERS_DIR}/frag.spv ${SHADERS_DIR}/vert.spv)
endfunction ()

function (add_slang_shader_target TARGET)
cmake_parse_arguments ("SHADER" "" "CHAPTER_NAME" "SOURCES" ${ARGN})
set (SHADERS_DIR ${SHADER_CHAPTER_NAME}/shaders)
set (SHADERS_DIR ${CMAKE_BINARY_DIR}/${SHADER_CHAPTER_NAME}/shaders)
file(GLOB HAS_COMPUTE ${CHAPTER_SHADER}.comp)
set (ENTRY_POINTS -entry vertMain -entry fragMain)
if(HAS_COMPUTE)
list(APPEND ENTRY_POINTS -entry compMain)
endif()
add_custom_command (
OUTPUT ${SHADERS_DIR}
COMMAND ${CMAKE_COMMAND} -E make_directory ${SHADERS_DIR}
OUTPUT ${SHADERS_DIR}
COMMAND ${CMAKE_COMMAND} -E make_directory ${SHADERS_DIR}
)
add_custom_command (
OUTPUT ${SHADERS_DIR}/slang.spv
COMMAND ${SLANGC_EXECUTABLE} ${SHADER_SOURCES} -target spirv -profile spirv_1_4+spvRayQueryKHR -emit-spirv-directly -fvk-use-entrypoint-name ${ENTRY_POINTS} -o slang.spv
WORKING_DIRECTORY ${SHADERS_DIR}
DEPENDS ${SHADERS_DIR} ${SHADER_SOURCES}
COMMENT "Compiling Slang Shaders"
VERBATIM
OUTPUT ${SHADERS_DIR}/slang.spv
COMMAND ${SLANGC_EXECUTABLE} ${SHADER_SOURCES} -target spirv -profile spirv_1_4+spvRayQueryKHR -emit-spirv-directly -fvk-use-entrypoint-name ${ENTRY_POINTS} -o slang.spv
WORKING_DIRECTORY ${SHADERS_DIR}
DEPENDS ${SHADER_SOURCES}
COMMENT "Compiling Slang Shaders for ${TARGET}"
VERBATIM
)
add_custom_target (${TARGET} DEPENDS ${SHADERS_DIR}/slang.spv)
endfunction()
Expand Down Expand Up @@ -165,15 +165,66 @@ function (add_chapter CHAPTER_NAME)
target_link_libraries (${CHAPTER_NAME} ${CHAPTER_LIBS})
endif ()
if (DEFINED CHAPTER_MODELS)
list(TRANSFORM CHAPTER_MODELS PREPEND "${CMAKE_SOURCE_DIR}/assets/")
list(TRANSFORM CHAPTER_MODELS PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/assets/")
file (COPY ${CHAPTER_MODELS} DESTINATION ${CMAKE_BINARY_DIR}/${CHAPTER_NAME}/models)
endif ()
if (DEFINED CHAPTER_TEXTURES)
list(TRANSFORM CHAPTER_TEXTURES PREPEND "${CMAKE_SOURCE_DIR}/assets/")
list(TRANSFORM CHAPTER_TEXTURES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/assets/")
file (COPY ${CHAPTER_TEXTURES} DESTINATION ${CMAKE_BINARY_DIR}/${CHAPTER_NAME}/textures)
endif ()

# Post-build step to copy assets to executable directory
if(${CMAKE_GENERATOR} MATCHES "Visual Studio.*" OR
${CMAKE_GENERATOR} MATCHES "Ninja Multi-Config")

set(EXECUTABLE_DIR $<TARGET_FILE_DIR:${CHAPTER_NAME}>)
if(DEFINED CHAPTER_SHADER)
sync_directory(
"${CMAKE_BINARY_DIR}/${CHAPTER_NAME}/shaders"
"${EXECUTABLE_DIR}/shaders"
${CHAPTER_NAME}
"${CHAPTER_NAME}: Shaders"
)
endif()

if(DEFINED CHAPTER_MODELS)
sync_directory(
"${CMAKE_BINARY_DIR}/${CHAPTER_NAME}/models"
"${EXECUTABLE_DIR}/models"
${CHAPTER_NAME}
"${CHAPTER_NAME}: Models"
)
endif()

if(DEFINED CHAPTER_TEXTURES)
sync_directory(
"${CMAKE_BINARY_DIR}/${CHAPTER_NAME}/textures"
"${EXECUTABLE_DIR}/textures"
${CHAPTER_NAME}
"${CHAPTER_NAME}: Textures"
)
endif()
endif()
endfunction ()

function(sync_directory SRC_DIR DST_DIR TARGET_NAME LABEL)
file(GLOB_RECURSE FILES "${SRC_DIR}/*")

foreach(FILE IN LISTS FILES)
file(RELATIVE_PATH REL_PATH "${SRC_DIR}" "${FILE}")
set(DST_FILE "${DST_DIR}/${REL_PATH}")
get_filename_component(DST_DIR_PATH "${DST_FILE}" DIRECTORY)

add_custom_command(
TARGET ${TARGET_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory "${DST_DIR_PATH}"
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${FILE}" "${DST_FILE}"
COMMENT "${LABEL}: Syncing ${REL_PATH}"
)
endforeach()
endfunction()

add_chapter (00_base_code)

add_chapter (01_instance_creation)
Expand Down
Loading