diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index a1677027d..bda992262 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -880,11 +880,30 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* gls spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage()); builder.clearAccessChain(); - builder.setSource(TranslateSourceLanguage(glslangIntermediate->getSource(), glslangIntermediate->getProfile()), glslangIntermediate->getVersion()); + builder.setSource(TranslateSourceLanguage(glslangIntermediate->getSource(), glslangIntermediate->getProfile()), + glslangIntermediate->getVersion()); + if (options.generateDebugInfo) { - builder.setSourceFile(glslangIntermediate->getSourceFile()); - builder.setSourceText(glslangIntermediate->getSourceText()); builder.setEmitOpLines(); + builder.setSourceFile(glslangIntermediate->getSourceFile()); + + // Set the source shader's text. If for SPV version 1.0, include + // a preamble in comments stating the OpModuleProcessed instructions. + // Otherwise, emit those as actual instructions. + std::string text; + const std::vector& processes = glslangIntermediate->getProcesses(); + for (int p = 0; p < (int)processes.size(); ++p) { + if (glslangIntermediate->getSpv().spv < 0x00010100) { + text.append("// OpModuleProcessed "); + text.append(processes[p]); + text.append("\n"); + } else + builder.addModuleProcessed(processes[p]); + } + if (glslangIntermediate->getSpv().spv < 0x00010100 && (int)processes.size() > 0) + text.append("#line 1\n"); + text.append(glslangIntermediate->getSourceText()); + builder.setSourceText(text); } stdBuiltins = builder.import("GLSL.std.450"); builder.setMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450); diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp index 9246a8195..289d59af7 100644 --- a/SPIRV/SpvBuilder.cpp +++ b/SPIRV/SpvBuilder.cpp @@ -2430,6 +2430,7 @@ void Builder::dump(std::vector& out) const // Debug instructions dumpInstructions(out, strings); + dumpModuleProcesses(out); dumpSourceInstructions(out); for (int e = 0; e < (int)sourceExtensions.size(); ++e) { Instruction sourceExtInst(0, 0, OpSourceExtension); @@ -2637,4 +2638,15 @@ void Builder::dumpInstructions(std::vector& out, const std::vector } } +void Builder::dumpModuleProcesses(std::vector& out) const +{ + for (int i = 0; i < (int)moduleProcesses.size(); ++i) { + // TODO: switch this out for the 1.1 headers + const spv::Op OpModuleProcessed = (spv::Op)330; + Instruction moduleProcessed(OpModuleProcessed); + moduleProcessed.addStringOperand(moduleProcesses[i]); + moduleProcessed.dump(out); + } +} + }; // end spv namespace diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h index 3a949190a..59b1da2ee 100755 --- a/SPIRV/SpvBuilder.h +++ b/SPIRV/SpvBuilder.h @@ -79,6 +79,7 @@ public: } void setSourceText(const std::string& text) { sourceText = text; } void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); } + void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); } void setEmitOpLines() { emitOpLines = true; } void addExtension(const char* ext) { extensions.insert(ext); } Id import(const char*); @@ -582,6 +583,7 @@ public: void createSelectionMerge(Block* mergeBlock, unsigned int control); void dumpSourceInstructions(std::vector&) const; void dumpInstructions(std::vector&, const std::vector >&) const; + void dumpModuleProcesses(std::vector&) const; SourceLanguage source; int sourceVersion; @@ -591,6 +593,7 @@ public: bool emitOpLines; std::set extensions; std::vector sourceExtensions; + std::vector moduleProcesses; AddressingModel addressModel; MemoryModel memoryModel; std::set capabilities; diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp index 3301df453..53a33b8a7 100644 --- a/StandAlone/StandAlone.cpp +++ b/StandAlone/StandAlone.cpp @@ -152,6 +152,7 @@ int ClientInputSemanticsVersion = 100; // maps to, say, #define VULKAN 100 int VulkanClientVersion = 100; // would map to, say, Vulkan 1.0 int OpenGLClientVersion = 450; // doesn't influence anything yet, but maps to OpenGL 4.50 unsigned int TargetVersion = 0x00001000; // maps to, say, SPIR-V 1.0 +std::vector Processes; // what should be recorded by OpModuleProcessed, or equivalent std::array baseSamplerBinding; std::array baseTextureBinding; @@ -175,6 +176,9 @@ public: text.append("#define "); fixLine(def); + Processes.push_back("D"); + Processes.back().append(def); + // The first "=" needs to turn into a space const size_t equal = def.find_first_of("="); if (equal != def.npos) @@ -189,6 +193,10 @@ public: { text.append("#undef "); fixLine(undef); + + Processes.push_back("U"); + Processes.back().append(undef); + text.append(undef); text.append("\n"); } @@ -421,6 +429,8 @@ void ProcessArguments(std::vector>& workItem } else if (lowerword == "no-storage-format" || // synonyms lowerword == "nsf") { Options |= EOptionNoStorageFormat; + } else if (lowerword == "relaxed-errors") { + Options |= EOptionRelaxedErrors; } else if (lowerword == "resource-set-bindings" || // synonyms lowerword == "resource-set-binding" || lowerword == "rsb") { @@ -459,6 +469,8 @@ void ProcessArguments(std::vector>& workItem sourceEntryPointName = argv[1]; bumpArg(); break; + } else if (lowerword == "suppress-warnings") { + Options |= EOptionSuppressWarnings; } else if (lowerword == "target-env") { if (argc > 1) { if (strcmp(argv[1], "vulkan1.0") == 0) { @@ -737,6 +749,7 @@ void CompileAndLinkShaderUnits(std::vector compUnits) shader->setSourceEntryPoint(sourceEntryPointName); if (UserPreamble.isSet()) shader->setPreamble(UserPreamble.get()); + shader->addProcesses(Processes); shader->setShiftSamplerBinding(baseSamplerBinding[compUnit.stage]); shader->setShiftTextureBinding(baseTextureBinding[compUnit.stage]); @@ -1162,11 +1175,11 @@ void usage() " -m memory leak mode\n" " -o save binary to , requires a binary option (e.g., -V)\n" " -q dump reflection query database\n" - " -r relaxed semantic error-checking mode\n" + " -r synonym for --relaxed-errors\n" " -s silent mode\n" " -t multi-threaded mode\n" " -v print version strings\n" - " -w suppress warnings (except as required by #extension : warn)\n" + " -w synonym for --suppress-warnings\n" " -x save binary output as text-based 32-bit hexadecimal numbers\n" " --auto-map-bindings automatically bind uniform variables\n" " without explicit bindings.\n" @@ -1185,6 +1198,7 @@ void usage() " --ku synonym for --keep-uncalled\n" " --no-storage-format use Unknown image format\n" " --nsf synonym for --no-storage-format\n" + " --relaxed-errors relaxed GLSL semantic error-checking mode\n" " --resource-set-binding [stage] name set binding\n" " Set descriptor set and binding for individual resources\n" " --resource-set-binding [stage] set\n" @@ -1206,11 +1220,13 @@ void usage() " --source-entrypoint name the given shader source function is\n" " renamed to be the entry point given in -e\n" " --sep synonym for --source-entrypoint\n" - " --target-env {vulkan1.0|opengl} set the execution environment the generated\n" - " code will execute in (as opposed to language\n" - " semantics selected by --client)\n" - " default is 'vulkan1.0' under '--client vulkan'\n" - " default is 'opengl' under '--client opengl'\n" + " --suppress-warnings suppress GLSL warnings\n" + " (except as required by #extension : warn)\n" + " --target-env {vulkan1.0|opengl} set the execution environment code will\n" + " execute in (as opposed to language\n" + " semantics selected by --client) defaults:\n" + " 'vulkan1.0' under '--client vulkan'\n" + " 'opengl' under '--client opengl'\n" " --variable-name Creates a C header file that contains a\n" " uint32_t array named \n" " initialized with the shader binary code.\n" diff --git a/Test/baseResults/spv.debugInfo.frag.out b/Test/baseResults/spv.debugInfo.frag.out index f501528a5..2e0d1b383 100644 --- a/Test/baseResults/spv.debugInfo.frag.out +++ b/Test/baseResults/spv.debugInfo.frag.out @@ -7,9 +7,19 @@ spv.debugInfo.frag 2: ExtInstImport "GLSL.std.450" MemoryModel Logical GLSL450 EntryPoint Fragment 5 "main" 24 52 - ExecutionMode 5 OriginUpperLeft + ExecutionMode 5 OriginLowerLeft 1: String "spv.debugInfo.frag" - Source GLSL 450 1 "#version 450 + Source GLSL 450 1 "// OpModuleProcessed no-storage-format +// OpModuleProcessed resource-set-binding 3 +// OpModuleProcessed auto-map-locations +// OpModuleProcessed client opengl100 +// OpModuleProcessed target-env opengl +// OpModuleProcessed relaxed-errors +// OpModuleProcessed suppress-warnings +// OpModuleProcessed hlsl-offsets +// OpModuleProcessed entry-point main +#line 1 +#version 450 struct S { int a; @@ -84,8 +94,8 @@ void main() MemberDecorate 53(S) 0 Offset 0 MemberDecorate 54(ubuf) 0 Offset 0 Decorate 54(ubuf) Block - Decorate 56 DescriptorSet 0 - Decorate 69(s2d) DescriptorSet 0 + Decorate 56 DescriptorSet 3 + Decorate 69(s2d) DescriptorSet 3 3: TypeVoid 4: TypeFunction 3 7: TypeInt 32 1 diff --git a/Test/baseResults/spv.hlslDebugInfo.frag.out b/Test/baseResults/spv.hlslDebugInfo.frag.out new file mode 100644 index 000000000..571e59410 --- /dev/null +++ b/Test/baseResults/spv.hlslDebugInfo.frag.out @@ -0,0 +1,58 @@ +spv.hlslDebugInfo.vert +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 19 + + Capability Shader + 2: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Vertex 5 "newMain" 17 + 1: String "spv.hlslDebugInfo.vert" + Source HLSL 500 1 "// OpModuleProcessed entry-point newMain +// OpModuleProcessed shift-sampler-binding 2 +// OpModuleProcessed shift-texture-binding 4 +// OpModuleProcessed shift-image-binding 1 +// OpModuleProcessed shift-UBO-binding 6 +// OpModuleProcessed shift-ssbo-binding 3 +// OpModuleProcessed shift-uav-binding 5 +// OpModuleProcessed flatten-uniform-arrays +// OpModuleProcessed no-storage-format +// OpModuleProcessed resource-set-binding t0 0 0 +// OpModuleProcessed hlsl-iomap +// OpModuleProcessed auto-map-bindings +// OpModuleProcessed auto-map-locations +// OpModuleProcessed client vulkan100 +// OpModuleProcessed target-env vulkan1.0 +// OpModuleProcessed source-entrypoint origMain +// OpModuleProcessed hlsl-offsets +#line 1 +float4 origMain() : SV_Position +{ + return (float4)0; +} +" + Name 5 "newMain" + Name 10 "@newMain(" + Name 17 "@entryPointOutput" + Decorate 17(@entryPointOutput) BuiltIn Position + 3: TypeVoid + 4: TypeFunction 3 + 7: TypeFloat 32 + 8: TypeVector 7(float) 4 + 9: TypeFunction 8(fvec4) + 12: 7(float) Constant 0 + 13: 8(fvec4) ConstantComposite 12 12 12 12 + 16: TypePointer Output 8(fvec4) +17(@entryPointOutput): 16(ptr) Variable Output + 5(newMain): 3 Function None 4 + 6: Label + Line 1 2 0 + 18: 8(fvec4) FunctionCall 10(@newMain() + Store 17(@entryPointOutput) 18 + Return + FunctionEnd + 10(@newMain(): 8(fvec4) Function None 9 + 11: Label + Line 1 3 0 + ReturnValue 13 + FunctionEnd diff --git a/Test/runtests b/Test/runtests index c5a93378f..98cd944db 100755 --- a/Test/runtests +++ b/Test/runtests @@ -116,8 +116,12 @@ diff -b $BASEDIR/spv.noBuiltInLoc.vert.out $TARGETDIR/spv.noBuiltInLoc.vert.out # Testing debug information # echo Testing SPV Debug Information -$EXE -g -H spv.debugInfo.frag > $TARGETDIR/spv.debugInfo.frag.out +$EXE -g --relaxed-errors --suppress-warnings --aml --hlsl-offsets --nsf \ + -G -H spv.debugInfo.frag --rsb frag 3 > $TARGETDIR/spv.debugInfo.frag.out diff -b $BASEDIR/spv.debugInfo.frag.out $TARGETDIR/spv.debugInfo.frag.out || HASERROR=1 +$EXE -g -D -e newMain -g --amb --aml --fua --hlsl-iomap --nsf --sib 1 --ssb 2 --sbb 3 --stb 4 --suavb 5 --sub 6 \ + --sep origMain -H spv.hlslDebugInfo.vert --rsb vert t0 0 0 > $TARGETDIR/spv.hlslDebugInfo.frag.out +diff -b $BASEDIR/spv.hlslDebugInfo.frag.out $TARGETDIR/spv.hlslDebugInfo.frag.out || HASERROR=1 # # Testing Includer diff --git a/Test/spv.hlslDebugInfo.vert b/Test/spv.hlslDebugInfo.vert new file mode 100644 index 000000000..b2bc18778 --- /dev/null +++ b/Test/spv.hlslDebugInfo.vert @@ -0,0 +1,4 @@ +float4 origMain() : SV_Position +{ + return (float4)0; +} diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index d2964e4d2..2a904f45e 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -675,6 +675,22 @@ void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages } } +// Most processes are recorded when set in the intermediate representation, +// These are the few that are not. +void RecordProcesses(TIntermediate& intermediate, EShMessages messages, const std::string& sourceEntryPointName) +{ + if ((messages & EShMsgRelaxedErrors) != 0) + intermediate.addProcess("relaxed-errors"); + if ((messages & EShMsgSuppressWarnings) != 0) + intermediate.addProcess("suppress-warnings"); + if ((messages & EShMsgKeepUncalled) != 0) + intermediate.addProcess("keep-uncalled"); + if (sourceEntryPointName.size() > 0) { + intermediate.addProcess("source-entrypoint"); + intermediate.addProcessArgument(sourceEntryPointName); + } +} + // This is the common setup and cleanup code for PreprocessDeferred and // CompileDeferred. // It takes any callable with a signature of @@ -798,6 +814,7 @@ bool ProcessDeferred( intermediate.setVersion(version); intermediate.setProfile(profile); intermediate.setSpv(spvVersion); + RecordProcesses(intermediate, messages, sourceEntryPointName); if (spvVersion.vulkan >= 100) intermediate.setOriginUpperLeft(); if ((messages & EShMsgHlslOffsets) || source == EShSourceHlsl) @@ -1641,6 +1658,11 @@ void TShader::setSourceEntryPoint(const char* name) sourceEntryPointName = name; } +void TShader::addProcesses(const std::vector& p) +{ + intermediate->addProcesses(p); +} + // Set binding base for sampler types void TShader::setShiftSamplerBinding(unsigned int base) { intermediate->setShiftSamplerBinding(base); } // Set binding base for texture types (SRV) @@ -1658,7 +1680,7 @@ void TShader::setShiftSsboBinding(unsigned int base) { intermediate->setShift // Enables binding automapping using TIoMapper void TShader::setAutoMapBindings(bool map) { intermediate->setAutoMapBindings(map); } // Fragile: currently within one stage: simple auto-assignment of location -void TShader::setAutoMapLocations(bool map) { intermediate->setAutoMapLocations(map); } +void TShader::setAutoMapLocations(bool map) { intermediate->setAutoMapLocations(map); } // See comment above TDefaultHlslIoMapper in iomapper.cpp: void TShader::setHlslIoMapping(bool hlslIoMap) { intermediate->setHlslIoMapping(hlslIoMap); } void TShader::setFlattenUniformArrays(bool flatten) { intermediate->setFlattenUniformArrays(flatten); } diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index c1daf1b50..d3219cc54 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -150,6 +150,54 @@ struct TXfbBuffer { bool containsDouble; }; +// Track a set of strings describing how the module was processed. +// Using the form: +// process arg0 arg1 arg2 ... +// process arg0 arg1 arg2 ... +// where everything is textual, and there can be zero or more arguments +class TProcesses { +public: + TProcesses() {} + ~TProcesses() {} + + void addProcess(const char* process) + { + processes.push_back(process); + } + void addProcess(const std::string& process) + { + processes.push_back(process); + } + void addArgument(int arg) + { + processes.back().append(" "); + std::string argString = std::to_string(arg); + processes.back().append(argString); + } + void addArgument(const char* arg) + { + processes.back().append(" "); + processes.back().append(arg); + } + void addArgument(const std::string& arg) + { + processes.back().append(" "); + processes.back().append(arg); + } + void addIfNonZero(const char* process, int value) + { + if (value != 0) { + addProcess(process); + addArgument(value); + } + } + + const std::vector& getProcesses() const { return processes; } + +private: + std::vector processes; +}; + class TSymbolTable; class TSymbol; class TVariable; @@ -201,46 +249,135 @@ public: void setSource(EShSource s) { source = s; } EShSource getSource() const { return source; } - void setEntryPointName(const char* ep) { entryPointName = ep; } + void setEntryPointName(const char* ep) + { + entryPointName = ep; + processes.addProcess("entry-point"); + processes.addArgument(entryPointName); + } void setEntryPointMangledName(const char* ep) { entryPointMangledName = ep; } const std::string& getEntryPointName() const { return entryPointName; } const std::string& getEntryPointMangledName() const { return entryPointMangledName; } - void setShiftSamplerBinding(unsigned int shift) { shiftSamplerBinding = shift; } + void setShiftSamplerBinding(unsigned int shift) + { + shiftSamplerBinding = shift; + processes.addIfNonZero("shift-sampler-binding", shift); + } unsigned int getShiftSamplerBinding() const { return shiftSamplerBinding; } - void setShiftTextureBinding(unsigned int shift) { shiftTextureBinding = shift; } + void setShiftTextureBinding(unsigned int shift) + { + shiftTextureBinding = shift; + processes.addIfNonZero("shift-texture-binding", shift); + } unsigned int getShiftTextureBinding() const { return shiftTextureBinding; } - void setShiftImageBinding(unsigned int shift) { shiftImageBinding = shift; } + void setShiftImageBinding(unsigned int shift) + { + shiftImageBinding = shift; + processes.addIfNonZero("shift-image-binding", shift); + } unsigned int getShiftImageBinding() const { return shiftImageBinding; } - void setShiftUboBinding(unsigned int shift) { shiftUboBinding = shift; } - unsigned int getShiftUboBinding() const { return shiftUboBinding; } - void setShiftSsboBinding(unsigned int shift) { shiftSsboBinding = shift; } - unsigned int getShiftSsboBinding() const { return shiftSsboBinding; } - void setShiftUavBinding(unsigned int shift) { shiftUavBinding = shift; } - unsigned int getShiftUavBinding() const { return shiftUavBinding; } - void setResourceSetBinding(const std::vector& shift) { resourceSetBinding = shift; } + void setShiftUboBinding(unsigned int shift) + { + shiftUboBinding = shift; + processes.addIfNonZero("shift-UBO-binding", shift); + } + unsigned int getShiftUboBinding() const { return shiftUboBinding; } + void setShiftSsboBinding(unsigned int shift) + { + shiftSsboBinding = shift; + processes.addIfNonZero("shift-ssbo-binding", shift); + } + unsigned int getShiftSsboBinding() const { return shiftSsboBinding; } + void setShiftUavBinding(unsigned int shift) + { + shiftUavBinding = shift; + processes.addIfNonZero("shift-uav-binding", shift); + } + unsigned int getShiftUavBinding() const { return shiftUavBinding; } + void setResourceSetBinding(const std::vector& shift) + { + resourceSetBinding = shift; + if (shift.size() > 0) { + processes.addProcess("resource-set-binding"); + for (int s = 0; s < (int)shift.size(); ++s) + processes.addArgument(shift[s]); + } + } const std::vector& getResourceSetBinding() const { return resourceSetBinding; } - void setAutoMapBindings(bool map) { autoMapBindings = map; } - bool getAutoMapBindings() const { return autoMapBindings; } - void setAutoMapLocations(bool map) { autoMapLocations = map; } - bool getAutoMapLocations() const { return autoMapLocations; } - void setFlattenUniformArrays(bool flatten) { flattenUniformArrays = flatten; } - bool getFlattenUniformArrays() const { return flattenUniformArrays; } - void setNoStorageFormat(bool b) { useUnknownFormat = b; } - bool getNoStorageFormat() const { return useUnknownFormat; } - void setHlslOffsets() { hlslOffsets = true; } + void setAutoMapBindings(bool map) + { + autoMapBindings = map; + if (autoMapBindings) + processes.addProcess("auto-map-bindings"); + } + bool getAutoMapBindings() const { return autoMapBindings; } + void setAutoMapLocations(bool map) + { + autoMapLocations = map; + if (autoMapLocations) + processes.addProcess("auto-map-locations"); + } + bool getAutoMapLocations() const { return autoMapLocations; } + void setFlattenUniformArrays(bool flatten) + { + flattenUniformArrays = flatten; + if (flattenUniformArrays) + processes.addProcess("flatten-uniform-arrays"); + } + bool getFlattenUniformArrays() const { return flattenUniformArrays; } + void setNoStorageFormat(bool b) + { + useUnknownFormat = b; + if (useUnknownFormat) + processes.addProcess("no-storage-format"); + } + bool getNoStorageFormat() const { return useUnknownFormat; } + void setHlslOffsets() + { + hlslOffsets = true; + if (hlslOffsets) + processes.addProcess("hlsl-offsets"); + } bool usingHlslOFfsets() const { return hlslOffsets; } - void setUseStorageBuffer() { useStorageBuffer = true; } + void setUseStorageBuffer() + { + useStorageBuffer = true; + processes.addProcess("use-storage-buffer"); + } bool usingStorageBuffer() const { return useStorageBuffer; } - void setHlslIoMapping(bool b) { hlslIoMapping = b; } - bool usingHlslIoMapping() { return hlslIoMapping; } + void setHlslIoMapping(bool b) + { + hlslIoMapping = b; + if (hlslIoMapping) + processes.addProcess("hlsl-iomap"); + } + bool usingHlslIoMapping() { return hlslIoMapping; } + void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; } void setVersion(int v) { version = v; } int getVersion() const { return version; } void setProfile(EProfile p) { profile = p; } EProfile getProfile() const { return profile; } - void setSpv(const SpvVersion& s) { spvVersion = s; } + void setSpv(const SpvVersion& s) + { + spvVersion = s; + + // client processes + if (spvVersion.vulkan > 0) + processes.addProcess("client vulkan100"); + if (spvVersion.openGl > 0) + processes.addProcess("client opengl100"); + + // target-environment processes + if (spvVersion.vulkan == 100) + processes.addProcess("target-env vulkan1.0"); + else if (spvVersion.vulkan > 0) + processes.addProcess("target-env vulkanUnknown"); + if (spvVersion.openGl > 0) + processes.addProcess("target-env opengl"); + } const SpvVersion& getSpv() const { return spvVersion; } EShLanguage getStage() const { return language; } void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); } @@ -462,6 +599,13 @@ public: const std::string& getSourceFile() const { return sourceFile; } void addSourceText(const char* text) { sourceText = sourceText + text; } const std::string& getSourceText() const { return sourceText; } + void addProcesses(const std::vector& p) { + for (int i = 0; i < (int)p.size(); ++i) + processes.addProcess(p[i]); + } + void addProcess(const std::string& process) { processes.addProcess(process); } + void addProcessArgument(const std::string& arg) { processes.addArgument(arg); } + const std::vector& getProcesses() const { return processes.getProcesses(); } const char* const implicitThisName = "@this"; @@ -558,6 +702,9 @@ protected: std::string sourceFile; std::string sourceText; + // for OpModuleProcessed, or equivalent + TProcesses processes; + private: void operator=(TIntermediate&); // prevent assignments }; diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h index 12672eeea..b968967d2 100644 --- a/glslang/Public/ShaderLang.h +++ b/glslang/Public/ShaderLang.h @@ -346,6 +346,7 @@ public: void setPreamble(const char* s) { preamble = s; } void setEntryPoint(const char* entryPoint); void setSourceEntryPoint(const char* sourceEntryPointName); + void addProcesses(const std::vector&); void setShiftSamplerBinding(unsigned int base); void setShiftTextureBinding(unsigned int base); void setShiftImageBinding(unsigned int base);