Add GL_OES_standard_derivatives. Also added extension infrastructure that allows built-in symbols to be tagged with extensions and automatically error checked against them.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24002 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
		
							parent
							
								
									115a0adc29
								
							
						
					
					
						commit
						06a37c3964
					
				@ -88,4 +88,16 @@ void foo234()
 | 
			
		||||
{
 | 
			
		||||
    texture3D(s3D2, vec3(0.2), 0.2);
 | 
			
		||||
    texture3DProj(s3D2, v[1], 0.4);
 | 
			
		||||
    dFdx(v[0]);    // ERROR
 | 
			
		||||
    dFdy(3.2);     // ERROR
 | 
			
		||||
    fwidth(f13);   // ERROR
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#extension GL_OES_standard_derivatives : enable
 | 
			
		||||
 | 
			
		||||
void foo236()
 | 
			
		||||
{
 | 
			
		||||
    dFdx(v[0]);
 | 
			
		||||
    dFdy(3.2);
 | 
			
		||||
    fwidth(f13);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -42,7 +42,10 @@ ERROR: 0:76: 'h' : cannot use storage or interpolation qualifiers on structure m
 | 
			
		||||
ERROR: 0:77: 'i' : cannot use invariant qualifier on structure members 
 | 
			
		||||
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: 0:91: 'dFdx' : required extension not requested: GL_OES_standard_derivatives
 | 
			
		||||
ERROR: 0:92: 'dFdy' : required extension not requested: GL_OES_standard_derivatives
 | 
			
		||||
ERROR: 0:93: 'fwidth' : required extension not requested: GL_OES_standard_derivatives
 | 
			
		||||
ERROR: 40 compilation errors.  No code generated.
 | 
			
		||||
 | 
			
		||||
ERROR: node is still EOpNull!
 | 
			
		||||
0:3  Sequence
 | 
			
		||||
@ -142,6 +145,27 @@ ERROR: node is still EOpNull!
 | 
			
		||||
0:90            1 (const int)
 | 
			
		||||
0:90        Constant:
 | 
			
		||||
0:90          0.400000
 | 
			
		||||
0:91      dPdx (mediump 4-component vector of float)
 | 
			
		||||
0:91        direct index (smooth mediump 4-component vector of float)
 | 
			
		||||
0:91          'v' (smooth in 3-element array of mediump 4-component vector of float)
 | 
			
		||||
0:91          Constant:
 | 
			
		||||
0:91            0 (const int)
 | 
			
		||||
0:92      Constant:
 | 
			
		||||
0:92        0.000000
 | 
			
		||||
0:93      fwidth (mediump float)
 | 
			
		||||
0:93        'f13' (invariant mediump float)
 | 
			
		||||
0:98  Function Definition: foo236( (void)
 | 
			
		||||
0:98    Function Parameters: 
 | 
			
		||||
0:100    Sequence
 | 
			
		||||
0:100      dPdx (mediump 4-component vector of float)
 | 
			
		||||
0:100        direct index (smooth mediump 4-component vector of float)
 | 
			
		||||
0:100          'v' (smooth in 3-element array of mediump 4-component vector of float)
 | 
			
		||||
0:100          Constant:
 | 
			
		||||
0:100            0 (const int)
 | 
			
		||||
0:101      Constant:
 | 
			
		||||
0:101        0.000000
 | 
			
		||||
0:102      fwidth (mediump float)
 | 
			
		||||
0:102        'f13' (invariant mediump float)
 | 
			
		||||
0:?   Linker Objects
 | 
			
		||||
0:?     'a' (3-element array of mediump int)
 | 
			
		||||
0:?     'uint' (mediump int)
 | 
			
		||||
 | 
			
		||||
@ -42,8 +42,10 @@
 | 
			
		||||
// Where to put a built-in:
 | 
			
		||||
//   TBuiltIns::initialize(version,profile)       context-independent textual built-ins; add them to the right string
 | 
			
		||||
//   TBuiltIns::initialize(resources,...)         context-dependent textual built-ins; add them to the right string
 | 
			
		||||
//   IdentifyBuiltIns(...,symbolTable)            context-independent programmatic additions/mappings to the symbol table
 | 
			
		||||
//   IdentifyBuiltIns(...,symbolTable, resources) context-dependent programmatic additions/mappings to the symbol table
 | 
			
		||||
//   IdentifyBuiltIns(...,symbolTable)            context-independent programmatic additions/mappings to the symbol table,
 | 
			
		||||
//                                                including identify what extensions are needed if a version does not allow a symbol
 | 
			
		||||
//   IdentifyBuiltIns(...,symbolTable, resources) context-dependent programmatic additions/mappings to the symbol table,
 | 
			
		||||
//                                                including identify what extensions are needed if a version does not allow a symbol
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include "../Include/intermediate.h"
 | 
			
		||||
@ -2120,8 +2122,8 @@ void SpecialQualifier(const char* name, TStorageQualifier qualifier, TSymbolTabl
 | 
			
		||||
void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymbolTable& symbolTable)
 | 
			
		||||
{
 | 
			
		||||
    //
 | 
			
		||||
    // First, insert some special built-in variables that are not in
 | 
			
		||||
    // the built-in text strings.
 | 
			
		||||
    // Tag built-in variables and functions with additional qualifier and extension information
 | 
			
		||||
    // that cannot be declared with the text strings.
 | 
			
		||||
    //
 | 
			
		||||
    switch(language) {
 | 
			
		||||
    case EShLangVertex:
 | 
			
		||||
@ -2141,6 +2143,11 @@ void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymb
 | 
			
		||||
        SpecialQualifier("gl_PointCoord",  EvqPointCoord, symbolTable);
 | 
			
		||||
        SpecialQualifier("gl_FragColor",   EvqFragColor, symbolTable);
 | 
			
		||||
        SpecialQualifier("gl_FragDepth",   EvqFragDepth, symbolTable);
 | 
			
		||||
        if (version == 100) {
 | 
			
		||||
            symbolTable.setFunctionExtensions("dFdx",   1, &GL_OES_standard_derivatives);
 | 
			
		||||
            symbolTable.setFunctionExtensions("dFdy",   1, &GL_OES_standard_derivatives);
 | 
			
		||||
            symbolTable.setFunctionExtensions("fwidth", 1, &GL_OES_standard_derivatives);
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case EShLangCompute:
 | 
			
		||||
 | 
			
		||||
@ -385,6 +385,10 @@ TIntermTyped* TParseContext::handleVariable(TSourceLoc loc, TSymbol* symbol, TSt
 | 
			
		||||
{
 | 
			
		||||
    TIntermTyped* node = 0;
 | 
			
		||||
 | 
			
		||||
    // Error check for function requiring specific extensions present.
 | 
			
		||||
    if (symbol && symbol->getNumExtensions())
 | 
			
		||||
        requireExtensions(loc, symbol->getNumExtensions(), symbol->getExtensions(), symbol->getName().c_str());
 | 
			
		||||
 | 
			
		||||
    const TAnonMember* anon = symbol ? symbol->getAsAnonMember() : 0;
 | 
			
		||||
    if (anon) {
 | 
			
		||||
        // it was a member of an anonymous container, have to insert its dereference
 | 
			
		||||
@ -903,6 +907,10 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal
 | 
			
		||||
        bool builtIn;
 | 
			
		||||
        fnCandidate = findFunction(loc, *fnCall, builtIn);
 | 
			
		||||
        if (fnCandidate) {
 | 
			
		||||
            // Error check for function requiring specific extensions present.
 | 
			
		||||
            if (builtIn && fnCandidate->getNumExtensions())
 | 
			
		||||
                requireExtensions(loc, fnCandidate->getNumExtensions(), fnCandidate->getExtensions(), fnCandidate->getName().c_str());
 | 
			
		||||
 | 
			
		||||
            //
 | 
			
		||||
            // A declared function.  But, it might still map to a built-in
 | 
			
		||||
            // operation.
 | 
			
		||||
 | 
			
		||||
@ -185,6 +185,7 @@ public:
 | 
			
		||||
    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);
 | 
			
		||||
    void requireExtensions(TSourceLoc, int numExtensions, const char* const extensions[], const char *featureDesc);
 | 
			
		||||
    TExtensionBehavior getExtensionBehavior(const char*);
 | 
			
		||||
    bool extensionsTurnedOn(int numExtensions, const char* const extensions[]);
 | 
			
		||||
    void updateExtensionBehavior(const char* const extension, const char* behavior);
 | 
			
		||||
 | 
			
		||||
@ -207,6 +207,23 @@ void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Make all function overloads of the given name require an extension(s).
 | 
			
		||||
// Should only be used for a version/profile that actually needs the extension(s).
 | 
			
		||||
void TSymbolTableLevel::setFunctionExtensions(const char* name, int num, const char* const extensions[])
 | 
			
		||||
{
 | 
			
		||||
    tLevel::const_iterator candidate = level.lower_bound(name);
 | 
			
		||||
    while (candidate != level.end()) {
 | 
			
		||||
        const TString& candidateName = (*candidate).first;
 | 
			
		||||
        TString::size_type parenAt = candidateName.find_first_of('(');
 | 
			
		||||
        if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) {
 | 
			
		||||
            TSymbol* symbol = candidate->second;
 | 
			
		||||
            symbol->setExtensions(num, extensions);
 | 
			
		||||
        } else
 | 
			
		||||
            break;
 | 
			
		||||
        ++candidate;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Make all symbols in this table level read only.
 | 
			
		||||
//
 | 
			
		||||
@ -230,6 +247,8 @@ TVariable::TVariable(const TVariable& copyOf) : TSymbol(copyOf)
 | 
			
		||||
{	
 | 
			
		||||
    type.deepCopy(copyOf.type);
 | 
			
		||||
    userType = copyOf.userType;
 | 
			
		||||
    extensions = 0;
 | 
			
		||||
    setExtensions(copyOf.numExtensions, copyOf.extensions);
 | 
			
		||||
 | 
			
		||||
    if (! copyOf.unionArray.empty()) {
 | 
			
		||||
        assert(!copyOf.type.getStruct());
 | 
			
		||||
@ -255,6 +274,8 @@ TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf)
 | 
			
		||||
        parameters.back().copyParam(copyOf.parameters[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    extensions = 0;    
 | 
			
		||||
    setExtensions(copyOf.numExtensions, copyOf.extensions);
 | 
			
		||||
    returnType.deepCopy(copyOf.returnType);
 | 
			
		||||
    mangledName = copyOf.mangledName;
 | 
			
		||||
    op = copyOf.op;
 | 
			
		||||
 | 
			
		||||
@ -81,9 +81,9 @@ class TAnonMember;
 | 
			
		||||
class TSymbol {
 | 
			
		||||
public:
 | 
			
		||||
    POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
 | 
			
		||||
    explicit TSymbol(const TString *n) :  name(n), writable(true) { }
 | 
			
		||||
    explicit TSymbol(const TString *n) :  name(n), writable(true), numExtensions(0), extensions(0) { }
 | 
			
		||||
	virtual TSymbol* clone() const = 0;
 | 
			
		||||
    virtual ~TSymbol() { }
 | 
			
		||||
    virtual ~TSymbol() { delete [] extensions; }
 | 
			
		||||
 | 
			
		||||
    virtual const TString& getName() const { return *name; }
 | 
			
		||||
    virtual void changeName(const TString* newName) { name = newName; }
 | 
			
		||||
@ -97,6 +97,16 @@ public:
 | 
			
		||||
    virtual TType& getWritableType() = 0;
 | 
			
		||||
    virtual void setUniqueId(int id) { uniqueId = id; }
 | 
			
		||||
    virtual int getUniqueId() const { return uniqueId; }
 | 
			
		||||
    virtual void setExtensions(int num, const char* const exts[])
 | 
			
		||||
    {
 | 
			
		||||
        assert(extensions == 0);
 | 
			
		||||
        numExtensions = num;
 | 
			
		||||
        extensions = new const char*[numExtensions];
 | 
			
		||||
        for (int e = 0; e < num; ++e)
 | 
			
		||||
            extensions[e] = exts[e];
 | 
			
		||||
    }
 | 
			
		||||
    virtual int getNumExtensions() const { return numExtensions; }
 | 
			
		||||
    virtual const char** getExtensions() const { return extensions; }
 | 
			
		||||
    virtual void dump(TInfoSink &infoSink) const = 0;
 | 
			
		||||
 | 
			
		||||
    virtual bool isReadOnly() const { return ! writable; }
 | 
			
		||||
@ -109,6 +119,11 @@ protected:
 | 
			
		||||
    const TString *name;
 | 
			
		||||
    unsigned int uniqueId;      // For cross-scope comparing during code generation
 | 
			
		||||
 | 
			
		||||
    // For tracking what extensions must be present 
 | 
			
		||||
    // (don't use if correct version/profile is present).
 | 
			
		||||
    int numExtensions;
 | 
			
		||||
    const char** extensions; // an array of pointers to existing constant char strings
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // N.B.: Non-const functions that will be generally used should assert an this,
 | 
			
		||||
    // to avoid overwriting shared symbol-table information.
 | 
			
		||||
@ -376,6 +391,7 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void relateToOperator(const char* name, TOperator op);
 | 
			
		||||
    void setFunctionExtensions(const char* name, int num, const char* const extensions[]);
 | 
			
		||||
    void dump(TInfoSink &infoSink) const;
 | 
			
		||||
	TSymbolTableLevel* clone() const;
 | 
			
		||||
    void readOnly();
 | 
			
		||||
@ -552,6 +568,12 @@ public:
 | 
			
		||||
            table[level]->relateToOperator(name, op);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    void setFunctionExtensions(const char* name, int num, const char* const extensions[])
 | 
			
		||||
    {
 | 
			
		||||
        for (unsigned int level = 0; level < table.size(); ++level)
 | 
			
		||||
            table[level]->setFunctionExtensions(name, num, extensions);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int getMaxSymbolId() { return uniqueId; }
 | 
			
		||||
    void dump(TInfoSink &infoSink) const;
 | 
			
		||||
	void copyTable(const TSymbolTable& copyOf);
 | 
			
		||||
 | 
			
		||||
@ -60,6 +60,7 @@
 | 
			
		||||
//        requireStage()
 | 
			
		||||
//        checkDeprecated()
 | 
			
		||||
//        requireNotRemoved()
 | 
			
		||||
//        requireExtensions()
 | 
			
		||||
//    
 | 
			
		||||
//    Typically, only the first two calls are needed.  They go into a code path that 
 | 
			
		||||
//    implements Feature F, and will log the proper error/warning messages.  Parsing 
 | 
			
		||||
@ -129,8 +130,12 @@
 | 
			
		||||
// 
 | 
			
		||||
//        ~EEsProfile
 | 
			
		||||
//
 | 
			
		||||
// 6) If built-in symbols are added by the extension, add them in Initialize.cpp; see
 | 
			
		||||
//    the comment at the top of that file for where to put them.
 | 
			
		||||
// 6) If built-in symbols are added by the extension, add them in Initialize.cpp:  Their use
 | 
			
		||||
//    will be automatically error checked against the extensions enabled at that moment.
 | 
			
		||||
//    see the comment at the top of Initialize.cpp for where to put them.  Establish them at
 | 
			
		||||
//    the earliest release that supports the extension.  Then, tag them with the
 | 
			
		||||
//    set of extensions that both enable them and are necessary, given the version of the symbol
 | 
			
		||||
//    table. (There is a different symbol table for each version.)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include "ParseHelper.h"
 | 
			
		||||
@ -145,6 +150,7 @@ namespace glslang {
 | 
			
		||||
void TParseContext::initializeExtensionBehavior()
 | 
			
		||||
{
 | 
			
		||||
    extensionBehavior[GL_OES_texture_3D]               = EBhDisable;
 | 
			
		||||
    extensionBehavior[GL_OES_standard_derivatives]     = EBhDisable;
 | 
			
		||||
 | 
			
		||||
    extensionBehavior[GL_ARB_texture_rectangle]        = EBhDisable;
 | 
			
		||||
    extensionBehavior[GL_3DL_array_objects]            = EBhDisable;
 | 
			
		||||
@ -159,8 +165,9 @@ const char* TParseContext::getPreamble()
 | 
			
		||||
{
 | 
			
		||||
    if (profile == EEsProfile) {
 | 
			
		||||
        return
 | 
			
		||||
            "#define GL_ES 1\n"
 | 
			
		||||
            "#define GL_OES_texture_3D 1\n"
 | 
			
		||||
            "#define GL_ES 1\n";
 | 
			
		||||
            "#define GL_OES_standard_derivatives 1\n";
 | 
			
		||||
    } else {
 | 
			
		||||
        return
 | 
			
		||||
            "#define GL_FRAGMENT_PRECISION_HIGH 1\n"
 | 
			
		||||
@ -316,6 +323,41 @@ void TParseContext::requireNotRemoved(TSourceLoc loc, int profileMask, int remov
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Use when there are no profile/version to check, it's just an error if one of the
 | 
			
		||||
// extensions is not present.
 | 
			
		||||
//
 | 
			
		||||
void TParseContext::requireExtensions(TSourceLoc loc, int numExtensions, const char* const extensions[], const char *featureDesc)
 | 
			
		||||
{
 | 
			
		||||
    // First, see if any of the extensions are enabled
 | 
			
		||||
    for (int i = 0; i < numExtensions; ++i) {
 | 
			
		||||
        TExtensionBehavior behavior = getExtensionBehavior(extensions[i]);
 | 
			
		||||
        if (behavior == EBhEnable || behavior == EBhRequire)
 | 
			
		||||
            return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // See if any extensions want to give a warning on use; give warnings for all such extensions
 | 
			
		||||
    bool warned = false;
 | 
			
		||||
    for (int i = 0; i < numExtensions; ++i) {
 | 
			
		||||
        TExtensionBehavior behavior = getExtensionBehavior(extensions[i]);
 | 
			
		||||
        if (behavior == EBhWarn) {
 | 
			
		||||
            infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), loc);
 | 
			
		||||
            warned = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (warned)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    // If we get this far, give errors explaining what extensions are needed
 | 
			
		||||
    if (numExtensions == 1)
 | 
			
		||||
        error(loc, "required extension not requested:", featureDesc, extensions[0]);
 | 
			
		||||
    else {
 | 
			
		||||
        error(loc, "required extension not requested:", featureDesc, "Possible extensions include:");
 | 
			
		||||
        for (int i = 0; i < numExtensions; ++i)
 | 
			
		||||
            infoSink.info.message(EPrefixNone, extensions[i]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TExtensionBehavior TParseContext::getExtensionBehavior(const char* extension)
 | 
			
		||||
{
 | 
			
		||||
    TMap<TString, TExtensionBehavior>::iterator iter = extensionBehavior.find(TString(extension));
 | 
			
		||||
@ -375,12 +417,12 @@ void TParseContext::updateExtensionBehavior(const char* extension, const char* b
 | 
			
		||||
        if (iter == extensionBehavior.end()) {
 | 
			
		||||
            switch (behavior) {
 | 
			
		||||
            case EBhRequire:
 | 
			
		||||
                error(getCurrentLoc(), "extension not supported", "#extension", extension);
 | 
			
		||||
                error(getCurrentLoc(), "extension not supported:", "#extension", extension);
 | 
			
		||||
                break;
 | 
			
		||||
            case EBhEnable:
 | 
			
		||||
            case EBhWarn:
 | 
			
		||||
            case EBhDisable:
 | 
			
		||||
                warn(getCurrentLoc(), "extension not supported", "#extension", extension);
 | 
			
		||||
                warn(getCurrentLoc(), "extension not supported:", "#extension", extension);
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                assert(0 && "unexpected behavior");
 | 
			
		||||
 | 
			
		||||
@ -73,7 +73,7 @@ typedef enum {
 | 
			
		||||
// 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_OES_standard_derivatives     = "GL_OES_standard_derivatives";
 | 
			
		||||
 | 
			
		||||
const char* const GL_ARB_texture_rectangle        = "GL_ARB_texture_rectangle";
 | 
			
		||||
const char* const GL_3DL_array_objects            = "GL_3DL_array_objects";
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user