223 lines
8.5 KiB
CMake
223 lines
8.5 KiB
CMake
|
|
# VulkZample! Your example in Vulkan!
|
|
# Copyright (C) 2024 Rebekah Rowe
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
cmake_minimum_required(VERSION 3.28)
|
|
|
|
project(vulkzample LANGUAGES CXX VERSION 1.0.0)
|
|
|
|
set(CMAKE_CXX_STANDARD 23)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
set(CMAKE_EXPORT_COMPILE_COMMANDS true)
|
|
|
|
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
|
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION true)
|
|
endif()
|
|
|
|
find_package(glm REQUIRED)
|
|
find_package(SDL2 REQUIRED)
|
|
find_package(SDL2pp REQUIRED)
|
|
find_package(Vulkan REQUIRED COMPONENTS glslc)
|
|
find_package(VulkanMemoryAllocator-Hpp REQUIRED)
|
|
#find_package(Doxygen)
|
|
|
|
add_executable(${PROJECT_NAME} "")
|
|
|
|
target_include_directories(${PROJECT_NAME} PRIVATE
|
|
SDL2pp::Headers
|
|
|
|
Vulkan::Headers
|
|
VulkanMemoryAllocator-Hpp::VulkanMemoryAllocator-Hpp
|
|
)
|
|
|
|
target_link_libraries(${PROJECT_NAME} PUBLIC
|
|
SDL2pp::SDL2pp
|
|
Vulkan::Vulkan
|
|
VulkanMemoryAllocator-Hpp::VulkanMemoryAllocator-Hpp
|
|
)
|
|
|
|
file(GLOB_RECURSE sources "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
|
|
target_sources(${PROJECT_NAME} PRIVATE ${sources})
|
|
|
|
#if (DOXYGEN_FOUND)
|
|
# doxygen_add_docs(${PROJECT_NAME})
|
|
#endif()
|
|
|
|
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
|
target_compile_options(${PROJECT_NAME} PRIVATE -O0 -fno-omit-frame-pointer -ggdb -Wall -Werror -fno-common)
|
|
target_link_options(${PROJECT_NAME} PRIVATE -O0 -fno-omit-frame-pointer -ggdb -Wall -Werror -fno-common)
|
|
if (ENABLE_ASAN)
|
|
target_compile_options(${PROJECT_NAME} PRIVATE -fsanitize=address)
|
|
target_link_options(${PROJECT_NAME} PRIVATE -fsanitize=address)
|
|
endif()
|
|
endif()
|
|
|
|
if (ENABLE_TESTS)
|
|
message(STATUS "Tests Enabled, Building with Testing!")
|
|
target_compile_definitions(${PROJECT_NAME} PRIVATE -DENABLE_TESTS=1)
|
|
endif()
|
|
|
|
# SHADER COMPILATION
|
|
function(CommandCompileGLSLToSPV file_in)
|
|
cmake_path(GET file_in FILENAME filename)
|
|
cmake_path(GET file_in PARENT_PATH filepath)
|
|
|
|
cmake_path(GET file_in STEM LAST_ONLY filepath_without_glsl_ext)
|
|
cmake_path(GET filepath_without_glsl_ext EXTENSION LAST_ONLY file_shader_type)
|
|
if(file_shader_type MATCHES "^\\..*")
|
|
string(REGEX REPLACE "^\\." "" file_shader_type "${file_shader_type}") # Remove the dot: ".vertex"
|
|
endif()
|
|
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${filename}.spv
|
|
WORKING_DIRECTORY ${filepath}
|
|
COMMAND Vulkan::glslc
|
|
ARGS -fshader-stage="${file_shader_type}" ${filename} -o ${CMAKE_CURRENT_BINARY_DIR}/${filename}.spv
|
|
DEPENDS ${file_in}
|
|
POST_BUILD)
|
|
set(FUNC_RET ${CMAKE_CURRENT_BINARY_DIR}/${filename}.spv PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
function(CommandCompileMassGSGLShaders)
|
|
set(SHADILER_OBJ_RET "")
|
|
foreach(file_path ${ARGV})
|
|
CommandCompileGLSLToSPV(${file_path})
|
|
list(APPEND SHADILER_OBJ_RET "${FUNC_RET}")
|
|
|
|
endforeach()
|
|
set(SHADILER_OBJ_RET "${SHADILER_OBJ_RET}" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
file(GLOB_RECURSE shaders_frag "${CMAKE_CURRENT_SOURCE_DIR}/shader/*.frag.glsl")
|
|
file(GLOB_RECURSE shaders_vertex "${CMAKE_CURRENT_SOURCE_DIR}/shader/*.vertex.glsl")
|
|
CommandCompileMassGSGLShaders(${shaders_frag} ${shaders_vertex})
|
|
|
|
|
|
# EMBED CMAKE
|
|
find_package(ImageMagick REQUIRED COMPONENTS convert identify)
|
|
function(CommandConvertImageToRgba file_in)
|
|
cmake_path(GET file_in FILENAME filename)
|
|
cmake_path(GET file_in PARENT_PATH filepath)
|
|
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${filename}.rgba
|
|
WORKING_DIRECTORY ${filepath}
|
|
COMMAND ${ImageMagick_convert_EXECUTABLE}
|
|
ARGS ${filename} -depth 8 -format rgba ${CMAKE_CURRENT_BINARY_DIR}/${filename}.rgba
|
|
DEPENDS ${file_in}
|
|
POST_BUILD)
|
|
set(FUNC_RET ${CMAKE_CURRENT_BINARY_DIR}/${filename}.rgba PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
function(CommandConvertToObjcopy file_in)
|
|
cmake_path(GET file_in FILENAME filename)
|
|
cmake_path(GET file_in PARENT_PATH filepath)
|
|
|
|
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "amd64")
|
|
set(OBJCOPY_ARCH "elf64-x86-64")
|
|
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "arm64")
|
|
set(OBJCOPY_ARCH "elf64-littleaarch64")
|
|
else()
|
|
message(FATAL_ERROR "Unsupported architecture: ${CMAKE_SYSTEM_PROCESSOR}")
|
|
endif()
|
|
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${filename}.o
|
|
WORKING_DIRECTORY ${filepath}
|
|
COMMAND ${CMAKE_OBJCOPY}
|
|
ARGS --input-target binary --output-target "${OBJCOPY_ARCH}" "${filename}" "${CMAKE_CURRENT_BINARY_DIR}/${filename}.o"
|
|
DEPENDS ${file_in}
|
|
POST_BUILD)
|
|
set(FUNC_RET ${CMAKE_CURRENT_BINARY_DIR}/${filename}.o PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
function(CommandConvertImageToObject file_in)
|
|
CommandConvertImageToRgba("${file_in}")
|
|
CommandConvertToObjcopy(${FUNC_RET})
|
|
set(FUNC_RET ${FUNC_RET} PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
function(EmbedResources)
|
|
set(EMBED_HEADER_DIR "${CMAKE_CURRENT_BINARY_DIR}/")
|
|
set(EMBED_HEADER_DIR "${EMBED_HEADER_DIR}" PARENT_SCOPE)
|
|
file(WRITE "${EMBED_HEADER_DIR}/embed_resources.hpp" "
|
|
/* AUTOGENERATED CMAKE EMBEDED FILE HEADER!!! DO NOT EDIT THIS FILE!!!
|
|
ALL CHANGES WILL BE WIPED!!! */
|
|
#include <cstddef>
|
|
#include <iterator>
|
|
class EmbededResource {
|
|
public:
|
|
constexpr EmbededResource(const std::byte* _begin, const std::byte* _end)
|
|
: begin(_begin), end(_end), size(std::distance(_begin, _end)) {
|
|
//static_assert(this->begin != nullptr && this->end != nullptr);
|
|
}
|
|
const std::byte* const begin;
|
|
const std::byte* const end;
|
|
std::size_t size;
|
|
};
|
|
class EmbededImage {
|
|
public:
|
|
constexpr EmbededImage(std::size_t _width, std::size_t _height, EmbededResource _data)\
|
|
: width(_width), height(_height), data(_data) {
|
|
//static_assert(this->width != 0 && this->height);
|
|
}
|
|
const std::size_t width;
|
|
const std::size_t height;
|
|
const EmbededResource data;
|
|
};
|
|
")
|
|
|
|
set(EMBED_OBJ_RET "")
|
|
foreach(file_path ${ARGV})
|
|
cmake_path(GET file_path EXTENSION LAST_ONLY file_ext)
|
|
set(type "embed")
|
|
if (file_ext STREQUAL ".jpg")
|
|
set(type "image")
|
|
endif()
|
|
if (file_ext STREQUAL ".png")
|
|
set(type "image")
|
|
endif()
|
|
|
|
if (type STREQUAL "image")
|
|
CommandConvertImageToObject(${file_path})
|
|
elseif (type STREQUAL "embed")
|
|
CommandConvertToObjcopy(${file_path})
|
|
endif()
|
|
list(APPEND EMBED_OBJ_RET "${FUNC_RET}")
|
|
|
|
cmake_path(GET FUNC_RET STEM LAST_ONLY obj_filestem)
|
|
string(REPLACE "." "_" obj_cleaned_name "${obj_filestem}")
|
|
file(APPEND "${EMBED_HEADER_DIR}/embed_resources.hpp" "extern const std::byte _binary_${obj_cleaned_name}_start; extern const std::byte _binary_${obj_cleaned_name}_end; \n")
|
|
|
|
if (type STREQUAL "image")
|
|
cmake_path(GET file_path PARENT_PATH file_parent)
|
|
cmake_path(GET file_path FILENAME file_name)
|
|
execute_process(COMMAND "${ImageMagick_identify_EXECUTABLE}" -format "%[fx:w]" "${file_name}"
|
|
WORKING_DIRECTORY "${file_parent}"
|
|
OUTPUT_VARIABLE image_width
|
|
COMMAND_ERROR_IS_FATAL ANY)
|
|
execute_process(COMMAND "${ImageMagick_identify_EXECUTABLE}" -format "%[fx:h]" "${file_name}"
|
|
WORKING_DIRECTORY "${file_parent}"
|
|
OUTPUT_VARIABLE image_height
|
|
COMMAND_ERROR_IS_FATAL ANY)
|
|
file(APPEND "${EMBED_HEADER_DIR}/embed_resources.hpp" "inline EmbededImage embeded_${obj_cleaned_name}(${image_width}, ${image_height}, EmbededResource(&_binary_${obj_cleaned_name}_start, &_binary_${obj_cleaned_name}_end)); \n")
|
|
|
|
elseif (type STREQUAL "embed")
|
|
file(APPEND "${EMBED_HEADER_DIR}/embed_resources.hpp" "inline EmbededResource embeded_${obj_cleaned_name}(&_binary_${obj_cleaned_name}_start, &_binary_${obj_cleaned_name}_end); \n")
|
|
endif()
|
|
|
|
endforeach()
|
|
set(EMBED_OBJ_RET "${EMBED_OBJ_RET}" PARENT_SCOPE)
|
|
endfunction()
|
|
EmbedResources(${SHADILER_OBJ_RET} "${CMAKE_CURRENT_SOURCE_DIR}/res/debug_north.png")
|
|
|
|
target_sources(${PROJECT_NAME} PRIVATE ${EMBED_OBJ_RET})
|
|
target_include_directories(${PROJECT_NAME} PUBLIC "${EMBED_HEADER_DIR}")
|