Merge pull request #542 from steve-lunarg/rwbuffers
HLSL: phase 2: add operator[]
This commit is contained in:
commit
f042e407a9
15 changed files with 4149 additions and 169 deletions
|
|
@ -136,13 +136,7 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
|
|||
// Need a new node holding things together. Make
|
||||
// one and promote it to the right type.
|
||||
//
|
||||
TIntermBinary* node = new TIntermBinary(op);
|
||||
if (loc.line == 0)
|
||||
loc = right->getLoc();
|
||||
node->setLoc(loc);
|
||||
|
||||
node->setLeft(left);
|
||||
node->setRight(right);
|
||||
TIntermBinary* node = addBinaryNode(op, left, right, loc);
|
||||
if (! node->promote())
|
||||
return 0;
|
||||
|
||||
|
|
@ -172,6 +166,56 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
|
|||
return node;
|
||||
}
|
||||
|
||||
//
|
||||
// Low level: add binary node (no promotions or other argument modifications)
|
||||
//
|
||||
TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc) const
|
||||
{
|
||||
// build the node
|
||||
TIntermBinary* node = new TIntermBinary(op);
|
||||
if (loc.line == 0)
|
||||
loc = left->getLoc();
|
||||
node->setLoc(loc);
|
||||
node->setLeft(left);
|
||||
node->setRight(right);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
//
|
||||
// like non-type form, but sets node's type.
|
||||
//
|
||||
TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc, const TType& type) const
|
||||
{
|
||||
TIntermBinary* node = addBinaryNode(op, left, right, loc);
|
||||
node->setType(type);
|
||||
return node;
|
||||
}
|
||||
|
||||
//
|
||||
// Low level: add unary node (no promotions or other argument modifications)
|
||||
//
|
||||
TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc loc) const
|
||||
{
|
||||
TIntermUnary* node = new TIntermUnary(op);
|
||||
if (loc.line == 0)
|
||||
loc = child->getLoc();
|
||||
node->setLoc(loc);
|
||||
node->setOperand(child);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
//
|
||||
// like non-type form, but sets node's type.
|
||||
//
|
||||
TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc loc, const TType& type) const
|
||||
{
|
||||
TIntermUnary* node = addUnaryNode(op, child, loc);
|
||||
node->setType(type);
|
||||
return node;
|
||||
}
|
||||
|
||||
//
|
||||
// Connect two nodes through an assignment.
|
||||
//
|
||||
|
|
@ -200,12 +244,7 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm
|
|||
right = addShapeConversion(op, left->getType(), right);
|
||||
|
||||
// build the node
|
||||
TIntermBinary* node = new TIntermBinary(op);
|
||||
if (loc.line == 0)
|
||||
loc = left->getLoc();
|
||||
node->setLoc(loc);
|
||||
node->setLeft(left);
|
||||
node->setRight(right);
|
||||
TIntermBinary* node = addBinaryNode(op, left, right, loc);
|
||||
|
||||
if (! node->promote())
|
||||
return nullptr;
|
||||
|
|
@ -224,16 +263,8 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm
|
|||
//
|
||||
TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc loc)
|
||||
{
|
||||
TIntermBinary* node = new TIntermBinary(op);
|
||||
if (loc.line == 0)
|
||||
loc = index->getLoc();
|
||||
node->setLoc(loc);
|
||||
node->setLeft(base);
|
||||
node->setRight(index);
|
||||
|
||||
// caller should set the type
|
||||
|
||||
return node;
|
||||
return addBinaryNode(op, base, index, loc);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -316,11 +347,7 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSo
|
|||
//
|
||||
// Make a new node for the operator.
|
||||
//
|
||||
TIntermUnary* node = new TIntermUnary(op);
|
||||
if (loc.line == 0)
|
||||
loc = child->getLoc();
|
||||
node->setLoc(loc);
|
||||
node->setOperand(child);
|
||||
TIntermUnary* node = addUnaryNode(op, child, loc);
|
||||
|
||||
if (! node->promote())
|
||||
return 0;
|
||||
|
|
@ -357,12 +384,7 @@ TIntermTyped* TIntermediate::addBuiltInFunctionCall(const TSourceLoc& loc, TOper
|
|||
return folded;
|
||||
}
|
||||
|
||||
TIntermUnary* node = new TIntermUnary(op);
|
||||
node->setLoc(child->getLoc());
|
||||
node->setOperand(child);
|
||||
node->setType(returnType);
|
||||
|
||||
return node;
|
||||
return addUnaryNode(op, child, child->getLoc(), returnType);
|
||||
} else {
|
||||
// setAggregateOperater() calls fold() for constant folding
|
||||
TIntermTyped* node = setAggregateOperator(childNode, op, returnType, loc);
|
||||
|
|
@ -725,9 +747,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
|
|||
}
|
||||
|
||||
TType newType(promoteTo, EvqTemporary, node->getVectorSize(), node->getMatrixCols(), node->getMatrixRows());
|
||||
newNode = new TIntermUnary(newOp, newType);
|
||||
newNode->setLoc(node->getLoc());
|
||||
newNode->setOperand(node);
|
||||
newNode = addUnaryNode(newOp, node, node->getLoc(), newType);
|
||||
|
||||
// TODO: it seems that some unary folding operations should occur here, but are not
|
||||
|
||||
|
|
|
|||
|
|
@ -113,6 +113,114 @@ void C_DECL TParseContextBase::ppWarn(const TSourceLoc& loc, const char* szReaso
|
|||
va_end(args);
|
||||
}
|
||||
|
||||
//
|
||||
// Both test and if necessary, spit out an error, to see if the node is really
|
||||
// an l-value that can be operated on this way.
|
||||
//
|
||||
// Returns true if there was an error.
|
||||
//
|
||||
bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
|
||||
{
|
||||
TIntermBinary* binaryNode = node->getAsBinaryNode();
|
||||
|
||||
if (binaryNode) {
|
||||
switch(binaryNode->getOp()) {
|
||||
case EOpIndexDirect:
|
||||
case EOpIndexIndirect: // fall through
|
||||
case EOpIndexDirectStruct: // fall through
|
||||
case EOpVectorSwizzle:
|
||||
return lValueErrorCheck(loc, op, binaryNode->getLeft());
|
||||
default:
|
||||
break;
|
||||
}
|
||||
error(loc, " l-value required", op, "", "");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* symbol = nullptr;
|
||||
TIntermSymbol* symNode = node->getAsSymbolNode();
|
||||
if (symNode != nullptr)
|
||||
symbol = symNode->getName().c_str();
|
||||
|
||||
const char* message = nullptr;
|
||||
switch (node->getQualifier().storage) {
|
||||
case EvqConst: message = "can't modify a const"; break;
|
||||
case EvqConstReadOnly: message = "can't modify a const"; break;
|
||||
case EvqUniform: message = "can't modify a uniform"; break;
|
||||
case EvqBuffer:
|
||||
if (node->getQualifier().readonly)
|
||||
message = "can't modify a readonly buffer";
|
||||
break;
|
||||
|
||||
default:
|
||||
//
|
||||
// Type that can't be written to?
|
||||
//
|
||||
switch (node->getBasicType()) {
|
||||
case EbtSampler:
|
||||
message = "can't modify a sampler";
|
||||
break;
|
||||
case EbtAtomicUint:
|
||||
message = "can't modify an atomic_uint";
|
||||
break;
|
||||
case EbtVoid:
|
||||
message = "can't modify void";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (message == nullptr && binaryNode == nullptr && symNode == nullptr) {
|
||||
error(loc, " l-value required", op, "", "");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Everything else is okay, no error.
|
||||
//
|
||||
if (message == nullptr)
|
||||
return false;
|
||||
|
||||
//
|
||||
// If we get here, we have an error and a message.
|
||||
//
|
||||
if (symNode)
|
||||
error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message);
|
||||
else
|
||||
error(loc, " l-value required", op, "(%s)", message);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test for and give an error if the node can't be read from.
|
||||
void TParseContextBase::rValueErrorCheck(const 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());
|
||||
}
|
||||
|
||||
// Make a shared symbol have a non-shared version that can be edited by the current
|
||||
// compile, such that editing its type will not change the shared version and will
|
||||
// effect all nodes sharing it.
|
||||
|
|
|
|||
|
|
@ -1902,14 +1902,14 @@ void TParseContext::variableCheck(TIntermTyped*& nodePtr)
|
|||
// Both test and if necessary, spit out an error, to see if the node is really
|
||||
// an l-value that can be operated on this way.
|
||||
//
|
||||
// Returns true if the was an error.
|
||||
// Returns true if there was an error.
|
||||
//
|
||||
bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
|
||||
{
|
||||
TIntermBinary* binaryNode = node->getAsBinaryNode();
|
||||
|
||||
if (binaryNode) {
|
||||
bool errorReturn;
|
||||
bool errorReturn = false;
|
||||
|
||||
switch(binaryNode->getOp()) {
|
||||
case EOpIndexDirect:
|
||||
|
|
@ -1928,9 +1928,9 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt
|
|||
}
|
||||
}
|
||||
|
||||
// fall through
|
||||
break; // left node is checked by base class
|
||||
case EOpIndexDirectStruct:
|
||||
return lValueErrorCheck(loc, op, binaryNode->getLeft());
|
||||
break; // left node is checked by base class
|
||||
case EOpVectorSwizzle:
|
||||
errorReturn = lValueErrorCheck(loc, op, binaryNode->getLeft());
|
||||
if (!errorReturn) {
|
||||
|
|
@ -1955,11 +1955,16 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt
|
|||
default:
|
||||
break;
|
||||
}
|
||||
error(loc, " l-value required", op, "", "");
|
||||
|
||||
return true;
|
||||
if (errorReturn) {
|
||||
error(loc, " l-value required", op, "", "");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Let the base class check errors
|
||||
if (TParseContextBase::lValueErrorCheck(loc, op, node))
|
||||
return true;
|
||||
|
||||
const char* symbol = nullptr;
|
||||
TIntermSymbol* symNode = node->getAsSymbolNode();
|
||||
|
|
@ -1968,19 +1973,12 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt
|
|||
|
||||
const char* message = nullptr;
|
||||
switch (node->getQualifier().storage) {
|
||||
case EvqConst: message = "can't modify a const"; break;
|
||||
case EvqConstReadOnly: message = "can't modify a const"; break;
|
||||
case EvqVaryingIn: message = "can't modify shader input"; break;
|
||||
case EvqInstanceId: message = "can't modify gl_InstanceID"; break;
|
||||
case EvqVertexId: message = "can't modify gl_VertexID"; break;
|
||||
case EvqFace: message = "can't modify gl_FrontFace"; break;
|
||||
case EvqFragCoord: message = "can't modify gl_FragCoord"; break;
|
||||
case EvqPointCoord: message = "can't modify gl_PointCoord"; break;
|
||||
case EvqUniform: message = "can't modify a uniform"; break;
|
||||
case EvqBuffer:
|
||||
if (node->getQualifier().readonly)
|
||||
message = "can't modify a readonly buffer";
|
||||
break;
|
||||
case EvqFragDepth:
|
||||
intermediate.setDepthReplacing();
|
||||
// "In addition, it is an error to statically write to gl_FragDepth in the fragment shader."
|
||||
|
|
@ -1989,22 +1987,7 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt
|
|||
break;
|
||||
|
||||
default:
|
||||
//
|
||||
// Type that can't be written to?
|
||||
//
|
||||
switch (node->getBasicType()) {
|
||||
case EbtSampler:
|
||||
message = "can't modify a sampler";
|
||||
break;
|
||||
case EbtAtomicUint:
|
||||
message = "can't modify an atomic_uint";
|
||||
break;
|
||||
case EbtVoid:
|
||||
message = "can't modify void";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (message == nullptr && binaryNode == nullptr && symNode == nullptr) {
|
||||
|
|
@ -2013,7 +1996,6 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Everything else is okay, no error.
|
||||
//
|
||||
|
|
@ -2034,30 +2016,14 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt
|
|||
// Test for and give an error if the node can't be read from.
|
||||
void TParseContext::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
|
||||
{
|
||||
if (! node)
|
||||
return;
|
||||
// Let the base class check errors
|
||||
TParseContextBase::rValueErrorCheck(loc, op, node);
|
||||
|
||||
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());
|
||||
#ifdef AMD_EXTENSIONS
|
||||
else if (symNode && symNode->getQualifier().explicitInterp)
|
||||
error(loc, "can't read from explicitly-interpolated object: ", op, symNode->getName().c_str());
|
||||
TIntermSymbol* symNode = node->getAsSymbolNode();
|
||||
if (!(symNode && symNode->getQualifier().writeonly)) // base class checks
|
||||
if (symNode && symNode->getQualifier().explicitInterp)
|
||||
error(loc, "can't read from explicitly-interpolated object: ", op, symNode->getName().c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -143,6 +143,9 @@ public:
|
|||
virtual void growGlobalUniformBlock(TSourceLoc&, TType&, TString& memberName);
|
||||
virtual bool insertGlobalUniformBlock();
|
||||
|
||||
virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
|
||||
virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
|
||||
|
||||
protected:
|
||||
TParseContextBase(TParseContextBase&);
|
||||
TParseContextBase& operator=(TParseContextBase&);
|
||||
|
|
@ -278,8 +281,8 @@ public:
|
|||
void unaryOpError(const TSourceLoc&, const char* op, TString operand);
|
||||
void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);
|
||||
void variableCheck(TIntermTyped*& nodePtr);
|
||||
bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
|
||||
void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
|
||||
bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
|
||||
void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
|
||||
void constantValueCheck(TIntermTyped* node, const char* token);
|
||||
void integerCheck(const TIntermTyped* node, const char* token);
|
||||
void globalCheck(const TSourceLoc&, const char* token);
|
||||
|
|
|
|||
|
|
@ -236,6 +236,13 @@ public:
|
|||
TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
|
||||
TIntermTyped* addSwizzle(TVectorFields&, const TSourceLoc&);
|
||||
|
||||
// Low level functions to add nodes (no conversions or other higher level transformations)
|
||||
// If a type is provided, the node's type will be set to it.
|
||||
TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc) const;
|
||||
TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, const TType&) const;
|
||||
TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc) const;
|
||||
TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc, const TType&) const;
|
||||
|
||||
// Constant folding (in Constant.cpp)
|
||||
TIntermTyped* fold(TIntermAggregate* aggrNode);
|
||||
TIntermTyped* foldConstructor(TIntermAggregate* aggrNode);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue