From 9536f4dfbb92b4a9f037bb1da8fad16564fa847a Mon Sep 17 00:00:00 2001 From: Lucas Alber Date: Tue, 5 Nov 2024 18:20:11 +0100 Subject: [PATCH] Start improved compiler implementation --- include/merian/vk/extension/extension.hpp | 11 ++++- include/merian/vk/shader/shader_compiler.hpp | 46 +++++++++++++++---- .../shader_compiler_glsllangValidator.hpp | 22 +++++++++ .../vk/shader/shader_compiler_shaderc.hpp | 1 - meson.build | 2 + .../vk/shader/shader_compiler_shaderc.cpp | 7 +-- 6 files changed, 74 insertions(+), 15 deletions(-) create mode 100644 include/merian/vk/shader/shader_compiler_glsllangValidator.hpp diff --git a/include/merian/vk/extension/extension.hpp b/include/merian/vk/extension/extension.hpp index 953a87b7..8f9552ae 100644 --- a/include/merian/vk/extension/extension.hpp +++ b/include/merian/vk/extension/extension.hpp @@ -21,7 +21,7 @@ class Extension { friend Context; public: - Extension(std::string name) : name(name) {} + Extension(const std::string& name) : name(name) {} virtual ~Extension() = 0; @@ -109,6 +109,15 @@ class Extension { spdlog::warn("extension {} not supported ({})", name, reason); } + // OTHER + + // return strings that should be defined when compiling shaders with Merians shader compiler. + // Note that device and instance extensions are automatically defined as + // MERIAN_DEVICE_EXT_ENABLE_ and MERIAN_INSTANCE_EXT_ENABLE_ + virtual std::vector shader_defines() { + return {}; + } + public: const std::string name; }; diff --git a/include/merian/vk/shader/shader_compiler.hpp b/include/merian/vk/shader/shader_compiler.hpp index 01c73eb6..e3a3deb8 100644 --- a/include/merian/vk/shader/shader_compiler.hpp +++ b/include/merian/vk/shader/shader_compiler.hpp @@ -11,6 +11,9 @@ namespace merian { +// A compiler for shaders. +// +// Include paths for the merian-nodes library and context extensions must be automatically added. class ShaderCompiler { public: class compilation_failed : public std::runtime_error { @@ -19,7 +22,13 @@ class ShaderCompiler { }; public: - ShaderCompiler() {} + ShaderCompiler(const std::vector& user_include_paths = {}, + const std::map& user_macro_definitions = {}) + : include_paths(user_include_paths), macro_definitions(user_macro_definitions) { + // search merian-shaders + + // add macro definitions from context extensions and enabled instance and device extensions. + } virtual ~ShaderCompiler() = 0; @@ -55,8 +64,16 @@ class ShaderCompiler { const std::string& source_name, const vk::ShaderStageFlagBits shader_kind) = 0; + const std::vector& get_include_paths() const { + return include_paths; + } + + const std::map& get_macro_definitions() const { + return macro_definitions; + } + private: - vk::ShaderStageFlagBits guess_kind(const std::filesystem::path& path) { + static vk::ShaderStageFlagBits guess_kind(const std::filesystem::path& path) { std::string extension; if (path.extension().string() == ".glsl") { extension = std::filesystem::path(path.string().substr(0, path.string().size() - 5)) @@ -65,23 +82,32 @@ class ShaderCompiler { } else { extension = path.extension().string(); } + if (extension == ".vert") { return vk::ShaderStageFlagBits::eVertex; - } else if (extension == ".tesc") { + } + if (extension == ".tesc") { return vk::ShaderStageFlagBits::eTessellationControl; - } else if (extension == ".tese") { + } + if (extension == ".tese") { return vk::ShaderStageFlagBits::eTessellationEvaluation; - } else if (extension == ".geom") { + } + if (extension == ".geom") { return vk::ShaderStageFlagBits::eGeometry; - } else if (extension == ".frag") { + } + if (extension == ".frag") { return vk::ShaderStageFlagBits::eFragment; - } else if (extension == ".comp") { + } + if (extension == ".comp") { return vk::ShaderStageFlagBits::eCompute; - } else { - throw compilation_failed{ - fmt::format("Shader kind could not be determined for path {}", path.string())}; } + + throw compilation_failed{ + fmt::format("Shader kind could not be determined for path {}", path.string())}; } + + std::vector include_paths; + std::map macro_definitions; }; using ShaderCompilerHandle = std::shared_ptr; diff --git a/include/merian/vk/shader/shader_compiler_glsllangValidator.hpp b/include/merian/vk/shader/shader_compiler_glsllangValidator.hpp new file mode 100644 index 00000000..cfa00252 --- /dev/null +++ b/include/merian/vk/shader/shader_compiler_glsllangValidator.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "merian/vk/shader/shader_compiler.hpp" +#include + +namespace merian { + +// Uses glslangValidator executable to compile shaders. +class GLSLLangValidatorCompiler : public ShaderCompiler { + public: + // Include paths for the merian-nodes library are automatically added + GLSLLangValidatorCompiler(const std::vector& include_paths = {}, + const std::map& macro_definitions = {}); + + ~GLSLLangValidatorCompiler(); + + std::vector compile_glsl(const std::string& source, + const std::string& source_name, + const vk::ShaderStageFlagBits shader_kind) override; +}; + +} // namespace merian diff --git a/include/merian/vk/shader/shader_compiler_shaderc.hpp b/include/merian/vk/shader/shader_compiler_shaderc.hpp index b0f78875..007707b4 100644 --- a/include/merian/vk/shader/shader_compiler_shaderc.hpp +++ b/include/merian/vk/shader/shader_compiler_shaderc.hpp @@ -17,7 +17,6 @@ namespace merian { class ShadercCompiler : public ShaderCompiler { public: - // Include paths for the merian-nodes library are automatically added ShadercCompiler(const std::vector& include_paths = {}, const std::map& macro_definitions = {}); diff --git a/meson.build b/meson.build index fb715c44..78b8decc 100644 --- a/meson.build +++ b/meson.build @@ -156,3 +156,5 @@ merian_dep = declare_dependency( vulkan, ] ) + +install_subdir('include', install_dir: get_option('includedir'), strip_directory: true) diff --git a/src/merian/vk/shader/shader_compiler_shaderc.cpp b/src/merian/vk/shader/shader_compiler_shaderc.cpp index cc2ee607..9e8330c0 100644 --- a/src/merian/vk/shader/shader_compiler_shaderc.cpp +++ b/src/merian/vk/shader/shader_compiler_shaderc.cpp @@ -105,14 +105,15 @@ shaderc_shader_kind_for_stage_flag_bit(const vk::ShaderStageFlagBits shader_kind } ShadercCompiler::ShadercCompiler(const std::vector& include_paths, - const std::map& macro_definitions) { + const std::map& macro_definitions) + : ShaderCompiler(include_paths, macro_definitions) { - for (const auto& [key, value] : macro_definitions) { + for (const auto& [key, value] : get_macro_definitions()) { compile_options.AddMacroDefinition(key, value); } auto includer = std::make_unique(); - for (const auto& include_path : include_paths) { + for (const auto& include_path : get_include_paths()) { includer->get_file_loader().add_search_path(include_path); } compile_options.SetIncluder(std::move(includer));