From 271347ad0205e6ea206cfc01e04b4fe1d1165d8c Mon Sep 17 00:00:00 2001 From: Tobias Frisch <tfrisch@uni-koblenz.de> Date: Sat, 13 Jan 2024 01:47:24 +0100 Subject: [PATCH] Implement separate compiler classes for LLVM and slim front-ends Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de> --- modules/shader_compiler/CMakeLists.txt | 6 + .../include/vkcv/shader/GlslangCompiler.hpp | 2 - .../include/vkcv/shader/LLVMCompiler.hpp | 53 ++++++++ .../include/vkcv/shader/ShadyCompiler.hpp | 55 +++++++- .../include/vkcv/shader/SlimCompiler.hpp | 53 ++++++++ .../src/vkcv/shader/LLVMCompiler.cpp | 119 +++++++++++++++++ .../src/vkcv/shader/ShadyCompiler.cpp | 126 +++--------------- .../src/vkcv/shader/SlimCompiler.cpp | 119 +++++++++++++++++ 8 files changed, 417 insertions(+), 116 deletions(-) create mode 100644 modules/shader_compiler/include/vkcv/shader/LLVMCompiler.hpp create mode 100644 modules/shader_compiler/include/vkcv/shader/SlimCompiler.hpp create mode 100644 modules/shader_compiler/src/vkcv/shader/LLVMCompiler.cpp create mode 100644 modules/shader_compiler/src/vkcv/shader/SlimCompiler.cpp diff --git a/modules/shader_compiler/CMakeLists.txt b/modules/shader_compiler/CMakeLists.txt index 35b31192..960eb65c 100644 --- a/modules/shader_compiler/CMakeLists.txt +++ b/modules/shader_compiler/CMakeLists.txt @@ -24,6 +24,12 @@ set(vkcv_shader_compiler_sources ${vkcv_shader_compiler_include}/vkcv/shader/ShadyCompiler.hpp ${vkcv_shader_compiler_source}/vkcv/shader/ShadyCompiler.cpp + + ${vkcv_shader_compiler_include}/vkcv/shader/SlimCompiler.hpp + ${vkcv_shader_compiler_source}/vkcv/shader/SlimCompiler.cpp + + ${vkcv_shader_compiler_include}/vkcv/shader/LLVMCompiler.hpp + ${vkcv_shader_compiler_source}/vkcv/shader/LLVMCompiler.cpp ) filter_headers(vkcv_shader_compiler_sources ${vkcv_shader_compiler_include} vkcv_shader_compiler_headers) diff --git a/modules/shader_compiler/include/vkcv/shader/GlslangCompiler.hpp b/modules/shader_compiler/include/vkcv/shader/GlslangCompiler.hpp index 837b9b1d..161c796e 100644 --- a/modules/shader_compiler/include/vkcv/shader/GlslangCompiler.hpp +++ b/modules/shader_compiler/include/vkcv/shader/GlslangCompiler.hpp @@ -19,8 +19,6 @@ namespace vkcv::shader { public: /** * The constructor of a runtime Glslang shader compiler instance. - * - * @param[in] target Compile target (optional) */ GlslangCompiler(); diff --git a/modules/shader_compiler/include/vkcv/shader/LLVMCompiler.hpp b/modules/shader_compiler/include/vkcv/shader/LLVMCompiler.hpp new file mode 100644 index 00000000..2d075d7b --- /dev/null +++ b/modules/shader_compiler/include/vkcv/shader/LLVMCompiler.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include <filesystem> + +#include <vkcv/ShaderStage.hpp> +#include "ShadyCompiler.hpp" + +namespace vkcv::shader { + + /** + * @addtogroup vkcv_shader + * @{ + */ + + enum class LLVMCompileTarget { + UNKNOWN + }; + + /** + * A class to handle LLVM runtime shader compilation. + */ + class LLVMCompiler : public ShadyCompiler { + private: + LLVMCompileTarget m_target; + + public: + /** + * The constructor of a runtime LLVM shader compiler instance. + * + * @param[in] target Compile target (optional) + */ + explicit LLVMCompiler(LLVMCompileTarget target = LLVMCompileTarget::UNKNOWN); + + /** + * Compile a LLVM 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/include/vkcv/shader/ShadyCompiler.hpp b/modules/shader_compiler/include/vkcv/shader/ShadyCompiler.hpp index 181d30da..65e732f0 100644 --- a/modules/shader_compiler/include/vkcv/shader/ShadyCompiler.hpp +++ b/modules/shader_compiler/include/vkcv/shader/ShadyCompiler.hpp @@ -7,20 +7,67 @@ namespace vkcv::shader { + /** + * @addtogroup vkcv_shader + * @{ + */ + + /** + * An abstract class to handle Shady runtime shader compilation. + */ class ShadyCompiler : public Compiler { public: + /** + * The constructor of a runtime Shady shader compiler instance. + */ ShadyCompiler(); - ShadyCompiler(const ShadyCompiler& other); + /** + * The copy-constructor of a runtime Shady shader compiler instance. + * + * @param[in] other Other instance of a Shady shader compiler instance + */ + ShadyCompiler(const ShadyCompiler& other) = default; + /** + * The move-constructor of a runtime Shady shader compiler instance. + * + * @param[out] other Other instance of a Shady shader compiler instance + */ ShadyCompiler(ShadyCompiler&& other) = default; - ~ShadyCompiler(); + /** + * The destructor of a runtime Shady shader compiler instance. + */ + ~ShadyCompiler() = default; - ShadyCompiler& operator=(const ShadyCompiler& other); + /** + * The copy-operator of a runtime Shady shader compiler instance. + * + * @param[in] other Other instance of a Shady shader compiler instance + * @return Reference to this instance + */ + ShadyCompiler& operator=(const ShadyCompiler& other) = default; + /** + * The copy-operator of a runtime Shady shader compiler instance. + * + * @param[out] other Other instance of a Shady shader compiler instance + * @return Reference to this instance + */ 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, @@ -29,4 +76,6 @@ namespace vkcv::shader { }; + /** @} */ + } diff --git a/modules/shader_compiler/include/vkcv/shader/SlimCompiler.hpp b/modules/shader_compiler/include/vkcv/shader/SlimCompiler.hpp new file mode 100644 index 00000000..47d9596e --- /dev/null +++ b/modules/shader_compiler/include/vkcv/shader/SlimCompiler.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include <filesystem> + +#include <vkcv/ShaderStage.hpp> +#include "ShadyCompiler.hpp" + +namespace vkcv::shader { + + /** + * @addtogroup vkcv_shader + * @{ + */ + + enum class SlimCompileTarget { + UNKNOWN + }; + + /** + * A class to handle Slim runtime shader compilation. + */ + class SlimCompiler : public ShadyCompiler { + private: + SlimCompileTarget m_target; + + public: + /** + * The constructor of a runtime Slim shader compiler instance. + * + * @param[in] target Compile target (optional) + */ + explicit SlimCompiler(SlimCompileTarget target = SlimCompileTarget::UNKNOWN); + + /** + * Compile a Slim 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/src/vkcv/shader/LLVMCompiler.cpp b/modules/shader_compiler/src/vkcv/shader/LLVMCompiler.cpp new file mode 100644 index 00000000..04435ae6 --- /dev/null +++ b/modules/shader_compiler/src/vkcv/shader/LLVMCompiler.cpp @@ -0,0 +1,119 @@ + +#include "vkcv/shader/LLVMCompiler.hpp" + +#include <vkcv/File.hpp> +#include <vkcv/Logger.hpp> + +#include <shady/driver.h> + +namespace vkcv::shader { + + LLVMCompiler::LLVMCompiler(LLVMCompileTarget target) + : ShadyCompiler(), m_target(target) {} + + static bool shadyCompileModule(Module* module, + ShaderStage shaderStage, + const std::string& shaderSource, + const ShaderCompiledFunction &compiled, + const std::filesystem::path &includePath) { + ShadyErrorCodes codes = driver_load_source_file( + SrcLLVM, + shaderSource.length(), + shaderSource.c_str(), + module + ); + + switch (codes) { + case NoError: + break; + case MissingInputArg: + case MissingOutputArg: + case InputFileDoesNotExist: + case InputFileIOError: + case MissingDumpCfgArg: + case MissingDumpIrArg: + case IncorrectLogLevel: + case InvalidTarget: + case ClangInvocationFailed: + default: + vkcv_log(LogLevel::ERROR, "Unknown error while loading shader"); + return false; + } + + const std::filesystem::path tmp_path = generateTemporaryFilePath(); + + DriverConfig config = default_driver_config(); + + config.target = TgtSPV; + config.output_filename = tmp_path.c_str(); + + codes = driver_compile(&config, module); + destroy_driver_config(&config); + + switch (codes) { + case NoError: + break; + case MissingInputArg: + case MissingOutputArg: + case InputFileDoesNotExist: + case InputFileIOError: + case MissingDumpCfgArg: + case MissingDumpIrArg: + case IncorrectLogLevel: + case InvalidTarget: + case ClangInvocationFailed: + default: + vkcv_log(LogLevel::ERROR, "Unknown error while compiling shader"); + return false; + } + + if (compiled) { + compiled(shaderStage, tmp_path); + } + + std::filesystem::remove(tmp_path); + return true; + } + + static bool shadyCompileArena(IrArena* arena, + ShaderStage shaderStage, + const std::string& shaderSource, + const ShaderCompiledFunction &compiled, + const std::filesystem::path &includePath) { + Module* module = new_module(arena, "slim_module"); + + if (nullptr == module) { + vkcv_log(LogLevel::ERROR, "Module could not be created"); + return false; + } + + bool result = shadyCompileModule(module, shaderStage, shaderSource, compiled, includePath); + + destroy_module(module); + return result; + } + + bool LLVMCompiler::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; + } + + ArenaConfig config = default_arena_config(); + IrArena* arena = new_ir_arena(config); + + if (nullptr == arena) { + vkcv_log(LogLevel::ERROR, "IR Arena could not be created"); + return false; + } + + bool result = shadyCompileArena(arena, shaderStage, shaderSource, compiled, includePath); + + destroy_ir_arena(arena); + return result; + } + +} diff --git a/modules/shader_compiler/src/vkcv/shader/ShadyCompiler.cpp b/modules/shader_compiler/src/vkcv/shader/ShadyCompiler.cpp index 54a10bf4..13319e22 100644 --- a/modules/shader_compiler/src/vkcv/shader/ShadyCompiler.cpp +++ b/modules/shader_compiler/src/vkcv/shader/ShadyCompiler.cpp @@ -8,127 +8,31 @@ namespace vkcv::shader { - ShadyCompiler::ShadyCompiler() : Compiler() { - // TODO - } - - ShadyCompiler::ShadyCompiler(const ShadyCompiler &other) : Compiler(other) { - // TODO - } - - ShadyCompiler::~ShadyCompiler() { - // TODO - } - - ShadyCompiler &ShadyCompiler::operator=(const ShadyCompiler &other) { - // TODO - return *this; - } - - static bool shadyCompileModule(Module* module, - ShaderStage shaderStage, - const std::filesystem::path &shaderPath, - const ShaderCompiledFunction &compiled, - const std::filesystem::path &includePath) { - ShadyErrorCodes codes = driver_load_source_file_from_filename( - shaderPath.c_str(), module - ); - - switch (codes) { - case NoError: - break; - case MissingInputArg: - case MissingOutputArg: - case InputFileDoesNotExist: - case InputFileIOError: - case MissingDumpCfgArg: - case MissingDumpIrArg: - case IncorrectLogLevel: - case InvalidTarget: - case ClangInvocationFailed: - default: - vkcv_log(LogLevel::ERROR, "Unknown error while loading shader"); - return false; - } - - const std::filesystem::path tmp_path = generateTemporaryFilePath(); - - DriverConfig config = default_driver_config(); - - config.output_filename = tmp_path.c_str(); - - // TODO - - codes = driver_compile(&config, module); - destroy_driver_config(&config); - - switch (codes) { - case NoError: - break; - case MissingInputArg: - case MissingOutputArg: - case InputFileDoesNotExist: - case InputFileIOError: - case MissingDumpCfgArg: - case MissingDumpIrArg: - case IncorrectLogLevel: - case InvalidTarget: - case ClangInvocationFailed: - default: - vkcv_log(LogLevel::ERROR, "Unknown error while compiling shader"); - return false; - } - - if (compiled) { - compiled(shaderStage, tmp_path); - } - - std::filesystem::remove(tmp_path); - return true; - } - - static bool shadyCompileArena(IrArena* arena, - ShaderStage shaderStage, - const std::filesystem::path &shaderPath, - const ShaderCompiledFunction &compiled, - const std::filesystem::path &includePath) { - Module* module = new_module(arena, "main"); - - if (nullptr == module) { - vkcv_log(LogLevel::ERROR, "Module could not be created"); - return false; - } - - bool result = shadyCompileModule(module, shaderStage, shaderPath, compiled, includePath); - - destroy_module(module); - return result; - } + ShadyCompiler::ShadyCompiler() + : Compiler() {} void ShadyCompiler::compile(ShaderStage shaderStage, const std::filesystem::path &shaderPath, const ShaderCompiledFunction &compiled, const std::filesystem::path &includePath, bool update) { - ArenaConfig config {}; - - // TODO - - IrArena* arena = new_ir_arena(config); - - if (nullptr == arena) { - vkcv_log(LogLevel::ERROR, "IR Arena could not be created"); - return; + std::string shaderCode; + bool result = readTextFromFile(shaderPath, shaderCode); + + if (!result) { + vkcv_log(LogLevel::ERROR, "Loading shader failed: (%s)", shaderPath.string().c_str()); } - - bool result = shadyCompileArena(arena, shaderStage, shaderPath, compiled, includePath); - - destroy_ir_arena(arena); - + + 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/SlimCompiler.cpp b/modules/shader_compiler/src/vkcv/shader/SlimCompiler.cpp new file mode 100644 index 00000000..940ae700 --- /dev/null +++ b/modules/shader_compiler/src/vkcv/shader/SlimCompiler.cpp @@ -0,0 +1,119 @@ + +#include "vkcv/shader/SlimCompiler.hpp" + +#include <vkcv/File.hpp> +#include <vkcv/Logger.hpp> + +#include <shady/driver.h> + +namespace vkcv::shader { + + SlimCompiler::SlimCompiler(SlimCompileTarget target) + : ShadyCompiler(), m_target(target) {} + + static bool shadyCompileModule(Module* module, + ShaderStage shaderStage, + const std::string& shaderSource, + const ShaderCompiledFunction &compiled, + const std::filesystem::path &includePath) { + ShadyErrorCodes codes = driver_load_source_file( + SrcSlim, + shaderSource.length(), + shaderSource.c_str(), + module + ); + + switch (codes) { + case NoError: + break; + case MissingInputArg: + case MissingOutputArg: + case InputFileDoesNotExist: + case InputFileIOError: + case MissingDumpCfgArg: + case MissingDumpIrArg: + case IncorrectLogLevel: + case InvalidTarget: + case ClangInvocationFailed: + default: + vkcv_log(LogLevel::ERROR, "Unknown error while loading shader"); + return false; + } + + const std::filesystem::path tmp_path = generateTemporaryFilePath(); + + DriverConfig config = default_driver_config(); + + config.target = TgtSPV; + config.output_filename = tmp_path.c_str(); + + codes = driver_compile(&config, module); + destroy_driver_config(&config); + + switch (codes) { + case NoError: + break; + case MissingInputArg: + case MissingOutputArg: + case InputFileDoesNotExist: + case InputFileIOError: + case MissingDumpCfgArg: + case MissingDumpIrArg: + case IncorrectLogLevel: + case InvalidTarget: + case ClangInvocationFailed: + default: + vkcv_log(LogLevel::ERROR, "Unknown error while compiling shader"); + return false; + } + + if (compiled) { + compiled(shaderStage, tmp_path); + } + + std::filesystem::remove(tmp_path); + return true; + } + + static bool shadyCompileArena(IrArena* arena, + ShaderStage shaderStage, + const std::string& shaderSource, + const ShaderCompiledFunction &compiled, + const std::filesystem::path &includePath) { + Module* module = new_module(arena, "slim_module"); + + if (nullptr == module) { + vkcv_log(LogLevel::ERROR, "Module could not be created"); + return false; + } + + bool result = shadyCompileModule(module, shaderStage, shaderSource, compiled, includePath); + + destroy_module(module); + return result; + } + + 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; + } + + ArenaConfig config = default_arena_config(); + IrArena* arena = new_ir_arena(config); + + if (nullptr == arena) { + vkcv_log(LogLevel::ERROR, "IR Arena could not be created"); + return false; + } + + bool result = shadyCompileArena(arena, shaderStage, shaderSource, compiled, includePath); + + destroy_ir_arena(arena); + return result; + } + +} -- GitLab