Support multiple source languages, adding HLSL as an option.

This commit is contained in:
John Kessenich 2016-03-12 18:34:36 -07:00
parent 4d65ee31a6
commit 66e2faf844
7 changed files with 54 additions and 17 deletions

View File

@ -160,8 +160,10 @@ protected:
// //
// Translate glslang profile to SPIR-V source language. // Translate glslang profile to SPIR-V source language.
spv::SourceLanguage TranslateSourceLanguage(EProfile profile) spv::SourceLanguage TranslateSourceLanguage(glslang::EShSource source, EProfile profile)
{ {
switch (source) {
case glslang::EShSourceGlsl:
switch (profile) { switch (profile) {
case ENoProfile: case ENoProfile:
case ECoreProfile: case ECoreProfile:
@ -172,6 +174,11 @@ spv::SourceLanguage TranslateSourceLanguage(EProfile profile)
default: default:
return spv::SourceLanguageUnknown; return spv::SourceLanguageUnknown;
} }
case glslang::EShSourceHlsl:
return spv::SourceLanguageHLSL;
default:
return spv::SourceLanguageUnknown;
}
} }
// Translate glslang language (stage) to SPIR-V execution model. // Translate glslang language (stage) to SPIR-V execution model.
@ -587,7 +594,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* gls
spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage()); spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage());
builder.clearAccessChain(); builder.clearAccessChain();
builder.setSource(TranslateSourceLanguage(glslangIntermediate->getProfile()), glslangIntermediate->getVersion()); builder.setSource(TranslateSourceLanguage(glslangIntermediate->getSource(), glslangIntermediate->getProfile()), glslangIntermediate->getVersion());
stdBuiltins = builder.import("GLSL.std.450"); stdBuiltins = builder.import("GLSL.std.450");
builder.setMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450); builder.setMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450);
shaderEntry = builder.makeEntrypoint(glslangIntermediate->getEntryPoint().c_str()); shaderEntry = builder.makeEntrypoint(glslangIntermediate->getEntryPoint().c_str());

View File

