Skip to content

Commit

Permalink
merian: ShaderCompiler: Allow additional includes and macros
Browse files Browse the repository at this point in the history
  • Loading branch information
LDAP committed Nov 21, 2024
1 parent 3bd6376 commit b65b380
Show file tree
Hide file tree
Showing 10 changed files with 141 additions and 64 deletions.
65 changes: 47 additions & 18 deletions include/merian/vk/shader/shader_compiler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,34 +78,46 @@ class ShaderCompiler {
// Attempt to guess the shader_kind from the file extension if shader_kind = std::nullopt.
//
// May throw compilation_failed.
virtual std::vector<uint32_t>
compile_glsl(const std::filesystem::path& path,
const std::optional<vk::ShaderStageFlagBits> optional_shader_kind = std::nullopt) {
virtual std::vector<uint32_t> compile_glsl(
const std::filesystem::path& path,
const std::optional<vk::ShaderStageFlagBits> optional_shader_kind = std::nullopt,
const std::vector<std::string>& additional_include_paths = {},
const std::map<std::string, std::string>& additional_macro_definitions = {}) const {
return compile_glsl(FileLoader::load_file(path), path.string(),
optional_shader_kind.value_or(guess_kind(path)));
optional_shader_kind.value_or(guess_kind(path)),
additional_include_paths, additional_macro_definitions);
}

// May throw compilation_failed.
virtual std::vector<uint32_t> compile_glsl(const std::string& source,
const std::string& source_name,
const vk::ShaderStageFlagBits shader_kind) = 0;
virtual std::vector<uint32_t> compile_glsl(
const std::string& source,
const std::string& source_name,
const vk::ShaderStageFlagBits shader_kind,
const std::vector<std::string>& additional_include_paths = {},
const std::map<std::string, std::string>& additional_macro_definitions = {}) const = 0;

// ------------------------------------------------

ShaderModuleHandle compile_glsl_to_shadermodule(
const ContextHandle& context,
const std::filesystem::path& path,
const std::optional<vk::ShaderStageFlagBits> optional_shader_kind = std::nullopt) {
const std::optional<vk::ShaderStageFlagBits> optional_shader_kind = std::nullopt,
const std::vector<std::string>& additional_include_paths = {},
const std::map<std::string, std::string>& additional_macro_definitions = {}) const {
const vk::ShaderStageFlagBits shader_kind = optional_shader_kind.value_or(guess_kind(path));
return std::make_shared<ShaderModule>(context, compile_glsl(path, shader_kind),
shader_kind);
return std::make_shared<ShaderModule>(
context,
compile_glsl(path, shader_kind, additional_include_paths, additional_macro_definitions),
shader_kind);
}

// uses the file_loader provided from context.
ShaderModuleHandle find_compile_glsl_to_shadermodule(
const ContextHandle& context,
const std::filesystem::path& path,
const std::optional<vk::ShaderStageFlagBits> optional_shader_kind = std::nullopt) {
const std::optional<vk::ShaderStageFlagBits> optional_shader_kind = std::nullopt,
const std::vector<std::string>& additional_include_paths = {},
const std::map<std::string, std::string>& additional_macro_definitions = {}) const {

const std::optional<std::filesystem::path> resolved = context->file_loader.find_file(path);
if (!resolved) {
Expand All @@ -114,20 +126,37 @@ class ShaderCompiler {

const vk::ShaderStageFlagBits shader_kind =
optional_shader_kind.value_or(guess_kind(*resolved));
return std::make_shared<ShaderModule>(context, compile_glsl(*resolved, shader_kind),
return std::make_shared<ShaderModule>(context,
compile_glsl(*resolved, shader_kind,
additional_include_paths,
additional_macro_definitions),
shader_kind);
}

ShaderModuleHandle compile_glsl_to_shadermodule(const ContextHandle& context,
const std::string& source,
const std::string& source_name,
const vk::ShaderStageFlagBits shader_kind) {
return std::make_shared<ShaderModule>(
context, compile_glsl(source, source_name, shader_kind), shader_kind);
ShaderModuleHandle compile_glsl_to_shadermodule(
const ContextHandle& context,
const std::string& source,
const std::string& source_name,
const vk::ShaderStageFlagBits shader_kind,
const std::vector<std::string>& additional_include_paths = {},
const std::map<std::string, std::string>& additional_macro_definitions = {}) const {
return std::make_shared<ShaderModule>(context,
compile_glsl(source, source_name, shader_kind,
additional_include_paths,
additional_macro_definitions),
shader_kind);
}

// ------------------------------------------------

void add_include_path(const std::string& include_path) {
include_paths.emplace_back(include_path);
}

void add_macro_definition(const std::string& key, const std::string& value) {
macro_definitions.emplace(key, value);
}

const std::vector<std::string>& get_include_paths() const {
return include_paths;
}
Expand Down
11 changes: 7 additions & 4 deletions include/merian/vk/shader/shader_compiler_shaderc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,19 @@ class ShadercCompiler : public ShaderCompiler {

~ShadercCompiler();

std::vector<uint32_t> compile_glsl(const std::string& source,
const std::string& source_name,
const vk::ShaderStageFlagBits shader_kind) override;
std::vector<uint32_t> compile_glsl(
const std::string& source,
const std::string& source_name,
const vk::ShaderStageFlagBits shader_kind,
const std::vector<std::string>& additional_include_paths = {},
const std::map<std::string, std::string>& additional_macro_definitions = {}) const override;

bool available() const override;

private:
const uint32_t vk_api_version;
#ifdef MERIAN_SHADERC_FOUND
shaderc::Compiler shader_compiler;
shaderc::CompileOptions compile_options;
#endif
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@ class SystemGlslangValidatorCompiler : public ShaderCompiler {

~SystemGlslangValidatorCompiler();

std::vector<uint32_t> compile_glsl(const std::string& source,
const std::string& source_name,
const vk::ShaderStageFlagBits shader_kind) override;
std::vector<uint32_t> compile_glsl(
const std::string& source,
const std::string& source_name,
const vk::ShaderStageFlagBits shader_kind,
const std::vector<std::string>& additional_include_paths = {},
const std::map<std::string, std::string>& additional_macro_definitions = {}) const override;

bool available() const override;

Expand Down
9 changes: 6 additions & 3 deletions include/merian/vk/shader/shader_compiler_system_glslc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ class SystemGlslcCompiler : public ShaderCompiler {

~SystemGlslcCompiler();

std::vector<uint32_t> compile_glsl(const std::string& source,
const std::string& source_name,
const vk::ShaderStageFlagBits shader_kind) override;
std::vector<uint32_t> compile_glsl(
const std::string& source,
const std::string& source_name,
const vk::ShaderStageFlagBits shader_kind,
const std::vector<std::string>& additional_include_paths = {},
const std::map<std::string, std::string>& additional_macro_definitions = {}) const override;

bool available() const override;

Expand Down
13 changes: 9 additions & 4 deletions src/merian-nodes/nodes/shadertoy/shadertoy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,17 @@ class ShadertoyInjectCompiler : public ShaderCompiler {

~ShadertoyInjectCompiler() {}

std::vector<uint32_t> compile_glsl(const std::string& source,
const std::string& source_name,
const vk::ShaderStageFlagBits shader_kind) final override {
std::vector<uint32_t>
compile_glsl(const std::string& source,
const std::string& source_name,
const vk::ShaderStageFlagBits shader_kind,
const std::vector<std::string>& additional_include_paths = {},
const std::map<std::string, std::string>& additional_macro_definitions = {})
const final override {
SPDLOG_INFO("(re-)compiling {}", source_name);
return forwarding_compiler->compile_glsl(shadertoy_pre + source + shadertoy_post,
source_name, shader_kind);
source_name, shader_kind, additional_include_paths,
additional_macro_definitions);
}

bool available() const override {
Expand Down
11 changes: 7 additions & 4 deletions src/merian/vk/shader/shader_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ class DummyShaderCompiler : public ShaderCompiler {
std::vector<uint32_t>
compile_glsl([[maybe_unused]] const std::string& source,
[[maybe_unused]] const std::string& source_name,
[[maybe_unused]] const vk::ShaderStageFlagBits shader_kind) override {
[[maybe_unused]] const vk::ShaderStageFlagBits shader_kind,
[[maybe_unused]] const std::vector<std::string>& additional_include_paths = {},
[[maybe_unused]] const std::map<std::string, std::string>&
additional_macro_definitions = {}) const override {
throw compilation_failed{"compiler not available"};
}

Expand Down Expand Up @@ -47,8 +50,7 @@ ShaderCompiler::get(const ContextHandle& context,
}

ShaderCompilerHandle glslc =
std::make_shared<SystemGlslcCompiler>(context, user_include_paths,
user_macro_definitions);
std::make_shared<SystemGlslcCompiler>(context, user_include_paths, user_macro_definitions);
if (glslc->available()) {
SPDLOG_DEBUG("using installed glslc as default compiler");
return glslc;
Expand All @@ -62,7 +64,8 @@ ShaderCompiler::get(const ContextHandle& context,
ShaderCompiler::ShaderCompiler(const ContextHandle& context,
const std::vector<std::string>& user_include_paths,
const std::map<std::string, std::string>& user_macro_definitions)
: include_paths(user_include_paths), macro_definitions(user_macro_definitions) {
: include_paths(user_include_paths.begin(), user_include_paths.end()),
macro_definitions(user_macro_definitions) {

insert_all(include_paths, context->get_default_shader_include_paths());
macro_definitions.insert(context->get_default_shader_macro_definitions().begin(),
Expand Down
35 changes: 23 additions & 12 deletions src/merian/vk/shader/shader_compiler_shaderc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,41 +111,52 @@ shaderc_shader_kind_for_stage_flag_bit(const vk::ShaderStageFlagBits shader_kind
ShadercCompiler::ShadercCompiler(const ContextHandle& context,
const std::vector<std::string>& user_include_paths,
const std::map<std::string, std::string>& user_macro_definitions)
: ShaderCompiler(context, user_include_paths, user_macro_definitions) {
: ShaderCompiler(context, user_include_paths, user_macro_definitions),
vk_api_version(context->vk_api_version) {}

ShadercCompiler::~ShadercCompiler() {}

std::vector<uint32_t> ShadercCompiler::compile_glsl(
const std::string& source,
const std::string& source_name,
const vk::ShaderStageFlagBits shader_kind,
const std::vector<std::string>& additional_include_paths,
const std::map<std::string, std::string>& additional_macro_definitions) const {
const shaderc_shader_kind kind = shaderc_shader_kind_for_stage_flag_bit(shader_kind);

shaderc::CompileOptions compile_options;

for (const auto& [key, value] : get_macro_definitions()) {
compile_options.AddMacroDefinition(key, value);
}
for (const auto& [key, value] : additional_macro_definitions) {
compile_options.AddMacroDefinition(key, value);
}

auto includer = std::make_unique<FileIncluder>();
for (const auto& include_path : get_include_paths()) {
includer->get_file_loader().add_search_path(include_path);
}
for (const auto& include_path : additional_include_paths) {
includer->get_file_loader().add_search_path(include_path);
}
compile_options.SetIncluder(std::move(includer));
compile_options.SetOptimizationLevel(
shaderc_optimization_level::shaderc_optimization_level_performance);

if (context->vk_api_version == VK_API_VERSION_1_0) {
if (vk_api_version == VK_API_VERSION_1_0) {
compile_options.SetTargetEnvironment(shaderc_target_env_vulkan,
shaderc_env_version_vulkan_1_0);
} else if (context->vk_api_version == VK_API_VERSION_1_1) {
} else if (vk_api_version == VK_API_VERSION_1_1) {
compile_options.SetTargetEnvironment(shaderc_target_env_vulkan,
shaderc_env_version_vulkan_1_1);
} else if (context->vk_api_version == VK_API_VERSION_1_2) {
} else if (vk_api_version == VK_API_VERSION_1_2) {
compile_options.SetTargetEnvironment(shaderc_target_env_vulkan,
shaderc_env_version_vulkan_1_2);
} else {
compile_options.SetTargetEnvironment(shaderc_target_env_vulkan,
shaderc_env_version_vulkan_1_3);
}
}

ShadercCompiler::~ShadercCompiler() {}

std::vector<uint32_t> ShadercCompiler::compile_glsl(const std::string& source,
const std::string& source_name,
const vk::ShaderStageFlagBits shader_kind) {
const shaderc_shader_kind kind = shaderc_shader_kind_for_stage_flag_bit(shader_kind);

SPDLOG_DEBUG("preprocess {}", source_name);
const auto preprocess_result =
Expand Down
12 changes: 7 additions & 5 deletions src/merian/vk/shader/shader_compiler_shaderc_stub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ namespace merian {
ShadercCompiler::ShadercCompiler(const ContextHandle& context,
const std::vector<std::string>& include_paths,
const std::map<std::string, std::string>& macro_definitions)
: ShaderCompiler(context, include_paths, macro_definitions) {}
: ShaderCompiler(context, include_paths, macro_definitions), vk_api_version(-1) {}

ShadercCompiler::~ShadercCompiler() {}

std::vector<uint32_t>
ShadercCompiler::compile_glsl([[maybe_unused]] const std::string& source,
[[maybe_unused]] const std::string& source_name,
[[maybe_unused]] const vk::ShaderStageFlagBits shader_kind) {
std::vector<uint32_t> ShadercCompiler::compile_glsl(
[[maybe_unused]] const std::string& source,
[[maybe_unused]] const std::string& source_name,
[[maybe_unused]] const vk::ShaderStageFlagBits shader_kind,
[[maybe_unused]] const std::vector<std::string>& additional_include_paths,
[[maybe_unused]] const std::map<std::string, std::string>& additional_macro_definitions) const {
throw merian::ShaderCompiler::compilation_failed{
"shaderc is not available (was not found or enabled at compile time)"};
}
Expand Down
20 changes: 14 additions & 6 deletions src/merian/vk/shader/shader_compiler_system_glslangValidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ SystemGlslangValidatorCompiler::SystemGlslangValidatorCompiler(

SystemGlslangValidatorCompiler::~SystemGlslangValidatorCompiler() {}

std::vector<uint32_t>
SystemGlslangValidatorCompiler::compile_glsl(const std::string& source,
const std::string& source_name,
const vk::ShaderStageFlagBits shader_kind) {
std::vector<uint32_t> SystemGlslangValidatorCompiler::compile_glsl(
const std::string& source,
const std::string& source_name,
const vk::ShaderStageFlagBits shader_kind,
const std::vector<std::string>& additional_include_paths,
const std::map<std::string, std::string>& additional_macro_definitions) const {
if (compiler_executable.empty()) {
throw compilation_failed{"compiler not available"};
}
Expand Down Expand Up @@ -59,8 +61,14 @@ SystemGlslangValidatorCompiler::compile_glsl(const std::string& source,
for (const auto& inc_dir : get_include_paths()) {
command.emplace_back(fmt::format("-I{}", inc_dir));
}
for (const auto& macro_def : get_macro_definitions()) {
command.emplace_back(fmt::format("-D{}={}", macro_def.first, macro_def.second));
for (const auto& inc_dir : additional_include_paths) {
command.emplace_back(fmt::format("-I{}", inc_dir));
}
for (const auto& [key, value] : get_macro_definitions()) {
command.emplace_back(fmt::format("-D{}={}", key, value));
}
for (const auto& [key, value] : additional_macro_definitions) {
command.emplace_back(fmt::format("-D{}={}", key, value));
}

const std::string output_file = temporary_file();
Expand Down
20 changes: 15 additions & 5 deletions src/merian/vk/shader/shader_compiler_system_glslc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@ SystemGlslcCompiler::SystemGlslcCompiler(

SystemGlslcCompiler::~SystemGlslcCompiler() {}

std::vector<uint32_t> SystemGlslcCompiler::compile_glsl(const std::string& source,
const std::string& source_name,
const vk::ShaderStageFlagBits shader_kind) {
std::vector<uint32_t> SystemGlslcCompiler::compile_glsl(
const std::string& source,
const std::string& source_name,
const vk::ShaderStageFlagBits shader_kind,
const std::vector<std::string>& additional_include_paths,
const std::map<std::string, std::string>& additional_macro_definitions) const {
if (compiler_executable.empty()) {
throw compilation_failed{"compiler not available"};
}
Expand All @@ -57,8 +60,15 @@ std::vector<uint32_t> SystemGlslcCompiler::compile_glsl(const std::string& sourc
command.emplace_back("-I");
command.emplace_back(inc_dir);
}
for (const auto& macro_def : get_macro_definitions()) {
command.emplace_back(fmt::format("-D{}={}", macro_def.first, macro_def.second));
for (const auto& inc_dir : additional_include_paths) {
command.emplace_back("-I");
command.emplace_back(inc_dir);
}
for (const auto& [key, value] : get_macro_definitions()) {
command.emplace_back(fmt::format("-D{}={}", key, value));
}
for (const auto& [key, value] : additional_macro_definitions) {
command.emplace_back(fmt::format("-D{}={}", key, value));
}

// turn on optimization
Expand Down

0 comments on commit b65b380

Please sign in to comment.