Files
window_renderer_test/CMakeLists.txt
T
2026-10-28 23:57:48 +00:00

402 lines
14 KiB
CMake

cmake_minimum_required(VERSION 3.24)
project(window_renderer_test VERSION 0.1.0 LANGUAGES C CXX)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type" FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug Release RelWithDebInfo MinSizeRel)
endif()
option(WR_FETCH_MISSING_DEPENDENCIES
"Download and build dependencies (SDL3, Vulkan, Slang) that are not installed" ON)
option(WR_COMPILE_SHADERS
"Compile the Slang shader during the build (requires slangc)" ON)
include(FetchContent)
# ---------------------------------------------------------------------------
# SDL3
# ---------------------------------------------------------------------------
find_package(SDL3 3.2 CONFIG QUIET)
if(NOT SDL3_FOUND)
if(NOT WR_FETCH_MISSING_DEPENDENCIES)
message(FATAL_ERROR
"SDL3 was not found. Install SDL3, or configure with "
"-DWR_FETCH_MISSING_DEPENDENCIES=ON.")
endif()
message(STATUS "SDL3 not found; fetching and building it from source")
# Build a static SDL3 so the result does not depend on a system SDL3
# runtime being present when the application is run.
set(SDL_SHARED OFF CACHE BOOL "Build the SDL3 shared library")
set(SDL_STATIC ON CACHE BOOL "Build the SDL3 static library")
set(SDL_TEST_LIBRARY OFF CACHE BOOL "Build the SDL3 test library")
set(SDL_TESTS OFF CACHE BOOL "Build the SDL3 tests")
set(SDL_EXAMPLES OFF CACHE BOOL "Build the SDL3 examples")
set(SDL_INSTALL OFF CACHE BOOL "Enable SDL3 install rules")
FetchContent_Declare(SDL3
GIT_REPOSITORY https://github.com/libsdl-org/SDL.git
GIT_TAG release-3.4.18
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(SDL3)
endif()
# ---------------------------------------------------------------------------
# Vulkan headers
# ---------------------------------------------------------------------------
find_package(Vulkan QUIET)
if(Vulkan_FOUND AND Vulkan_INCLUDE_DIRS)
set(WR_VULKAN_INCLUDE_DIRS ${Vulkan_INCLUDE_DIRS})
else()
if(NOT WR_FETCH_MISSING_DEPENDENCIES)
message(FATAL_ERROR
"Vulkan headers were not found. Install the Vulkan SDK, or configure "
"with -DWR_FETCH_MISSING_DEPENDENCIES=ON.")
endif()
message(STATUS "Vulkan headers not found; fetching Vulkan-Headers")
FetchContent_Declare(vulkan_headers
GIT_REPOSITORY https://github.com/KhronosGroup/Vulkan-Headers.git
GIT_TAG vulkan-sdk-1.4.350.0
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(vulkan_headers)
set(WR_VULKAN_INCLUDE_DIRS ${vulkan_headers_SOURCE_DIR}/include)
endif()
# ---------------------------------------------------------------------------
# volk (Vulkan meta-loader)
#
# volk is not guaranteed to be shipped with Vulkan headers. The project
# includes <volk/volk.h>, so a fetched volk checkout is placed in a generated
# include directory with the expected layout.
# ---------------------------------------------------------------------------
find_path(WR_VOLK_INCLUDE_DIR
NAMES volk/volk.h
HINTS ${WR_VULKAN_INCLUDE_DIRS}
)
find_file(WR_VOLK_SOURCE_FILE
NAMES volk.c
HINTS ${WR_VULKAN_INCLUDE_DIRS}
PATH_SUFFIXES volk
)
if(NOT WR_VOLK_INCLUDE_DIR OR NOT WR_VOLK_SOURCE_FILE)
if(NOT WR_FETCH_MISSING_DEPENDENCIES)
message(FATAL_ERROR
"volk was not found in the Vulkan headers. Install volk, or configure "
"with -DWR_FETCH_MISSING_DEPENDENCIES=ON.")
endif()
message(STATUS "volk not found; fetching it")
FetchContent_Declare(volk
GIT_REPOSITORY https://github.com/zeux/volk.git
GIT_TAG vulkan-sdk-1.4.350.0
GIT_SHALLOW TRUE
SOURCE_SUBDIR _disable_add_subdirectory
)
FetchContent_MakeAvailable(volk)
set(WR_VOLK_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated/include)
file(MAKE_DIRECTORY ${WR_VOLK_INCLUDE_DIR}/volk)
configure_file(
${volk_SOURCE_DIR}/volk.h
${WR_VOLK_INCLUDE_DIR}/volk/volk.h
COPYONLY
)
set(WR_VOLK_SOURCE_FILE ${volk_SOURCE_DIR}/volk.c)
endif()
# ---------------------------------------------------------------------------
# Vulkan Memory Allocator (VMA)
#
# VMA is not part of the Vulkan headers either. The project includes
# <vma/vk_mem_alloc.h>, so a fetched copy is placed in the same generated
# include directory.
# ---------------------------------------------------------------------------
find_path(WR_VMA_INCLUDE_DIR
NAMES vma/vk_mem_alloc.h
HINTS ${WR_VULKAN_INCLUDE_DIRS}
)
if(NOT WR_VMA_INCLUDE_DIR)
if(NOT WR_FETCH_MISSING_DEPENDENCIES)
message(FATAL_ERROR
"Vulkan Memory Allocator (VMA) was not found. Install VMA, or configure "
"with -DWR_FETCH_MISSING_DEPENDENCIES=ON.")
endif()
message(STATUS "Vulkan Memory Allocator not found; fetching it")
FetchContent_Declare(vma
GIT_REPOSITORY https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
GIT_TAG v3.5.0
GIT_SHALLOW TRUE
SOURCE_SUBDIR _disable_add_subdirectory
)
FetchContent_MakeAvailable(vma)
set(WR_VMA_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated/include)
file(MAKE_DIRECTORY ${WR_VMA_INCLUDE_DIR}/vma)
configure_file(
${vma_SOURCE_DIR}/include/vk_mem_alloc.h
${WR_VMA_INCLUDE_DIR}/vma/vk_mem_alloc.h
COPYONLY
)
endif()
# ---------------------------------------------------------------------------
# Application
# ---------------------------------------------------------------------------
add_executable(main
src/main.c
src/wapp/wapp.c
src/config/config_src.c
src/window/window_src.c
src/gpu/gpu_c_src.c
src/gpu/gpu_cc_src.cpp
${WR_VOLK_SOURCE_FILE}
)
target_include_directories(main PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
${WR_VULKAN_INCLUDE_DIRS}
${WR_VOLK_INCLUDE_DIR}
${WR_VMA_INCLUDE_DIR}
)
target_compile_definitions(main PRIVATE
WP_DEBUG_ASSERT
CGLM_DEFINE_PRINTS
USE_SDL_WINDOW_BACKEND
USE_VULKAN_RENDER_BACKEND
VK_NO_PROTOTYPES
)
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
target_compile_options(main PRIVATE
$<$<COMPILE_LANGUAGE:CXX>:-Wno-nullability-completeness>
)
endif()
target_link_libraries(main PRIVATE
SDL3::SDL3
${CMAKE_DL_LIBS}
)
if(UNIX AND NOT APPLE)
target_link_libraries(main PRIVATE m)
endif()
# ---------------------------------------------------------------------------
# Shaders
#
# The application loads "shaders/shader.spv" relative to its working directory,
# so the SPIR-V output is placed in <build-dir>/shaders.
# ---------------------------------------------------------------------------
if(WR_COMPILE_SHADERS)
find_program(SLANGC_EXECUTABLE NAMES slangc)
if(NOT SLANGC_EXECUTABLE AND WR_FETCH_MISSING_DEPENDENCIES)
# Download the prebuilt Slang release instead of requiring the user to
# install the compiler. Asset names and hashes come from the pinned
# GitHub release below.
set(WR_SLANG_VERSION "2026.20")
string(TOLOWER "${CMAKE_HOST_SYSTEM_PROCESSOR}" WR_SLANG_ARCH)
if(WR_SLANG_ARCH MATCHES "^(x86_64|amd64|x64)$")
set(WR_SLANG_ARCH "x86_64")
elseif(WR_SLANG_ARCH MATCHES "^(aarch64|arm64|arm64e)$")
set(WR_SLANG_ARCH "aarch64")
else()
set(WR_SLANG_ARCH "")
endif()
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
set(WR_SLANG_OS "linux")
elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
set(WR_SLANG_OS "macos")
elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
set(WR_SLANG_OS "windows")
else()
set(WR_SLANG_OS "")
endif()
if(WR_SLANG_OS AND WR_SLANG_ARCH)
set(WR_SLANG_PLATFORM "${WR_SLANG_OS}-${WR_SLANG_ARCH}")
else()
set(WR_SLANG_PLATFORM "")
endif()
if(WR_SLANG_PLATFORM STREQUAL "linux-x86_64")
set(WR_SLANG_ASSET
"slang-${WR_SLANG_VERSION}-linux-x86_64-glibc-2.28.tar.gz")
set(WR_SLANG_SHA256
"84ebd777968caceea26b21bfd014341078be6047be6c5a963a69f984f896cebd")
elseif(WR_SLANG_PLATFORM STREQUAL "linux-aarch64")
set(WR_SLANG_ASSET
"slang-${WR_SLANG_VERSION}-linux-aarch64-glibc-2.28.tar.gz")
set(WR_SLANG_SHA256
"9959d741713162efdbd863ff6d32400432b6e103eae3a9ee0afbdba6a00c6a9e")
elseif(WR_SLANG_PLATFORM STREQUAL "macos-x86_64")
set(WR_SLANG_ASSET
"slang-${WR_SLANG_VERSION}-macos-x86_64.tar.gz")
set(WR_SLANG_SHA256
"b4f01f615dc625f60c593d7d0a4bbd38e05dfa2a34bfd3973017c309d866feaa")
elseif(WR_SLANG_PLATFORM STREQUAL "macos-aarch64")
set(WR_SLANG_ASSET
"slang-${WR_SLANG_VERSION}-macos-aarch64.tar.gz")
set(WR_SLANG_SHA256
"07fa8833fdbb343c3674c84fdd885910f495f3daaaa0c732b32980151e8b58c4")
elseif(WR_SLANG_PLATFORM STREQUAL "windows-x86_64")
set(WR_SLANG_ASSET
"slang-${WR_SLANG_VERSION}-windows-x86_64.zip")
set(WR_SLANG_SHA256
"e6dd32bbddf1720ebb4e679d55e9635ce792865a5bd84f3d2cd9af28647c0174")
elseif(WR_SLANG_PLATFORM STREQUAL "windows-aarch64")
set(WR_SLANG_ASSET
"slang-${WR_SLANG_VERSION}-windows-aarch64.zip")
set(WR_SLANG_SHA256
"4f18a7e76a59969bc9bf6ea596bd9e496a3c689af173990ae028b18f03e1ac1a")
else()
set(WR_SLANG_ASSET "")
endif()
if(NOT WR_SLANG_ASSET)
message(FATAL_ERROR
"slangc was not found, and no prebuilt Slang archive is available "
"for ${CMAKE_HOST_SYSTEM_NAME}/${CMAKE_HOST_SYSTEM_PROCESSOR}. "
"Install the Slang compiler, or configure with "
"-DWR_COMPILE_SHADERS=OFF.")
endif()
set(WR_SLANG_DOWNLOAD_DIR "${CMAKE_CURRENT_BINARY_DIR}/_deps/slang")
set(WR_SLANG_ARCHIVE
"${WR_SLANG_DOWNLOAD_DIR}/${WR_SLANG_ASSET}")
set(WR_SLANG_URL
"https://github.com/shader-slang/slang/releases/download/v${WR_SLANG_VERSION}/${WR_SLANG_ASSET}")
if(EXISTS "${WR_SLANG_ARCHIVE}")
file(SHA256 "${WR_SLANG_ARCHIVE}" WR_SLANG_ACTUAL_SHA256)
if(NOT WR_SLANG_ACTUAL_SHA256 STREQUAL WR_SLANG_SHA256)
message(STATUS "Removing corrupt Slang archive")
file(REMOVE "${WR_SLANG_ARCHIVE}")
endif()
endif()
if(NOT EXISTS "${WR_SLANG_ARCHIVE}")
message(STATUS "Downloading Slang ${WR_SLANG_VERSION} for ${WR_SLANG_PLATFORM}")
file(DOWNLOAD
"${WR_SLANG_URL}"
"${WR_SLANG_ARCHIVE}"
EXPECTED_HASH SHA256=${WR_SLANG_SHA256}
STATUS WR_SLANG_DOWNLOAD_STATUS
TLS_VERIFY ON
)
list(GET WR_SLANG_DOWNLOAD_STATUS 0 WR_SLANG_DOWNLOAD_CODE)
list(GET WR_SLANG_DOWNLOAD_STATUS 1 WR_SLANG_DOWNLOAD_MESSAGE)
if(NOT WR_SLANG_DOWNLOAD_CODE EQUAL 0)
file(REMOVE "${WR_SLANG_ARCHIVE}")
message(FATAL_ERROR
"Failed to download Slang from ${WR_SLANG_URL}: "
"${WR_SLANG_DOWNLOAD_MESSAGE}")
endif()
endif()
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
set(WR_SLANG_EXECUTABLE
"${WR_SLANG_DOWNLOAD_DIR}/bin/slangc.exe")
else()
set(WR_SLANG_EXECUTABLE
"${WR_SLANG_DOWNLOAD_DIR}/bin/slangc")
endif()
if(NOT EXISTS "${WR_SLANG_EXECUTABLE}")
message(STATUS "Extracting Slang ${WR_SLANG_VERSION}")
file(ARCHIVE_EXTRACT
INPUT "${WR_SLANG_ARCHIVE}"
DESTINATION "${WR_SLANG_DOWNLOAD_DIR}"
)
endif()
if(NOT EXISTS "${WR_SLANG_EXECUTABLE}")
message(FATAL_ERROR
"The Slang archive did not contain bin/slangc")
endif()
set(SLANGC_EXECUTABLE "${WR_SLANG_EXECUTABLE}")
message(STATUS "Using downloaded Slang compiler: ${SLANGC_EXECUTABLE}")
endif()
if(NOT SLANGC_EXECUTABLE)
message(FATAL_ERROR
"slangc was not found. Install the Slang compiler, configure with "
"-DWR_FETCH_MISSING_DEPENDENCIES=ON to download it, or configure with "
"-DWR_COMPILE_SHADERS=OFF.")
endif()
set(WR_SHADER_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src/shaders/shader.slang)
set(WR_SHADER_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/shaders)
set(WR_SHADER_OUTPUT ${WR_SHADER_OUTPUT_DIR}/shader.spv)
add_custom_command(
OUTPUT ${WR_SHADER_OUTPUT}
COMMAND ${CMAKE_COMMAND} -E make_directory ${WR_SHADER_OUTPUT_DIR}
COMMAND ${SLANGC_EXECUTABLE}
${WR_SHADER_SOURCE}
-entry vertMain
-entry fragMain
-o ${WR_SHADER_OUTPUT}
DEPENDS ${WR_SHADER_SOURCE}
COMMENT "Compiling shader.slang"
VERBATIM
)
add_custom_target(shaders ALL DEPENDS ${WR_SHADER_OUTPUT})
add_dependencies(main shaders)
endif()
# ---------------------------------------------------------------------------
# Assets
#
# The application loads "assets/collections.png" relative to its working
# directory, so the assets directory is copied into <build-dir>/assets.
# ---------------------------------------------------------------------------
set(WR_ASSETS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/assets)
set(WR_ASSETS_DEST_DIR ${CMAKE_CURRENT_BINARY_DIR}/assets)
if(EXISTS ${WR_ASSETS_SOURCE_DIR})
add_custom_target(copy_assets ALL
COMMAND ${CMAKE_COMMAND} -E copy_directory
${WR_ASSETS_SOURCE_DIR}
${WR_ASSETS_DEST_DIR}
COMMENT "Copying assets"
VERBATIM
)
add_dependencies(main copy_assets)
endif()
add_custom_target(run
COMMAND $<TARGET_FILE:main>
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS main
USES_TERMINAL
)
if(TARGET shaders)
add_dependencies(run shaders)
endif()