@ -64,7 +64,7 @@ namespace spv {
// (for non-sparse mask enums, this is the number of enumurants) // (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) const char* SourceString(int source)
{ {
@ -74,6 +74,7 @@ const char* SourceString(int source)
case 2: return "GLSL"; case 2: return "GLSL";
case 3: return "OpenCL_C"; case 3: return "OpenCL_C";
case 4: return "OpenCL_CPP"; case 4: return "OpenCL_CPP";
case 5: return "HLSL";
case SourceLanguageCeiling: case SourceLanguageCeiling:
default: return "Bad"; default: return "Bad";

View File

@ -61,6 +61,7 @@ enum SourceLanguage {
SourceLanguageGLSL = 2, SourceLanguageGLSL = 2,
SourceLanguageOpenCL_C = 3, SourceLanguageOpenCL_C = 3,
SourceLanguageOpenCL_CPP = 4, SourceLanguageOpenCL_CPP = 4,
SourceLanguageHLSL = 5,
}; };
enum ExecutionModel { enum ExecutionModel {

View File

@ -74,6 +74,7 @@ enum TOptions {
EOptionVulkanRules = 0x2000, EOptionVulkanRules = 0x2000,
EOptionDefaultDesktop = 0x4000, EOptionDefaultDesktop = 0x4000,
EOptionOutputPreprocessed = 0x8000, EOptionOutputPreprocessed = 0x8000,
EOptionReadHlsl = 0x10000,
}; };
// //
@ -538,6 +539,9 @@ void ProcessArguments(int argc, char* argv[])
case 'd': case 'd':
Options |= EOptionDefaultDesktop; Options |= EOptionDefaultDesktop;
break; break;
case 'D':
Options |= EOptionReadHlsl;
break;
case 'e': case 'e':
// HLSL todo: entry point handle needs much more sophistication. // HLSL todo: entry point handle needs much more sophistication.
// This is okay for one compilation unit with one entry point. // This is okay for one compilation unit with one entry point.
@ -627,6 +631,8 @@ void SetMessageOptions(EShMessages& messages)
messages = (EShMessages)(messages | EShMsgVulkanRules); messages = (EShMessages)(messages | EShMsgVulkanRules);
if (Options & EOptionOutputPreprocessed) if (Options & EOptionOutputPreprocessed)
messages = (EShMessages)(messages | EShMsgOnlyPreprocessor); 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" " creates the default configuration file (redirect to a .conf file)\n"
" -d default to desktop (#version 110) when there is no shader #version\n" " -d default to desktop (#version 110) when there is no shader #version\n"
" (default is ES version 100)\n" " (default is ES version 100)\n"
" -D input is HLSL\n"
" -e specify entry-point name\n" " -e specify entry-point name\n"
" -h print this usage message\n" " -h print this usage message\n"
" -i intermediate tree (glslang AST) is printed out\n" " -i intermediate tree (glslang AST) is printed out\n"

View File

@ -307,11 +307,19 @@ void SetupBuiltinSymbolTable(int version, EProfile profile, int spv, int vulkan)
glslang::ReleaseGlobalLock(); 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; const int FirstProfileVersion = 150;
bool correct = true; bool correct = true;
if (source == EShSourceHlsl) {
version = defaultVersion;
profile = ENoProfile;
return correct;
}
// Get a good version... // Get a good version...
if (version == 0) { if (version == 0) {
version = defaultVersion; 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 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 versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst));
bool warnVersionNotFirst = false; bool warnVersionNotFirst = false;
if (! versionWillBeError && versionNotFirstToken) { 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 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.setVersion(version);
intermediate.setProfile(profile); intermediate.setProfile(profile);
intermediate.setSpv(spv); intermediate.setSpv(spv);

View File

@ -124,7 +124,8 @@ class TVariable;
// //
class TIntermediate { class TIntermediate {
public: 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), numMains(0), numErrors(0), numPushConstants(0), recursive(false),
invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet), inputPrimitive(ElgNone), outputPrimitive(ElgNone), invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet), inputPrimitive(ElgNone), outputPrimitive(ElgNone),
pixelCenterInteger(false), originUpperLeft(false), pixelCenterInteger(false), originUpperLeft(false),
@ -145,6 +146,8 @@ public:
void output(TInfoSink&, bool tree); 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; } void setEntryPoint(const char* ep) { entryPoint = ep; }
const TString& getEntryPoint() const { return entryPoint; } const TString& getEntryPoint() const { return entryPoint; }
void setVersion(int v) { version = v; } void setVersion(int v) { version = v; }
@ -339,12 +342,13 @@ protected:
bool userOutputUsed() const; bool userOutputUsed() const;
static int getBaseAlignmentScalar(const TType&, int& size); 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; TString entryPoint;
TIntermNode* treeRoot;
EProfile profile; EProfile profile;
int version; int version;
int spv; int spv;
TIntermNode* treeRoot;
std::set<std::string> requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them std::set<std::string> requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them
TBuiltInResource resources; TBuiltInResource resources;
int numMains; int numMains;

View File

@ -86,7 +86,7 @@ typedef enum {
EShLangFragment, EShLangFragment,
EShLangCompute, EShLangCompute,
EShLangCount, EShLangCount,
} EShLanguage; } EShLanguage; // would be better as stage, but this is ancient now
typedef enum { typedef enum {
EShLangVertexMask = (1 << EShLangVertex), EShLangVertexMask = (1 << EShLangVertex),
@ -99,6 +99,12 @@ typedef enum {
namespace glslang { namespace glslang {
typedef enum {
EShSourceNone,
EShSourceGlsl,
EShSourceHlsl,
} EShSource; // if EShLanguage were EShStage, this could be EShLanguage instead
const char* StageName(EShLanguage); const char* StageName(EShLanguage);
} // end namespace glslang } // end namespace glslang
@ -132,6 +138,7 @@ enum EShMessages {
EShMsgSpvRules = (1 << 3), // issue messages for SPIR-V generation EShMsgSpvRules = (1 << 3), // issue messages for SPIR-V generation
EShMsgVulkanRules = (1 << 4), // issue messages for Vulkan-requirements of GLSL for SPIR-V EShMsgVulkanRules = (1 << 4), // issue messages for Vulkan-requirements of GLSL for SPIR-V
EShMsgOnlyPreprocessor = (1 << 5), // only print out errors produced by the preprocessor EShMsgOnlyPreprocessor = (1 << 5), // only print out errors produced by the preprocessor
EShMsgReadHlsl = (1 << 6), // use HLSL parsing rules and semantics
}; };
// //