Make VulkanMemoryAllocator a header only library

Dramatically simplify the CMake code for end users. The intent
is to make the CMake for this library very easy to maintain.
While also making it easier for end users to consume.

This makes the CMake code very similar to:
- KhronosGroup/Vulkan-Headers
- KhronosGroup/SPIRV-Headers

Which is good for consistency/expectations.

The VmaUsage library still highlights the expected usage of
the "stb-style" single header file in a project.

closes #346
This commit is contained in:
Juan Ramos 2023-07-05 13:14:09 -06:00
parent d9a2e4641b
commit 3d23bb07e3
5 changed files with 110 additions and 199 deletions

View File

@ -1,53 +1,43 @@
cmake_minimum_required(VERSION 3.9)
cmake_minimum_required(VERSION 3.15...3.26)
project(VulkanMemoryAllocator LANGUAGES CXX)
project(VMA LANGUAGES CXX)
# VulkanMemoryAllocator contains an sample application which is not built by default
option(VMA_BUILD_SAMPLE "Build VulkanMemoryAllocator sample application" OFF)
option(VMA_BUILD_SAMPLE_SHADERS "Build VulkanMemoryAllocator sample application's shaders" OFF)
add_library(VulkanMemoryAllocator INTERFACE)
add_library(GPUOpen::VulkanMemoryAllocator ALIAS VulkanMemoryAllocator)
message(STATUS "VMA_BUILD_SAMPLE = ${VMA_BUILD_SAMPLE}")
message(STATUS "VMA_BUILD_SAMPLE_SHADERS = ${VMA_BUILD_SAMPLE_SHADERS}")
target_include_directories(VulkanMemoryAllocator INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
option(VMA_STATIC_VULKAN_FUNCTIONS "Link statically with Vulkan API" ON)
option(VMA_DYNAMIC_VULKAN_FUNCTIONS "Fetch pointers to Vulkan functions internally (no static linking)" OFF)
option(VMA_DEBUG_ALWAYS_DEDICATED_MEMORY "Every allocation will have its own memory block" OFF)
option(VMA_DEBUG_INITIALIZE_ALLOCATIONS "Automatically fill new allocations and destroyed allocations with some bit pattern" OFF)
option(VMA_DEBUG_GLOBAL_MUTEX "Enable single mutex protecting all entry calls to the library" OFF)
option(VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT "Never exceed VkPhysicalDeviceLimits::maxMemoryAllocationCount and return error" OFF)
message(STATUS "VMA_STATIC_VULKAN_FUNCTIONS = ${VMA_STATIC_VULKAN_FUNCTIONS}")
message(STATUS "VMA_DYNAMIC_VULKAN_FUNCTIONS = ${VMA_DYNAMIC_VULKAN_FUNCTIONS}")
message(STATUS "VMA_DEBUG_ALWAYS_DEDICATED_MEMORY = ${VMA_DEBUG_ALWAYS_DEDICATED_MEMORY}")
message(STATUS "VMA_DEBUG_INITIALIZE_ALLOCATIONS = ${VMA_DEBUG_INITIALIZE_ALLOCATIONS}")
message(STATUS "VMA_DEBUG_GLOBAL_MUTEX = ${VMA_DEBUG_GLOBAL_MUTEX}")
message(STATUS "VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT = ${VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT}")
if(VMA_STATIC_VULKAN_FUNCTIONS OR VMA_BUILD_SAMPLE)
find_package(Vulkan REQUIRED)
else()
find_package(VulkanHeaders REQUIRED)
if (CMAKE_VERSION VERSION_LESS "3.21")
# https://cmake.org/cmake/help/latest/variable/PROJECT_IS_TOP_LEVEL.html
string(COMPARE EQUAL ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR} PROJECT_IS_TOP_LEVEL)
endif()
if(VMA_BUILD_SAMPLE)
set(VMA_BUILD_SAMPLE_SHADERS ON)
if (PROJECT_IS_TOP_LEVEL)
include(GNUInstallDirs)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(TARGETS VulkanMemoryAllocator EXPORT VulkanMemoryAllocatorConfig INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(EXPORT VulkanMemoryAllocatorConfig NAMESPACE "GPUOpen::" DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/VulkanMemoryAllocator")
option(VMA_BUILD_DOCUMENTATION "Create and install the HTML based API documentation")
if(VMA_BUILD_DOCUMENTATION)
find_package(Doxygen REQUIRED)
# set input and output files
set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile)
set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
# request to configure the file
configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY)
# note the option ALL which allows to build the docs together with the application
add_custom_target(doc_doxygen ALL
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM
)
endif()
option(VMA_BUILD_SAMPLES "Build samples")
if (VMA_BUILD_SAMPLES)
add_subdirectory(src)
endif()
endif()
option(BUILD_DOCUMENTATION "Create and install the HTML based API documentation (requires Doxygen)" OFF)
if(BUILD_DOCUMENTATION)
find_package(Doxygen REQUIRED)
# set input and output files
set(DOXYGEN_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile)
set(DOXYGEN_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
# request to configure the file
configure_file(${DOXYGEN_IN} ${DOXYGEN_OUT} @ONLY)
# note the option ALL which allows to build the docs together with the application
add_custom_target( doc_doxygen ALL
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYGEN_OUT}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM )
endif()
add_subdirectory(src)

