diff --git a/.gitignore b/.gitignore index c6d15111..46f884b4 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,5 @@ attachments/simple_engine/android/app/build/** attachments/simple_engine/android/gradle/wrapper/** attachments/simple_engine/android/gradlew attachments/simple_engine/android/gradlew.bat + +attachments/template/build/** \ No newline at end of file diff --git a/attachments/template/CMakeLists.txt b/attachments/template/CMakeLists.txt new file mode 100644 index 00000000..6edabec0 --- /dev/null +++ b/attachments/template/CMakeLists.txt @@ -0,0 +1,119 @@ +cmake_minimum_required (VERSION 3.29) + +set (TEMPLATE_NAME "VulkanTutorial") + +project (${TEMPLATE_NAME}) + +# Add option to enable/disable C++ 20 module +option(ENABLE_CPP20_MODULE "Enable C++ 20 module support for Vulkan" OFF) + +# Enable C++ module dependency scanning only if C++ 20 module is enabled +if(ENABLE_CPP20_MODULE) + set(CMAKE_CXX_SCAN_FOR_MODULES ON) +endif() + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../cmake") + +find_package(glfw3 REQUIRED) +find_package(glm REQUIRED) +find_package(Vulkan 1.4.335 REQUIRED) +find_package(tinyobjloader REQUIRED) +find_package(tinygltf REQUIRED) +find_package(KTX REQUIRED) + +# Set up Vulkan C++ module only if enabled +if(ENABLE_CPP20_MODULE) + add_library(VulkanCppModule) + add_library(Vulkan::cppm ALIAS VulkanCppModule) + + target_compile_definitions(VulkanCppModule PUBLIC VULKAN_HPP_DISPATCH_LOADER_DYNAMIC=1 VULKAN_HPP_NO_STRUCT_CONSTRUCTORS=1) + target_include_directories(VulkanCppModule PUBLIC "${Vulkan_INCLUDE_DIR}") + target_link_libraries(VulkanCppModule PUBLIC Vulkan::Vulkan) + + set_target_properties(VulkanCppModule PROPERTIES CXX_STANDARD 20) + + # Add MSVC-specific compiler options for proper C++ module support + if(MSVC) + target_compile_options(VulkanCppModule PRIVATE + /std:c++latest # Use latest C++ standard for better module support + /permissive- # Standards conformance mode + /Zc:__cplusplus # Enable correct __cplusplus macro + /EHsc # Enable C++ exception handling + /Zc:preprocessor # Use conforming preprocessor + /translateInclude # Automatically translate #include to import for standard library + ) + endif() + + target_sources(VulkanCppModule + PUBLIC + FILE_SET cxx_modules TYPE CXX_MODULES + BASE_DIRS + "${Vulkan_INCLUDE_DIR}" + FILES + "${Vulkan_INCLUDE_DIR}/vulkan/vulkan.cppm" + ) + + + # Add the vulkan.cppm file directly as a source file + target_sources(VulkanCppModule + PRIVATE + "${Vulkan_INCLUDE_DIR}/vulkan/vulkan.cppm" + ) +else() + # Create a dummy interface library when C++ 20 module is disabled + add_library(VulkanCppModule INTERFACE) + add_library(Vulkan::cppm ALIAS VulkanCppModule) + target_link_libraries(VulkanCppModule INTERFACE Vulkan::Vulkan) + target_compile_definitions(VulkanCppModule + INTERFACE VULKAN_HPP_DISPATCH_LOADER_DYNAMIC=1 VULKAN_HPP_NO_STRUCT_CONSTRUCTORS=1 + ) +endif() + +find_package(stb REQUIRED) +set(STB_INCLUDEDIR ${stb_INCLUDE_DIRS}) + +find_program(SLANGC_EXECUTABLE slangc HINTS $ENV{VULKAN_SDK}/bin REQUIRED) + +set(TEMPLATE_DIR ${CMAKE_BINARY_DIR}/${TEMPLATE_NAME}) + +add_executable (${TEMPLATE_NAME} main.cpp) +set_target_properties (${TEMPLATE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${TEMPLATE_DIR}) +set_target_properties (${TEMPLATE_NAME} PROPERTIES CXX_STANDARD 20) +target_link_libraries (${TEMPLATE_NAME} Vulkan::cppm glfw) +target_include_directories (${TEMPLATE_NAME} PRIVATE ${STB_INCLUDEDIR}) + +# Add compile definition if C++ 20 module is enabled +if(ENABLE_CPP20_MODULE) + target_compile_definitions(${TEMPLATE_NAME} PRIVATE USE_CPP20_MODULES=1) +endif() + +# Define VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS to treat VK_ERROR_OUT_OF_DATE_KHR as a success code +target_compile_definitions(${TEMPLATE_NAME} PRIVATE "VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS" ) + +if(WIN32) + if(${CMAKE_GENERATOR} MATCHES "Visual Studio.*") + set_target_properties(${TEMPLATE_NAME} PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${TEMPLATE_DIR}) + endif() +endif() + +# Slang shader +set (SHADER_TARGET ${TEMPLATE_NAME}Shader) +set (SHADERS_DIR ${TEMPLATE_DIR}/shaders) +set (SHADER_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/shader.slang") +set (ENTRY_POINTS -entry vertMain -entry fragMain) +add_custom_command(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 -emit-spirv-directly -fvk-use-entrypoint-name ${ENTRY_POINTS} -o ${TEMPLATE_DIR}/shaders/slang.spv + WORKING_DIRECTORY ${SHADERS_DIR} + DEPENDS ${SHADERS_DIR} ${SHADER_SOURCES} + COMMENT "Compiling Slang Shaders" + VERBATIM +) +add_custom_target(${SHADER_TARGET} DEPENDS ${SHADERS_DIR}/slang.spv) +add_dependencies(${TEMPLATE_NAME} ${SHADER_TARGET}) + +# Assets +set (ASSET_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../assets/") +file (COPY ${ASSET_DIR}/viking_room.obj DESTINATION ${TEMPLATE_DIR}/models) +file (COPY ${ASSET_DIR}/viking_room.png DESTINATION ${TEMPLATE_DIR}/textures) diff --git a/attachments/template/main.cpp b/attachments/template/main.cpp new file mode 100644 index 00000000..3b685670 --- /dev/null +++ b/attachments/template/main.cpp @@ -0,0 +1,74 @@ +#include +#if defined(__INTELLISENSE__) || !defined(USE_CPP20_MODULES) +# include +#else +import vulkan_hpp; +#endif +#include + +#include +#include +#include + +const uint32_t WIDTH = 800; +const uint32_t HEIGHT = 600; + +class HelloTriangleApplication +{ + public: + void run() + { + initWindow(); + initVulkan(); + mainLoop(); + cleanup(); + } + + private: + GLFWwindow *window = nullptr; + + void initWindow() + { + glfwInit(); + + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); + + window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr); + } + + void initVulkan() + { + } + + void mainLoop() + { + while (!glfwWindowShouldClose(window)) + { + glfwPollEvents(); + } + } + + void cleanup() + { + glfwDestroyWindow(window); + + glfwTerminate(); + } +}; + +int main() +{ + try + { + HelloTriangleApplication app; + app.run(); + } + catch (const std::exception &e) + { + std::cerr << e.what() << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/attachments/template/shader.slang b/attachments/template/shader.slang new file mode 100644 index 00000000..a4fe6442 --- /dev/null +++ b/attachments/template/shader.slang @@ -0,0 +1,35 @@ +struct VSInput { + float3 inPosition; + float3 inColor; + float2 inTexCoord; +}; + +struct UniformBuffer { + float4x4 model; + float4x4 view; + float4x4 proj; +}; +ConstantBuffer ubo; + +struct VSOutput +{ + float4 pos : SV_Position; + float3 fragColor; + float2 fragTexCoord; +}; + +[shader("vertex")] +VSOutput vertMain(VSInput input) { + VSOutput output; + output.pos = mul(ubo.proj, mul(ubo.view, mul(ubo.model, float4(input.inPosition, 1.0)))); + output.fragColor = input.inColor; + output.fragTexCoord = input.inTexCoord; + return output; +} + +Sampler2D texture; + +[shader("fragment")] +float4 fragMain(VSOutput vertIn) : SV_TARGET { + return texture.Sample(vertIn.fragTexCoord); +} \ No newline at end of file diff --git a/en/02_Development_environment.adoc b/en/02_Development_environment.adoc index 75dc9eb2..ef632fb6 100644 --- a/en/02_Development_environment.adoc +++ b/en/02_Development_environment.adoc @@ -278,21 +278,6 @@ image::/images/library_directory.png[] Tinyobjloader can be installed with vcpkg like so: vcpkg install tinyobjloader -=== Setting up Visual Studio - -==== Setting up a CMake project - -Now that you have installed all the dependencies, we can set up a basic -CMake project for Vulkan and write a little bit of code to make sure that -everything works. - -We will assume that you already have some basic experience with CMake, like -how variables and rules work. If not, you can get up to speed very quickly with https://cmake.org/cmake/help/book/mastering-cmake/cmake/Help/guide/tutorial/[this tutorial]. - -You can now use the code from any of the following chapters found in the `attachment` folder as a template for your Vulkan projects. Make a copy, rename it to something like `HelloTriangle` and remove all the code in `main.cpp`. - -Congratulations, you're all set for xref:03_Drawing_a_triangle/00_Setup/00_Base_code.adoc[playing with Vulkan]! - == Linux These instructions will be aimed at Ubuntu, Fedora and Arch Linux users, but @@ -515,3 +500,28 @@ You are now all set for xref:03_Drawing_a_triangle/00_Setup/00_Base_code.adoc[th == Android Vulkan is a first-class API on Android and widely supported. But using it differs in several key areas from window management to build systems. So while the basic chapters focus on desktop platforms, the tutorial also has a xref:14_Android.adoc[dedicated chapter] that walks you through setting up your development environment and getting the tutorial code up-and-running on Android. + +== Setting up a CMake project + +Now that you have installed all the dependencies, we can set up a basic +CMake project for Vulkan and write a little bit of code to make sure that +everything works. + +We will assume that you already have some basic experience with CMake, like +how variables and rules work. If not, you can get up to speed very quickly with https://cmake.org/cmake/help/book/mastering-cmake/cmake/Help/guide/tutorial/[this tutorial]. + +The `attachment\template` folder contains a CMake template that you can use to create a project file in the `build` folder for your IDE of choice. Use this as a starting point to work along the tutorial: + +---- +cd attachments\template +cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=[path\to\vcpkg]\scripts\buildsystems\vcpkg.cmake +---- + +Alternatively you can do the same in the `attachments` folder, which will create a project with all chapters from the tutorial: + +---- +cd attachments +cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=[path\to\vcpkg]\scripts\buildsystems\vcpkg.cmake +---- + +Congratulations, you're all set for xref:03_Drawing_a_triangle/00_Setup/00_Base_code.adoc[playing with Vulkan]!