diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 7a7baa2b..1c6abec9 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -160,15 +160,22 @@ protected: // // Translate glslang profile to SPIR-V source language. -spv::SourceLanguage TranslateSourceLanguage(EProfile profile) +spv::SourceLanguage TranslateSourceLanguage(glslang::EShSource source, EProfile profile) { - switch (profile) { - case ENoProfile: - case ECoreProfile: - case ECompatibilityProfile: - return spv::SourceLanguageGLSL; - case EEsProfile: - return spv::SourceLanguageESSL; + switch (source) { + case glslang::EShSourceGlsl: + switch (profile) { + case ENoProfile: + case ECoreProfile: + case ECompatibilityProfile: + return spv::SourceLanguageGLSL; + case EEsProfile: + return spv::SourceLanguageESSL; + default: + return spv::SourceLanguageUnknown; + } + case glslang::EShSourceHlsl: + return spv::SourceLanguageHLSL; default: return spv::SourceLanguageUnknown; } @@ -587,7 +594,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* gls spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage()); builder.clearAccessChain(); - builder.setSource(TranslateSourceLanguage(glslangIntermediate->getProfile()), glslangIntermediate->getVersion()); + builder.setSource(TranslateSourceLanguage(glslangIntermediate->getSource(), glslangIntermediate->getProfile()), glslangIntermediate->getVersion()); stdBuiltins = builder.import("GLSL.std.450"); builder.setMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450); shaderEntry = builder.makeEntrypoint(glslangIntermediate->getEntryPoint().c_str()); diff --git a/SPIRV/doc.cpp b/SPIRV/doc.cpp index 7cf1c87f..7ee86b5b 100755 --- a/SPIRV/doc.cpp +++ b/SPIRV/doc.cpp @@ -64,7 +64,7 @@ namespace spv { // (for non-sparse mask enums, this is the number of enumurants) // -const int SourceLanguageCeiling = 5; +const int SourceLanguageCeiling = 6; // HLSL todo: need official enumerant const char* SourceString(int source) { @@ -74,6 +74,7 @@ const char* SourceString(int source) case 2: return "GLSL"; case 3: return "OpenCL_C"; case 4: return "OpenCL_CPP"; + case 5: return "HLSL"; case SourceLanguageCeiling: default: return "Bad"; diff --git a/SPIRV/spirv.hpp b/SPIRV/spirv.hpp index 5620aba7..7447fcf7 100755 --- a/SPIRV/spirv.hpp +++ b/SPIRV/spirv.hpp @@ -61,6 +61,7 @@ enum SourceLanguage { SourceLanguageGLSL = 2, SourceLanguageOpenCL_C = 3, SourceLanguageOpenCL_CPP = 4, + SourceLanguageHLSL = 5, }; enum ExecutionModel { diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp index 408f114e..2e0db6d4 100644 --- a/StandAlone/StandAlone.cpp +++ b/StandAlone/StandAlone.cpp @@ -74,6 +74,7 @@ enum TOptions { EOptionVulkanRules = 0x2000, EOptionDefaultDesktop = 0x4000, EOptionOutputPreprocessed = 0x8000, + EOptionReadHlsl = 0x10000, }; // @@ -538,6 +539,9 @@ void ProcessArguments(int argc, char* argv[]) case 'd': Options |= EOptionDefaultDesktop; break; + case 'D': + Options |= EOptionReadHlsl; + break; case 'e': // HLSL todo: entry point handle needs much more sophistication. // This is okay for one compilation unit with one entry point. @@ -627,6 +631,8 @@ void SetMessageOptions(EShMessages& messages) messages = (EShMessages)(messages | EShMsgVulkanRules); if (Options & EOptionOutputPreprocessed) messages = (EShMessages)(messages | EShMsgOnlyPreprocessor); + if (Options & EOptionReadHlsl) + messages = (EShMessages)(messages | EShMsgReadHlsl); } // @@ -1047,6 +1053,7 @@ void usage() " creates the default configuration file (redirect to a .conf file)\n" " -d default to desktop (#version 110) when there is no shader #version\n" " (default is ES version 100)\n" + " -D input is HLSL\n" " -e specify entry-point name\n" " -h print this usage message\n" " -i intermediate tree (glslang AST) is printed out\n" diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index 4b2bf832..230929aa 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -307,11 +307,19 @@ void SetupBuiltinSymbolTable(int version, EProfile profile, int spv, int vulkan) glslang::ReleaseGlobalLock(); } -bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNotFirst, int defaultVersion, int& version, EProfile& profile, int spv) +// Return true if the shader was correctly specified for version/profile/stage. +bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNotFirst, int defaultVersion, + EShSource source, int& version, EProfile& profile, int spv) { const int FirstProfileVersion = 150; bool correct = true; + if (source == EShSourceHlsl) { + version = defaultVersion; + profile = ENoProfile; + return correct; + } + // Get a good version... if (version == 0) { version = defaultVersion; @@ -552,7 +560,8 @@ bool ProcessDeferred( } int spv = (messages & EShMsgSpvRules) ? 100 : 0; // TODO find path to get real version number here, for now non-0 is what matters - bool goodVersion = DeduceVersionProfile(compiler->infoSink, compiler->getLanguage(), versionNotFirst, defaultVersion, version, profile, spv); + EShSource source = (messages & EShMsgReadHlsl) ? EShSourceHlsl : EShSourceGlsl; + bool goodVersion = DeduceVersionProfile(compiler->infoSink, compiler->getLanguage(), versionNotFirst, defaultVersion, source, version, profile, spv); bool versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst)); bool warnVersionNotFirst = false; if (! versionWillBeError && versionNotFirstToken) { @@ -563,6 +572,7 @@ bool ProcessDeferred( } int vulkan = (messages & EShMsgVulkanRules) ? 100 : 0; // TODO find path to get real version number here, for now non-0 is what matters + intermediate.setSource(source); intermediate.setVersion(version); intermediate.setProfile(profile); intermediate.setSpv(spv); diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index b1e833ba..efffb716 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -124,7 +124,8 @@ class TVariable; // class TIntermediate { public: - explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : language(l), treeRoot(0), profile(p), version(v), spv(0), + explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : + source(EShSourceNone), language(l), profile(p), version(v), spv(0), treeRoot(0), numMains(0), numErrors(0), numPushConstants(0), recursive(false), invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet), inputPrimitive(ElgNone), outputPrimitive(ElgNone), pixelCenterInteger(false), originUpperLeft(false), @@ -143,8 +144,10 @@ public: bool postProcess(TIntermNode*, EShLanguage); void output(TInfoSink&, bool tree); - void removeTree(); + void removeTree(); + void setSource(EShSource s) { source = s; } + EShSource getSource() const { return source; } void setEntryPoint(const char* ep) { entryPoint = ep; } const TString& getEntryPoint() const { return entryPoint; } void setVersion(int v) { version = v; } @@ -339,12 +342,13 @@ protected: bool userOutputUsed() const; static int getBaseAlignmentScalar(const TType&, int& size); - const EShLanguage language; + const EShLanguage language; // stage, known at construction time + EShSource source; // source language, known a bit later TString entryPoint; - TIntermNode* treeRoot; EProfile profile; int version; int spv; + TIntermNode* treeRoot; std::set requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them TBuiltInResource resources; int numMains; diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h index 7a708f2b..e676211a 100644 --- a/glslang/Public/ShaderLang.h +++ b/glslang/Public/ShaderLang.h @@ -86,7 +86,7 @@ typedef enum { EShLangFragment, EShLangCompute, EShLangCount, -} EShLanguage; +} EShLanguage; // would be better as stage, but this is ancient now typedef enum { EShLangVertexMask = (1 << EShLangVertex), @@ -99,6 +99,12 @@ typedef enum { namespace glslang { +typedef enum { + EShSourceNone, + EShSourceGlsl, + EShSourceHlsl, +} EShSource; // if EShLanguage were EShStage, this could be EShLanguage instead + const char* StageName(EShLanguage); } // end namespace glslang @@ -132,6 +138,7 @@ enum EShMessages { EShMsgSpvRules = (1 << 3), // issue messages for SPIR-V generation EShMsgVulkanRules = (1 << 4), // issue messages for Vulkan-requirements of GLSL for SPIR-V EShMsgOnlyPreprocessor = (1 << 5), // only print out errors produced by the preprocessor + EShMsgReadHlsl = (1 << 6), // use HLSL parsing rules and semantics }; //