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 =
"MaxComputeWorkGroupCountY 65535\n"
"MaxComputeWorkGroupCountZ 65535\n"
"MaxComputeWorkGroupSizeX 1024\n"
"MaxComputeWorkGroupSizeX 1024\n"
"MaxComputeWorkGroupSizeY 1024\n"
"MaxComputeWorkGroupSizeZ 64\n"
"MaxComputeUniformComponents 1024\n"
"MaxComputeTextureImageUnits 16\n"
......
......@@ -77,8 +77,8 @@ uniform iimage2DArray ii2dabad; // ERROR, not writeonly
uniform writeonly iimage2DArray ii2da;
layout(r32i) uniform iimage2D iimg2D;
layout(rgba32i) uniform iimage2D iimg2Drgba;
layout(rgba32f) uniform image2D img2Drgba;
layout(rgba32i) uniform readonly iimage2D iimg2Drgba;
layout(rgba32f) uniform readonly image2D img2Drgba;
layout(r32ui) uniform uimage2D uimg2D;
void qux()
......@@ -111,12 +111,12 @@ void passrc()
passr(iimg2D);
}
layout(rg8i) uniform uimage2D i1bad; // ERROR, type mismatch
layout(rgba32i) uniform image2D i2bad; // ERROR, type mismatch
layout(rgba32f) uniform uimage2D i3bad; // ERROR, type mismatch
layout(r8_snorm) uniform iimage2D i4bad; // ERROR, type mismatch
layout(rgba32ui) uniform iimage2D i5bad; // ERROR, type mismatch
layout(r8ui) uniform iimage2D i6bad; // ERROR, type mismatch
layout(rg8i) uniform readonly uimage2D i1bad; // ERROR, type mismatch
layout(rgba32i) uniform readonly image2D i2bad; // ERROR, type mismatch
layout(rgba32f) uniform readonly uimage2D i3bad; // ERROR, type mismatch
layout(r8_snorm) uniform readonly iimage2D i4bad; // ERROR, type mismatch
layout(rgba32ui) uniform readonly iimage2D i5bad; // ERROR, type mismatch
layout(r8ui) uniform readonly iimage2D i6bad; // ERROR, type mismatch
layout(binding = 0) uniform atomic_uint counter;
......@@ -146,7 +146,7 @@ uniform int i;
void opac()
{
int a[3];
a[counter]; // ERROR
a[counter]; // ERROR, non-integer
countArr[2];
countArr[i];
}
......@@ -172,3 +172,54 @@ uniform samplerCubeArray sca; // ERROR
uniform iimage2DRect i2dr; // ERROR
uniform image2DMS i2dms; // 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
MaxComputeWorkGroupCountY 65535
MaxComputeWorkGroupCountZ 65535
MaxComputeWorkGroupSizeX 1024
MaxComputeWorkGroupSizeX 1024
MaxComputeWorkGroupSizeY 1024
MaxComputeWorkGroupSizeZ 64
MaxComputeUniformComponents 1024
MaxComputeTextureImageUnits 16
......
......@@ -187,10 +187,8 @@ TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermT
//
// 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)
return 0;
......
......@@ -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.
//
......@@ -1540,7 +1568,6 @@ void TParseContext::variableCheck(TIntermTyped*& nodePtr)
//
bool TParseContext::lValueErrorCheck(TSourceLoc loc, const char* op, TIntermTyped* node)
{
TIntermSymbol* symNode = node->getAsSymbolNode();
TIntermBinary* binaryNode = node->getAsBinaryNode();
if (binaryNode) {
......@@ -1582,6 +1609,7 @@ bool TParseContext::lValueErrorCheck(TSourceLoc loc, const char* op, TIntermType
const char* symbol = 0;
TIntermSymbol* symNode = node->getAsSymbolNode();
if (symNode != 0)
symbol = symNode->getName().c_str();
......@@ -1644,6 +1672,32 @@ bool TParseContext::lValueErrorCheck(TSourceLoc loc, const char* op, TIntermType
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
// a constant.
......@@ -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), "");
if (type.getSampler().type == EbtUint && qualifier.layoutFormat < ElfIntGuard)
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)
error(loc, "image variables not declared 'writeonly' must have a format layout qualifier", "", "");
......@@ -3828,7 +3891,9 @@ TIntermNode* TParseContext::declareVariable(TSourceLoc loc, TString& identifier,
if (voidErrorCheck(loc, identifier, type.getBasicType()))
return 0;
if (! initializer)
if (initializer)
rValueErrorCheck(loc, "initializer", initializer);
else
nonInitConstCheck(loc, identifier, type);
invariantCheck(loc, type, identifier);
......@@ -4118,8 +4183,9 @@ TIntermTyped* TParseContext::convertInitializerList(TSourceLoc loc, const TType&
//
TIntermTyped* TParseContext::addConstructor(TSourceLoc loc, TIntermNode* node, const TType& type, TOperator op)
{
if (node == 0)
if (node == 0 || node->getAsTyped() == 0)
return 0;
rValueErrorCheck(loc, "constructor", node->getAsTyped());
TIntermAggregate* aggrNode = node->getAsAggregate();
......@@ -4150,7 +4216,7 @@ TIntermTyped* TParseContext::addConstructor(TSourceLoc loc, TIntermNode* node, c
else if (op == EOpConstructStruct)
newNode = constructStruct(node, *(*memberTypes).type, 1, node->getLoc());
else
newNode = constructBuiltIn(type, op, node, node->getLoc(), false);
newNode = constructBuiltIn(type, op, node->getAsTyped(), node->getLoc(), false);
if (newNode && (type.isArray() || op == EOpConstructStruct))
newNode = intermediate.setAggregateOperator(newNode, EOpConstructStruct, type, loc);
......@@ -4178,7 +4244,7 @@ TIntermTyped* TParseContext::addConstructor(TSourceLoc loc, TIntermNode* node, c
else if (op == EOpConstructStruct)
newNode = constructStruct(*p, *(memberTypes[paramCount]).type, paramCount+1, node->getLoc());
else
newNode = constructBuiltIn(type, op, *p, node->getLoc(), true);
newNode = constructBuiltIn(type, op, (*p)->getAsTyped(), node->getLoc(), true);
if (newNode)
*p = newNode;
......@@ -4198,7 +4264,7 @@ TIntermTyped* TParseContext::addConstructor(TSourceLoc loc, TIntermNode* node, c
//
// 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;
TOperator basicOp;
......
......@@ -95,6 +95,8 @@ public:
int getIoArrayImplicitSize() const;
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);
TFunction* handleFunctionDeclarator(TSourceLoc loc, TFunction& function, bool prototype);
TIntermAggregate* handleFunctionDefinition(TSourceLoc, TFunction&);
......@@ -111,6 +113,7 @@ public:
void binaryOpError(TSourceLoc, const char* op, TString left, TString right);
void variableCheck(TIntermTyped*& nodePtr);
bool lValueErrorCheck(TSourceLoc, const char* op, TIntermTyped*);
void rValueErrorCheck(TSourceLoc, const char* op, TIntermTyped*);
void constantValueCheck(TIntermTyped* node, const char* token);
void integerCheck(const TIntermTyped* node, const char* token);
void globalCheck(TSourceLoc, const char* token);
......@@ -170,7 +173,7 @@ public:
TIntermNode* declareVariable(TSourceLoc, TString& identifier, const TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0);
TIntermTyped* addConstructor(TSourceLoc, TIntermNode*, const TType&, TOperator);
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 fixBlockLocations(TSourceLoc, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
void fixBlockXfbOffsets(TSourceLoc, TQualifier&, TTypeList&);
......
......@@ -677,8 +677,7 @@ int TScanContext::tokenizeIdentifier()
if (parseContext.profile == EEsProfile && parseContext.version >= 310 ||
parseContext.extensionsTurnedOn(1, &GL_ARB_shader_atomic_counters))
return keyword;
else
return es30ReservedFromGLSL(420);
return es30ReservedFromGLSL(420);
case COHERENT:
case RESTRICT:
......@@ -686,10 +685,11 @@ int TScanContext::tokenizeIdentifier()
case WRITEONLY:
if (parseContext.profile == EEsProfile && parseContext.version >= 310)
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:
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))))
reservedWord();
return keyword;
......
......@@ -161,7 +161,7 @@ public:
TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, 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);
bool canImplicitlyPromote(TBasicType from, TBasicType to) const;
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