diff --git a/.gitmodules b/.gitmodules index c3b3e5b45234cb4b36b4367c5b112ffbc3ac8b4b..5f3821ff682a4526afabc87530291327f14af8bf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -82,3 +82,16 @@ [submodule "modules/shader_compiler/lib/json-c"] path = modules/shader_compiler/lib/json-c url = https://github.com/json-c/json-c.git +[submodule "modules/shader_compiler/lib/slang"] + path = modules/shader_compiler/lib/slang + url = https://github.com/TheJackiMonster/slang.git + branch = master +[submodule "modules/shader_compiler/lib/unordered_dense"] + path = modules/shader_compiler/lib/unordered_dense + url = https://github.com/martinus/unordered_dense.git +[submodule "modules/shader_compiler/lib/lz4"] + path = modules/shader_compiler/lib/lz4 + url = https://github.com/lz4/lz4.git +[submodule "modules/shader_compiler/lib/miniz"] + path = modules/shader_compiler/lib/miniz + url = https://github.com/richgel999/miniz.git diff --git a/modules/shader_compiler/CMakeLists.txt b/modules/shader_compiler/CMakeLists.txt index a00a896d500647b7ed38768f26235d36c8df6d29..b7452fe1ae8ca93d40b402bd820443d874c31d16 100644 --- a/modules/shader_compiler/CMakeLists.txt +++ b/modules/shader_compiler/CMakeLists.txt @@ -30,6 +30,9 @@ set(vkcv_shader_compiler_sources ${vkcv_shader_compiler_include}/vkcv/shader/LLVMCompiler.hpp ${vkcv_shader_compiler_source}/vkcv/shader/LLVMCompiler.cpp + + ${vkcv_shader_compiler_include}/vkcv/shader/SlangCompiler.hpp + ${vkcv_shader_compiler_source}/vkcv/shader/SlangCompiler.cpp ) filter_headers(vkcv_shader_compiler_sources ${vkcv_shader_compiler_include} vkcv_shader_compiler_headers) @@ -53,6 +56,12 @@ include(config/GLSLANG.cmake) include(config/Murmur3.cmake) include(config/Shady.cmake) +# Check and load SLANG +include(config/MINIZ.cmake) +include(config/LZ4.cmake) +include(config/UNORDERED_DENSE.cmake) +include(config/SLANG.cmake) + # link the required libraries to the module target_link_libraries(vkcv_shader_compiler ${vkcv_shader_compiler_libraries} vkcv) diff --git a/modules/shader_compiler/config/LZ4.cmake b/modules/shader_compiler/config/LZ4.cmake new file mode 100644 index 0000000000000000000000000000000000000000..87b2c906e9206efdc65383be328cbeb46fb7be16 --- /dev/null +++ b/modules/shader_compiler/config/LZ4.cmake @@ -0,0 +1,16 @@ + +use_git_submodule("${vkcv_shader_compiler_lib_path}/lz4" lz4_status) + +if (${lz4_status}) + set(LZ4_BUNDLED_MODE ON) + add_subdirectory(${vkcv_shader_compiler_lib}/lz4/build/cmake SYSTEM) + + if(MSVC) + target_compile_options( + lz4_static + PRIVATE /wd5045 /wd4820 /wd4711 /wd6385 /wd6262 + ) + endif() + + set(lz4_include ${vkcv_shader_compiler_lib}/lz4/lib) +endif () diff --git a/modules/shader_compiler/config/MINIZ.cmake b/modules/shader_compiler/config/MINIZ.cmake new file mode 100644 index 0000000000000000000000000000000000000000..0b32ea3667862cb4fb07bb4daa7ebb001aed4bd4 --- /dev/null +++ b/modules/shader_compiler/config/MINIZ.cmake @@ -0,0 +1,14 @@ + +use_git_submodule("${vkcv_shader_compiler_lib_path}/miniz" miniz_status) + +if (${miniz_status}) + add_subdirectory(${vkcv_shader_compiler_lib}/miniz SYSTEM) + + set_property(TARGET miniz PROPERTY POSITION_INDEPENDENT_CODE ON) + # Work around https://github.com/richgel999/miniz/pull/292 + get_target_property(miniz_c_launcher miniz C_COMPILER_LAUNCHER) + if(MSVC AND miniz_c_launcher MATCHES "ccache") + set_property(TARGET miniz PROPERTY C_COMPILER_LAUNCHER) + set_property(TARGET miniz PROPERTY MSVC_DEBUG_INFORMATION_FORMAT "") + endif() +endif () diff --git a/modules/shader_compiler/config/SLANG.cmake b/modules/shader_compiler/config/SLANG.cmake new file mode 100644 index 0000000000000000000000000000000000000000..a9bd071fa00293a5e28e011ee51bad4569188053 --- /dev/null +++ b/modules/shader_compiler/config/SLANG.cmake @@ -0,0 +1,64 @@ + +use_git_submodule("${vkcv_shader_compiler_lib_path}/slang" slang_status) + +if (${slang_status}) + set(EXTERNAL_MINIZ ON CACHE INTERNAL "") + set(EXTERNAL_LZ4 ON CACHE INTERNAL "") + set(EXTERNAL_VULKAN_HEADERS ON CACHE INTERNAL "") + set(EXTERNAL_SPIRV_HEADERS ON CACHE INTERNAL "") + set(EXTERNAL_UNORDERED_DENSE ON CACHE INTERNAL "") + + set(SLANG_ENABLE_CUDA OFF CACHE INTERNAL "") + set(SLANG_ENABLE_OPTIX OFF CACHE INTERNAL "") + set(SLANG_ENABLE_NVAPI OFF CACHE INTERNAL "") + set(SLANG_ENABLE_XLIB OFF CACHE INTERNAL "") + set(SLANG_ENABLE_AFTERMATH OFF CACHE INTERNAL "") + set(SLANG_ENABLE_DX_ON_VK OFF CACHE INTERNAL "") + set(SLANG_EMBED_STDLIB_SOURCE OFF CACHE INTERNAL "") + set(SLANG_EMBED_STDLIB ON CACHE INTERNAL "") + set(SLANG_ENABLE_FULL_IR_VALIDATION OFF CACHE INTERNAL "") + set(SLANG_ENABLE_IR_BREAK_ALLOC OFF CACHE INTERNAL "") + set(SLANG_ENABLE_ASAN OFF CACHE INTERNAL "") + set(SLANG_ENABLE_PREBUILT_BINARIES OFF CACHE INTERNAL "") + set(SLANG_ENABLE_GFX OFF CACHE INTERNAL "") + set(SLANG_ENABLE_SLANGD OFF CACHE INTERNAL "") + set(SLANG_ENABLE_SLANGC OFF CACHE INTERNAL "") + set(SLANG_ENABLE_SLANGRT OFF CACHE INTERNAL "") + set(SLANG_ENABLE_SLANG_GLSLANG OFF CACHE INTERNAL "") + set(SLANG_ENABLE_TESTS OFF CACHE INTERNAL "") + set(SLANG_ENABLE_EXAMPLES OFF CACHE INTERNAL "") + set(SLANG_LIB_TYPE ${vkcv_build_attribute} CACHE INTERNAL "") + set(SLANG_SPIRV_HEADERS_INCLUDE_DIR ${spirv_headers_include} CACHE INTERNAL "") + + add_subdirectory(${vkcv_shader_compiler_lib}/slang) + + set(slang_system_includes "") + list(APPEND slang_system_includes ${spirv_headers_include}) + list(APPEND slang_system_includes ${unordered_dense_include}) + list(APPEND slang_system_includes ${lz4_include}) + + target_include_directories(core SYSTEM BEFORE PRIVATE ${slang_system_includes}) + target_include_directories(compiler-core SYSTEM BEFORE PRIVATE ${slang_system_includes}) + target_include_directories(slang SYSTEM BEFORE PRIVATE ${slang_system_includes}) + target_include_directories(slang-cpp-extractor SYSTEM BEFORE PRIVATE ${slang_system_includes}) + target_include_directories(slang-embed SYSTEM BEFORE PRIVATE ${slang_system_includes}) + target_include_directories(slang-generate SYSTEM BEFORE PRIVATE ${slang_system_includes}) + target_include_directories(slang-lookup-generator SYSTEM BEFORE PRIVATE ${slang_system_includes}) + target_include_directories(slang-capability-generator SYSTEM BEFORE PRIVATE ${slang_system_includes}) + target_include_directories(slang-spirv-embed-generator SYSTEM BEFORE PRIVATE ${slang_system_includes}) + target_include_directories(slang-bootstrap SYSTEM BEFORE PRIVATE ${slang_system_includes}) + target_include_directories(prelude SYSTEM BEFORE PRIVATE ${slang_system_includes}) + target_include_directories(slang-capability-defs SYSTEM BEFORE PRIVATE ${slang_system_includes}) + target_include_directories(slang-capability-lookup SYSTEM BEFORE PRIVATE ${slang_system_includes}) + target_include_directories(slang-lookup-tables SYSTEM BEFORE PRIVATE ${slang_system_includes}) + target_include_directories(slang-no-embedded-stdlib SYSTEM BEFORE PRIVATE ${slang_system_includes}) + + set(SLANG_STDLIB_META_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/${vkcv_shader_compiler_lib}/slang/source/slang/stdlib-meta) + + target_include_directories(slang BEFORE PUBLIC ${SLANG_STDLIB_META_OUTPUT_DIR}) + + message(WARNING ${SLANG_STDLIB_META_OUTPUT_DIR}) + + list(APPEND vkcv_shader_compiler_libraries slang lz4_static miniz unordered_dense::unordered_dense) + list(APPEND vkcv_shader_compiler_includes ${vkcv_shader_compiler_lib}/slang/include ${slang_system_includes}) +endif () diff --git a/modules/shader_compiler/config/SPIRV-Headers.cmake b/modules/shader_compiler/config/SPIRV-Headers.cmake index b5f47dbe91d3da73f585a55765514bcb3a7412c9..5ef39caa39344c459d90883674beae176c8d1c68 100644 --- a/modules/shader_compiler/config/SPIRV-Headers.cmake +++ b/modules/shader_compiler/config/SPIRV-Headers.cmake @@ -2,8 +2,10 @@ use_git_submodule("${vkcv_shader_compiler_lib_path}/SPIRV-Headers" spriv_headers_status) if (${spriv_headers_status}) - add_subdirectory(${vkcv_shader_compiler_lib}/SPIRV-Headers) + add_subdirectory(${vkcv_shader_compiler_lib}/SPIRV-Headers SYSTEM) + + set(spirv_headers_include ${vkcv_shader_compiler_lib_path}/SPIRV-Headers/include) list(APPEND vkcv_shader_compiler_libraries SPIRV-Headers) - list(APPEND vkcv_shader_compiler_includes ${vkcv_shader_compiler_lib}/SPIRV-Headers/include) + list(APPEND vkcv_shader_compiler_includes ${spirv_headers_include}) endif () diff --git a/modules/shader_compiler/config/Shady.cmake b/modules/shader_compiler/config/Shady.cmake index 56da131a23e3680e487c678260de6af2c9c3aba6..3156521dbc200ff202f48f3994caa783801f3af5 100644 --- a/modules/shader_compiler/config/Shady.cmake +++ b/modules/shader_compiler/config/Shady.cmake @@ -3,8 +3,8 @@ use_git_submodule("${vkcv_shader_compiler_lib_path}/shady" shady_status) if (${shady_status}) set(EXTERNAL_JSON_C ON CACHE INTERNAL "") - set(EXTERNAL_SPIRV_HEADERS ON CACHE INTERNAL "") - set(EXTERNAL_MURMUR3 ON CACHE INTERNAL "") + set(EXTERNAL_SPIRV_HEADERS ON CACHE INTERNAL "") + set(EXTERNAL_MURMUR3 ON CACHE INTERNAL "") set(EXTERNAL_JSON_C_INCLUDE ${JSON_C_INCLUDE_DIR} CACHE INTERNAL "") diff --git a/modules/shader_compiler/config/UNORDERED_DENSE.cmake b/modules/shader_compiler/config/UNORDERED_DENSE.cmake new file mode 100644 index 0000000000000000000000000000000000000000..8c2e60aa129dbe2248b1691b7b07b09d66da0eb8 --- /dev/null +++ b/modules/shader_compiler/config/UNORDERED_DENSE.cmake @@ -0,0 +1,8 @@ + +use_git_submodule("${vkcv_shader_compiler_lib_path}/unordered_dense" unordered_dense_status) + +if (${unordered_dense_status}) + add_subdirectory(${vkcv_shader_compiler_lib}/unordered_dense SYSTEM) + + set(unordered_dense_include ${vkcv_shader_compiler_lib_path}/unordered_dense/include) +endif () diff --git a/modules/shader_compiler/include/vkcv/shader/Compiler.hpp b/modules/shader_compiler/include/vkcv/shader/Compiler.hpp index 873c7ba05c27075e020f9b660f74572ad4120a7d..67d63a280497374bd0bfb8cdf5f3bd53ce43f8bd 100644 --- a/modules/shader_compiler/include/vkcv/shader/Compiler.hpp +++ b/modules/shader_compiler/include/vkcv/shader/Compiler.hpp @@ -84,11 +84,11 @@ namespace vkcv::shader { * @param[in] includePath Include path for shaders * @param[in] update Flag to update shaders during runtime */ - virtual void compile(ShaderStage shaderStage, + void compile(ShaderStage shaderStage, const std::filesystem::path& shaderPath, const ShaderCompiledFunction& compiled, - const std::filesystem::path& includePath, - bool update) = 0; + const std::filesystem::path& includePath = "", + bool update = false); /** * Compile a shader program from a specific map of given file paths for diff --git a/modules/shader_compiler/include/vkcv/shader/GlslangCompiler.hpp b/modules/shader_compiler/include/vkcv/shader/GlslangCompiler.hpp index 161c796ec8cd7fbb1a74ad673c25fc07804b9c97..443290de52d858a59eca5954c0a427b3fb0fef27 100644 --- a/modules/shader_compiler/include/vkcv/shader/GlslangCompiler.hpp +++ b/modules/shader_compiler/include/vkcv/shader/GlslangCompiler.hpp @@ -1,7 +1,5 @@ #pragma once -#include <filesystem> - #include <vkcv/ShaderStage.hpp> #include "Compiler.hpp" @@ -57,23 +55,6 @@ namespace vkcv::shader { */ GlslangCompiler& operator=(GlslangCompiler&& other) = default; - /** - * Compile a shader from a specific file path for a target stage with - * a custom shader include path and an event function called if the - * compilation completes. - * - * @param[in] shaderStage Shader pipeline stage - * @param[in] shaderPath Filepath of shader - * @param[in] compiled Shader compilation event - * @param[in] includePath Include path for shaders - * @param[in] update Flag to update shaders during runtime - */ - void compile(ShaderStage shaderStage, - const std::filesystem::path& shaderPath, - const ShaderCompiledFunction& compiled, - const std::filesystem::path& includePath = "", - bool update = false) override; - }; /** @} */ diff --git a/modules/shader_compiler/include/vkcv/shader/ShadyCompiler.hpp b/modules/shader_compiler/include/vkcv/shader/ShadyCompiler.hpp index 65e732f021d80d60a653962c82b51e44b4ab887b..f9278329d9278d51bfa36649bafe924bdd1936c7 100644 --- a/modules/shader_compiler/include/vkcv/shader/ShadyCompiler.hpp +++ b/modules/shader_compiler/include/vkcv/shader/ShadyCompiler.hpp @@ -57,23 +57,6 @@ namespace vkcv::shader { */ ShadyCompiler& operator=(ShadyCompiler&& other) = default; - /** - * Compile a shader from a specific file path for a target stage with - * a custom shader include path and an event function called if the - * compilation completes. - * - * @param[in] shaderStage Shader pipeline stage - * @param[in] shaderPath Filepath of shader - * @param[in] compiled Shader compilation event - * @param[in] includePath Include path for shaders - * @param[in] update Flag to update shaders during runtime - */ - void compile(ShaderStage shaderStage, - const std::filesystem::path& shaderPath, - const ShaderCompiledFunction& compiled, - const std::filesystem::path& includePath = "", - bool update = false) override; - }; /** @} */ diff --git a/modules/shader_compiler/include/vkcv/shader/SlangCompiler.hpp b/modules/shader_compiler/include/vkcv/shader/SlangCompiler.hpp new file mode 100644 index 0000000000000000000000000000000000000000..556627e97b90f5312bc21535fcf30d39629a5bab --- /dev/null +++ b/modules/shader_compiler/include/vkcv/shader/SlangCompiler.hpp @@ -0,0 +1,91 @@ +#pragma once + +#include <filesystem> + +#include <vkcv/ShaderStage.hpp> +#include "Compiler.hpp" + +namespace vkcv::shader { + + /** + * @addtogroup vkcv_shader + * @{ + */ + + enum class SlangCompileProfile { + GLSL, + HLSL, + SPIRV, + UNKNOWN + }; + + /** + * An abstract class to handle Slang runtime shader compilation. + */ + class SlangCompiler : public Compiler { + private: + SlangCompileProfile m_profile; + + public: + /** + * The constructor of a runtime Slang shader compiler instance. + * + * @param[in] profile Compile profile (optional) + */ + SlangCompiler(SlangCompileProfile profile = SlangCompileProfile::UNKNOWN); + + /** + * The copy-constructor of a runtime Slang shader compiler instance. + * + * @param[in] other Other instance of a Slang shader compiler instance + */ + SlangCompiler(const SlangCompiler& other); + + /** + * The move-constructor of a runtime Slang shader compiler instance. + * + * @param[out] other Other instance of a Slang shader compiler instance + */ + SlangCompiler(SlangCompiler&& other) = default; + + /** + * The destructor of a runtime Slang shader compiler instance. + */ + ~SlangCompiler(); + + /** + * The copy-operator of a runtime Slang shader compiler instance. + * + * @param[in] other Other instance of a Slang shader compiler instance + * @return Reference to this instance + */ + SlangCompiler& operator=(const SlangCompiler& other); + + /** + * The copy-operator of a runtime Slang shader compiler instance. + * + * @param[out] other Other instance of a Slang shader compiler instance + * @return Reference to this instance + */ + SlangCompiler& operator=(SlangCompiler&& other) = default; + + /** + * Compile a shader from source for a target stage with a custom shader + * include path and an event function called if the compilation completes. + * + * @param[in] shaderStage Shader pipeline stage + * @param[in] shaderSource Source of shader + * @param[in] compiled Shader compilation event + * @param[in] includePath Include path for shaders + * @return Result if the compilation succeeds + */ + bool compileSource(ShaderStage shaderStage, + const std::string& shaderSource, + const ShaderCompiledFunction& compiled, + const std::filesystem::path& includePath) override; + + }; + + /** @} */ + +} diff --git a/modules/shader_compiler/lib/lz4 b/modules/shader_compiler/lib/lz4 new file mode 160000 index 0000000000000000000000000000000000000000..68959d27c3ec37b339b3b8ecfea155faf0ef94f2 --- /dev/null +++ b/modules/shader_compiler/lib/lz4 @@ -0,0 +1 @@ +Subproject commit 68959d27c3ec37b339b3b8ecfea155faf0ef94f2 diff --git a/modules/shader_compiler/lib/miniz b/modules/shader_compiler/lib/miniz new file mode 160000 index 0000000000000000000000000000000000000000..bf7a1f0a5aa1deae9cab2d73b5ef9edec41b877c --- /dev/null +++ b/modules/shader_compiler/lib/miniz @@ -0,0 +1 @@ +Subproject commit bf7a1f0a5aa1deae9cab2d73b5ef9edec41b877c diff --git a/modules/shader_compiler/lib/slang b/modules/shader_compiler/lib/slang new file mode 160000 index 0000000000000000000000000000000000000000..e1734897a3681f7685b4768fd8d40f446134d483 --- /dev/null +++ b/modules/shader_compiler/lib/slang @@ -0,0 +1 @@ +Subproject commit e1734897a3681f7685b4768fd8d40f446134d483 diff --git a/modules/shader_compiler/lib/unordered_dense b/modules/shader_compiler/lib/unordered_dense new file mode 160000 index 0000000000000000000000000000000000000000..d911053e390816ecc5dedd5a9d6b4bb5ed92b4c9 --- /dev/null +++ b/modules/shader_compiler/lib/unordered_dense @@ -0,0 +1 @@ +Subproject commit d911053e390816ecc5dedd5a9d6b4bb5ed92b4c9 diff --git a/modules/shader_compiler/src/vkcv/shader/Compiler.cpp b/modules/shader_compiler/src/vkcv/shader/Compiler.cpp index 194faee90b6e8156c663ddabbffec509bf6a0451..842ad6ab2ab2edd69bf24c529cf8296b1b3f8b1c 100644 --- a/modules/shader_compiler/src/vkcv/shader/Compiler.cpp +++ b/modules/shader_compiler/src/vkcv/shader/Compiler.cpp @@ -41,6 +41,33 @@ namespace vkcv::shader { }, directory ); } + + void Compiler::compile(ShaderStage shaderStage, + const std::filesystem::path &shaderPath, + const ShaderCompiledFunction &compiled, + const std::filesystem::path &includePath, + bool update) { + std::string shaderCode; + bool result = readTextFromFile(shaderPath, shaderCode); + + if (!result) { + vkcv_log(LogLevel::ERROR, "Loading shader failed: (%s)", shaderPath.string().c_str()); + } + + if (!includePath.empty()) { + result = compileSource(shaderStage, shaderCode, compiled, includePath); + } else { + result = compileSource(shaderStage, shaderCode, compiled, shaderPath.parent_path()); + } + + if (!result) { + vkcv_log(LogLevel::ERROR, "Shader compilation failed: (%s)", shaderPath.string().c_str()); + } + + if (update) { + // TODO: Shader hot compilation during runtime + } + } void Compiler::compileProgram(ShaderProgram& program, const Dictionary<ShaderStage, const std::filesystem::path>& stages, diff --git a/modules/shader_compiler/src/vkcv/shader/GlslangCompiler.cpp b/modules/shader_compiler/src/vkcv/shader/GlslangCompiler.cpp index 2a2847ada699364c025f957b204b58b3190a8ed2..b749f9501989ab20fd239086ba4e66e18ed30f54 100644 --- a/modules/shader_compiler/src/vkcv/shader/GlslangCompiler.cpp +++ b/modules/shader_compiler/src/vkcv/shader/GlslangCompiler.cpp @@ -36,31 +36,4 @@ namespace vkcv::shader { return *this; } - void GlslangCompiler::compile(ShaderStage shaderStage, - const std::filesystem::path &shaderPath, - const ShaderCompiledFunction &compiled, - const std::filesystem::path &includePath, - bool update) { - std::string shaderCode; - bool result = readTextFromFile(shaderPath, shaderCode); - - if (!result) { - vkcv_log(LogLevel::ERROR, "Loading shader failed: (%s)", shaderPath.string().c_str()); - } - - if (!includePath.empty()) { - result = compileSource(shaderStage, shaderCode, compiled, includePath); - } else { - result = compileSource(shaderStage, shaderCode, compiled, shaderPath.parent_path()); - } - - if (!result) { - vkcv_log(LogLevel::ERROR, "Shader compilation failed: (%s)", shaderPath.string().c_str()); - } - - if (update) { - // TODO: Shader hot compilation during runtime - } - } - } diff --git a/modules/shader_compiler/src/vkcv/shader/ShadyCompiler.cpp b/modules/shader_compiler/src/vkcv/shader/ShadyCompiler.cpp index 6168fcfa2baa04b8a7f261db8828bfab8c2ed018..80b44a3626f2238cebaae5d2cc23ed5fb9f98681 100644 --- a/modules/shader_compiler/src/vkcv/shader/ShadyCompiler.cpp +++ b/modules/shader_compiler/src/vkcv/shader/ShadyCompiler.cpp @@ -9,31 +9,4 @@ namespace vkcv::shader { ShadyCompiler::ShadyCompiler() : Compiler() {} - void ShadyCompiler::compile(ShaderStage shaderStage, - const std::filesystem::path &shaderPath, - const ShaderCompiledFunction &compiled, - const std::filesystem::path &includePath, - bool update) { - std::string shaderCode; - bool result = readTextFromFile(shaderPath, shaderCode); - - if (!result) { - vkcv_log(LogLevel::ERROR, "Loading shader failed: (%s)", shaderPath.string().c_str()); - } - - if (!includePath.empty()) { - result = compileSource(shaderStage, shaderCode, compiled, includePath); - } else { - result = compileSource(shaderStage, shaderCode, compiled, shaderPath.parent_path()); - } - - if (!result) { - vkcv_log(LogLevel::ERROR, "Shader compilation failed: (%s)", shaderPath.string().c_str()); - } - - if (update) { - // TODO: Shader hot compilation during runtime - } - } - } diff --git a/modules/shader_compiler/src/vkcv/shader/SlangCompiler.cpp b/modules/shader_compiler/src/vkcv/shader/SlangCompiler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7feff09b5190cc36d6f25ee9a230335c1435cf0d --- /dev/null +++ b/modules/shader_compiler/src/vkcv/shader/SlangCompiler.cpp @@ -0,0 +1,187 @@ + +#include "vkcv/shader/SlangCompiler.hpp" + +#include <cstdint> +#include <vkcv/File.hpp> +#include <vkcv/Logger.hpp> + +#include <slang.h> +#include <slang-com-ptr.h> +#include <slang-com-helper.h> +#include <vkcv/ShaderStage.hpp> + +namespace vkcv::shader { + + static uint32_t s_CompilerCount = 0; + static Slang::ComPtr<slang::IGlobalSession> s_GlobalSession; + + SlangCompiler::SlangCompiler(SlangCompileProfile profile) + : Compiler(), m_profile(profile) { + if (s_CompilerCount == 0) { + slang::createGlobalSession(s_GlobalSession.writeRef()); + } + + s_CompilerCount++; + } + + SlangCompiler::SlangCompiler(const SlangCompiler &other) + : Compiler(other), m_profile(other.m_profile) { + s_CompilerCount++; + } + + SlangCompiler::~SlangCompiler() { + s_CompilerCount--; + } + + SlangCompiler &SlangCompiler::operator=(const SlangCompiler &other) { + m_profile = other.m_profile; + s_CompilerCount++; + return *this; + } + + constexpr SlangStage findShaderLanguage(ShaderStage shaderStage) { + switch (shaderStage) { + case ShaderStage::VERTEX: + return SlangStage::SLANG_STAGE_VERTEX; + case ShaderStage::TESS_CONTROL: + return SlangStage::SLANG_STAGE_HULL; + case ShaderStage::TESS_EVAL: + return SlangStage::SLANG_STAGE_DOMAIN; + case ShaderStage::GEOMETRY: + return SlangStage::SLANG_STAGE_GEOMETRY; + case ShaderStage::FRAGMENT: + return SlangStage::SLANG_STAGE_FRAGMENT; + case ShaderStage::COMPUTE: + return SlangStage::SLANG_STAGE_COMPUTE; + case ShaderStage::TASK: + return SlangStage::SLANG_STAGE_AMPLIFICATION; + case ShaderStage::MESH: + return SlangStage::SLANG_STAGE_MESH; + case ShaderStage::RAY_GEN: + return SlangStage::SLANG_STAGE_RAY_GENERATION; + case ShaderStage::RAY_CLOSEST_HIT: + return SlangStage::SLANG_STAGE_CLOSEST_HIT; + case ShaderStage::RAY_MISS: + return SlangStage::SLANG_STAGE_MISS; + case ShaderStage::RAY_INTERSECTION: + return SlangStage::SLANG_STAGE_INTERSECTION; + case ShaderStage::RAY_ANY_HIT: + return SlangStage::SLANG_STAGE_ANY_HIT; + case ShaderStage::RAY_CALLABLE: + return SlangStage::SLANG_STAGE_CALLABLE; + default: + return SlangStage::SLANG_STAGE_NONE; + } + } + + bool SlangCompiler::compileSource(ShaderStage shaderStage, + const std::string& shaderSource, + const ShaderCompiledFunction& compiled, + const std::filesystem::path& includePath) { + slang::SessionDesc sessionDesc = {}; + slang::TargetDesc targetDesc = {}; + SlangSourceLanguage lang; + + targetDesc.format = SLANG_SPIRV; + + switch (m_profile) { + case SlangCompileProfile::GLSL: + targetDesc.profile = s_GlobalSession->findProfile("glsl_460"); + sessionDesc.defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_COLUMN_MAJOR; + sessionDesc.allowGLSLSyntax = true; + lang = SLANG_SOURCE_LANGUAGE_GLSL; + break; + case SlangCompileProfile::HLSL: + targetDesc.profile = s_GlobalSession->findProfile("sm_5_0"); + sessionDesc.defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_ROW_MAJOR; + lang = SLANG_SOURCE_LANGUAGE_HLSL; + break; + case SlangCompileProfile::SPIRV: + targetDesc.profile = s_GlobalSession->findProfile("spirv_1_5"); + targetDesc.flags = SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY; + lang = SLANG_SOURCE_LANGUAGE_SPIRV; + break; + default: + lang = SLANG_SOURCE_LANGUAGE_UNKNOWN; + break; + } + + sessionDesc.targets = &targetDesc; + sessionDesc.targetCount = 1; + + const char *searchPath = includePath.c_str(); + sessionDesc.searchPaths = &searchPath; + sessionDesc.searchPathCount = 1; + + std::vector<slang::PreprocessorMacroDesc> macros; + macros.reserve(m_defines.size()); + + for (const auto& define : m_defines) { + const slang::PreprocessorMacroDesc macro = { + define.first.c_str(), + define.second.c_str() + }; + + macros.push_back(macro); + } + + sessionDesc.preprocessorMacros = macros.data(); + sessionDesc.preprocessorMacroCount = macros.size(); + + Slang::ComPtr<slang::ISession> session; + if (SLANG_FAILED(s_GlobalSession->createSession(sessionDesc, session.writeRef()))) { + vkcv_log(LogLevel::ERROR, "Compiler session could not be created"); + return false; + } + + Slang::ComPtr<slang::ICompileRequest> request; + if (SLANG_FAILED(session->createCompileRequest(request.writeRef()))) { + vkcv_log(LogLevel::ERROR, "Compilation request could not be created"); + return false; + } + + const int translationUnit = request->addTranslationUnit(lang, nullptr); + request->addTranslationUnitSourceString(translationUnit, nullptr, shaderSource.c_str()); + + const int entryPoint = request->addEntryPoint( + translationUnit, "main", findShaderLanguage(shaderStage) + ); + + if (SLANG_FAILED(request->compile())) { + vkcv_log(LogLevel::ERROR, "Compilation process failed"); + return false; + } + + size_t size; + const void *code = request->getEntryPointCode(entryPoint, &size); + + if (0 == size) { + code = request->getCompileRequestCode(&size); + } + + if ((0 == size) || (!code)) { + vkcv_log(LogLevel::ERROR, "Entry point could not be found\n%s", + request->getDiagnosticOutput()); + return false; + } + + std::vector<uint32_t> spirv; + spirv.resize(size / sizeof(uint32_t)); + memcpy(spirv.data(), code, spirv.size() * sizeof(uint32_t)); + + const std::filesystem::path tmp_path = generateTemporaryFilePath(); + + if (!writeBinaryToFile(tmp_path, spirv)) { + vkcv_log(LogLevel::ERROR, "Spir-V could not be written to disk"); + return false; + } + + if (compiled) { + compiled(shaderStage, tmp_path); + } + + std::filesystem::remove(tmp_path); + return true; + } + +} diff --git a/modules/shader_compiler/src/vkcv/shader/SlimCompiler.cpp b/modules/shader_compiler/src/vkcv/shader/SlimCompiler.cpp index 028d0618940d27cf00af920653e87d89f3ff7025..6270bb8efa245617da4c7f8f5a7e8663ccd282d1 100644 --- a/modules/shader_compiler/src/vkcv/shader/SlimCompiler.cpp +++ b/modules/shader_compiler/src/vkcv/shader/SlimCompiler.cpp @@ -14,15 +14,15 @@ namespace vkcv::shader { : ShadyCompiler(), m_target(target) {} static bool shadyCompileModule(Module* module, - ShaderStage shaderStage, - const std::string& shaderSource, - const ShaderCompiledFunction &compiled, - const std::filesystem::path &includePath) { + ShaderStage shaderStage, + const std::string& shaderSource, + const ShaderCompiledFunction &compiled, + const std::filesystem::path &includePath) { ShadyErrorCodes codes = driver_load_source_file( - SrcSlim, - shaderSource.length(), + SrcSlim, + shaderSource.length(), shaderSource.c_str(), - module + module ); switch (codes) { @@ -46,7 +46,7 @@ namespace vkcv::shader { DriverConfig config = default_driver_config(); - config.target = TgtSPV; + config.target = TgtSPV; config.output_filename = tmp_path.string().c_str(); codes = driver_compile(&config, module); @@ -78,10 +78,10 @@ namespace vkcv::shader { } static bool shadyCompileArena(IrArena* arena, - ShaderStage shaderStage, - const std::string& shaderSource, - const ShaderCompiledFunction &compiled, - const std::filesystem::path &includePath) { + ShaderStage shaderStage, + const std::string& shaderSource, + const ShaderCompiledFunction &compiled, + const std::filesystem::path &includePath) { Module* module = new_module(arena, "slim_module"); if (nullptr == module) { @@ -92,11 +92,11 @@ namespace vkcv::shader { return shadyCompileModule(module, shaderStage, shaderSource, compiled, includePath); } - bool SlimCompiler::compileSource(ShaderStage shaderStage, - const std::string& shaderSource, - const ShaderCompiledFunction& compiled, - const std::filesystem::path& includePath) { - if (ShaderStage::COMPUTE != shaderStage) { + bool SlimCompiler::compileSource(ShaderStage shaderStage, + const std::string& shaderSource, + const ShaderCompiledFunction& compiled, + const std::filesystem::path& includePath) { + if (ShaderStage::COMPUTE != shaderStage) { vkcv_log(LogLevel::ERROR, "Shader stage not supported"); return false; } @@ -112,7 +112,7 @@ namespace vkcv::shader { bool result = shadyCompileArena(arena, shaderStage, shaderSource, compiled, includePath); destroy_ir_arena(arena); - return result; - } + return result; + } }