View File

@ -99,38 +99,37 @@ With this one function call:
# How to build
On Windows it is recommended to use [CMake UI](https://cmake.org/runningcmake/). Alternatively you can generate a Visual Studio project map using CMake in command line: `cmake -B./build/ -DCMAKE_BUILD_TYPE=Debug -G "Visual Studio 16 2019" -A x64 ./`
On Windows it is recommended to use [CMake GUI](https://cmake.org/runningcmake/).
Alternatively you can generate/open a Visual Studio from the command line:
```sh
# By default CMake picks the newest version of Visual Studio it can use
cmake -S . -B build -D VMA_BUILD_SAMPLES=ON
cmake --open build
```
On Linux:
```
mkdir build
cd build
cmake ..
make
```sh
cmake -S . -B build
# Since VMA has no source files, you can skip to installation immediately
cmake --install build --prefix build/install
```
The following targets are available
## How to use
| Target | Description | CMake option | Default setting |
| ------------- | ------------- | ------------- | ------------- |
| VmaSample | VMA sample application | `VMA_BUILD_SAMPLE` | `OFF` |
| VmaBuildSampleShaders | Shaders for VmaSample | `VMA_BUILD_SAMPLE_SHADERS` | `OFF` |
After calling either `find_package` or `add_subdirectory` simply link the library.
This automatically handles configuring the include directory.
Please note that while VulkanMemoryAllocator library is supported on other platforms besides Windows, VmaSample is not.
EX:
These CMake options are available
```cmake
find_package(VulkanMemoryAllocator CONFIG REQUIRED)
target_link_libraries(YourGameEngine PRIVATE GPUOpen::VulkanMemoryAllocator)
```
| CMake option | Description | Default setting |
| ------------- | ------------- | ------------- |
| `VMA_RECORDING_ENABLED` | Enable VMA memory recording for debugging | `OFF` |
| `VMA_USE_STL_CONTAINERS` | Use C++ STL containers instead of VMA's containers | `OFF` |
| `VMA_STATIC_VULKAN_FUNCTIONS` | Link statically with Vulkan API | `OFF` |
| `VMA_DYNAMIC_VULKAN_FUNCTIONS` | Fetch pointers to Vulkan functions internally (no static linking) | `ON` |
| `VMA_DEBUG_ALWAYS_DEDICATED_MEMORY` | Every allocation will have its own memory block | `OFF` |
| `VMA_DEBUG_INITIALIZE_ALLOCATIONS` | Automatically fill new allocations and destroyed allocations with some bit pattern | `OFF` |
| `VMA_DEBUG_GLOBAL_MUTEX` | Enable single mutex protecting all entry calls to the library | `OFF` |
| `VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT` | Never exceed [VkPhysicalDeviceLimits::maxMemoryAllocationCount](https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#limits-maxMemoryAllocationCount) and return error | `OFF` |
For more info on using CMake visit the official [CMake documentation](https://cmake.org/cmake/help/latest/index.html).
## Building using vcpkg

View File

@ -1,107 +1,76 @@
set(CMAKE_DEBUG_POSTFIX d)
set(CMAKE_RELWITHDEBINFO_POSTFIX rd)
set(CMAKE_MINSIZEREL_POSTFIX s)
add_library(VulkanMemoryAllocator
VmaUsage.cpp
VmaUsage.h
${PROJECT_SOURCE_DIR}/include/vk_mem_alloc.h
)
if (MSVC)
# Provides MSVC users nicer debugging support
target_sources(VulkanMemoryAllocator PRIVATE ${CMAKE_CURRENT_LIST_DIR}/vk_mem_alloc.natvis)
if (NOT WIN32)
message(STATUS "VmaSample application is only supported on Windows")
return()
endif()
set_target_properties(
VulkanMemoryAllocator PROPERTIES
option(VMA_STATIC_VULKAN_FUNCTIONS "Link statically with Vulkan API" ON)
option(VMA_DYNAMIC_VULKAN_FUNCTIONS "Fetch pointers to Vulkan functions internally (no static linking)" OFF)
option(VMA_DEBUG_ALWAYS_DEDICATED_MEMORY "Every allocation will have its own memory block" OFF)
option(VMA_DEBUG_INITIALIZE_ALLOCATIONS "Automatically fill new allocations and destroyed allocations with some bit pattern" OFF)
option(VMA_DEBUG_GLOBAL_MUTEX "Enable single mutex protecting all entry calls to the library" OFF)
option(VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT "Never exceed VkPhysicalDeviceLimits::maxMemoryAllocationCount and return error" OFF)
CXX_EXTENSIONS OFF
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
message(STATUS "VMA_STATIC_VULKAN_FUNCTIONS = ${VMA_STATIC_VULKAN_FUNCTIONS}")
message(STATUS "VMA_DYNAMIC_VULKAN_FUNCTIONS = ${VMA_DYNAMIC_VULKAN_FUNCTIONS}")
message(STATUS "VMA_DEBUG_ALWAYS_DEDICATED_MEMORY = ${VMA_DEBUG_ALWAYS_DEDICATED_MEMORY}")
message(STATUS "VMA_DEBUG_INITIALIZE_ALLOCATIONS = ${VMA_DEBUG_INITIALIZE_ALLOCATIONS}")
message(STATUS "VMA_DEBUG_GLOBAL_MUTEX = ${VMA_DEBUG_GLOBAL_MUTEX}")
message(STATUS "VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT = ${VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT}")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
add_library(VmaUsage STATIC)
target_sources(VmaUsage PRIVATE
VmaUsage.cpp
VmaUsage.h
)
target_include_directories(VulkanMemoryAllocator PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
)
target_link_libraries(VmaUsage PUBLIC GPUOpen::VulkanMemoryAllocator)
# Provides MSVC users nicer debugging support
target_sources(VmaUsage PRIVATE vk_mem_alloc.natvis)
find_package(Vulkan REQUIRED)
# Only link to Vulkan library if static linking is used, but always add Vulkan headers directory
if(VMA_STATIC_VULKAN_FUNCTIONS)
target_link_libraries(VulkanMemoryAllocator PUBLIC Vulkan::Vulkan)
target_link_libraries(VmaUsage PUBLIC Vulkan::Vulkan)
else()
target_link_libraries(VulkanMemoryAllocator PUBLIC Vulkan::Headers)
target_link_libraries(VmaUsage PUBLIC Vulkan::Headers)
endif()
target_compile_definitions(
VulkanMemoryAllocator
PUBLIC
target_compile_definitions(VmaUsage PUBLIC
VMA_STATIC_VULKAN_FUNCTIONS=$<BOOL:${VMA_STATIC_VULKAN_FUNCTIONS}>
VMA_DYNAMIC_VULKAN_FUNCTIONS=$<BOOL:${VMA_DYNAMIC_VULKAN_FUNCTIONS}>
VMA_DEBUG_ALWAYS_DEDICATED_MEMORY=$<BOOL:${VMA_DEBUG_ALWAYS_DEDICATED_MEMORY}>
VMA_DEBUG_INITIALIZE_ALLOCATIONS=$<BOOL:${VMA_DEBUG_INITIALIZE_ALLOCATIONS}>
VMA_DEBUG_GLOBAL_MUTEX=$<BOOL:${VMA_DEBUG_GLOBAL_MUTEX}>
VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT=$<BOOL:${VMA_DEBUG_DONT_EXCEED_MAX_MEMORY_ALLOCATION_COUNT}>
VMA_RECORDING_ENABLED=$<BOOL:${VMA_RECORDING_ENABLED}>
)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/install_target.cmake)
add_executable(VmaSample)
target_sources(VmaSample PRIVATE
Common.cpp
Common.h
SparseBindingTest.cpp
SparseBindingTest.h
Tests.cpp
Tests.h
VulkanSample.cpp
)
if(VMA_BUILD_SAMPLE)
if(WIN32)
set(VMA_SAMPLE_SOURCE_FILES
Common.cpp
Common.h
SparseBindingTest.cpp
SparseBindingTest.h
Tests.cpp
Tests.h
VulkanSample.cpp
)
target_link_libraries(VmaSample PRIVATE VmaUsage)
add_executable(VmaSample ${VMA_SAMPLE_SOURCE_FILES})
add_dependencies(VmaSample VulkanMemoryAllocator VmaSampleShaders)
add_subdirectory(Shaders)
add_dependencies(VmaSample VmaSampleShaders)
if(MSVC)
# Use Unicode instead of multibyte set
add_compile_definitions(UNICODE _UNICODE)
# Use Unicode instead of multibyte set
add_compile_definitions(UNICODE _UNICODE)
# Add C++ warnings and security checks
add_compile_options(/permissive- /sdl /W3)
# Add C++ warnings and security checks
add_compile_options(/permissive- /sdl /W3)
# Enable multithreaded compiling
target_compile_options(VmaSample PRIVATE "/MP")
# Set VmaSample as startup project
set_property(DIRECTORY "${PROJECT_SOURCE_DIR}" PROPERTY VS_STARTUP_PROJECT "VmaSample")
# Set working directory for Visual Studio debugger
set_target_properties(
VmaSample
PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/bin"
)
endif()
set_target_properties(
VmaSample PROPERTIES
CXX_EXTENSIONS OFF
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
)
target_link_libraries(
VmaSample
PRIVATE
VulkanMemoryAllocator
Vulkan::Vulkan
)
else()
message(STATUS "VmaSample application is not supported to Linux")
endif()
endif()
if(VMA_BUILD_SAMPLE_SHADERS)
add_subdirectory(Shaders)
endif()
# Set VmaSample as startup project
set_property(DIRECTORY "${PROJECT_SOURCE_DIR}" PROPERTY VS_STARTUP_PROJECT "VmaSample")

View File

@ -1,14 +0,0 @@
@PACKAGE_INIT@
include(CMakeFindDependencyMacro)
if(@VMA_STATIC_VULKAN_FUNCTIONS@)
find_dependency(Vulkan)
else()
find_dependency(VulkanHeaders)
endif()
include("${CMAKE_CURRENT_LIST_DIR}/VulkanMemoryAllocatorTargets.cmake")
check_required_components("@PROJECT_NAME@")

View File

@ -1,33 +0,0 @@
include(GNUInstallDirs)
target_include_directories(VulkanMemoryAllocator PUBLIC
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDE_DIRS}>
)
install(TARGETS VulkanMemoryAllocator
EXPORT VulkanMemoryAllocatorTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
# install(FILES "${PROJECT_SOURCE_DIR}/include/vk_mem_alloc.h" DESTINATION "include")
install(FILES "${PROJECT_SOURCE_DIR}/include/vk_mem_alloc.h"
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
install(EXPORT VulkanMemoryAllocatorTargets
FILE VulkanMemoryAllocatorTargets.cmake
NAMESPACE VulkanMemoryAllocator::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/VulkanMemoryAllocator
)
include(CMakePackageConfigHelpers)
configure_package_config_file(${CMAKE_CURRENT_LIST_DIR}/Config.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/VulkanMemoryAllocatorConfig.cmake"
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/VulkanMemoryAllocator
)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/VulkanMemoryAllocatorConfig.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/VulkanMemoryAllocator
)
add_library(VulkanMemoryAllocator::VulkanMemoryAllocator ALIAS VulkanMemoryAllocator)