Commit da66bc7d by John Kessenich

Implement write-only semantic checking, the non-r32f/i/u readonly/writeonly…

Implement write-only semantic checking, the non-r32f/i/u readonly/writeonly check, and ES 3.1 support of volatile. Also, fix a typo in MaxComputeGroupY. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@27765 e7fa87d3-cd2b-0410-9028-fcbf551c1848
parent bd2d8fb0
...@@ -142,7 +142,7 @@ const char* DefaultConfig = ...@@ -142,7 +142,7 @@ const char* DefaultConfig =
"MaxComputeWorkGroupCountY 65535\n" "MaxComputeWorkGroupCountY 65535\n"
"MaxComputeWorkGroupCountZ 65535\n" "MaxComputeWorkGroupCountZ 65535\n"
"MaxComputeWorkGroupSizeX 1024\n" "MaxComputeWorkGroupSizeX 1024\n"
"MaxComputeWorkGroupSizeX 1024\n" "MaxComputeWorkGroupSizeY 1024\n"
"MaxComputeWorkGroupSizeZ 64\n" "MaxComputeWorkGroupSizeZ 64\n"
"MaxComputeUniformComponents 1024\n" "MaxComputeUniformComponents 1024\n"
"MaxComputeTextureImageUnits 16\n" "MaxComputeTextureImageUnits 16\n"
......
...@@ -77,8 +77,8 @@ uniform iimage2DArray ii2dabad; // ERROR, not writeonly ...@@ -77,8 +77,8 @@ uniform iimage2DArray ii2dabad; // ERROR, not writeonly
uniform writeonly iimage2DArray ii2da; uniform writeonly iimage2DArray ii2da;
layout(r32i) uniform iimage2D iimg2D; layout(r32i) uniform iimage2D iimg2D;
layout(rgba32i) uniform iimage2D iimg2Drgba; layout(rgba32i) uniform readonly iimage2D iimg2Drgba;
layout(rgba32f) uniform image2D img2Drgba; layout(rgba32f) uniform readonly image2D img2Drgba;
layout(r32ui) uniform uimage2D uimg2D; layout(r32ui) uniform uimage2D uimg2D;
void qux() void qux()
...@@ -111,12 +111,12 @@ void passrc() ...@@ -111,12 +111,12 @@ void passrc()
passr(iimg2D); passr(iimg2D);
} }
layout(rg8i) uniform uimage2D i1bad; // ERROR, type mismatch layout(rg8i) uniform readonly uimage2D i1bad; // ERROR, type mismatch
layout(rgba32i) uniform image2D i2bad; // ERROR, type mismatch layout(rgba32i) uniform readonly image2D i2bad; // ERROR, type mismatch
layout(rgba32f) uniform uimage2D i3bad; // ERROR, type mismatch layout(rgba32f) uniform readonly uimage2D i3bad; // ERROR, type mismatch
layout(r8_snorm) uniform iimage2D i4bad; // ERROR, type mismatch layout(r8_snorm) uniform readonly iimage2D i4bad; // ERROR, type mismatch
layout(rgba32ui) uniform iimage2D i5bad; // ERROR, type mismatch layout(rgba32ui) uniform readonly iimage2D i5bad; // ERROR, type mismatch
layout(r8ui) uniform iimage2D i6bad; // ERROR, type mismatch layout(r8ui) uniform readonly iimage2D i6bad; // ERROR, type mismatch
layout(binding = 0) uniform atomic_uint counter; layout(binding = 0) uniform atomic_uint counter;
...@@ -146,7 +146,7 @@ uniform int i; ...@@ -146,7 +146,7 @@ uniform int i;
void opac() void opac()
{ {
int a[3]; int a[3];
a[counter]; // ERROR a[counter]; // ERROR, non-integer
countArr[2]; countArr[2];
countArr[i]; countArr[i];
} }
...@@ -172,3 +172,54 @@ uniform samplerCubeArray sca; // ERROR ...@@ -172,3 +172,54 @@ uniform samplerCubeArray sca; // ERROR
uniform iimage2DRect i2dr; // ERROR uniform iimage2DRect i2dr; // ERROR
uniform image2DMS i2dms; // ERROR uniform image2DMS i2dms; // ERROR
uniform uimage2DMSArray u2dmsa; // ERROR uniform uimage2DMSArray u2dmsa; // ERROR
layout(r32f) coherent volatile restrict readonly writeonly uniform image2D okay1;
layout(r32i) coherent volatile restrict readonly uniform iimage2D okay2;
layout(r32ui) coherent volatile restrict writeonly uniform uimage2D okay3;
layout(r32f) coherent volatile restrict uniform image2D okay4;
layout(rgba32f) coherent volatile restrict uniform image2D badQ1; // ERROR, bad qualifiers
layout(rgba8i) coherent volatile restrict uniform iimage2D badQ2; // ERROR, bad qualifiers
layout(rgba16ui) coherent volatile restrict uniform uimage2D badQ3; // ERROR, bad qualifiers
writeonly buffer woblock
{
int value;
float values[];
} wo;
void foowo()
{
float g;
g = wo.values[2]; // ERROR, writeonly
float f = wo.values[2]; // ERROR, writeonly
++wo.values[2]; // ERROR, writeonly
wo.values[2]--; // ERROR, writeonly
f + wo.values[2]; // ERROR, writeonly
wo.values[2] - f; // ERROR, writeonly
bool b;
b ? f : wo.values[2]; // ERROR, writeonly
b ? wo.values[2] : f; // ERROR, writeonly
if (f == wo.values[2]) // ERROR, writeonly
++f;
if (f >= wo.values[2]) // ERROR, writeonly
++f;
f = vec3(wo.values[2]).x; // ERROR, writeonly
~wo.value; // ERROR, writeonly
wo.values[2] = 3.4;
}
buffer multioblock
{
readonly int value;
writeonly float values[];
} multio;
void foomultio()
{
float g;
g = wo.values[2]; // ERROR, writeonly
~wo.value;
wo.values[2] = 3.4;
wo.value = 2; // ERROR, readonly
}
...@@ -22,7 +22,7 @@ MaxComputeWorkGroupCountX 65535 ...@@ -22,7 +22,7 @@ MaxComputeWorkGroupCountX 65535
MaxComputeWorkGroupCountY 65535 MaxComputeWorkGroupCountY 65535
MaxComputeWorkGroupCountZ 65535 MaxComputeWorkGroupCountZ 65535
MaxComputeWorkGroupSizeX 1024 MaxComputeWorkGroupSizeX 1024
MaxComputeWorkGroupSizeX 1024 MaxComputeWorkGroupSizeY 1024
MaxComputeWorkGroupSizeZ 64 MaxComputeWorkGroupSizeZ 64
MaxComputeUniformComponents 1024 MaxComputeUniformComponents 1024
MaxComputeTextureImageUnits 16 MaxComputeTextureImageUnits 16
......
...@@ -187,10 +187,8 @@ TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermT ...@@ -187,10 +187,8 @@ TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermT
// //
// Returns the added node. // Returns the added node.
// //
TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc loc) TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSourceLoc loc)
{ {
TIntermTyped* child = childNode->getAsTyped();
if (child->getType().getBasicType() == EbtBlock) if (child->getType().getBasicType() == EbtBlock)
return 0; return 0;
......
...@@ -678,6 +678,34 @@ void TParseContext::checkIoArrayConsistency(TSourceLoc loc, int requiredSize, co ...@@ -678,6 +678,34 @@ void TParseContext::checkIoArrayConsistency(TSourceLoc loc, int requiredSize, co
} }
} }
// Handle seeing a binary node with a math operation.
TIntermTyped* TParseContext::handleBinaryMath(TSourceLoc loc, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right)
{
rValueErrorCheck(loc, str, left->getAsTyped());
rValueErrorCheck(loc, str, right->getAsTyped());
TIntermTyped* result = intermediate.addBinaryMath(op, left, right, loc);
if (! result)
binaryOpError(loc, str, left->getCompleteString(), right->getCompleteString());
return result;
}
// Handle seeing a unary node with a math operation.
TIntermTyped* TParseContext::handleUnaryMath(TSourceLoc loc, const char* str, TOperator op, TIntermTyped* childNode)
{
rValueErrorCheck(loc, str, childNode);
TIntermTyped* result = intermediate.addUnaryMath(op, childNode, loc);
if (result)
return result;
else
unaryOpError(loc, str, childNode->getCompleteString());
return childNode;
}
// //
// Handle seeing a base.field dereference in the grammar. // Handle seeing a base.field dereference in the grammar.
// //
...@@ -1540,7 +1568,6 @@ void TParseContext::variableCheck(TIntermTyped*& nodePtr) ...@@ -1540,7 +1568,6 @@ void TParseContext::variableCheck(TIntermTyped*& nodePtr)
// //
bool TParseContext::lValueErrorCheck(TSourceLoc loc, const char* op, TIntermTyped* node) bool TParseContext::lValueErrorCheck(TSourceLoc loc, const char* op, TIntermTyped* node)
{ {
TIntermSymbol* symNode = node->getAsSymbolNode();
TIntermBinary* binaryNode = node->getAsBinaryNode(); TIntermBinary* binaryNode = node->getAsBinaryNode();
if (binaryNode) { if (binaryNode) {
...@@ -1582,6 +1609,7 @@ bool TParseContext::lValueErrorCheck(TSourceLoc loc, const char* op, TIntermType ...@@ -1582,6 +1609,7 @@ bool TParseContext::lValueErrorCheck(TSourceLoc loc, const char* op, TIntermType
const char* symbol = 0; const char* symbol = 0;
TIntermSymbol* symNode = node->getAsSymbolNode();
if (symNode != 0) if (symNode != 0)
symbol = symNode->getName().c_str(); symbol = symNode->getName().c_str();
...@@ -1644,6 +1672,32 @@ bool TParseContext::lValueErrorCheck(TSourceLoc loc, const char* op, TIntermType ...@@ -1644,6 +1672,32 @@ bool TParseContext::lValueErrorCheck(TSourceLoc loc, const char* op, TIntermType
return true; return true;
} }
// Test for and give an error if the node can't be read from.
void TParseContext::rValueErrorCheck(TSourceLoc loc, const char* op, TIntermTyped* node)
{
if (! node)
return;
TIntermBinary* binaryNode = node->getAsBinaryNode();
if (binaryNode) {
switch(binaryNode->getOp()) {
case EOpIndexDirect:
case EOpIndexIndirect:
case EOpIndexDirectStruct:
case EOpVectorSwizzle:
rValueErrorCheck(loc, op, binaryNode->getLeft());
default:
break;
}
return;
}
TIntermSymbol* symNode = node->getAsSymbolNode();
if (symNode && symNode->getQualifier().writeonly)
error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str());
}
// //
// Both test, and if necessary spit out an error, to see if the node is really // Both test, and if necessary spit out an error, to see if the node is really
// a constant. // a constant.
...@@ -3530,6 +3584,15 @@ void TParseContext::layoutTypeCheck(TSourceLoc loc, const TType& type) ...@@ -3530,6 +3584,15 @@ void TParseContext::layoutTypeCheck(TSourceLoc loc, const TType& type)
error(loc, "does not apply to signed integer images", TQualifier::getLayoutFormatString(qualifier.layoutFormat), ""); error(loc, "does not apply to signed integer images", TQualifier::getLayoutFormatString(qualifier.layoutFormat), "");
if (type.getSampler().type == EbtUint && qualifier.layoutFormat < ElfIntGuard) if (type.getSampler().type == EbtUint && qualifier.layoutFormat < ElfIntGuard)
error(loc, "does not apply to unsigned integer images", TQualifier::getLayoutFormatString(qualifier.layoutFormat), ""); error(loc, "does not apply to unsigned integer images", TQualifier::getLayoutFormatString(qualifier.layoutFormat), "");
if (profile == EEsProfile) {
// "Except for image variables qualified with the format qualifiers r32f, r32i, and r32ui, image variables must
// specify either memory qualifier readonly or the memory qualifier writeonly."
if (! (qualifier.layoutFormat == ElfR32f || qualifier.layoutFormat == ElfR32i || qualifier.layoutFormat == ElfR32ui)) {
if (! qualifier.readonly && ! qualifier.writeonly)
error(loc, "format requires readonly or writeonly memory qualifier", TQualifier::getLayoutFormatString(qualifier.layoutFormat), "");
}
}
} }
} else if (type.isImage() && ! qualifier.writeonly) } else if (type.isImage() && ! qualifier.writeonly)
error(loc, "image variables not declared 'writeonly' must have a format layout qualifier", "", ""); error(loc, "image variables not declared 'writeonly' must have a format layout qualifier", "", "");
...@@ -3828,7 +3891,9 @@ TIntermNode* TParseContext::declareVariable(TSourceLoc loc, TString& identifier, ...@@ -3828,7 +3891,9 @@ TIntermNode* TParseContext::declareVariable(TSourceLoc loc, TString& identifier,
if (voidErrorCheck(loc, identifier, type.getBasicType())) if (voidErrorCheck(loc, identifier, type.getBasicType()))
return 0; return 0;
if (! initializer) if (initializer)
rValueErrorCheck(loc, "initializer", initializer);
else
nonInitConstCheck(loc, identifier, type); nonInitConstCheck(loc, identifier, type);
invariantCheck(loc, type, identifier); invariantCheck(loc, type, identifier);
...@@ -4118,8 +4183,9 @@ TIntermTyped* TParseContext::convertInitializerList(TSourceLoc loc, const TType& ...@@ -4118,8 +4183,9 @@ TIntermTyped* TParseContext::convertInitializerList(TSourceLoc loc, const TType&
// //
TIntermTyped* TParseContext::addConstructor(TSourceLoc loc, TIntermNode* node, const TType& type, TOperator op) TIntermTyped* TParseContext::addConstructor(TSourceLoc loc, TIntermNode* node, const TType& type, TOperator op)
{ {
if (node == 0) if (node == 0 || node->getAsTyped() == 0)
return 0; return 0;
rValueErrorCheck(loc, "constructor", node->getAsTyped());
TIntermAggregate* aggrNode = node->getAsAggregate(); TIntermAggregate* aggrNode = node->getAsAggregate();
...@@ -4150,7 +4216,7 @@ TIntermTyped* TParseContext::addConstructor(TSourceLoc loc, TIntermNode* node, c ...@@ -4150,7 +4216,7 @@ TIntermTyped* TParseContext::addConstructor(TSourceLoc loc, TIntermNode* node, c
else if (op == EOpConstructStruct) else if (op == EOpConstructStruct)
newNode = constructStruct(node, *(*memberTypes).type, 1, node->getLoc()); newNode = constructStruct(node, *(*memberTypes).type, 1, node->getLoc());
else else
newNode = constructBuiltIn(type, op, node, node->getLoc(), false); newNode = constructBuiltIn(type, op, node->getAsTyped(), node->getLoc(), false);
if (newNode && (type.isArray() || op == EOpConstructStruct)) if (newNode && (type.isArray() || op == EOpConstructStruct))
newNode = intermediate.setAggregateOperator(newNode, EOpConstructStruct, type, loc); newNode = intermediate.setAggregateOperator(newNode, EOpConstructStruct, type, loc);
...@@ -4178,7 +4244,7 @@ TIntermTyped* TParseContext::addConstructor(TSourceLoc loc, TIntermNode* node, c ...@@ -4178,7 +4244,7 @@ TIntermTyped* TParseContext::addConstructor(TSourceLoc loc, TIntermNode* node, c
else if (op == EOpConstructStruct) else if (op == EOpConstructStruct)
newNode = constructStruct(*p, *(memberTypes[paramCount]).type, paramCount+1, node->getLoc()); newNode = constructStruct(*p, *(memberTypes[paramCount]).type, paramCount+1, node->getLoc());
else else
newNode = constructBuiltIn(type, op, *p, node->getLoc(), true); newNode = constructBuiltIn(type, op, (*p)->getAsTyped(), node->getLoc(), true);
if (newNode) if (newNode)
*p = newNode; *p = newNode;
...@@ -4198,7 +4264,7 @@ TIntermTyped* TParseContext::addConstructor(TSourceLoc loc, TIntermNode* node, c ...@@ -4198,7 +4264,7 @@ TIntermTyped* TParseContext::addConstructor(TSourceLoc loc, TIntermNode* node, c
// //
// Returns 0 for an error or the constructed node. // Returns 0 for an error or the constructed node.
// //
TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, TIntermNode* node, TSourceLoc loc, bool subset) TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, TIntermTyped* node, TSourceLoc loc, bool subset)
{ {
TIntermTyped* newNode; TIntermTyped* newNode;
TOperator basicOp; TOperator basicOp;
......
...@@ -95,6 +95,8 @@ public: ...@@ -95,6 +95,8 @@ public:
int getIoArrayImplicitSize() const; int getIoArrayImplicitSize() const;
void checkIoArrayConsistency(TSourceLoc, int requiredSize, const char* feature, TType&, const TString&); void checkIoArrayConsistency(TSourceLoc, int requiredSize, const char* feature, TType&, const TString&);
TIntermTyped* handleBinaryMath(TSourceLoc, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
TIntermTyped* handleUnaryMath(TSourceLoc, const char* str, TOperator op, TIntermTyped* childNode);
TIntermTyped* handleDotDereference(TSourceLoc, TIntermTyped* base, TString& field); TIntermTyped* handleDotDereference(TSourceLoc, TIntermTyped* base, TString& field);
TFunction* handleFunctionDeclarator(TSourceLoc loc, TFunction& function, bool prototype); TFunction* handleFunctionDeclarator(TSourceLoc loc, TFunction& function, bool prototype);
TIntermAggregate* handleFunctionDefinition(TSourceLoc, TFunction&); TIntermAggregate* handleFunctionDefinition(TSourceLoc, TFunction&);
...@@ -111,6 +113,7 @@ public: ...@@ -111,6 +113,7 @@ public:
void binaryOpError(TSourceLoc, const char* op, TString left, TString right); void binaryOpError(TSourceLoc, const char* op, TString left, TString right);
void variableCheck(TIntermTyped*& nodePtr); void variableCheck(TIntermTyped*& nodePtr);
bool lValueErrorCheck(TSourceLoc, const char* op, TIntermTyped*); bool lValueErrorCheck(TSourceLoc, const char* op, TIntermTyped*);
void rValueErrorCheck(TSourceLoc, const char* op, TIntermTyped*);
void constantValueCheck(TIntermTyped* node, const char* token); void constantValueCheck(TIntermTyped* node, const char* token);
void integerCheck(const TIntermTyped* node, const char* token); void integerCheck(const TIntermTyped* node, const char* token);
void globalCheck(TSourceLoc, const char* token); void globalCheck(TSourceLoc, const char* token);
...@@ -170,7 +173,7 @@ public: ...@@ -170,7 +173,7 @@ public:
TIntermNode* declareVariable(TSourceLoc, TString& identifier, const TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0); TIntermNode* declareVariable(TSourceLoc, TString& identifier, const TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0);
TIntermTyped* addConstructor(TSourceLoc, TIntermNode*, const TType&, TOperator); TIntermTyped* addConstructor(TSourceLoc, TIntermNode*, const TType&, TOperator);
TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc); TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc);
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermNode*, TSourceLoc, bool subset); TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, TSourceLoc, bool subset);
void declareBlock(TSourceLoc, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0); void declareBlock(TSourceLoc, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
void fixBlockLocations(TSourceLoc, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation); void fixBlockLocations(TSourceLoc, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
void fixBlockXfbOffsets(TSourceLoc, TQualifier&, TTypeList&); void fixBlockXfbOffsets(TSourceLoc, TQualifier&, TTypeList&);
......
...@@ -677,7 +677,6 @@ int TScanContext::tokenizeIdentifier() ...@@ -677,7 +677,6 @@ int TScanContext::tokenizeIdentifier()
if (parseContext.profile == EEsProfile && parseContext.version >= 310 || if (parseContext.profile == EEsProfile && parseContext.version >= 310 ||
parseContext.extensionsTurnedOn(1, &GL_ARB_shader_atomic_counters)) parseContext.extensionsTurnedOn(1, &GL_ARB_shader_atomic_counters))
return keyword; return keyword;
else
return es30ReservedFromGLSL(420); return es30ReservedFromGLSL(420);
case COHERENT: case COHERENT:
...@@ -686,10 +685,11 @@ int TScanContext::tokenizeIdentifier() ...@@ -686,10 +685,11 @@ int TScanContext::tokenizeIdentifier()
case WRITEONLY: case WRITEONLY:
if (parseContext.profile == EEsProfile && parseContext.version >= 310) if (parseContext.profile == EEsProfile && parseContext.version >= 310)
return keyword; return keyword;
else
return es30ReservedFromGLSL(parseContext.extensionsTurnedOn(1, &GL_ARB_shader_image_load_store) ? 130 : 420); return es30ReservedFromGLSL(parseContext.extensionsTurnedOn(1, &GL_ARB_shader_image_load_store) ? 130 : 420);
case VOLATILE: case VOLATILE:
if (parseContext.profile == EEsProfile && parseContext.version >= 310)
return keyword;
if (! parseContext.symbolTable.atBuiltInLevel() && (parseContext.profile == EEsProfile || (parseContext.version < 420 && ! parseContext.extensionsTurnedOn(1, &GL_ARB_shader_image_load_store)))) if (! parseContext.symbolTable.atBuiltInLevel() && (parseContext.profile == EEsProfile || (parseContext.version < 420 && ! parseContext.extensionsTurnedOn(1, &GL_ARB_shader_image_load_store))))
reservedWord(); reservedWord();
return keyword; return keyword;
......
...@@ -161,7 +161,7 @@ public: ...@@ -161,7 +161,7 @@ public:
TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc); TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc); TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc); TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
TIntermTyped* addUnaryMath(TOperator, TIntermNode* child, TSourceLoc); TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, TSourceLoc);
TIntermTyped* addBuiltInFunctionCall(TSourceLoc line, TOperator, bool unary, TIntermNode*, const TType& returnType); TIntermTyped* addBuiltInFunctionCall(TSourceLoc line, TOperator, bool unary, TIntermNode*, const TType& returnType);
bool canImplicitlyPromote(TBasicType from, TBasicType to) const; bool canImplicitlyPromote(TBasicType from, TBasicType to) const;
TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right); TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment