diff --git a/bin/resources/Shader.glsl.binding.json b/bin/resources/Shader.glsl.binding.json new file mode 100644 index 0000000..c6780d4 --- /dev/null +++ b/bin/resources/Shader.glsl.binding.json @@ -0,0 +1,10 @@ +{ + "bindings": [ + { + "set": 0, + "binding": 0, + "glsl_binding": 0 + } + ], + "push_constant_binding": 1 +} \ No newline at end of file diff --git a/bin/resources/Shader.nzsl b/bin/resources/Shader.nzsl index 8fbdcd5..a719d7c 100644 --- a/bin/resources/Shader.nzsl +++ b/bin/resources/Shader.nzsl @@ -8,6 +8,17 @@ import GetColor as Color from Color; import * from DataStruct; import * from OutputStruct; +[layout(std140)] +struct PushConstants +{ + color: vec4[f32] +} + +external ExternalResources +{ + constants: push_constant[PushConstants] +} + [entry(frag)] fn main() -> Output { @@ -15,7 +26,7 @@ fn main() -> Output data.color = Color(); let output: Output; - output.color = GetColorFromData(data); + output.color = GetColorFromData(data) * ExternalResources.constants.color; return output; } diff --git a/include/CNZSL/GlslWriter.h b/include/CNZSL/GlslWriter.h index 7d7e6ed..0b940a9 100644 --- a/include/CNZSL/GlslWriter.h +++ b/include/CNZSL/GlslWriter.h @@ -21,7 +21,7 @@ extern "C" #endif typedef struct nzslGlslWriter nzslGlslWriter; -typedef struct nzslGlslBindingMapping nzslGlslBindingMapping; +typedef struct nzslGlslWriterParameters nzslGlslWriterParameters; typedef struct nzslGlslOutput nzslGlslOutput; typedef struct @@ -34,16 +34,17 @@ typedef struct int allowDrawParametersUniformsFallback; } nzslGlslWriterEnvironment; -CNZSL_API nzslGlslBindingMapping* nzslGlslBindingMappingCreate(void); -CNZSL_API void nzslGlslBindingMappingDestroy(nzslGlslBindingMapping* bindingMappingPtr); +CNZSL_API nzslGlslWriterParameters* nzslGlslWriterParametersCreate(void); +CNZSL_API void nzslGlslWriterParametersDestroy(nzslGlslWriterParameters* parameterPtr); -CNZSL_API void nzslGlslBindingMappingSetBinding(nzslGlslBindingMapping* bindingMappingPtr, uint32_t setIndex, uint32_t bindingIndex, unsigned int glBinding); +CNZSL_API void nzslGlslWriterParametersSetBindingMapping(nzslGlslWriterParameters* parameterPtr, uint32_t setIndex, uint32_t bindingIndex, unsigned int glBinding); +CNZSL_API void nzslGlslWriterParametersSetPushConstantBinding(nzslGlslWriterParameters* parameterPtr, unsigned int glBinding); +CNZSL_API void nzslGlslWriterParametersSetShaderStage(nzslGlslWriterParameters* parameterPtr, nzslShaderStageType stage); CNZSL_API nzslGlslWriter* nzslGlslWriterCreate(void); CNZSL_API void nzslGlslWriterDestroy(nzslGlslWriter* writerPtr); -CNZSL_API nzslGlslOutput* nzslGlslWriterGenerate(nzslGlslWriter* writerPtr, const nzslModule* modulePtr, const nzslGlslBindingMapping* bindingMapping, const nzslWriterStates* statesPtr); -CNZSL_API nzslGlslOutput* nzslGlslWriterGenerateStage(nzslShaderStageType stage, nzslGlslWriter* writerPtr, const nzslModule* modulePtr, const nzslGlslBindingMapping* bindingMapping, const nzslWriterStates* statesPtr); +CNZSL_API nzslGlslOutput* nzslGlslWriterGenerate(nzslGlslWriter* writerPtr, const nzslModule* modulePtr, const nzslGlslWriterParameters* parameterPtr, const nzslWriterStates* statesPtr); /** ** Gets the last error message set by the last operation to this writer diff --git a/include/NZSL/GlslWriter.hpp b/include/NZSL/GlslWriter.hpp index 092a765..5855d4d 100644 --- a/include/NZSL/GlslWriter.hpp +++ b/include/NZSL/GlslWriter.hpp @@ -23,18 +23,17 @@ namespace nzsl class NZSL_API GlslWriter : public ShaderWriter, public Ast::ExpressionVisitorExcept, public Ast::StatementVisitorExcept { public: - using BindingMapping = std::unordered_map; using ExtSupportCallback = std::function; struct Environment; struct Output; + struct Parameters; inline GlslWriter(); GlslWriter(const GlslWriter&) = delete; GlslWriter(GlslWriter&&) = delete; ~GlslWriter() = default; - inline Output Generate(const Ast::Module& module, const BindingMapping& bindingMapping = {}, const States& states = {}); - Output Generate(std::optional shaderStage, const Ast::Module& module, const BindingMapping& bindingMapping = {}, const States& states = {}); + Output Generate(const Ast::Module& module, const Parameters& parameters = {}, const States& states = {}); void SetEnv(Environment environment); @@ -49,6 +48,13 @@ namespace nzsl bool allowDrawParametersUniformsFallback = false; }; + struct Parameters + { + std::optional pushConstantBinding; + std::optional shaderStage; + std::unordered_map bindingMapping; + }; + struct Output { std::string code; diff --git a/include/NZSL/GlslWriter.inl b/include/NZSL/GlslWriter.inl index 7d2dfa1..0675cc6 100644 --- a/include/NZSL/GlslWriter.inl +++ b/include/NZSL/GlslWriter.inl @@ -2,16 +2,10 @@ // This file is part of the "Nazara Shading Language" project // For conditions of distribution and use, see copyright notice in Config.hpp - namespace nzsl { inline GlslWriter::GlslWriter() : m_currentState(nullptr) { } - - inline auto GlslWriter::Generate(const Ast::Module& shader, const BindingMapping& bindingMapping, const States& states) -> Output - { - return Generate(std::nullopt, shader, bindingMapping, states); - } } diff --git a/src/CNZSL/GlslWriter.cpp b/src/CNZSL/GlslWriter.cpp index c43bd42..8fec132 100644 --- a/src/CNZSL/GlslWriter.cpp +++ b/src/CNZSL/GlslWriter.cpp @@ -3,7 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include -#include +#include #include #include #include @@ -14,68 +14,53 @@ extern "C" { - CNZSL_API nzslGlslBindingMapping* nzslGlslBindingMappingCreate(void) + CNZSL_API nzslGlslWriterParameters* nzslGlslWriterParametersCreate(void) { - return new nzslGlslBindingMapping; + return new nzslGlslWriterParameters; } - CNZSL_API void nzslGlslBindingMappingDestroy(nzslGlslBindingMapping* bindingMappingPtr) + CNZSL_API void nzslGlslWriterParametersDestroy(nzslGlslWriterParameters* parameterPtr) { - delete bindingMappingPtr; + delete parameterPtr; } - CNZSL_API void nzslGlslBindingMappingSetBinding(nzslGlslBindingMapping* bindingMappingPtr, uint32_t setIndex, uint32_t bindingIndex, unsigned int glBinding) + CNZSL_API void nzslGlslWriterParametersSetBindingMapping(nzslGlslWriterParameters* parameterPtr, uint32_t setIndex, uint32_t bindingIndex, unsigned int glBinding) { uint64_t setBinding = setIndex; setBinding <<= 32; setBinding |= bindingIndex; - bindingMappingPtr->mappings[setBinding] = glBinding; + parameterPtr->parameters.bindingMapping[setBinding] = glBinding; } - CNZSL_API nzslGlslWriter* nzslGlslWriterCreate(void) + CNZSL_API void nzslGlslWriterParametersSetPushConstantBinding(nzslGlslWriterParameters* parameterPtr, unsigned int glBinding) { - return new nzslGlslWriter; + parameterPtr->parameters.pushConstantBinding = glBinding; } - CNZSL_API void nzslGlslWriterDestroy(nzslGlslWriter* writerPtr) + CNZSL_API void nzslGlslWriterParametersSetShaderStage(nzslGlslWriterParameters* parameterPtr, nzslShaderStageType stage) { - delete writerPtr; + constexpr std::array s_shaderStages = { + nzsl::ShaderStageType::Compute, // NZSL_STAGE_COMPUTE + nzsl::ShaderStageType::Fragment, // NZSL_STAGE_FRAGMENT + nzsl::ShaderStageType::Vertex // NZSL_STAGE_VERTEX + }; + + parameterPtr->parameters.shaderStage = s_shaderStages[stage]; } - CNZSL_API nzslGlslOutput* nzslGlslWriterGenerate(nzslGlslWriter* writerPtr, const nzslModule* modulePtr, const nzslGlslBindingMapping* bindingMapping, const nzslWriterStates* statesPtr) + CNZSL_API nzslGlslWriter* nzslGlslWriterCreate(void) { - try - { - nzsl::GlslWriter::States states; - if (statesPtr) - states = static_cast(*statesPtr); - - std::unique_ptr output = std::make_unique(); - static_cast(*output) = writerPtr->writer.Generate(*modulePtr->module, bindingMapping->mappings, states); - - return output.release(); - } - catch (std::exception& e) - { - writerPtr->lastError = fmt::format("nzslGlslWriterGenerate failed: {}", e.what()); - return nullptr; - } - catch (...) - { - writerPtr->lastError = "nzslGlslWriterGenerate failed with unknown error"; - return nullptr; - } + return new nzslGlslWriter; } - CNZSL_API nzslGlslOutput* nzslGlslWriterGenerateStage(nzslShaderStageType stage, nzslGlslWriter* writerPtr, const nzslModule* modulePtr, const nzslGlslBindingMapping* bindingMapping, const nzslWriterStates* statesPtr) + CNZSL_API void nzslGlslWriterDestroy(nzslGlslWriter* writerPtr) { - constexpr std::array s_shaderStages = { - nzsl::ShaderStageType::Compute, // NZSL_STAGE_COMPUTE - nzsl::ShaderStageType::Fragment, // NZSL_STAGE_FRAGMENT - nzsl::ShaderStageType::Vertex // NZSL_STAGE_VERTEX - }; + delete writerPtr; + } + CNZSL_API nzslGlslOutput* nzslGlslWriterGenerate(nzslGlslWriter* writerPtr, const nzslModule* modulePtr, const nzslGlslWriterParameters* parameters, const nzslWriterStates* statesPtr) + { try { nzsl::GlslWriter::States states; @@ -83,7 +68,7 @@ extern "C" states = static_cast(*statesPtr); std::unique_ptr output = std::make_unique(); - static_cast(*output) = writerPtr->writer.Generate(s_shaderStages[stage], *modulePtr->module, bindingMapping->mappings, states); + static_cast(*output) = writerPtr->writer.Generate(*modulePtr->module, parameters->parameters, states); return output.release(); } diff --git a/src/CNZSL/Structs/GlslBindingMapping.hpp b/src/CNZSL/Structs/GlslWriterParameters.hpp similarity index 56% rename from src/CNZSL/Structs/GlslBindingMapping.hpp rename to src/CNZSL/Structs/GlslWriterParameters.hpp index af1958d..dea3091 100644 --- a/src/CNZSL/Structs/GlslBindingMapping.hpp +++ b/src/CNZSL/Structs/GlslWriterParameters.hpp @@ -4,14 +4,14 @@ #pragma once -#ifndef CNZSL_STRUCTS_GLSLBINDINGMAPPING_HPP -#define CNZSL_STRUCTS_GLSLBINDINGMAPPING_HPP +#ifndef CNZSL_STRUCTS_GLSLWRITERPARAMETERS_HPP +#define CNZSL_STRUCTS_GLSLWRITERPARAMETERS_HPP #include -struct nzslGlslBindingMapping +struct nzslGlslWriterParameters { - nzsl::GlslWriter::BindingMapping mappings; + nzsl::GlslWriter::Parameters parameters; }; -#endif // CNZSL_STRUCTS_GLSLBINDINGMAPPING_HPP +#endif // CNZSL_STRUCTS_GLSLWRITERPARAMETERS_HPP diff --git a/src/NZSL/GlslWriter.cpp b/src/NZSL/GlslWriter.cpp index b477296..c722c71 100644 --- a/src/NZSL/GlslWriter.cpp +++ b/src/NZSL/GlslWriter.cpp @@ -35,6 +35,7 @@ namespace nzsl constexpr std::string_view s_glslWriterShaderDrawParametersBaseVertexName = "_nzslBaseVertex"; constexpr std::string_view s_glslWriterShaderDrawParametersDrawIndexName = "_nzslDrawID"; constexpr std::string_view s_glslWriterBlockBindingPrefix = "_nzslBinding"; + constexpr std::string_view s_glslWriterPushConstantPrefix = "_nzslPushConstant"; constexpr std::string_view s_glslWriterVaryingPrefix = "_nzslVarying"; constexpr std::string_view s_glslWriterInputPrefix = "_nzslIn"; constexpr std::string_view s_glslWriterOutputPrefix = "_nzslOut"; @@ -318,8 +319,8 @@ namespace nzsl struct GlslWriter::State { - State(const GlslWriter::BindingMapping& bindings) : - bindingMapping(bindings) + State(const GlslWriter::Parameters& parameters) : + writerParameters(parameters) { } @@ -346,7 +347,7 @@ namespace nzsl std::unordered_map explicitUniformBlockBinding; std::unordered_set reservedNames; Nz::Bitset<> declaredFunctions; - const GlslWriter::BindingMapping& bindingMapping; + const GlslWriter::Parameters& writerParameters; GlslWriterPreVisitor previsitor; ShaderStageType stage; const States* states = nullptr; @@ -361,9 +362,9 @@ namespace nzsl unsigned int indentLevel = 0; }; - auto GlslWriter::Generate(std::optional shaderStage, const Ast::Module& module, const BindingMapping& bindingMapping, const States& states) -> GlslWriter::Output + auto GlslWriter::Generate(const Ast::Module& module, const Parameters& parameters, const States& states) -> GlslWriter::Output { - State state(bindingMapping); + State state(parameters); state.states = &states; m_currentState = &state; @@ -388,7 +389,7 @@ namespace nzsl sanitizedModule = Ast::PropagateConstants(*targetModule); Ast::DependencyCheckerVisitor::Config dependencyConfig; - dependencyConfig.usedShaderStages = (shaderStage) ? *shaderStage : ShaderStageType_All; //< only one should exist anyway + dependencyConfig.usedShaderStages = (parameters.shaderStage) ? *parameters.shaderStage : ShaderStageType_All; //< only one should exist anyway sanitizedModule = Ast::EliminateUnusedPass(*sanitizedModule, dependencyConfig); @@ -414,7 +415,7 @@ namespace nzsl } } - state.previsitor.selectedStage = shaderStage; + state.previsitor.selectedStage = parameters.shaderStage; for (const auto& importedModule : targetModule->importedModules) { @@ -2257,7 +2258,7 @@ namespace nzsl const Ast::ExpressionType& exprType = externalVar.type.GetResultingValue(); - bool isUniformOrStorageBuffer = IsStorageType(exprType) || IsUniformType(exprType); + bool isUniformOrStorageBuffer = IsPushConstantType(exprType) || IsStorageType(exprType) || IsUniformType(exprType); const char* memoryLayout = nullptr; if (isUniformOrStorageBuffer) @@ -2324,38 +2325,51 @@ namespace nzsl Append(") "); }; - if (!m_currentState->bindingMapping.empty()) + if (!IsPushConstantType(exprType)) { - assert(externalVar.bindingIndex.HasValue()); + if (!m_currentState->writerParameters.bindingMapping.empty()) + { + assert(externalVar.bindingIndex.HasValue()); - std::uint64_t bindingIndex = externalVar.bindingIndex.GetResultingValue(); - std::uint64_t bindingSet; - if (externalVar.bindingSet.HasValue()) - bindingSet = externalVar.bindingSet.GetResultingValue(); - else - bindingSet = 0; + std::uint64_t bindingIndex = externalVar.bindingIndex.GetResultingValue(); + std::uint64_t bindingSet; + if (externalVar.bindingSet.HasValue()) + bindingSet = externalVar.bindingSet.GetResultingValue(); + else + bindingSet = 0; - auto bindingIt = m_currentState->bindingMapping.find(bindingSet << 32 | bindingIndex); - if (bindingIt == m_currentState->bindingMapping.end()) - throw std::runtime_error("no binding found for (set=" + std::to_string(bindingSet) + ", binding=" + std::to_string(bindingIndex) + ")"); + auto bindingIt = m_currentState->writerParameters.bindingMapping.find(bindingSet << 32 | bindingIndex); + if (bindingIt == m_currentState->writerParameters.bindingMapping.end()) + throw std::runtime_error("no binding found for (set=" + std::to_string(bindingSet) + ", binding=" + std::to_string(bindingIndex) + ")"); - unsigned int glslBindingIndex = bindingIt->second; + unsigned int glslBindingIndex = bindingIt->second; + + if (!m_currentState->requiresExplicitUniformBinding) + { + BeginLayout(); + Append("binding = ", glslBindingIndex); + } + else + { + // Ensure name is unique + varName += std::to_string(glslBindingIndex); + if (IsSamplerType(exprType)) + m_currentState->explicitTextureBinding.emplace(varName, glslBindingIndex); + else + m_currentState->explicitUniformBlockBinding.emplace(std::string(s_glslWriterBlockBindingPrefix) + varName, glslBindingIndex); + } + } + } + else if (m_currentState->writerParameters.pushConstantBinding.has_value()) + { if (!m_currentState->requiresExplicitUniformBinding) { BeginLayout(); - Append("binding = ", glslBindingIndex); + Append("binding = ", *m_currentState->writerParameters.pushConstantBinding); } else - { - // Ensure name is unique - varName += std::to_string(glslBindingIndex); - - if (IsSamplerType(exprType)) - m_currentState->explicitTextureBinding.emplace(varName, glslBindingIndex); - else - m_currentState->explicitUniformBlockBinding.emplace(std::string(s_glslWriterBlockBindingPrefix) + varName, glslBindingIndex); - } + m_currentState->explicitUniformBlockBinding.emplace(s_glslWriterPushConstantPrefix, *m_currentState->writerParameters.pushConstantBinding); } if (IsTextureType(exprType)) @@ -2395,8 +2409,13 @@ namespace nzsl if (isUniformOrStorageBuffer) { - Append(s_glslWriterBlockBindingPrefix); - AppendLine(varName); + if (IsPushConstantType(exprType)) + AppendLine(s_glslWriterPushConstantPrefix); + else + { + Append(s_glslWriterBlockBindingPrefix); + AppendLine(varName); + } EnterScope(); { diff --git a/src/ShaderCompiler/Compiler.cpp b/src/ShaderCompiler/Compiler.cpp index 6b038d6..3d1dd58 100644 --- a/src/ShaderCompiler/Compiler.cpp +++ b/src/ShaderCompiler/Compiler.cpp @@ -324,11 +324,11 @@ You can also specify -header as a suffix (ex: --compile=glsl-header) to generate env.glMinorVersion = (version % 100) / 10; } - nzsl::GlslWriter::BindingMapping bindingMapping; + nzsl::GlslWriter::Parameters parameters; if (m_options.count("gl-bindingmap") > 0) { unsigned int glslBinding = 0; - nlohmann::json bindingArray; + nlohmann::ordered_json bindingArray; nzsl::Ast::ReflectVisitor::Callbacks callbacks; callbacks.onExternalDeclaration = [&](const nzsl::Ast::DeclareExternalStatement& extDecl) @@ -344,6 +344,12 @@ You can also specify -header as a suffix (ex: --compile=glsl-header) to generate for (auto& extVar : extDecl.externalVars) { + if (IsPushConstantType(extVar.type.GetResultingValue())) + { + parameters.pushConstantBinding = glslBinding++; + continue; + } + std::uint64_t bindingSet = extSet; if (extVar.bindingSet.HasValue()) { @@ -360,9 +366,9 @@ You can also specify -header as a suffix (ex: --compile=glsl-header) to generate bindingIndex = extVar.bindingIndex.GetResultingValue(); std::uint64_t binding = bindingSet << 32 | bindingIndex; - bindingMapping.emplace(binding, glslBinding); + parameters.bindingMapping.emplace(binding, glslBinding); - nlohmann::json& bindingDoc = bindingArray.emplace_back(); + nlohmann::ordered_json& bindingDoc = bindingArray.emplace_back(); bindingDoc["set"] = bindingSet; bindingDoc["binding"] = bindingIndex; bindingDoc["glsl_binding"] = glslBinding; @@ -376,14 +382,17 @@ You can also specify -header as a suffix (ex: --compile=glsl-header) to generate if (!bindingArray.empty()) { - nlohmann::json finalDoc; + nlohmann::ordered_json finalDoc; finalDoc["bindings"] = std::move(bindingArray); + if (parameters.pushConstantBinding.has_value()) + finalDoc["push_constant_binding"] = *parameters.pushConstantBinding; + std::string bindingStr = finalDoc.dump(4); std::filesystem::path bindingOutputPath = outputPath; bindingOutputPath.replace_extension("glsl.binding.json"); - OutputFile(std::move(bindingOutputPath), bindingStr.data(), bindingStr.size()); + OutputFile(std::move(bindingOutputPath), bindingStr.data(), bindingStr.size(), true); } } @@ -407,7 +416,9 @@ You can also specify -header as a suffix (ex: --compile=glsl-header) to generate for (nzsl::ShaderStageType entryType : entryTypes) { - nzsl::GlslWriter::Output output = writer.Generate(entryType, module, bindingMapping, states); + parameters.shaderStage = entryType; + + nzsl::GlslWriter::Output output = writer.Generate(module, parameters, states); if (m_outputToStdout) { @@ -569,9 +580,9 @@ You can also specify -header as a suffix (ex: --compile=glsl-header) to generate } } - void Compiler::OutputFile(std::filesystem::path filePath, const void* data, std::size_t size) + void Compiler::OutputFile(std::filesystem::path filePath, const void* data, std::size_t size, bool disallowHeader) { - if (m_outputHeader) + if (m_outputHeader && !disallowHeader) { std::string headerFile = ToHeader(data, size); diff --git a/src/ShaderCompiler/Compiler.hpp b/src/ShaderCompiler/Compiler.hpp index b5c934d..adabef6 100644 --- a/src/ShaderCompiler/Compiler.hpp +++ b/src/ShaderCompiler/Compiler.hpp @@ -55,7 +55,7 @@ namespace nzslc void CompileToNZSLB(std::filesystem::path outputPath, const nzsl::Ast::Module& module); void CompileToSPV(std::filesystem::path outputPath, const nzsl::Ast::Module& module, bool textual); void PrintTime(); - void OutputFile(std::filesystem::path filePath, const void* data, std::size_t size); + void OutputFile(std::filesystem::path filePath, const void* data, std::size_t size, bool disallowHeader = false); void OutputToStdout(std::string_view str); void ReadInput(); void Sanitize(); diff --git a/tests/src/Tests/DebugInfoTests.cpp b/tests/src/Tests/DebugInfoTests.cpp index 59ea9be..5bbb22e 100644 --- a/tests/src/Tests/DebugInfoTests.cpp +++ b/tests/src/Tests/DebugInfoTests.cpp @@ -63,6 +63,16 @@ struct Output_OutputStruct vec4 color; }; +struct PushConstants +{ + vec4 color; +}; + +layout(std140) uniform _nzslPushConstant +{ + vec4 color; +} ExternalResources_constants; + layout(location = 0) out vec4 _nzslOutcolor; void main() @@ -70,7 +80,7 @@ void main() Data_DataStruct data; data.color = GetColor_Color(); Output_OutputStruct output_; - output_.color = GetColorFromData_OutputStruct(data); + output_.color = (GetColorFromData_OutputStruct(data)) * ExternalResources_constants.color; _nzslOutcolor = output_.color; return; @@ -79,13 +89,15 @@ void main() ExpectSPIRV(*shaderModule, R"( OpCapability Capability(Shader) OpMemoryModel AddressingModel(Logical) MemoryModel(GLSL450) - OpEntryPoint ExecutionModel(Fragment) %27 "main" %21 - OpExecutionMode %27 ExecutionMode(OriginUpperLeft) + OpEntryPoint ExecutionModel(Fragment) %30 "main" %24 + OpExecutionMode %30 ExecutionMode(OriginUpperLeft) OpDecorate %5 Decoration(Binding) 0 OpDecorate %5 Decoration(DescriptorSet) 0 - OpDecorate %21 Decoration(Location) 0 + OpDecorate %24 Decoration(Location) 0 OpMemberDecorate %12 0 Decoration(Offset) 0 - OpMemberDecorate %22 0 Decoration(Offset) 0 + OpDecorate %18 Decoration(Block) + OpMemberDecorate %18 0 Decoration(Offset) 0 + OpMemberDecorate %25 0 Decoration(Offset) 0 %1 = OpTypeFloat 32 %2 = OpTypeImage %1 Dim(Dim2D) 0 0 0 1 ImageFormat(Unknown) %3 = OpTypeSampledImage %2 @@ -102,50 +114,57 @@ void main() %15 = OpConstant %1 f32(0.5) %16 = OpConstant %1 f32(1) %17 = OpConstantComposite %6 %15 %15 %15 %16 -%18 = OpTypeVoid -%19 = OpTypeFunction %18 -%20 = OpTypePointer StorageClass(Output) %6 -%22 = OpTypeStruct %6 -%23 = OpTypePointer StorageClass(Function) %22 -%36 = OpTypePointer StorageClass(Function) %6 +%18 = OpTypeStruct %6 +%19 = OpTypePointer StorageClass(PushConstant) %18 +%21 = OpTypeVoid +%22 = OpTypeFunction %21 +%23 = OpTypePointer StorageClass(Output) %6 +%25 = OpTypeStruct %6 +%26 = OpTypePointer StorageClass(Function) %25 +%39 = OpTypePointer StorageClass(Function) %6 +%51 = OpTypePointer StorageClass(PushConstant) %6 %5 = OpVariable %4 StorageClass(UniformConstant) -%21 = OpVariable %20 StorageClass(Output) -%24 = OpFunction %6 FunctionControl(0) %7 -%28 = OpLabel -%29 = OpLoad %3 %5 -%30 = OpCompositeConstruct %11 %8 %8 -%31 = OpImageSampleImplicitLod %6 %29 %30 - OpReturnValue %31 - OpFunctionEnd -%25 = OpFunction %6 FunctionControl(0) %7 -%32 = OpLabel -%33 = OpFunctionCall %6 %24 - OpReturnValue %33 +%20 = OpVariable %19 StorageClass(PushConstant) +%24 = OpVariable %23 StorageClass(Output) +%27 = OpFunction %6 FunctionControl(0) %7 +%31 = OpLabel +%32 = OpLoad %3 %5 +%33 = OpCompositeConstruct %11 %8 %8 +%34 = OpImageSampleImplicitLod %6 %32 %33 + OpReturnValue %34 OpFunctionEnd -%26 = OpFunction %6 FunctionControl(0) %14 -%34 = OpFunctionParameter %13 +%28 = OpFunction %6 FunctionControl(0) %7 %35 = OpLabel -%37 = OpAccessChain %36 %34 %10 -%38 = OpLoad %6 %37 -%39 = OpFMul %6 %38 %17 - OpReturnValue %39 +%36 = OpFunctionCall %6 %27 + OpReturnValue %36 + OpFunctionEnd +%29 = OpFunction %6 FunctionControl(0) %14 +%37 = OpFunctionParameter %13 +%38 = OpLabel +%40 = OpAccessChain %39 %37 %10 +%41 = OpLoad %6 %40 +%42 = OpFMul %6 %41 %17 + OpReturnValue %42 OpFunctionEnd -%27 = OpFunction %18 FunctionControl(0) %19 -%40 = OpLabel -%41 = OpVariable %13 StorageClass(Function) -%42 = OpVariable %23 StorageClass(Function) -%43 = OpVariable %13 StorageClass(Function) -%44 = OpFunctionCall %6 %25 -%45 = OpAccessChain %36 %41 %10 - OpStore %45 %44 -%46 = OpLoad %12 %41 - OpStore %43 %46 -%47 = OpFunctionCall %6 %26 %43 -%48 = OpAccessChain %36 %42 %10 +%30 = OpFunction %21 FunctionControl(0) %22 +%43 = OpLabel +%44 = OpVariable %13 StorageClass(Function) +%45 = OpVariable %26 StorageClass(Function) +%46 = OpVariable %13 StorageClass(Function) +%47 = OpFunctionCall %6 %28 +%48 = OpAccessChain %39 %44 %10 OpStore %48 %47 -%49 = OpLoad %22 %42 -%50 = OpCompositeExtract %6 %49 0 - OpStore %21 %50 +%49 = OpLoad %12 %44 + OpStore %46 %49 +%50 = OpFunctionCall %6 %29 %46 +%52 = OpAccessChain %51 %20 %10 +%53 = OpLoad %6 %52 +%54 = OpFMul %6 %50 %53 +%55 = OpAccessChain %39 %45 %10 + OpStore %55 %54 +%56 = OpLoad %25 %45 +%57 = OpCompositeExtract %6 %56 0 + OpStore %24 %57 OpReturn OpFunctionEnd)", options, {}, true); } @@ -213,6 +232,16 @@ struct Output_OutputStruct // Description: Test module // License: MIT +struct PushConstants +{ + vec4 color; +}; + +layout(std140) uniform _nzslPushConstant +{ + vec4 color; +} ExternalResources_constants; + /*************** Outputs ***************/ layout(location = 0) out vec4 _nzslOutcolor; @@ -221,33 +250,37 @@ void main() Data_DataStruct data; data.color = GetColor_Color(); Output_OutputStruct output_; - output_.color = GetColorFromData_OutputStruct(data); + output_.color = (GetColorFromData_OutputStruct(data)) * ExternalResources_constants.color; _nzslOutcolor = output_.color; return; })", options); ExpectSPIRV(*shaderModule, R"( - OpCapability Capability(Shader) OpMemoryModel AddressingModel(Logical) MemoryModel(GLSL450) - OpEntryPoint ExecutionModel(Fragment) %27 "main" %21 - OpExecutionMode %27 ExecutionMode(OriginUpperLeft) + OpEntryPoint ExecutionModel(Fragment) %30 "main" %24 + OpExecutionMode %30 ExecutionMode(OriginUpperLeft) OpSource SourceLanguage(NZSL) 100 OpName %12 "Data" OpMemberName %12 0 "color" - OpName %22 "Output" - OpMemberName %22 0 "color" + OpName %18 "PushConstants" + OpMemberName %18 0 "color" + OpName %25 "Output" + OpMemberName %25 0 "color" OpName %5 "tex1" - OpName %21 "color" - OpName %24 "GenerateColor" - OpName %25 "GetColor" - OpName %26 "GetColorFromData" - OpName %27 "main" + OpName %20 "ExternalResources_constants" + OpName %24 "color" + OpName %27 "GenerateColor" + OpName %28 "GetColor" + OpName %29 "GetColorFromData" + OpName %30 "main" OpDecorate %5 Decoration(Binding) 0 OpDecorate %5 Decoration(DescriptorSet) 0 - OpDecorate %21 Decoration(Location) 0 + OpDecorate %24 Decoration(Location) 0 OpMemberDecorate %12 0 Decoration(Offset) 0 - OpMemberDecorate %22 0 Decoration(Offset) 0 + OpDecorate %18 Decoration(Block) + OpMemberDecorate %18 0 Decoration(Offset) 0 + OpMemberDecorate %25 0 Decoration(Offset) 0 %1 = OpTypeFloat 32 %2 = OpTypeImage %1 Dim(Dim2D) 0 0 0 1 ImageFormat(Unknown) %3 = OpTypeSampledImage %2 @@ -264,50 +297,57 @@ void main() %15 = OpConstant %1 f32(0.5) %16 = OpConstant %1 f32(1) %17 = OpConstantComposite %6 %15 %15 %15 %16 -%18 = OpTypeVoid -%19 = OpTypeFunction %18 -%20 = OpTypePointer StorageClass(Output) %6 -%22 = OpTypeStruct %6 -%23 = OpTypePointer StorageClass(Function) %22 -%36 = OpTypePointer StorageClass(Function) %6 +%18 = OpTypeStruct %6 +%19 = OpTypePointer StorageClass(PushConstant) %18 +%21 = OpTypeVoid +%22 = OpTypeFunction %21 +%23 = OpTypePointer StorageClass(Output) %6 +%25 = OpTypeStruct %6 +%26 = OpTypePointer StorageClass(Function) %25 +%39 = OpTypePointer StorageClass(Function) %6 +%51 = OpTypePointer StorageClass(PushConstant) %6 %5 = OpVariable %4 StorageClass(UniformConstant) -%21 = OpVariable %20 StorageClass(Output) -%24 = OpFunction %6 FunctionControl(0) %7 -%28 = OpLabel -%29 = OpLoad %3 %5 -%30 = OpCompositeConstruct %11 %8 %8 -%31 = OpImageSampleImplicitLod %6 %29 %30 - OpReturnValue %31 - OpFunctionEnd -%25 = OpFunction %6 FunctionControl(0) %7 -%32 = OpLabel -%33 = OpFunctionCall %6 %24 - OpReturnValue %33 +%20 = OpVariable %19 StorageClass(PushConstant) +%24 = OpVariable %23 StorageClass(Output) +%27 = OpFunction %6 FunctionControl(0) %7 +%31 = OpLabel +%32 = OpLoad %3 %5 +%33 = OpCompositeConstruct %11 %8 %8 +%34 = OpImageSampleImplicitLod %6 %32 %33 + OpReturnValue %34 OpFunctionEnd -%26 = OpFunction %6 FunctionControl(0) %14 -%34 = OpFunctionParameter %13 +%28 = OpFunction %6 FunctionControl(0) %7 %35 = OpLabel -%37 = OpAccessChain %36 %34 %10 -%38 = OpLoad %6 %37 -%39 = OpFMul %6 %38 %17 - OpReturnValue %39 +%36 = OpFunctionCall %6 %27 + OpReturnValue %36 + OpFunctionEnd +%29 = OpFunction %6 FunctionControl(0) %14 +%37 = OpFunctionParameter %13 +%38 = OpLabel +%40 = OpAccessChain %39 %37 %10 +%41 = OpLoad %6 %40 +%42 = OpFMul %6 %41 %17 + OpReturnValue %42 OpFunctionEnd -%27 = OpFunction %18 FunctionControl(0) %19 -%40 = OpLabel -%41 = OpVariable %13 StorageClass(Function) -%42 = OpVariable %23 StorageClass(Function) -%43 = OpVariable %13 StorageClass(Function) -%44 = OpFunctionCall %6 %25 -%45 = OpAccessChain %36 %41 %10 - OpStore %45 %44 -%46 = OpLoad %12 %41 - OpStore %43 %46 -%47 = OpFunctionCall %6 %26 %43 -%48 = OpAccessChain %36 %42 %10 +%30 = OpFunction %21 FunctionControl(0) %22 +%43 = OpLabel +%44 = OpVariable %13 StorageClass(Function) +%45 = OpVariable %26 StorageClass(Function) +%46 = OpVariable %13 StorageClass(Function) +%47 = OpFunctionCall %6 %28 +%48 = OpAccessChain %39 %44 %10 OpStore %48 %47 -%49 = OpLoad %22 %42 -%50 = OpCompositeExtract %6 %49 0 - OpStore %21 %50 +%49 = OpLoad %12 %44 + OpStore %46 %49 +%50 = OpFunctionCall %6 %29 %46 +%52 = OpAccessChain %51 %20 %10 +%53 = OpLoad %6 %52 +%54 = OpFMul %6 %50 %53 +%55 = OpAccessChain %39 %45 %10 + OpStore %55 %54 +%56 = OpLoad %25 %45 +%57 = OpCompositeExtract %6 %56 0 + OpStore %24 %57 OpReturn OpFunctionEnd)", options, {}, true); } @@ -388,16 +428,28 @@ struct Output_OutputStruct // Description: Test module // License: MIT +// @../resources/Shader.nzsl:12:1 +struct PushConstants +{ + vec4 color; +}; + +// @../resources/Shader.nzsl:17:1 +layout(std140) uniform _nzslPushConstant +{ + vec4 color; +} ExternalResources_constants; + /*************** Outputs ***************/ layout(location = 0) out vec4 _nzslOutcolor; -// @../resources/Shader.nzsl:12:1 +// @../resources/Shader.nzsl:23:1 void main() { Data_DataStruct data; data.color = GetColor_Color(); Output_OutputStruct output_; - output_.color = GetColorFromData_OutputStruct(data); + output_.color = (GetColorFromData_OutputStruct(data)) * ExternalResources_constants.color; _nzslOutcolor = output_.color; return; @@ -406,40 +458,45 @@ void main() ExpectSPIRV(*shaderModule, R"( OpCapability Capability(Shader) OpMemoryModel AddressingModel(Logical) MemoryModel(GLSL450) - OpEntryPoint ExecutionModel(Fragment) %27 "main" %21 - OpExecutionMode %27 ExecutionMode(OriginUpperLeft) -%28 = OpString "../resources/Shader.nzsl" -%29 = OpString "../resources/modules/Color.nzsl" -%30 = OpString "../resources/modules/Data/OutputStruct.nzsl" - OpSource SourceLanguage(NZSL) 100 %28 + OpEntryPoint ExecutionModel(Fragment) %30 "main" %24 + OpExecutionMode %30 ExecutionMode(OriginUpperLeft) +%31 = OpString "../resources/Shader.nzsl" +%32 = OpString "../resources/modules/Color.nzsl" +%33 = OpString "../resources/modules/Data/OutputStruct.nzsl" + OpSource SourceLanguage(NZSL) 100 %31 OpSourceExtension "ModuleName: Shader" OpSourceExtension "Author: SirLynix" OpSourceExtension "Description: Test module" OpSourceExtension "License: MIT" - OpSource SourceLanguage(NZSL) 100 %29 + OpSource SourceLanguage(NZSL) 100 %32 OpSourceExtension "ModuleName: Color" OpSourceExtension "Author: SirLynix" OpSourceExtension "Description: Test color module" OpSourceExtension "License: MIT" OpSource SourceLanguage(NZSL) 100 OpSourceExtension "ModuleName: DataStruct" - OpSource SourceLanguage(NZSL) 100 %30 + OpSource SourceLanguage(NZSL) 100 %33 OpSourceExtension "ModuleName: OutputStruct" OpName %12 "Data" OpMemberName %12 0 "color" - OpName %22 "Output" - OpMemberName %22 0 "color" + OpName %18 "PushConstants" + OpMemberName %18 0 "color" + OpName %25 "Output" + OpMemberName %25 0 "color" OpName %5 "tex1" - OpName %21 "color" - OpName %24 "GenerateColor" - OpName %25 "GetColor" - OpName %26 "GetColorFromData" - OpName %27 "main" + OpName %20 "ExternalResources_constants" + OpName %24 "color" + OpName %27 "GenerateColor" + OpName %28 "GetColor" + OpName %29 "GetColorFromData" + OpName %30 "main" OpDecorate %5 Decoration(Binding) 0 OpDecorate %5 Decoration(DescriptorSet) 0 - OpDecorate %21 Decoration(Location) 0 + OpDecorate %24 Decoration(Location) 0 OpMemberDecorate %12 0 Decoration(Offset) 0 - OpMemberDecorate %22 0 Decoration(Offset) 0 + OpDecorate %18 Decoration(Block) + OpMemberDecorate %18 0 Decoration(Offset) 0 + OpMemberDecorate %25 0 Decoration(Offset) 0 %1 = OpTypeFloat 32 %2 = OpTypeImage %1 Dim(Dim2D) 0 0 0 1 ImageFormat(Unknown) %3 = OpTypeSampledImage %2 @@ -456,75 +513,82 @@ void main() %15 = OpConstant %1 f32(0.5) %16 = OpConstant %1 f32(1) %17 = OpConstantComposite %6 %15 %15 %15 %16 -%18 = OpTypeVoid -%19 = OpTypeFunction %18 -%20 = OpTypePointer StorageClass(Output) %6 -%22 = OpTypeStruct %6 -%23 = OpTypePointer StorageClass(Function) %22 -%39 = OpTypePointer StorageClass(Function) %6 +%18 = OpTypeStruct %6 +%19 = OpTypePointer StorageClass(PushConstant) %18 +%21 = OpTypeVoid +%22 = OpTypeFunction %21 +%23 = OpTypePointer StorageClass(Output) %6 +%25 = OpTypeStruct %6 +%26 = OpTypePointer StorageClass(Function) %25 +%42 = OpTypePointer StorageClass(Function) %6 +%54 = OpTypePointer StorageClass(PushConstant) %6 %5 = OpVariable %4 StorageClass(UniformConstant) -%21 = OpVariable %20 StorageClass(Output) - OpLine %29 13 1 -%24 = OpFunction %6 FunctionControl(0) %7 -%31 = OpLabel +%20 = OpVariable %19 StorageClass(PushConstant) +%24 = OpVariable %23 StorageClass(Output) + OpLine %32 13 1 +%27 = OpFunction %6 FunctionControl(0) %7 +%34 = OpLabel OpNoLine - OpLine %29 15 5 - OpLine %29 15 12 -%32 = OpLoad %3 %5 -%33 = OpCompositeConstruct %11 %8 %8 -%34 = OpImageSampleImplicitLod %6 %32 %33 - OpReturnValue %34 + OpLine %32 15 5 + OpLine %32 15 12 +%35 = OpLoad %3 %5 +%36 = OpCompositeConstruct %11 %8 %8 +%37 = OpImageSampleImplicitLod %6 %35 %36 + OpReturnValue %37 OpFunctionEnd - OpLine %29 32 1 -%25 = OpFunction %6 FunctionControl(0) %7 -%35 = OpLabel + OpLine %32 32 1 +%28 = OpFunction %6 FunctionControl(0) %7 +%38 = OpLabel OpNoLine - OpLine %29 34 5 - OpLine %29 34 12 -%36 = OpFunctionCall %6 %24 - OpReturnValue %36 + OpLine %32 34 5 + OpLine %32 34 12 +%39 = OpFunctionCall %6 %27 + OpReturnValue %39 OpFunctionEnd - OpLine %30 9 1 -%26 = OpFunction %6 FunctionControl(0) %14 - OpLine %30 9 21 -%37 = OpFunctionParameter %13 -%38 = OpLabel + OpLine %33 9 1 +%29 = OpFunction %6 FunctionControl(0) %14 + OpLine %33 9 21 +%40 = OpFunctionParameter %13 +%41 = OpLabel OpNoLine - OpLine %30 11 5 - OpLine %30 11 12 -%40 = OpAccessChain %39 %37 %10 -%41 = OpLoad %6 %40 -%42 = OpFMul %6 %41 %17 - OpReturnValue %42 + OpLine %33 11 5 + OpLine %33 11 12 +%43 = OpAccessChain %42 %40 %10 +%44 = OpLoad %6 %43 +%45 = OpFMul %6 %44 %17 + OpReturnValue %45 OpFunctionEnd - OpLine %28 12 1 -%27 = OpFunction %18 FunctionControl(0) %19 -%43 = OpLabel + OpLine %31 23 1 +%30 = OpFunction %21 FunctionControl(0) %22 +%46 = OpLabel OpNoLine - OpLine %28 14 5 -%44 = OpVariable %13 StorageClass(Function) - OpLine %28 17 5 -%45 = OpVariable %23 StorageClass(Function) - OpLine %28 18 37 -%46 = OpVariable %13 StorageClass(Function) - OpLine %28 15 18 -%47 = OpFunctionCall %6 %25 - OpLine %28 15 5 -%48 = OpAccessChain %39 %44 %10 - OpStore %48 %47 - OpLine %28 18 37 -%49 = OpLoad %12 %44 - OpStore %46 %49 - OpLine %28 18 20 -%50 = OpFunctionCall %6 %26 %46 - OpLine %28 18 5 -%51 = OpAccessChain %39 %45 %10 + OpLine %31 25 5 +%47 = OpVariable %13 StorageClass(Function) + OpLine %31 28 5 +%48 = OpVariable %26 StorageClass(Function) + OpLine %31 29 37 +%49 = OpVariable %13 StorageClass(Function) + OpLine %31 26 18 +%50 = OpFunctionCall %6 %28 + OpLine %31 26 5 +%51 = OpAccessChain %42 %47 %10 OpStore %51 %50 - OpLine %28 20 12 -%52 = OpLoad %22 %45 -%53 = OpCompositeExtract %6 %52 0 - OpStore %21 %53 - OpLine %28 20 5 + OpLine %31 29 37 +%52 = OpLoad %12 %47 + OpStore %49 %52 + OpLine %31 29 20 +%53 = OpFunctionCall %6 %29 %49 +%55 = OpAccessChain %54 %20 %10 +%56 = OpLoad %6 %55 +%57 = OpFMul %6 %53 %56 + OpLine %31 29 5 +%58 = OpAccessChain %42 %48 %10 + OpStore %58 %57 + OpLine %31 31 12 +%59 = OpLoad %25 %48 +%60 = OpCompositeExtract %6 %59 0 + OpStore %24 %60 + OpLine %31 31 5 OpReturn OpFunctionEnd)", options, {}, true); } @@ -681,6 +745,17 @@ import GetColor as Color from Color; import * from DataStruct; import * from OutputStruct; +[layout(std140)] +struct PushConstants +{ + color: vec4[f32] +} + +external ExternalResources +{ + constants: push_constant[PushConstants] +} + [entry(frag)] fn main() -> Output { @@ -688,7 +763,7 @@ fn main() -> Output data.color = Color(); let output: Output; - output.color = GetColorFromData(data); + output.color = GetColorFromData(data) * ExternalResources.constants.color; return output; } @@ -699,16 +774,28 @@ fn main() -> Output // Description: Test module // License: MIT +// @../resources/Shader.nzsl:12:1 +struct PushConstants +{ + vec4 color; +}; + +// @../resources/Shader.nzsl:17:1 +layout(std140) uniform _nzslPushConstant +{ + vec4 color; +} ExternalResources_constants; + /*************** Outputs ***************/ layout(location = 0) out vec4 _nzslOutcolor; -// @../resources/Shader.nzsl:12:1 +// @../resources/Shader.nzsl:23:1 void main() { Data_DataStruct data; data.color = GetColor_Color(); Output_OutputStruct output_; - output_.color = GetColorFromData_OutputStruct(data); + output_.color = (GetColorFromData_OutputStruct(data)) * ExternalResources_constants.color; _nzslOutcolor = output_.color; return; @@ -717,12 +804,12 @@ void main() ExpectSPIRV(*shaderModule, R"( OpCapability Capability(Shader) OpMemoryModel AddressingModel(Logical) MemoryModel(GLSL450) - OpEntryPoint ExecutionModel(Fragment) %27 "main" %21 - OpExecutionMode %27 ExecutionMode(OriginUpperLeft) -%28 = OpString "../resources/Shader.nzsl" -%29 = OpString "../resources/modules/Color.nzsl" -%30 = OpString "../resources/modules/Data/OutputStruct.nzsl" - OpSource SourceLanguage(NZSL) 100 %28 "[nzsl_version("1.0")] + OpEntryPoint ExecutionModel(Fragment) %30 "main" %24 + OpExecutionMode %30 ExecutionMode(OriginUpperLeft) +%31 = OpString "../resources/Shader.nzsl" +%32 = OpString "../resources/modules/Color.nzsl" +%33 = OpString "../resources/modules/Data/OutputStruct.nzsl" + OpSource SourceLanguage(NZSL) 100 %31 "[nzsl_version("1.0")] [author("SirLynix")] [desc("Test module")] [license("MIT")] @@ -732,6 +819,17 @@ import GetColor as Color from Color; import * from DataStruct; import * from OutputStruct; +[layout(std140)] +struct PushConstants +{ + color: vec4[f32] +} + +external ExternalResources +{ + constants: push_constant[PushConstants] +} + [entry(frag)] fn main() -> Output { @@ -739,7 +837,7 @@ fn main() -> Output data.color = Color(); let output: Output; - output.color = GetColorFromData(data); + output.color = GetColorFromData(data) * ExternalResources.constants.color; return output; } @@ -748,7 +846,7 @@ fn main() -> Output OpSourceExtension "Author: SirLynix" OpSourceExtension "Description: Test module" OpSourceExtension "License: MIT" - OpSource SourceLanguage(NZSL) 100 %29 "[nzsl_version("1.0")] + OpSource SourceLanguage(NZSL) 100 %32 "[nzsl_version("1.0")] [author("SirLynix")] [desc("Test color module")] [license("MIT")] @@ -796,7 +894,7 @@ fn GetAnotherColor() -> vec4[f32] OpSourceExtension "License: MIT" OpSource SourceLanguage(NZSL) 100 OpSourceExtension "ModuleName: DataStruct" - OpSource SourceLanguage(NZSL) 100 %30 "[nzsl_version("1.0")] + OpSource SourceLanguage(NZSL) 100 %33 "[nzsl_version("1.0")] module OutputStruct; import * from DataStruct; @@ -818,19 +916,24 @@ struct Output OpSourceExtension "ModuleName: OutputStruct" OpName %12 "Data" OpMemberName %12 0 "color" - OpName %22 "Output" - OpMemberName %22 0 "color" + OpName %18 "PushConstants" + OpMemberName %18 0 "color" + OpName %25 "Output" + OpMemberName %25 0 "color" OpName %5 "tex1" - OpName %21 "color" - OpName %24 "GenerateColor" - OpName %25 "GetColor" - OpName %26 "GetColorFromData" - OpName %27 "main" + OpName %20 "ExternalResources_constants" + OpName %24 "color" + OpName %27 "GenerateColor" + OpName %28 "GetColor" + OpName %29 "GetColorFromData" + OpName %30 "main" OpDecorate %5 Decoration(Binding) 0 OpDecorate %5 Decoration(DescriptorSet) 0 - OpDecorate %21 Decoration(Location) 0 + OpDecorate %24 Decoration(Location) 0 OpMemberDecorate %12 0 Decoration(Offset) 0 - OpMemberDecorate %22 0 Decoration(Offset) 0 + OpDecorate %18 Decoration(Block) + OpMemberDecorate %18 0 Decoration(Offset) 0 + OpMemberDecorate %25 0 Decoration(Offset) 0 %1 = OpTypeFloat 32 %2 = OpTypeImage %1 Dim(Dim2D) 0 0 0 1 ImageFormat(Unknown) %3 = OpTypeSampledImage %2 @@ -847,75 +950,82 @@ struct Output %15 = OpConstant %1 f32(0.5) %16 = OpConstant %1 f32(1) %17 = OpConstantComposite %6 %15 %15 %15 %16 -%18 = OpTypeVoid -%19 = OpTypeFunction %18 -%20 = OpTypePointer StorageClass(Output) %6 -%22 = OpTypeStruct %6 -%23 = OpTypePointer StorageClass(Function) %22 -%39 = OpTypePointer StorageClass(Function) %6 +%18 = OpTypeStruct %6 +%19 = OpTypePointer StorageClass(PushConstant) %18 +%21 = OpTypeVoid +%22 = OpTypeFunction %21 +%23 = OpTypePointer StorageClass(Output) %6 +%25 = OpTypeStruct %6 +%26 = OpTypePointer StorageClass(Function) %25 +%42 = OpTypePointer StorageClass(Function) %6 +%54 = OpTypePointer StorageClass(PushConstant) %6 %5 = OpVariable %4 StorageClass(UniformConstant) -%21 = OpVariable %20 StorageClass(Output) - OpLine %29 13 1 -%24 = OpFunction %6 FunctionControl(0) %7 -%31 = OpLabel +%20 = OpVariable %19 StorageClass(PushConstant) +%24 = OpVariable %23 StorageClass(Output) + OpLine %32 13 1 +%27 = OpFunction %6 FunctionControl(0) %7 +%34 = OpLabel OpNoLine - OpLine %29 15 5 - OpLine %29 15 12 -%32 = OpLoad %3 %5 -%33 = OpCompositeConstruct %11 %8 %8 -%34 = OpImageSampleImplicitLod %6 %32 %33 - OpReturnValue %34 + OpLine %32 15 5 + OpLine %32 15 12 +%35 = OpLoad %3 %5 +%36 = OpCompositeConstruct %11 %8 %8 +%37 = OpImageSampleImplicitLod %6 %35 %36 + OpReturnValue %37 OpFunctionEnd - OpLine %29 32 1 -%25 = OpFunction %6 FunctionControl(0) %7 -%35 = OpLabel + OpLine %32 32 1 +%28 = OpFunction %6 FunctionControl(0) %7 +%38 = OpLabel OpNoLine - OpLine %29 34 5 - OpLine %29 34 12 -%36 = OpFunctionCall %6 %24 - OpReturnValue %36 + OpLine %32 34 5 + OpLine %32 34 12 +%39 = OpFunctionCall %6 %27 + OpReturnValue %39 OpFunctionEnd - OpLine %30 9 1 -%26 = OpFunction %6 FunctionControl(0) %14 - OpLine %30 9 21 -%37 = OpFunctionParameter %13 -%38 = OpLabel + OpLine %33 9 1 +%29 = OpFunction %6 FunctionControl(0) %14 + OpLine %33 9 21 +%40 = OpFunctionParameter %13 +%41 = OpLabel OpNoLine - OpLine %30 11 5 - OpLine %30 11 12 -%40 = OpAccessChain %39 %37 %10 -%41 = OpLoad %6 %40 -%42 = OpFMul %6 %41 %17 - OpReturnValue %42 + OpLine %33 11 5 + OpLine %33 11 12 +%43 = OpAccessChain %42 %40 %10 +%44 = OpLoad %6 %43 +%45 = OpFMul %6 %44 %17 + OpReturnValue %45 OpFunctionEnd - OpLine %28 12 1 -%27 = OpFunction %18 FunctionControl(0) %19 -%43 = OpLabel + OpLine %31 23 1 +%30 = OpFunction %21 FunctionControl(0) %22 +%46 = OpLabel OpNoLine - OpLine %28 14 5 -%44 = OpVariable %13 StorageClass(Function) - OpLine %28 17 5 -%45 = OpVariable %23 StorageClass(Function) - OpLine %28 18 37 -%46 = OpVariable %13 StorageClass(Function) - OpLine %28 15 18 -%47 = OpFunctionCall %6 %25 - OpLine %28 15 5 -%48 = OpAccessChain %39 %44 %10 - OpStore %48 %47 - OpLine %28 18 37 -%49 = OpLoad %12 %44 - OpStore %46 %49 - OpLine %28 18 20 -%50 = OpFunctionCall %6 %26 %46 - OpLine %28 18 5 -%51 = OpAccessChain %39 %45 %10 + OpLine %31 25 5 +%47 = OpVariable %13 StorageClass(Function) + OpLine %31 28 5 +%48 = OpVariable %26 StorageClass(Function) + OpLine %31 29 37 +%49 = OpVariable %13 StorageClass(Function) + OpLine %31 26 18 +%50 = OpFunctionCall %6 %28 + OpLine %31 26 5 +%51 = OpAccessChain %42 %47 %10 OpStore %51 %50 - OpLine %28 20 12 -%52 = OpLoad %22 %45 -%53 = OpCompositeExtract %6 %52 0 - OpStore %21 %53 - OpLine %28 20 5 + OpLine %31 29 37 +%52 = OpLoad %12 %47 + OpStore %49 %52 + OpLine %31 29 20 +%53 = OpFunctionCall %6 %29 %49 +%55 = OpAccessChain %54 %20 %10 +%56 = OpLoad %6 %55 +%57 = OpFMul %6 %53 %56 + OpLine %31 29 5 +%58 = OpAccessChain %42 %48 %10 + OpStore %58 %57 + OpLine %31 31 12 +%59 = OpLoad %25 %48 +%60 = OpCompositeExtract %6 %59 0 + OpStore %24 %60 + OpLine %31 31 5 OpReturn OpFunctionEnd)", options, {}, true); } diff --git a/tests/src/Tests/ExternalTests.cpp b/tests/src/Tests/ExternalTests.cpp index ca9cdb7..40da320 100644 --- a/tests/src/Tests/ExternalTests.cpp +++ b/tests/src/Tests/ExternalTests.cpp @@ -958,6 +958,7 @@ fn main() [nzsl_version("1.0")] module; +[layout(std140)] struct Data { index: i32 @@ -978,12 +979,10 @@ fn main() shaderModule = SanitizeModule(*shaderModule); ExpectGLSL(*shaderModule, R"( -struct Data +layout(std140) uniform _nzslPushConstant { int index; -}; - -uniform Data data; +} data; void main() { diff --git a/tests/src/Tests/FilesystemResolverTests.cpp b/tests/src/Tests/FilesystemResolverTests.cpp index f523fe7..08e2e2f 100644 --- a/tests/src/Tests/FilesystemResolverTests.cpp +++ b/tests/src/Tests/FilesystemResolverTests.cpp @@ -66,6 +66,16 @@ struct Output_OutputStruct // Description: Test module // License: MIT +struct PushConstants +{ + vec4 color; +}; + +layout(std140) uniform _nzslPushConstant +{ + vec4 color; +} ExternalResources_constants; + /*************** Outputs ***************/ layout(location = 0) out vec4 _nzslOutcolor; @@ -74,7 +84,7 @@ void main() Data_DataStruct data; data.color = GetColor_Color(); Output_OutputStruct output_; - output_.color = GetColorFromData_OutputStruct(data); + output_.color = (GetColorFromData_OutputStruct(data)) * ExternalResources_constants.color; _nzslOutcolor = output_.color; return; @@ -145,54 +155,68 @@ alias GetColorFromData = _OutputStruct.GetColorFromData; alias Output = _OutputStruct.Output; +[layout(std140)] +struct PushConstants +{ + color: vec4[f32] +} + +external ExternalResources +{ + constants: push_constant[PushConstants] +} + [entry(frag)] fn main() -> Output { let data: Data; data.color = Color(); let output: Output; - output.color = GetColorFromData(data); + output.color = (GetColorFromData(data)) * ExternalResources.constants.color; return output; } )"); ExpectSPIRV(*shaderModule, R"( -%24 = OpFunction %6 FunctionControl(0) %7 -%28 = OpLabel -%29 = OpLoad %3 %5 -%30 = OpCompositeConstruct %11 %8 %8 -%31 = OpImageSampleImplicitLod %6 %29 %30 - OpReturnValue %31 - OpFunctionEnd -%25 = OpFunction %6 FunctionControl(0) %7 -%32 = OpLabel -%33 = OpFunctionCall %6 %24 - OpReturnValue %33 +%27 = OpFunction %6 FunctionControl(0) %7 +%31 = OpLabel +%32 = OpLoad %3 %5 +%33 = OpCompositeConstruct %11 %8 %8 +%34 = OpImageSampleImplicitLod %6 %32 %33 + OpReturnValue %34 OpFunctionEnd -%26 = OpFunction %6 FunctionControl(0) %14 -%34 = OpFunctionParameter %13 +%28 = OpFunction %6 FunctionControl(0) %7 %35 = OpLabel -%37 = OpAccessChain %36 %34 %10 -%38 = OpLoad %6 %37 -%39 = OpFMul %6 %38 %17 - OpReturnValue %39 +%36 = OpFunctionCall %6 %27 + OpReturnValue %36 + OpFunctionEnd +%29 = OpFunction %6 FunctionControl(0) %14 +%37 = OpFunctionParameter %13 +%38 = OpLabel +%40 = OpAccessChain %39 %37 %10 +%41 = OpLoad %6 %40 +%42 = OpFMul %6 %41 %17 + OpReturnValue %42 OpFunctionEnd -%27 = OpFunction %18 FunctionControl(0) %19 -%40 = OpLabel -%41 = OpVariable %13 StorageClass(Function) -%42 = OpVariable %23 StorageClass(Function) -%43 = OpVariable %13 StorageClass(Function) -%44 = OpFunctionCall %6 %25 -%45 = OpAccessChain %36 %41 %10 - OpStore %45 %44 -%46 = OpLoad %12 %41 - OpStore %43 %46 -%47 = OpFunctionCall %6 %26 %43 -%48 = OpAccessChain %36 %42 %10 +%30 = OpFunction %21 FunctionControl(0) %22 +%43 = OpLabel +%44 = OpVariable %13 StorageClass(Function) +%45 = OpVariable %26 StorageClass(Function) +%46 = OpVariable %13 StorageClass(Function) +%47 = OpFunctionCall %6 %28 +%48 = OpAccessChain %39 %44 %10 OpStore %48 %47 -%49 = OpLoad %22 %42 -%50 = OpCompositeExtract %6 %49 0 - OpStore %21 %50 +%49 = OpLoad %12 %44 + OpStore %46 %49 +%50 = OpFunctionCall %6 %29 %46 +%52 = OpAccessChain %51 %20 %10 +%53 = OpLoad %6 %52 +%54 = OpFMul %6 %50 %53 +%55 = OpAccessChain %39 %45 %10 + OpStore %55 %54 +%56 = OpLoad %25 %45 +%57 = OpCompositeExtract %6 %56 0 + OpStore %24 %57 OpReturn OpFunctionEnd)", {}, {}, true); } diff --git a/tests/src/Tests/NzslcTests.cpp b/tests/src/Tests/NzslcTests.cpp index 383ab51..c399a34 100644 --- a/tests/src/Tests/NzslcTests.cpp +++ b/tests/src/Tests/NzslcTests.cpp @@ -1,16 +1,9 @@ #include -#include #include #include #include -#include -#include #include -#include #include -#include -#include -#include TEST_CASE("Standalone compiler", "[NZSLC]") { @@ -47,13 +40,14 @@ TEST_CASE("Standalone compiler", "[NZSLC]") ExecuteCommand("./nzslc ../resources/modules/Data/DataStruct.nzslb"); //< validation // Try to generate a full shader based on partial compilation result - ExecuteCommand("./nzslc --compile=glsl,glsl-header,nzsl,nzsl-header,nzslb,nzslb-header,spv,spv-header,spv-txt --debug-level=regular -o test_files -m ../resources/modules/Color.nzslb -m ../resources/modules/Data/OutputStruct.nzslb -m ../resources/modules/Data/DataStruct.nzslb ../resources/Shader.nzslb"); + ExecuteCommand("./nzslc --compile=glsl,glsl-header,nzsl,nzsl-header,nzslb,nzslb-header,spv,spv-header,spv-txt --gl-bindingmap --debug-level=regular -o test_files -m ../resources/modules/Color.nzslb -m ../resources/modules/Data/OutputStruct.nzslb -m ../resources/modules/Data/DataStruct.nzslb ../resources/Shader.nzslb"); // Validate generated files ExecuteCommand("./nzslc test_files/Shader.nzsl"); ExecuteCommand("./nzslc test_files/Shader.nzslb"); ExecuteCommand("glslang -S frag test_files/Shader.frag.glsl"); ExecuteCommand("spirv-val test_files/Shader.spv"); + CheckFileMatch("../resources/Shader.glsl.binding.json", "test_files/Shader.glsl.binding.json"); // Check that header version matches original files CheckHeaderMatch("test_files/Shader.frag.glsl"); diff --git a/tests/src/Tests/ShaderUtils.cpp b/tests/src/Tests/ShaderUtils.cpp index 4f2b10f..b8f599c 100644 --- a/tests/src/Tests/ShaderUtils.cpp +++ b/tests/src/Tests/ShaderUtils.cpp @@ -242,7 +242,10 @@ void ExpectGLSL(nzsl::ShaderStageType stageType, const nzsl::Ast::Module& shader nzsl::GlslWriter writer; writer.SetEnv(env); - nzsl::GlslWriter::Output output = writer.Generate(stageType, targetModule, {}, options); + nzsl::GlslWriter::Parameters parameters; + parameters.shaderStage = stageType; + + nzsl::GlslWriter::Output output = writer.Generate(targetModule, parameters, options); SECTION("Validating expected code") { diff --git a/tests/src/Tests/ToolUtils.cpp b/tests/src/Tests/ToolUtils.cpp index 09500a9..d895962 100644 --- a/tests/src/Tests/ToolUtils.cpp +++ b/tests/src/Tests/ToolUtils.cpp @@ -27,24 +27,49 @@ namespace NAZARA_ANONYMOUS_NAMESPACE return str; } + + std::vector ReadFile(const std::filesystem::path& filepath) + { + std::ifstream originalFile(filepath, std::ios::in | std::ios::binary); + REQUIRE(originalFile); + + originalFile.seekg(0, std::ios::end); + + std::streamsize length = originalFile.tellg(); + REQUIRE(length > 0); + if (length == 0) + return {}; //< ignore empty files + + originalFile.seekg(0, std::ios::beg); + + std::vector originalContent(Nz::SafeCast(length)); + REQUIRE(originalFile.read(&originalContent[0], length)); + + return originalContent; + } } -void CheckHeaderMatch(const std::filesystem::path& originalFilepath) +void CheckFileMatch(const std::filesystem::path& firstFile, const std::filesystem::path& secondFile) { - std::ifstream originalFile(originalFilepath, std::ios::in | std::ios::binary); - REQUIRE(originalFile); + NAZARA_USE_ANONYMOUS_NAMESPACE + + std::vector firstFileContent = ReadFile(firstFile); + std::vector secondFileContent = ReadFile(secondFile); + + std::string firstFileStr(firstFileContent.begin(), firstFileContent.end()); + ReplaceStr(firstFileStr, "\r\n", "\n"); - originalFile.seekg(0, std::ios::end); + std::string secondFileStr(secondFileContent.begin(), secondFileContent.end()); + ReplaceStr(secondFileStr, "\r\n", "\n"); - std::streamsize length = originalFile.tellg(); - REQUIRE(length > 0); - if (length == 0) - return; //< ignore empty files + REQUIRE(firstFileStr == secondFileStr); +} - originalFile.seekg(0, std::ios::beg); +void CheckHeaderMatch(const std::filesystem::path& originalFilepath) +{ + NAZARA_USE_ANONYMOUS_NAMESPACE - std::vector originalContent(Nz::SafeCast(length)); - REQUIRE(originalFile.read(&originalContent[0], length)); + std::vector originalContent = ReadFile(originalFilepath); std::filesystem::path headerFilepath = originalFilepath; headerFilepath.concat(".h"); diff --git a/tests/src/Tests/ToolUtils.hpp b/tests/src/Tests/ToolUtils.hpp index 2739ed3..1493019 100644 --- a/tests/src/Tests/ToolUtils.hpp +++ b/tests/src/Tests/ToolUtils.hpp @@ -6,6 +6,7 @@ #include #include +void CheckFileMatch(const std::filesystem::path& firstFile, const std::filesystem::path& secondFile); void CheckHeaderMatch(const std::filesystem::path& originalFilepath); void ExecuteCommand(const std::string& command, const std::string& pattern = {}, std::string expectedOutput = {});