From 7ba1f3514249fb7adaef18c7b7098edccacc4efe Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 25 Feb 2025 00:14:07 +0100 Subject: [PATCH] Split GLSL compiler from shader module creation --- .../ZVulkan/include/zvulkan/vulkanbuilders.h | 31 +++++--- libraries/ZVulkan/src/vulkanbuilders.cpp | 76 +++++++++++-------- libraries/ZVulkan/src/vulkaninstance.cpp | 2 +- 3 files changed, 64 insertions(+), 45 deletions(-) diff --git a/libraries/ZVulkan/include/zvulkan/vulkanbuilders.h b/libraries/ZVulkan/include/zvulkan/vulkanbuilders.h index 62575e46d..e9d5c62c8 100644 --- a/libraries/ZVulkan/include/zvulkan/vulkanbuilders.h +++ b/libraries/ZVulkan/include/zvulkan/vulkanbuilders.h @@ -218,31 +218,40 @@ public: std::string text; // the file contents - or include error message if name is empty }; -class ShaderBuilder +class GLSLCompiler { public: - ShaderBuilder(); - static void Init(); static void Deinit(); - ShaderBuilder& Type(ShaderType type); - ShaderBuilder& AddSource(const std::string& name, const std::string& code); + GLSLCompiler& Type(ShaderType type); + GLSLCompiler& AddSource(const std::string& name, const std::string& code); - ShaderBuilder& OnIncludeSystem(std::function onIncludeSystem); - ShaderBuilder& OnIncludeLocal(std::function onIncludeLocal); + GLSLCompiler& OnIncludeSystem(std::function onIncludeSystem); + GLSLCompiler& OnIncludeLocal(std::function onIncludeLocal); - ShaderBuilder& DebugName(const char* name) { debugName = name; return *this; } - - std::unique_ptr Create(const char *shadername, VulkanDevice *device); + std::vector Compile(uint32_t apiVersion/* = VK_API_VERSION_1_0*/); + std::vector Compile(VulkanDevice* device); private: std::vector> sources; std::function onIncludeSystem; std::function onIncludeLocal; int stage = 0; + friend class GLSLCompilerIncluderImpl; +}; + +class ShaderBuilder +{ +public: + ShaderBuilder& Code(std::vector spirv) { code = std::move(spirv); return *this; } + ShaderBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(const char *shadername, VulkanDevice *device); + +private: + std::vector code; const char* debugName = nullptr; - friend class ShaderBuilderIncluderImpl; }; class AccelerationStructureBuilder diff --git a/libraries/ZVulkan/src/vulkanbuilders.cpp b/libraries/ZVulkan/src/vulkanbuilders.cpp index e342c126e..61f75cdd5 100644 --- a/libraries/ZVulkan/src/vulkanbuilders.cpp +++ b/libraries/ZVulkan/src/vulkanbuilders.cpp @@ -6,21 +6,17 @@ #include "glslang/glslang/Public/ResourceLimits.h" #include "glslang/spirv/GlslangToSpv.h" -void ShaderBuilder::Init() +void GLSLCompiler::Init() { ShInitialize(); } -void ShaderBuilder::Deinit() +void GLSLCompiler::Deinit() { ShFinalize(); } -ShaderBuilder::ShaderBuilder() -{ -} - -ShaderBuilder& ShaderBuilder::Type(ShaderType type) +GLSLCompiler& GLSLCompiler::Type(ShaderType type) { switch (type) { @@ -34,34 +30,34 @@ ShaderBuilder& ShaderBuilder::Type(ShaderType type) return *this; } -ShaderBuilder& ShaderBuilder::AddSource(const std::string& name, const std::string& code) +GLSLCompiler& GLSLCompiler::AddSource(const std::string& name, const std::string& code) { sources.push_back({ name, code }); return *this; } -ShaderBuilder& ShaderBuilder::OnIncludeSystem(std::function onIncludeSystem) +GLSLCompiler& GLSLCompiler::OnIncludeSystem(std::function onIncludeSystem) { this->onIncludeSystem = std::move(onIncludeSystem); return *this; } -ShaderBuilder& ShaderBuilder::OnIncludeLocal(std::function onIncludeLocal) +GLSLCompiler& GLSLCompiler::OnIncludeLocal(std::function onIncludeLocal) { this->onIncludeLocal = std::move(onIncludeLocal); return *this; } -class ShaderBuilderIncluderImpl : public glslang::TShader::Includer +class GLSLCompilerIncluderImpl : public glslang::TShader::Includer { public: - ShaderBuilderIncluderImpl(ShaderBuilder* shaderBuilder) : shaderBuilder(shaderBuilder) + GLSLCompilerIncluderImpl(GLSLCompiler* compiler) : compiler(compiler) { } IncludeResult* includeSystem(const char* headerName, const char* includerName, size_t inclusionDepth) override { - if (!shaderBuilder->onIncludeSystem) + if (!compiler->onIncludeSystem) { return nullptr; } @@ -71,7 +67,7 @@ public: std::unique_ptr result; try { - result = std::make_unique(shaderBuilder->onIncludeSystem(headerName, includerName, inclusionDepth)); + result = std::make_unique(compiler->onIncludeSystem(headerName, includerName, inclusionDepth)); } catch (const std::exception& e) { @@ -95,7 +91,7 @@ public: IncludeResult* includeLocal(const char* headerName, const char* includerName, size_t inclusionDepth) override { - if (!shaderBuilder->onIncludeLocal) + if (!compiler->onIncludeLocal) { return nullptr; } @@ -105,7 +101,7 @@ public: std::unique_ptr result; try { - result = std::make_unique(shaderBuilder->onIncludeLocal(headerName, includerName, inclusionDepth)); + result = std::make_unique(compiler->onIncludeLocal(headerName, includerName, inclusionDepth)); } catch (const std::exception& e) { @@ -137,10 +133,15 @@ public: } private: - ShaderBuilder* shaderBuilder = nullptr; + GLSLCompiler* compiler = nullptr; }; -std::unique_ptr ShaderBuilder::Create(const char *shadername, VulkanDevice *device) +std::vector GLSLCompiler::Compile(VulkanDevice* device) +{ + return Compile(device->Instance->ApiVersion); +} + +std::vector GLSLCompiler::Compile(uint32_t apiVersion) { EShLanguage stage = (EShLanguage)this->stage; @@ -156,22 +157,23 @@ std::unique_ptr ShaderBuilder::Create(const char *shadername, Vulk glslang::TShader shader(stage); shader.setStringsWithLengthsAndNames(sourcesC.data(), lengthsC.data(), namesC.data(), (int)sources.size()); shader.setEnvInput(glslang::EShSourceGlsl, stage, glslang::EShClientVulkan, 100); - if (device->Instance->ApiVersion >= VK_API_VERSION_1_2) - { - shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_2); - shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_4); - } - else - { - shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_0); - shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_0); - } + if (apiVersion >= VK_API_VERSION_1_2) + { + shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_2); + shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_4); + } + else + { + shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_0); + shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_0); + } - ShaderBuilderIncluderImpl includer(this); + GLSLCompilerIncluderImpl includer(this); bool compileSuccess = shader.parse(GetDefaultResources(), 110, false, EShMsgVulkanRules, includer); if (!compileSuccess) { VulkanError((std::string("Shader compile failed: ") + shader.getInfoLog()).c_str()); + return {}; } glslang::TProgram program; @@ -180,12 +182,14 @@ std::unique_ptr ShaderBuilder::Create(const char *shadername, Vulk if (!linkSuccess) { VulkanError((std::string("Shader link failed: ") + program.getInfoLog()).c_str()); + return {}; } - glslang::TIntermediate *intermediate = program.getIntermediate(stage); + glslang::TIntermediate* intermediate = program.getIntermediate(stage); if (!intermediate) { VulkanError("Internal shader compiler error"); + return {}; } glslang::SpvOptions spvOptions; @@ -193,14 +197,20 @@ std::unique_ptr ShaderBuilder::Create(const char *shadername, Vulk spvOptions.disableOptimizer = false; spvOptions.optimizeSize = true; - std::vector spirv; + std::vector spirv; spv::SpvBuildLogger logger; glslang::GlslangToSpv(*intermediate, spirv, &logger, &spvOptions); + return spirv; +} +///////////////////////////////////////////////////////////////////////////// + +std::unique_ptr ShaderBuilder::Create(const char *shadername, VulkanDevice *device) +{ VkShaderModuleCreateInfo createInfo = {}; createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - createInfo.codeSize = spirv.size() * sizeof(unsigned int); - createInfo.pCode = spirv.data(); + createInfo.codeSize = code.size() * sizeof(uint32_t); + createInfo.pCode = code.data(); VkShaderModule shaderModule; VkResult result = vkCreateShaderModule(device->device, &createInfo, nullptr, &shaderModule); diff --git a/libraries/ZVulkan/src/vulkaninstance.cpp b/libraries/ZVulkan/src/vulkaninstance.cpp index 53340bcb1..b7bf300b7 100644 --- a/libraries/ZVulkan/src/vulkaninstance.cpp +++ b/libraries/ZVulkan/src/vulkaninstance.cpp @@ -11,7 +11,7 @@ VulkanInstance::VulkanInstance(std::vector apiVersionsToTry, std::set< { try { - ShaderBuilder::Init(); + GLSLCompiler::Init(); InitVolk(); CreateInstance(); }