From 115a0adc29123aa4b4eae3c31a4e031d4ee919cc Mon Sep 17 00:00:00 2001 From: John Kessenich <cepheus@frii.com> Date: Mon, 11 Nov 2013 18:50:06 +0000 Subject: [PATCH] Add GL_OES_texture_3D extension. Also, minor tweaks to extension adding infrastructure. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24001 e7fa87d3-cd2b-0410-9028-fcbf551c1848 --- Test/100.frag | 13 ++++++ Test/baseResults/100.frag.out | 25 ++++++++++- glslang/MachineIndependent/Initialize.cpp | 14 +++--- glslang/MachineIndependent/ParseHelper.cpp | 2 +- glslang/MachineIndependent/ParseHelper.h | 8 ++-- glslang/MachineIndependent/Scan.cpp | 13 +++++- glslang/MachineIndependent/Versions.cpp | 52 ++++++++++++++++------ glslang/MachineIndependent/Versions.h | 4 ++ 8 files changed, 105 insertions(+), 26 deletions(-) diff --git a/Test/100.frag b/Test/100.frag index 4250ab7fb..08dc51b68 100644 --- a/Test/100.frag +++ b/Test/100.frag @@ -76,3 +76,16 @@ struct sp { uniform float h; // ERROR invariant float i; // ERROR }; + +uniform sampler3D s3D; // ERROR + +#extension GL_OES_texture_3D : enable + +precision highp sampler3D; +uniform sampler3D s3D2; + +void foo234() +{ + texture3D(s3D2, vec3(0.2), 0.2); + texture3DProj(s3D2, v[1], 0.4); +} diff --git a/Test/baseResults/100.frag.out b/Test/baseResults/100.frag.out index 8c7b64fa0..d9a755a3c 100644 --- a/Test/baseResults/100.frag.out +++ b/Test/baseResults/100.frag.out @@ -40,7 +40,9 @@ ERROR: 0:71: 'sampler2D' : sampler/image types can only be used in uniform varia ERROR: 0:75: 'g' : cannot use storage or interpolation qualifiers on structure members ERROR: 0:76: 'h' : cannot use storage or interpolation qualifiers on structure members ERROR: 0:77: 'i' : cannot use invariant qualifier on structure members -ERROR: 35 compilation errors. No code generated. +ERROR: 0:80: 'sampler3D' : Reserved word. +ERROR: 0:80: 'sampler/image' : type requires declaration of default precision qualifier +ERROR: 37 compilation errors. No code generated. ERROR: node is still EOpNull! 0:3 Sequence @@ -121,6 +123,25 @@ ERROR: node is still EOpNull! 0:67 Function Definition: f11(s21; (void) 0:67 Function Parameters: 0:67 'p2d' (in lowp sampler2D) +0:87 Function Definition: foo234( (void) +0:87 Function Parameters: +0:89 Sequence +0:89 Function Call: texture3D(s31;vf3;f1; (highp 4-component vector of float) +0:89 's3D2' (uniform highp sampler3D) +0:89 Constant: +0:89 0.200000 +0:89 0.200000 +0:89 0.200000 +0:89 Constant: +0:89 0.200000 +0:90 Function Call: texture3DProj(s31;vf4;f1; (highp 4-component vector of float) +0:90 's3D2' (uniform highp sampler3D) +0:90 direct index (smooth mediump 4-component vector of float) +0:90 'v' (smooth in 3-element array of mediump 4-component vector of float) +0:90 Constant: +0:90 1 (const int) +0:90 Constant: +0:90 0.400000 0:? Linker Objects 0:? 'a' (3-element array of mediump int) 0:? 'uint' (mediump int) @@ -135,4 +156,6 @@ ERROR: node is still EOpNull! 0:? 'uv3' (invariant uniform mediump 3-component vector of float) 0:? 'glob2D' (lowp sampler2D) 0:? 'vary2D' (smooth in lowp sampler2D) +0:? 's3D' (uniform mediump sampler3D) +0:? 's3D2' (uniform highp sampler3D) diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp index b9d0a7612..a6b640483 100644 --- a/glslang/MachineIndependent/Initialize.cpp +++ b/glslang/MachineIndependent/Initialize.cpp @@ -659,6 +659,9 @@ void TBuiltIns::initialize(int version, EProfile profile) "vec4 texture2DProj(sampler2D, vec3);" "vec4 texture2DProj(sampler2D, vec4);" + "vec4 texture3D(sampler3D, vec3);" // OES_texture_3D, but caught by keyword check + "vec4 texture3DProj(sampler3D, vec4);" // OES_texture_3D, but caught by keyword check + "vec4 textureCube(samplerCube, vec3);" "\n"); @@ -673,9 +676,6 @@ void TBuiltIns::initialize(int version, EProfile profile) "vec4 texture1DProj(sampler1D, vec2);" "vec4 texture1DProj(sampler1D, vec4);" - "vec4 texture3D(sampler3D, vec3);" - "vec4 texture3DProj(sampler3D, vec4);" - "vec4 shadow1D(sampler1DShadow, vec3);" "vec4 shadow2D(sampler2DShadow, vec3);" "vec4 shadow1DProj(sampler1DShadow, vec4);" @@ -742,6 +742,8 @@ void TBuiltIns::initialize(int version, EProfile profile) "vec4 texture2DLod(sampler2D, vec2, float);" "vec4 texture2DProjLod(sampler2D, vec3, float);" "vec4 texture2DProjLod(sampler2D, vec4, float);" + "vec4 texture3DLod(sampler3D, vec3, float);" // OES_texture_3D, but caught by keyword check + "vec4 texture3DProjLod(sampler3D, vec4, float);" // OES_texture_3D, but caught by keyword check "vec4 textureCubeLod(samplerCube, vec3, float);" "\n"); @@ -753,8 +755,6 @@ void TBuiltIns::initialize(int version, EProfile profile) "vec4 texture1DLod(sampler1D, float, float);" "vec4 texture1DProjLod(sampler1D, vec2, float);" "vec4 texture1DProjLod(sampler1D, vec4, float);" - "vec4 texture3DLod(sampler3D, vec3, float);" - "vec4 texture3DProjLod(sampler3D, vec4, float);" "vec4 shadow1DLod(sampler1DShadow, vec3, float);" "vec4 shadow2DLod(sampler2DShadow, vec3, float);" "vec4 shadow1DProjLod(sampler1DShadow, vec4, float);" @@ -828,6 +828,8 @@ void TBuiltIns::initialize(int version, EProfile profile) "vec4 texture2D(sampler2D, vec2, float);" "vec4 texture2DProj(sampler2D, vec3, float);" "vec4 texture2DProj(sampler2D, vec4, float);" + "vec4 texture3D(sampler3D, vec3, float);" // OES_texture_3D + "vec4 texture3DProj(sampler3D, vec4, float);" // OES_texture_3D "vec4 textureCube(samplerCube, vec3, float);" "\n"); @@ -837,8 +839,6 @@ void TBuiltIns::initialize(int version, EProfile profile) "vec4 texture1D(sampler1D, float, float);" "vec4 texture1DProj(sampler1D, vec2, float);" "vec4 texture1DProj(sampler1D, vec4, float);" - "vec4 texture3D(sampler3D, vec3, float);" - "vec4 texture3DProj(sampler3D, vec4, float);" "vec4 shadow1D(sampler1DShadow, vec3, float);" "vec4 shadow2D(sampler2DShadow, vec3, float);" "vec4 shadow1DProj(sampler1DShadow, vec4, float);" diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 0af66b28b..557981f0e 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -974,7 +974,7 @@ void TParseContext::nonOpBuiltInCheck(TSourceLoc loc, const TFunction& fnCandida if (fnCandidate.getName().compare(0, 13, "textureGather") == 0) { const char* feature = "texture gather function"; requireProfile(loc, ~EEsProfile, feature); - profileRequires(loc, ~EEsProfile, 400, GL_ARB_texture_gather, feature); + profileRequires(loc, ~EEsProfile, 400, GL_ARB_texture_gather, feature); // TODO: GL_ARB_gpu_shader5 int lastArgIndex = fnCandidate.getParamCount() - 1; if (fnCandidate[lastArgIndex].type->getBasicType() == EbtInt && fnCandidate[lastArgIndex].type->isScalar()) { // the last integral argument to a texture gather must be a constant int between 0 and 3 diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 8b310377b..7c5b8ab0d 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -77,7 +77,6 @@ public: bool reservedErrorCheck(TSourceLoc, const TString&); bool builtInName(const TString&); - void updateExtensionBehavior(const char* extName, const char* behavior); void handlePragma(const char **tokens, int numTokens); TIntermTyped* handleVariable(TSourceLoc, TSymbol* symbol, TString* string); TIntermTyped* handleBracketDereference(TSourceLoc, TIntermTyped* base, TIntermTyped* index); @@ -180,12 +179,15 @@ public: // The following are implemented in Versions.cpp to localize version/profile/stage/extensions control void initializeExtensionBehavior(); void requireProfile(TSourceLoc, int queryProfiles, const char *featureDesc); - void profileRequires(TSourceLoc, int queryProfiles, int minVersion, int numExtensions, const char* extensions[], const char *featureDesc); - void profileRequires(TSourceLoc, int queryProfiles, int minVersion, const char* extension, const char *featureDesc); + void profileRequires(TSourceLoc, int queryProfiles, int minVersion, int numExtensions, const char* const extensions[], const char *featureDesc); + void profileRequires(TSourceLoc, int queryProfiles, int minVersion, const char* const extension, const char *featureDesc); void requireStage(TSourceLoc, EShLanguageMask, const char *featureDesc); void requireStage(TSourceLoc, EShLanguage, const char *featureDesc); void checkDeprecated(TSourceLoc, int queryProfiles, int depVersion, const char *featureDesc); void requireNotRemoved(TSourceLoc, int queryProfiles, int removedVersion, const char *featureDesc); + TExtensionBehavior getExtensionBehavior(const char*); + bool extensionsTurnedOn(int numExtensions, const char* const extensions[]); + void updateExtensionBehavior(const char* const extension, const char* behavior); void fullIntegerCheck(TSourceLoc, const char* op); void doubleCheck(TSourceLoc, const char* op); diff --git a/glslang/MachineIndependent/Scan.cpp b/glslang/MachineIndependent/Scan.cpp index 39774a994..c93099cd2 100644 --- a/glslang/MachineIndependent/Scan.cpp +++ b/glslang/MachineIndependent/Scan.cpp @@ -781,6 +781,13 @@ int TScanContext::tokenizeIdentifier() return keyword; case SAMPLER3D: + afterType = true; + if (parseContext.profile == EEsProfile && parseContext.version < 300) { + if (! parseContext.extensionsTurnedOn(1, &GL_OES_texture_3D)) + reservedWord(); + } + return keyword; + case SAMPLER2DSHADOW: afterType = true; if (parseContext.profile == EEsProfile && parseContext.version < 300) @@ -883,9 +890,13 @@ int TScanContext::identifierOrType() return IDENTIFIER; } +// Give an error for use of a reserved symbol. +// However, allow built-in declarations to use reserved words, to allow +// extension support before the extension is enabled. int TScanContext::reservedWord() { - parseContext.error(loc, "Reserved word.", tokenText, "", ""); + if (! parseContext.symbolTable.atBuiltInLevel()) + parseContext.error(loc, "Reserved word.", tokenText, "", ""); return 0; } diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp index 8b9680f8f..93e3c039d 100644 --- a/glslang/MachineIndependent/Versions.cpp +++ b/glslang/MachineIndependent/Versions.cpp @@ -65,7 +65,7 @@ // implements Feature F, and will log the proper error/warning messages. Parsing // will then always continue as if the tested feature was enabled. // -// There is typically no if-testing or conditional parsing, just insertion of requirements. +// There is typically no if-testing or conditional parsing, just insertion of the calls above. // However, if symbols specific to the extension are added (step 5), they will // only be added under tests that the minimum version and profile are present. // @@ -101,9 +101,9 @@ // // following the requireProfile() call... // profileRequires(loc, // ECoreProfile | ECompatibilityProfile, -// 420, // 0 if no version incorporated the feature into the core spec. +// 420, // 0 if no version incorporated the feature into the core spec. // XXX_extension_X, // can be a list of extensions that all add the feature -// "Feature F"); +// "Feature F Description"); // // This allows the feature if either A) one of the extensions is enabled or // B) the version is high enough. If no version yet incorporates the feature @@ -144,6 +144,8 @@ namespace glslang { // void TParseContext::initializeExtensionBehavior() { + extensionBehavior[GL_OES_texture_3D] = EBhDisable; + extensionBehavior[GL_ARB_texture_rectangle] = EBhDisable; extensionBehavior[GL_3DL_array_objects] = EBhDisable; extensionBehavior[GL_ARB_shading_language_420pack] = EBhDisable; @@ -156,7 +158,8 @@ void TParseContext::initializeExtensionBehavior() const char* TParseContext::getPreamble() { if (profile == EEsProfile) { - return + return + "#define GL_OES_texture_3D 1\n" "#define GL_ES 1\n"; } else { return @@ -185,7 +188,7 @@ const char* ProfileName(EProfile profile) // // When to use requireProfile(): // -// If only some profiles support a feature. However, if within a profile the feature +// Use if only some profiles support a feature. However, if within a profile the feature // is version or extension specific, follow this call with calls to profileRequires(). // // Operation: If the current profile is not one of the profileMask, @@ -230,15 +233,14 @@ const char* StageName(EShLanguage stage) // // entry point that takes multiple extensions -void TParseContext::profileRequires(TSourceLoc loc, int profileMask, int minVersion, int numExtensions, const char* extensions[], const char *featureDesc) +void TParseContext::profileRequires(TSourceLoc loc, int profileMask, int minVersion, int numExtensions, const char* const extensions[], const char *featureDesc) { if (profile & profileMask) { bool okay = false; if (minVersion > 0 && version >= minVersion) okay = true; for (int i = 0; i < numExtensions; ++i) { - TExtensionBehavior behavior = extensionBehavior[extensions[i]]; - switch (behavior) { + switch (getExtensionBehavior(extensions[i])) { case EBhWarn: infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), loc); // fall through @@ -314,10 +316,34 @@ void TParseContext::requireNotRemoved(TSourceLoc loc, int profileMask, int remov } } +TExtensionBehavior TParseContext::getExtensionBehavior(const char* extension) +{ + TMap<TString, TExtensionBehavior>::iterator iter = extensionBehavior.find(TString(extension)); + if (iter == extensionBehavior.end()) + return EBhMissing; + else + return iter->second; +} + +// See if any of the extensions are set to enable, require, or warn. +bool TParseContext::extensionsTurnedOn(int numExtensions, const char* const extensions[]) +{ + for (int i = 0; i < numExtensions; ++i) { + switch (getExtensionBehavior(extensions[i])) { + case EBhEnable: + case EBhRequire: + case EBhWarn: + return true; + } + } + + return false; +} + // // Change the current state of an extension's behavior. // -void TParseContext::updateExtensionBehavior(const char* extName, const char* behaviorString) +void TParseContext::updateExtensionBehavior(const char* extension, const char* behaviorString) { // Translate from text string of extension's behavior to an enum. TExtensionBehavior behavior = EBhDisable; @@ -334,7 +360,7 @@ void TParseContext::updateExtensionBehavior(const char* extName, const char* beh // Update the current behavior TMap<TString, TExtensionBehavior>::iterator iter; - if (! strcmp(extName, "all")) { + if (! strcmp(extension, "all")) { // special case for the 'all' extension; apply it to every extension present if (behavior == EBhRequire || behavior == EBhEnable) { error(getCurrentLoc(), "extension 'all' cannot have 'require' or 'enable' behavior", "#extension", ""); @@ -345,16 +371,16 @@ void TParseContext::updateExtensionBehavior(const char* extName, const char* beh } } else { // Do the update for this single extension - iter = extensionBehavior.find(TString(extName)); + iter = extensionBehavior.find(TString(extension)); if (iter == extensionBehavior.end()) { switch (behavior) { case EBhRequire: - error(getCurrentLoc(), "extension not supported", "#extension", extName); + error(getCurrentLoc(), "extension not supported", "#extension", extension); break; case EBhEnable: case EBhWarn: case EBhDisable: - warn(getCurrentLoc(), "extension not supported", "#extension", extName); + warn(getCurrentLoc(), "extension not supported", "#extension", extension); break; default: assert(0 && "unexpected behavior"); diff --git a/glslang/MachineIndependent/Versions.h b/glslang/MachineIndependent/Versions.h index bd0a5d0c3..66622a86a 100644 --- a/glslang/MachineIndependent/Versions.h +++ b/glslang/MachineIndependent/Versions.h @@ -61,6 +61,7 @@ namespace glslang { // The behaviors from the GLSL "#extension extension_name : behavior" // typedef enum { + EBhMissing = 0, EBhRequire, EBhEnable, EBhWarn, @@ -71,6 +72,9 @@ typedef enum { // Symbolic names for extensions. Strings may be directly used when calling the // functions, but better to have the compiler do spelling checks. // +const char* const GL_OES_texture_3D = "GL_OES_texture_3D"; + + const char* const GL_ARB_texture_rectangle = "GL_ARB_texture_rectangle"; const char* const GL_3DL_array_objects = "GL_3DL_array_objects"; const char* const GL_ARB_shading_language_420pack = "GL_ARB_shading_language_420pack"; -- GitLab