From fe5da8697d17281ac552fcf6b1f9b1a27cdbf10d Mon Sep 17 00:00:00 2001 From: Tobias Frisch <tfrisch@uni-koblenz.de> Date: Sun, 11 Dec 2022 21:40:30 +0100 Subject: [PATCH] Adjust shader module Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de> --- modules/shader_compiler/CMakeLists.txt | 6 + .../include/vkcv/shader/Compiler.hpp | 18 +- .../include/vkcv/shader/GLSLCompiler.hpp | 55 +--- .../include/vkcv/shader/GlslangCompiler.hpp | 102 +++++++ .../include/vkcv/shader/HLSLCompiler.hpp | 53 ++++ .../src/vkcv/shader/GLSLCompiler.cpp | 111 +------- .../src/vkcv/shader/GlslangCompiler.cpp | 100 +++++++ .../src/vkcv/shader/HLSLCompiler.cpp | 265 ++++++++++++++++++ 8 files changed, 559 insertions(+), 151 deletions(-) create mode 100644 modules/shader_compiler/include/vkcv/shader/GlslangCompiler.hpp create mode 100644 modules/shader_compiler/include/vkcv/shader/HLSLCompiler.hpp create mode 100644 modules/shader_compiler/src/vkcv/shader/GlslangCompiler.cpp create mode 100644 modules/shader_compiler/src/vkcv/shader/HLSLCompiler.cpp diff --git a/modules/shader_compiler/CMakeLists.txt b/modules/shader_compiler/CMakeLists.txt index 1389e1a9..bd85c7d8 100644 --- a/modules/shader_compiler/CMakeLists.txt +++ b/modules/shader_compiler/CMakeLists.txt @@ -13,8 +13,14 @@ set(vkcv_shader_compiler_sources ${vkcv_shader_compiler_include}/vkcv/shader/Compiler.hpp ${vkcv_shader_compiler_source}/vkcv/shader/Compiler.cpp + ${vkcv_shader_compiler_include}/vkcv/shader/GlslangCompiler.hpp + ${vkcv_shader_compiler_source}/vkcv/shader/GlslangCompiler.cpp + ${vkcv_shader_compiler_include}/vkcv/shader/GLSLCompiler.hpp ${vkcv_shader_compiler_source}/vkcv/shader/GLSLCompiler.cpp + + ${vkcv_shader_compiler_include}/vkcv/shader/HLSLCompiler.hpp + ${vkcv_shader_compiler_source}/vkcv/shader/HLSLCompiler.cpp ) filter_headers(vkcv_shader_compiler_sources ${vkcv_shader_compiler_include} vkcv_shader_compiler_headers) diff --git a/modules/shader_compiler/include/vkcv/shader/Compiler.hpp b/modules/shader_compiler/include/vkcv/shader/Compiler.hpp index f6219075..8096e9e2 100644 --- a/modules/shader_compiler/include/vkcv/shader/Compiler.hpp +++ b/modules/shader_compiler/include/vkcv/shader/Compiler.hpp @@ -41,6 +41,7 @@ namespace vkcv::shader { /** * 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 @@ -55,20 +56,24 @@ namespace vkcv::shader { * 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 */ - virtual void compile(ShaderStage shaderStage, const std::filesystem::path& shaderPath, + virtual 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) = 0; /** * Compile a shader program from a specific map of given file paths for * target pipeline stages with a custom shader include path and an event * function called if the compilation completes. + * * @param[in,out] program Shader program * @param[in] stages Shader pipeline stages * @param[in] compiled Shader program compilation event @@ -76,19 +81,24 @@ namespace vkcv::shader { * @param[in] update Flag to update shaders during runtime */ void compileProgram(ShaderProgram& program, - const std::unordered_map<ShaderStage, const std::filesystem::path>& stages, + const std::unordered_map<ShaderStage, + const std::filesystem::path>& stages, const ShaderProgramCompiledFunction& compiled, - const std::filesystem::path& includePath = "", bool update = false); + const std::filesystem::path& includePath = "", + bool update = false); /** * Return the definition value of a macro for shader compilation. + * * @param[in] name Macro definition name * @return Macro definition value */ + [[nodiscard]] std::string getDefine(const std::string& name) const; /** * Set a macro for shader compilation. + * * @param[in] name Macro definition name * @param[in] value Macro definition value */ diff --git a/modules/shader_compiler/include/vkcv/shader/GLSLCompiler.hpp b/modules/shader_compiler/include/vkcv/shader/GLSLCompiler.hpp index 0cb3a394..48b3024f 100644 --- a/modules/shader_compiler/include/vkcv/shader/GLSLCompiler.hpp +++ b/modules/shader_compiler/include/vkcv/shader/GLSLCompiler.hpp @@ -3,7 +3,7 @@ #include <filesystem> #include <vkcv/ShaderStage.hpp> -#include "Compiler.hpp" +#include "GlslangCompiler.hpp" namespace vkcv::shader { @@ -22,7 +22,7 @@ namespace vkcv::shader { /** * A class to handle GLSL runtime shader compilation. */ - class GLSLCompiler : public Compiler { + class GLSLCompiler : public GlslangCompiler { private: GLSLCompileTarget m_target; @@ -32,65 +32,22 @@ namespace vkcv::shader { * * @param[in] target Compile target (optional) */ - GLSLCompiler(GLSLCompileTarget target = GLSLCompileTarget::UNKNOWN); - - /** - * The copy-constructor of a runtime GLSL shader compiler instance. - * @param[in] other Other instance of a GLSL shader compiler instance - */ - GLSLCompiler(const GLSLCompiler& other); - - /** - * The move-constructor of a runtime GLSL shader compiler instance. - * @param[out] other Other instance of a GLSL shader compiler instance - */ - GLSLCompiler(GLSLCompiler&& other) = default; - - /** - * The destructor of a runtime GLSL shader compiler instance. - */ - ~GLSLCompiler(); - - /** - * The copy-operator of a runtime GLSL shader compiler instance. - * @param[in] other Other instance of a GLSL shader compiler instance - * @return Reference to this instance - */ - GLSLCompiler& operator=(const GLSLCompiler& other); - - /** - * The copy-operator of a runtime GLSL shader compiler instance. - * @param[out] other Other instance of a GLSL shader compiler instance - * @return Reference to this instance - */ - GLSLCompiler& operator=(GLSLCompiler&& other) = default; + explicit GLSLCompiler(GLSLCompileTarget target = GLSLCompileTarget::UNKNOWN); /** * Compile a GLSL 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 char* shaderSource, + bool compileSource(ShaderStage shaderStage, + const char* shaderSource, const ShaderCompiledFunction& compiled, const std::filesystem::path& includePath = "") override; - - /** - * Compile a GLSL 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/GlslangCompiler.hpp b/modules/shader_compiler/include/vkcv/shader/GlslangCompiler.hpp new file mode 100644 index 00000000..79a86cf5 --- /dev/null +++ b/modules/shader_compiler/include/vkcv/shader/GlslangCompiler.hpp @@ -0,0 +1,102 @@ +#pragma once + +#include <filesystem> + +#include <vkcv/ShaderStage.hpp> +#include "Compiler.hpp" + +namespace vkcv::shader { + + /** + * @addtogroup vkcv_shader + * @{ + */ + + /** + * An abstract class to handle Glslang runtime shader compilation. + */ + class GlslangCompiler : public Compiler { + protected: + /** + * + * + * @param[in] shaderPath Filepath of shader + * @param[out] spirv + * @return + */ + static bool writeSpirvCode(const std::filesystem::path &shaderPath, + const std::vector<uint32_t>& spirv); + + /** + * + * + * @param[in] shaderPath Filepath of shader + * @return + */ + static std::vector<char> readShaderCode(const std::filesystem::path &shaderPath); + + public: + /** + * The constructor of a runtime Glslang shader compiler instance. + * + * @param[in] target Compile target (optional) + */ + GlslangCompiler(); + + /** + * The copy-constructor of a runtime Glslang shader compiler instance. + * + * @param[in] other Other instance of a Glslang shader compiler instance + */ + GlslangCompiler(const GlslangCompiler& other); + + /** + * The move-constructor of a runtime Glslang shader compiler instance. + * + * @param[out] other Other instance of a Glslang shader compiler instance + */ + GlslangCompiler(GlslangCompiler&& other) = default; + + /** + * The destructor of a runtime Glslang shader compiler instance. + */ + ~GlslangCompiler(); + + /** + * The copy-operator of a runtime Glslang shader compiler instance. + * + * @param[in] other Other instance of a Glslang shader compiler instance + * @return Reference to this instance + */ + GlslangCompiler& operator=(const GlslangCompiler& other); + + /** + * The copy-operator of a runtime Glslang shader compiler instance. + * + * @param[out] other Other instance of a Glslang shader compiler instance + * @return Reference to this instance + */ + 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/HLSLCompiler.hpp b/modules/shader_compiler/include/vkcv/shader/HLSLCompiler.hpp new file mode 100644 index 00000000..9baf2cbf --- /dev/null +++ b/modules/shader_compiler/include/vkcv/shader/HLSLCompiler.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include <filesystem> + +#include <vkcv/ShaderStage.hpp> +#include "GlslangCompiler.hpp" + +namespace vkcv::shader { + + /** + * @addtogroup vkcv_shader + * @{ + */ + + enum class HLSLCompileTarget { + UNKNOWN + }; + + /** + * A class to handle HLSL runtime shader compilation. + */ + class HLSLCompiler : public GlslangCompiler { + private: + HLSLCompileTarget m_target; + + public: + /** + * The constructor of a runtime HLSL shader compiler instance. + * + * @param[in] target Compile target (optional) + */ + explicit HLSLCompiler(HLSLCompileTarget target = HLSLCompileTarget::UNKNOWN); + + /** + * Compile a HLSL 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 char* shaderSource, + const ShaderCompiledFunction& compiled, + const std::filesystem::path& includePath = "") override; + + }; + + /** @} */ + +} diff --git a/modules/shader_compiler/src/vkcv/shader/GLSLCompiler.cpp b/modules/shader_compiler/src/vkcv/shader/GLSLCompiler.cpp index 78a82113..0f423557 100644 --- a/modules/shader_compiler/src/vkcv/shader/GLSLCompiler.cpp +++ b/modules/shader_compiler/src/vkcv/shader/GLSLCompiler.cpp @@ -1,7 +1,6 @@ #include "vkcv/shader/GLSLCompiler.hpp" -#include <fstream> #include <sstream> #include <glslang/SPIRV/GlslangToSpv.h> #include <glslang/StandAlone/DirStackFileIncluder.h> @@ -11,34 +10,8 @@ namespace vkcv::shader { - static uint32_t s_CompilerCount = 0; - - GLSLCompiler::GLSLCompiler(GLSLCompileTarget target) : - Compiler(), - m_target(target) { - if (s_CompilerCount == 0) { - glslang::InitializeProcess(); - } - - s_CompilerCount++; - } - - GLSLCompiler::GLSLCompiler(const GLSLCompiler &other) : Compiler(other) { - s_CompilerCount++; - } - - GLSLCompiler::~GLSLCompiler() { - s_CompilerCount--; - - if (s_CompilerCount == 0) { - glslang::FinalizeProcess(); - } - } - - GLSLCompiler &GLSLCompiler::operator=(const GLSLCompiler &other) { - s_CompilerCount++; - return *this; - } + GLSLCompiler::GLSLCompiler(GLSLCompileTarget target) + : GlslangCompiler(), m_target(target) {} constexpr EShLanguage findShaderLanguage(ShaderStage shaderStage) { switch (shaderStage) { @@ -168,56 +141,19 @@ namespace vkcv::shader { resources.maxTaskWorkGroupSizeY_NV = 1; resources.maxTaskWorkGroupSizeZ_NV = 1; resources.maxMeshViewCountNV = 4; - resources.limits.nonInductiveForLoops = 1; - resources.limits.whileLoops = 1; - resources.limits.doWhileLoops = 1; - resources.limits.generalUniformIndexing = 1; - resources.limits.generalAttributeMatrixVectorIndexing = 1; - resources.limits.generalVaryingIndexing = 1; - resources.limits.generalSamplerIndexing = 1; - resources.limits.generalVariableIndexing = 1; - resources.limits.generalConstantMatrixVectorIndexing = 1; - } - - static std::vector<char> readShaderCode(const std::filesystem::path &shaderPath) { - std::ifstream file (shaderPath.string(), std::ios::ate); - - if (!file.is_open()) { - vkcv_log(LogLevel::ERROR, "The file could not be opened (%s)", shaderPath.string().c_str()); - return std::vector<char>{}; - } - - std::streamsize fileSize = file.tellg(); - std::vector<char> buffer (fileSize + 1); - - file.seekg(0); - file.read(buffer.data(), fileSize); - file.close(); - - buffer[fileSize] = '\0'; - return buffer; + resources.limits.nonInductiveForLoops = true; + resources.limits.whileLoops = true; + resources.limits.doWhileLoops = true; + resources.limits.generalUniformIndexing = true; + resources.limits.generalAttributeMatrixVectorIndexing = true; + resources.limits.generalVaryingIndexing = true; + resources.limits.generalSamplerIndexing = true; + resources.limits.generalVariableIndexing = true; + resources.limits.generalConstantMatrixVectorIndexing = true; } - static bool writeSpirvCode(const std::filesystem::path &shaderPath, const std::vector<uint32_t>& spirv) { - std::ofstream file (shaderPath.string(), std::ios::out | std::ios::binary); - - if (!file.is_open()) { - vkcv_log(LogLevel::ERROR, "The file could not be opened (%s)", shaderPath.string().c_str()); - return false; - } - - const auto fileSize = static_cast<std::streamsize>( - sizeof(uint32_t) * spirv.size() - ); - - file.seekp(0); - file.write(reinterpret_cast<const char*>(spirv.data()), fileSize); - file.close(); - - return true; - } - - bool GLSLCompiler::compileSource(ShaderStage shaderStage, const char* shaderSource, + bool GLSLCompiler::compileSource(ShaderStage shaderStage, + const char* shaderSource, const ShaderCompiledFunction &compiled, const std::filesystem::path& includePath) { const EShLanguage language = findShaderLanguage(shaderStage); @@ -334,25 +270,4 @@ namespace vkcv::shader { return true; } - void GLSLCompiler::compile(ShaderStage shaderStage, const std::filesystem::path &shaderPath, - const ShaderCompiledFunction& compiled, - const std::filesystem::path& includePath, bool update) { - const std::vector<char> code = readShaderCode(shaderPath); - bool result; - - if (!includePath.empty()) { - result = compileSource(shaderStage, code.data(), compiled, includePath); - } else { - result = compileSource(shaderStage, code.data(), 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/GlslangCompiler.cpp b/modules/shader_compiler/src/vkcv/shader/GlslangCompiler.cpp new file mode 100644 index 00000000..9ee6952b --- /dev/null +++ b/modules/shader_compiler/src/vkcv/shader/GlslangCompiler.cpp @@ -0,0 +1,100 @@ + +#include "vkcv/shader/GlslangCompiler.hpp" + +#include <vkcv/Logger.hpp> + +#include <fstream> +#include <glslang/SPIRV/GlslangToSpv.h> + +namespace vkcv::shader { + + static uint32_t s_CompilerCount = 0; + + GlslangCompiler::GlslangCompiler() : Compiler() { + if (s_CompilerCount == 0) { + glslang::InitializeProcess(); + } + + s_CompilerCount++; + } + + GlslangCompiler::GlslangCompiler(const GlslangCompiler &other) : Compiler(other) { + s_CompilerCount++; + } + + GlslangCompiler::~GlslangCompiler() { + s_CompilerCount--; + + if (s_CompilerCount == 0) { + glslang::FinalizeProcess(); + } + } + + GlslangCompiler &GlslangCompiler::operator=(const GlslangCompiler &other) { + s_CompilerCount++; + return *this; + } + + bool GlslangCompiler::writeSpirvCode(const std::filesystem::path &shaderPath, + const std::vector<uint32_t>& spirv) { + std::ofstream file (shaderPath.string(), std::ios::out | std::ios::binary); + + if (!file.is_open()) { + vkcv_log(LogLevel::ERROR, "The file could not be opened (%s)", shaderPath.string().c_str()); + return false; + } + + const auto fileSize = static_cast<std::streamsize>( + sizeof(uint32_t) * spirv.size() + ); + + file.seekp(0); + file.write(reinterpret_cast<const char*>(spirv.data()), fileSize); + file.close(); + + return true; + } + + std::vector<char> GlslangCompiler::readShaderCode(const std::filesystem::path &shaderPath) { + std::ifstream file (shaderPath.string(), std::ios::ate); + + if (!file.is_open()) { + vkcv_log(LogLevel::ERROR, "The file could not be opened (%s)", shaderPath.string().c_str()); + return std::vector<char>{}; + } + + std::streamsize fileSize = file.tellg(); + std::vector<char> buffer (fileSize + 1); + + file.seekg(0); + file.read(buffer.data(), fileSize); + file.close(); + + buffer[fileSize] = '\0'; + return buffer; + } + + void GlslangCompiler::compile(ShaderStage shaderStage, + const std::filesystem::path &shaderPath, + const ShaderCompiledFunction &compiled, + const std::filesystem::path &includePath, + bool update) { + const std::vector<char> code = readShaderCode(shaderPath); + bool result; + + if (!includePath.empty()) { + result = compileSource(shaderStage, code.data(), compiled, includePath); + } else { + result = compileSource(shaderStage, code.data(), 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/HLSLCompiler.cpp b/modules/shader_compiler/src/vkcv/shader/HLSLCompiler.cpp new file mode 100644 index 00000000..6724d008 --- /dev/null +++ b/modules/shader_compiler/src/vkcv/shader/HLSLCompiler.cpp @@ -0,0 +1,265 @@ + +#include "vkcv/shader/HLSLCompiler.hpp" + +#include <sstream> +#include <glslang/SPIRV/GlslangToSpv.h> +#include <glslang/StandAlone/DirStackFileIncluder.h> + +#include <vkcv/File.hpp> +#include <vkcv/Logger.hpp> + +namespace vkcv::shader { + + HLSLCompiler::HLSLCompiler(HLSLCompileTarget target) + : GlslangCompiler(), m_target(target) {} + + constexpr EShLanguage findShaderLanguage(ShaderStage shaderStage) { + switch (shaderStage) { + case ShaderStage::VERTEX: + return EShLangVertex; + case ShaderStage::TESS_CONTROL: + return EShLangTessControl; + case ShaderStage::TESS_EVAL: + return EShLangTessEvaluation; + case ShaderStage::GEOMETRY: + return EShLangGeometry; + case ShaderStage::FRAGMENT: + return EShLangFragment; + case ShaderStage::COMPUTE: + return EShLangCompute; + case ShaderStage::TASK: + return EShLangTaskNV; + case ShaderStage::MESH: + return EShLangMeshNV; + case ShaderStage::RAY_GEN: + return EShLangRayGen; + case ShaderStage::RAY_CLOSEST_HIT: + return EShLangClosestHit; + case ShaderStage::RAY_MISS: + return EShLangMiss; + case ShaderStage::RAY_INTERSECTION: + return EShLangIntersect; + case ShaderStage::RAY_ANY_HIT: + return EShLangAnyHit; + case ShaderStage::RAY_CALLABLE: + return EShLangCallable; + default: + return EShLangCount; + } + } + + static void initResources(TBuiltInResource& resources) { + resources.maxLights = 32; + resources.maxClipPlanes = 6; + resources.maxTextureUnits = 32; + resources.maxTextureCoords = 32; + resources.maxVertexAttribs = 64; + resources.maxVertexUniformComponents = 4096; + resources.maxVaryingFloats = 64; + resources.maxVertexTextureImageUnits = 32; + resources.maxCombinedTextureImageUnits = 80; + resources.maxTextureImageUnits = 32; + resources.maxFragmentUniformComponents = 4096; + resources.maxDrawBuffers = 32; + resources.maxVertexUniformVectors = 128; + resources.maxVaryingVectors = 8; + resources.maxFragmentUniformVectors = 16; + resources.maxVertexOutputVectors = 16; + resources.maxFragmentInputVectors = 15; + resources.minProgramTexelOffset = -8; + resources.maxProgramTexelOffset = 7; + resources.maxClipDistances = 8; + resources.maxComputeWorkGroupCountX = 65535; + resources.maxComputeWorkGroupCountY = 65535; + resources.maxComputeWorkGroupCountZ = 65535; + resources.maxComputeWorkGroupSizeX = 1024; + resources.maxComputeWorkGroupSizeY = 1024; + resources.maxComputeWorkGroupSizeZ = 64; + resources.maxComputeUniformComponents = 1024; + resources.maxComputeTextureImageUnits = 16; + resources.maxComputeImageUniforms = 8; + resources.maxComputeAtomicCounters = 8; + resources.maxComputeAtomicCounterBuffers = 1; + resources.maxVaryingComponents = 60; + resources.maxVertexOutputComponents = 64; + resources.maxGeometryInputComponents = 64; + resources.maxGeometryOutputComponents = 128; + resources.maxFragmentInputComponents = 128; + resources.maxImageUnits = 8; + resources.maxCombinedImageUnitsAndFragmentOutputs = 8; + resources.maxCombinedShaderOutputResources = 8; + resources.maxImageSamples = 0; + resources.maxVertexImageUniforms = 0; + resources.maxTessControlImageUniforms = 0; + resources.maxTessEvaluationImageUniforms = 0; + resources.maxGeometryImageUniforms = 0; + resources.maxFragmentImageUniforms = 8; + resources.maxCombinedImageUniforms = 8; + resources.maxGeometryTextureImageUnits = 16; + resources.maxGeometryOutputVertices = 256; + resources.maxGeometryTotalOutputComponents = 1024; + resources.maxGeometryUniformComponents = 1024; + resources.maxGeometryVaryingComponents = 64; + resources.maxTessControlInputComponents = 128; + resources.maxTessControlOutputComponents = 128; + resources.maxTessControlTextureImageUnits = 16; + resources.maxTessControlUniformComponents = 1024; + resources.maxTessControlTotalOutputComponents = 4096; + resources.maxTessEvaluationInputComponents = 128; + resources.maxTessEvaluationOutputComponents = 128; + resources.maxTessEvaluationTextureImageUnits = 16; + resources.maxTessEvaluationUniformComponents = 1024; + resources.maxTessPatchComponents = 120; + resources.maxPatchVertices = 32; + resources.maxTessGenLevel = 64; + resources.maxViewports = 16; + resources.maxVertexAtomicCounters = 0; + resources.maxTessControlAtomicCounters = 0; + resources.maxTessEvaluationAtomicCounters = 0; + resources.maxGeometryAtomicCounters = 0; + resources.maxFragmentAtomicCounters = 8; + resources.maxCombinedAtomicCounters = 8; + resources.maxAtomicCounterBindings = 1; + resources.maxVertexAtomicCounterBuffers = 0; + resources.maxTessControlAtomicCounterBuffers = 0; + resources.maxTessEvaluationAtomicCounterBuffers = 0; + resources.maxGeometryAtomicCounterBuffers = 0; + resources.maxFragmentAtomicCounterBuffers = 1; + resources.maxCombinedAtomicCounterBuffers = 1; + resources.maxAtomicCounterBufferSize = 16384; + resources.maxTransformFeedbackBuffers = 4; + resources.maxTransformFeedbackInterleavedComponents = 64; + resources.maxCullDistances = 8; + resources.maxCombinedClipAndCullDistances = 8; + resources.maxSamples = 4; + resources.maxMeshOutputVerticesNV = 256; + resources.maxMeshOutputPrimitivesNV = 512; + resources.maxMeshWorkGroupSizeX_NV = 32; + resources.maxMeshWorkGroupSizeY_NV = 1; + resources.maxMeshWorkGroupSizeZ_NV = 1; + resources.maxTaskWorkGroupSizeX_NV = 32; + resources.maxTaskWorkGroupSizeY_NV = 1; + resources.maxTaskWorkGroupSizeZ_NV = 1; + resources.maxMeshViewCountNV = 4; + resources.limits.nonInductiveForLoops = true; + resources.limits.whileLoops = true; + resources.limits.doWhileLoops = true; + resources.limits.generalUniformIndexing = true; + resources.limits.generalAttributeMatrixVectorIndexing = true; + resources.limits.generalVaryingIndexing = true; + resources.limits.generalSamplerIndexing = true; + resources.limits.generalVariableIndexing = true; + resources.limits.generalConstantMatrixVectorIndexing = true; + } + + bool HLSLCompiler::compileSource(ShaderStage shaderStage, + const char* shaderSource, + const ShaderCompiledFunction &compiled, + const std::filesystem::path& includePath) { + const EShLanguage language = findShaderLanguage(shaderStage); + + if (language == EShLangCount) { + vkcv_log(LogLevel::ERROR, "Shader stage not supported"); + return false; + } + + glslang::TShader shader (language); + switch (m_target) { + default: + break; + } + + glslang::TProgram program; + std::string source (shaderSource); + + if (!m_defines.empty()) { + std::ostringstream defines; + for (const auto& define : m_defines) { + defines << "#define " << define.first << " " << define.second << std::endl; + } + + size_t pos = source.find("#version") + 8; + if (pos >= source.length()) { + pos = 0; + } + + const size_t epos = source.find_last_of("#extension", pos) + 10; + if (epos < source.length()) { + pos = epos; + } + + const auto defines_str = defines.str(); + + pos = source.find('\n', pos) + 1; + source = source.insert(pos, defines_str); + } + + const char *shaderStrings [1]; + shaderStrings[0] = source.c_str(); + + shader.setStrings(shaderStrings, 1); + + TBuiltInResource resources = {}; + initResources(resources); + + const auto messages = (EShMessages)( + EShMsgSpvRules | + EShMsgVulkanRules + ); + + std::string preprocessedHLSL; + + DirStackFileIncluder includer; + includer.pushExternalLocalDirectory(includePath.string()); + + if (!shader.preprocess(&resources, 100, ENoProfile, + false, false, + messages, &preprocessedHLSL, includer)) { + vkcv_log(LogLevel::ERROR, "Shader preprocessing failed {\n%s\n%s\n}", + shader.getInfoLog(), shader.getInfoDebugLog()); + return false; + } + + const char* preprocessedCString = preprocessedHLSL.c_str(); + shader.setStrings(&preprocessedCString, 1); + + if (!shader.parse(&resources, 100, false, messages)) { + vkcv_log(LogLevel::ERROR, "Shader parsing failed {\n%s\n%s\n}", + shader.getInfoLog(), shader.getInfoDebugLog()); + return false; + } + + program.addShader(&shader); + + if (!program.link(messages)) { + vkcv_log(LogLevel::ERROR, "Shader linking failed {\n%s\n%s\n}", + shader.getInfoLog(), shader.getInfoDebugLog()); + return false; + } + + const glslang::TIntermediate* intermediate = program.getIntermediate(language); + + if (!intermediate) { + vkcv_log(LogLevel::ERROR, "No valid intermediate representation"); + return false; + } + + std::vector<uint32_t> spirv; + glslang::GlslangToSpv(*intermediate, spirv); + + const std::filesystem::path tmp_path = generateTemporaryFilePath(); + + if (!writeSpirvCode(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; + } + +} -- GitLab