Commit f042e407 by John Kessenich Committed by GitHub

Merge pull request #542 from steve-lunarg/rwbuffers

HLSL: phase 2: add operator[]
parents e4ad1bb6 b3da8a9c
This source diff could not be displayed because it is too large. You can view the blob instead.
SamplerState g_sSamp : register(s0);
RWTexture1D <float4> g_tTex1df4 : register(t0);
RWTexture1D <int4> g_tTex1di4;
RWTexture1D <uint4> g_tTex1du4;
RWTexture2D <float4> g_tTex2df4;
RWTexture2D <int4> g_tTex2di4;
RWTexture2D <uint4> g_tTex2du4;
RWTexture3D <float4> g_tTex3df4;
RWTexture3D <int4> g_tTex3di4;
RWTexture3D <uint4> g_tTex3du4;
RWTexture1DArray <float4> g_tTex1df4a;
RWTexture1DArray <int4> g_tTex1di4a;
RWTexture1DArray <uint4> g_tTex1du4a;
RWTexture2DArray <float4> g_tTex2df4a;
RWTexture2DArray <int4> g_tTex2di4a;
RWTexture2DArray <uint4> g_tTex2du4a;
struct PS_OUTPUT
{
float4 Color : SV_Target0;
};
uniform int c1;
uniform int2 c2;
uniform int3 c3;
uniform int4 c4;
uniform int o1;
uniform int2 o2;
uniform int3 o3;
uniform int4 o4;
uniform float4 uf4;
uniform int4 ui4;
uniform uint4 uu4;
int4 Fn1(in int4 x) { return x; }
uint4 Fn1(in uint4 x) { return x; }
float4 Fn1(in float4 x) { return x; }
void Fn2(out int4 x) { x = int4(0); }
void Fn2(out uint4 x) { x = uint4(0); }
void Fn2(out float4 x) { x = float4(0); }
float4 SomeValue() { return c4; }
PS_OUTPUT main()
{
PS_OUTPUT psout;
// 1D
g_tTex1df4[c1];
float4 r00 = g_tTex1df4[c1];
int4 r01 = g_tTex1di4[c1];
uint4 r02 = g_tTex1du4[c1];
// 2D
float4 r10 = g_tTex2df4[c2];
int4 r11 = g_tTex2di4[c2];
uint4 r12 = g_tTex2du4[c2];
// 3D
float4 r20 = g_tTex3df4[c3];
int4 r21 = g_tTex3di4[c3];
uint4 r22 = g_tTex3du4[c3];
float4 lf4 = uf4;
// Test as L-values
// 1D
g_tTex1df4[c1] = SomeValue(); // complex R-value
g_tTex1df4[c1] = lf4;
g_tTex1di4[c1] = int4(2,2,3,4);
g_tTex1du4[c1] = uint4(3,2,3,4);
// Test some operator= things, which need to do both a load and a store.
float4 val1 = (g_tTex1df4[c1] *= 2.0);
g_tTex1df4[c1] -= 3.0;
g_tTex1df4[c1] += 4.0;
g_tTex1di4[c1] /= 2;
g_tTex1di4[c1] %= 2;
g_tTex1di4[c1] &= 0xffff;
g_tTex1di4[c1] |= 0xf0f0;
g_tTex1di4[c1] <<= 2;
g_tTex1di4[c1] >>= 2;
// 2D
g_tTex2df4[c2] = SomeValue(); // complex L-value
g_tTex2df4[c2] = lf4;
g_tTex2di4[c2] = int4(5,2,3,4);
g_tTex2du4[c2] = uint4(6,2,3,4);
// 3D
g_tTex3df4[c3] = SomeValue(); // complex L-value
g_tTex3df4[c3] = lf4;
g_tTex3di4[c3] = int4(8,6,7,8);
g_tTex3du4[c3] = uint4(9,2,3,4);
// Test function calling
Fn1(g_tTex1df4[c1]); // in
Fn1(g_tTex1di4[c1]); // in
Fn1(g_tTex1du4[c1]); // in
Fn2(g_tTex1df4[c1]); // out
Fn2(g_tTex1di4[c1]); // out
Fn2(g_tTex1du4[c1]); // out
// Test increment operators
// pre-ops
++g_tTex1df4[c1];
++g_tTex1di4[c1];
++g_tTex1du4[c1];
--g_tTex1df4[c1];
--g_tTex1di4[c1];
--g_tTex1du4[c1];
// post-ops
g_tTex1df4[c1]++;
g_tTex1du4[c1]--;
g_tTex1di4[c1]++;
g_tTex1df4[c1]--;
g_tTex1di4[c1]++;
g_tTex1du4[c1]--;
// read and write
g_tTex1df4[1] = g_tTex2df4[int2(2,3)];
psout.Color = 1.0;
return psout;
}
...@@ -12,7 +12,7 @@ struct myS { ...@@ -12,7 +12,7 @@ struct myS {
myS s1; myS s1;
struct { static struct {
float4 i; float4 i;
} s2; } s2;
...@@ -40,4 +40,4 @@ float4 PixelShaderFunction(float4 input, IN_S s) : COLOR0 ...@@ -40,4 +40,4 @@ float4 PixelShaderFunction(float4 input, IN_S s) : COLOR0
s2.i = s.ff4; s2.i = s.ff4;
return input; return input;
} }
\ No newline at end of file
SamplerState g_sSamp : register(s0);
Texture1D <float4> g_tTex1df4 : register(t0);
Texture1D <int4> g_tTex1di4;
Texture1D <uint4> g_tTex1du4;
Texture2D <float4> g_tTex2df4;
Texture2D <int4> g_tTex2di4;
Texture2D <uint4> g_tTex2du4;
Texture3D <float4> g_tTex3df4;
Texture3D <int4> g_tTex3di4;
Texture3D <uint4> g_tTex3du4;
Texture1DArray <float4> g_tTex1df4a;
Texture1DArray <int4> g_tTex1di4a;
Texture1DArray <uint4> g_tTex1du4a;
Texture2DArray <float4> g_tTex2df4a;
Texture2DArray <int4> g_tTex2di4a;
Texture2DArray <uint4> g_tTex2du4a;
struct PS_OUTPUT
{
float4 Color : SV_Target0;
};
uniform int c1;
uniform int2 c2;
uniform int3 c3;
uniform int4 c4;
uniform int o1;
uniform int2 o2;
uniform int3 o3;
uniform int4 o4;
int4 Fn1(in int4 x) { return x; }
uint4 Fn1(in uint4 x) { return x; }
float4 Fn1(in float4 x) { return x; }
float4 SomeValue() { return c4; }
PS_OUTPUT main()
{
PS_OUTPUT psout;
// 1D
g_tTex1df4[c1];
float4 r00 = g_tTex1df4[c1];
int4 r01 = g_tTex1di4[c1];
uint4 r02 = g_tTex1du4[c1];
// 2D
float4 r10 = g_tTex2df4[c2];
int4 r11 = g_tTex2di4[c2];
uint4 r12 = g_tTex2du4[c2];
// 3D
float4 r20 = g_tTex3df4[c3];
int4 r21 = g_tTex3di4[c3];
uint4 r22 = g_tTex3du4[c3];
// Test function calling
Fn1(g_tTex1df4[c1]); // in
Fn1(g_tTex1di4[c1]); // in
Fn1(g_tTex1du4[c1]); // in
psout.Color = 1.0;
return psout;
}
...@@ -136,13 +136,7 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn ...@@ -136,13 +136,7 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
// Need a new node holding things together. Make // Need a new node holding things together. Make
// one and promote it to the right type. // one and promote it to the right type.
// //
TIntermBinary* node = new TIntermBinary(op); TIntermBinary* node = addBinaryNode(op, left, right, loc);
if (loc.line == 0)
loc = right->getLoc();
node->setLoc(loc);
node->setLeft(left);
node->setRight(right);
if (! node->promote()) if (! node->promote())
return 0; return 0;
...@@ -173,6 +167,56 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn ...@@ -173,6 +167,56 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
} }
// //
// 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. // Connect two nodes through an assignment.
// //
// Returns the added node. // Returns the added node.
...@@ -200,12 +244,7 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm ...@@ -200,12 +244,7 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm
right = addShapeConversion(op, left->getType(), right); right = addShapeConversion(op, left->getType(), right);
// build the node // build the node
TIntermBinary* node = new TIntermBinary(op); TIntermBinary* node = addBinaryNode(op, left, right, loc);
if (loc.line == 0)
loc = left->getLoc();
node->setLoc(loc);
node->setLeft(left);
node->setRight(right);
if (! node->promote()) if (! node->promote())
return nullptr; return nullptr;
...@@ -224,16 +263,8 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm ...@@ -224,16 +263,8 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm
// //
TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc loc) 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 // caller should set the type
return addBinaryNode(op, base, index, loc);
return node;
} }
// //
...@@ -316,11 +347,7 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSo ...@@ -316,11 +347,7 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSo
// //
// Make a new node for the operator. // Make a new node for the operator.
// //
TIntermUnary* node = new TIntermUnary(op); TIntermUnary* node = addUnaryNode(op, child, loc);
if (loc.line == 0)
loc = child->getLoc();
node->setLoc(loc);
node->setOperand(child);
if (! node->promote()) if (! node->promote())
return 0; return 0;
...@@ -357,12 +384,7 @@ TIntermTyped* TIntermediate::addBuiltInFunctionCall(const TSourceLoc& loc, TOper ...@@ -357,12 +384,7 @@ TIntermTyped* TIntermediate::addBuiltInFunctionCall(const TSourceLoc& loc, TOper
return folded; return folded;
} }
TIntermUnary* node = new TIntermUnary(op); return addUnaryNode(op, child, child->getLoc(), returnType);
node->setLoc(child->getLoc());
node->setOperand(child);
node->setType(returnType);
return node;
} else { } else {
// setAggregateOperater() calls fold() for constant folding // setAggregateOperater() calls fold() for constant folding
TIntermTyped* node = setAggregateOperator(childNode, op, returnType, loc); TIntermTyped* node = setAggregateOperator(childNode, op, returnType, loc);
...@@ -725,9 +747,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt ...@@ -725,9 +747,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
} }
TType newType(promoteTo, EvqTemporary, node->getVectorSize(), node->getMatrixCols(), node->getMatrixRows()); TType newType(promoteTo, EvqTemporary, node->getVectorSize(), node->getMatrixCols(), node->getMatrixRows());
newNode = new TIntermUnary(newOp, newType); newNode = addUnaryNode(newOp, node, node->getLoc(), newType);
newNode->setLoc(node->getLoc());
newNode->setOperand(node);
// TODO: it seems that some unary folding operations should occur here, but are not // 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 ...@@ -113,6 +113,114 @@ void C_DECL TParseContextBase::ppWarn(const TSourceLoc& loc, const char* szReaso
va_end(args); 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 // 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 // compile, such that editing its type will not change the shared version and will
// effect all nodes sharing it. // effect all nodes sharing it.
......
...@@ -1902,14 +1902,14 @@ void TParseContext::variableCheck(TIntermTyped*& nodePtr) ...@@ -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 // 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. // 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) bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
{ {
TIntermBinary* binaryNode = node->getAsBinaryNode(); TIntermBinary* binaryNode = node->getAsBinaryNode();
if (binaryNode) { if (binaryNode) {
bool errorReturn; bool errorReturn = false;
switch(binaryNode->getOp()) { switch(binaryNode->getOp()) {
case EOpIndexDirect: case EOpIndexDirect:
...@@ -1928,9 +1928,9 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt ...@@ -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: case EOpIndexDirectStruct:
return lValueErrorCheck(loc, op, binaryNode->getLeft()); break; // left node is checked by base class
case EOpVectorSwizzle: case EOpVectorSwizzle:
errorReturn = lValueErrorCheck(loc, op, binaryNode->getLeft()); errorReturn = lValueErrorCheck(loc, op, binaryNode->getLeft());
if (!errorReturn) { if (!errorReturn) {
...@@ -1955,11 +1955,16 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt ...@@ -1955,11 +1955,16 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt
default: default:
break; 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; const char* symbol = nullptr;
TIntermSymbol* symNode = node->getAsSymbolNode(); TIntermSymbol* symNode = node->getAsSymbolNode();
...@@ -1968,19 +1973,12 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt ...@@ -1968,19 +1973,12 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt
const char* message = nullptr; const char* message = nullptr;
switch (node->getQualifier().storage) { 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 EvqVaryingIn: message = "can't modify shader input"; break;
case EvqInstanceId: message = "can't modify gl_InstanceID"; break; case EvqInstanceId: message = "can't modify gl_InstanceID"; break;
case EvqVertexId: message = "can't modify gl_VertexID"; break; case EvqVertexId: message = "can't modify gl_VertexID"; break;
case EvqFace: message = "can't modify gl_FrontFace"; break; case EvqFace: message = "can't modify gl_FrontFace"; break;
case EvqFragCoord: message = "can't modify gl_FragCoord"; break; case EvqFragCoord: message = "can't modify gl_FragCoord"; break;
case EvqPointCoord: message = "can't modify gl_PointCoord"; 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: case EvqFragDepth:
intermediate.setDepthReplacing(); intermediate.setDepthReplacing();
// "In addition, it is an error to statically write to gl_FragDepth in the fragment shader." // "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 ...@@ -1989,22 +1987,7 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt
break; break;
default: default:
// break;
// 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) { if (message == nullptr && binaryNode == nullptr && symNode == nullptr) {
...@@ -2013,7 +1996,6 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt ...@@ -2013,7 +1996,6 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt
return true; return true;
} }
// //
// Everything else is okay, no error. // Everything else is okay, no error.
// //
...@@ -2034,30 +2016,14 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt ...@@ -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. // 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) void TParseContext::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
{ {
if (! node) // Let the base class check errors
return; 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 #ifdef AMD_EXTENSIONS
else if (symNode && symNode->getQualifier().explicitInterp) TIntermSymbol* symNode = node->getAsSymbolNode();
error(loc, "can't read from explicitly-interpolated object: ", op, symNode->getName().c_str()); 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 #endif
} }
......
...@@ -143,6 +143,9 @@ public: ...@@ -143,6 +143,9 @@ public:
virtual void growGlobalUniformBlock(TSourceLoc&, TType&, TString& memberName); virtual void growGlobalUniformBlock(TSourceLoc&, TType&, TString& memberName);
virtual bool insertGlobalUniformBlock(); virtual bool insertGlobalUniformBlock();
virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
protected: protected:
TParseContextBase(TParseContextBase&); TParseContextBase(TParseContextBase&);
TParseContextBase& operator=(TParseContextBase&); TParseContextBase& operator=(TParseContextBase&);
...@@ -278,8 +281,8 @@ public: ...@@ -278,8 +281,8 @@ public:
void unaryOpError(const TSourceLoc&, const char* op, TString operand); void unaryOpError(const TSourceLoc&, const char* op, TString operand);
void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right); void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);
void variableCheck(TIntermTyped*& nodePtr); void variableCheck(TIntermTyped*& nodePtr);
bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*); bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*); void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
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(const TSourceLoc&, const char* token); void globalCheck(const TSourceLoc&, const char* token);
......
...@@ -236,6 +236,13 @@ public: ...@@ -236,6 +236,13 @@ public:
TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&); TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
TIntermTyped* addSwizzle(TVectorFields&, 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) // Constant folding (in Constant.cpp)
TIntermTyped* fold(TIntermAggregate* aggrNode); TIntermTyped* fold(TIntermAggregate* aggrNode);
TIntermTyped* foldConstructor(TIntermAggregate* aggrNode); TIntermTyped* foldConstructor(TIntermAggregate* aggrNode);
......
...@@ -147,6 +147,7 @@ INSTANTIATE_TEST_CASE_P( ...@@ -147,6 +147,7 @@ INSTANTIATE_TEST_CASE_P(
{"hlsl.pp.line.frag", "main"}, {"hlsl.pp.line.frag", "main"},
{"hlsl.precise.frag", "main"}, {"hlsl.precise.frag", "main"},
{"hlsl.promotions.frag", "main"}, {"hlsl.promotions.frag", "main"},
{"hlsl.rw.bracket.frag", "main"},
{"hlsl.sample.array.dx10.frag", "main"}, {"hlsl.sample.array.dx10.frag", "main"},
{"hlsl.sample.basic.dx10.frag", "main"}, {"hlsl.sample.basic.dx10.frag", "main"},
{"hlsl.sample.offset.dx10.frag", "main"}, {"hlsl.sample.offset.dx10.frag", "main"},
...@@ -190,6 +191,7 @@ INSTANTIATE_TEST_CASE_P( ...@@ -190,6 +191,7 @@ INSTANTIATE_TEST_CASE_P(
{"hlsl.switch.frag", "PixelShaderFunction"}, {"hlsl.switch.frag", "PixelShaderFunction"},
{"hlsl.swizzle.frag", "PixelShaderFunction"}, {"hlsl.swizzle.frag", "PixelShaderFunction"},
{"hlsl.templatetypes.frag", "PixelShaderFunction"}, {"hlsl.templatetypes.frag", "PixelShaderFunction"},
{"hlsl.tx.bracket.frag", "main"},
{"hlsl.typedef.frag", "PixelShaderFunction"}, {"hlsl.typedef.frag", "PixelShaderFunction"},
{"hlsl.whileLoop.frag", "PixelShaderFunction"}, {"hlsl.whileLoop.frag", "PixelShaderFunction"},
{"hlsl.void.frag", "PixelShaderFunction"}, {"hlsl.void.frag", "PixelShaderFunction"},
......
...@@ -1783,6 +1783,8 @@ bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node) ...@@ -1783,6 +1783,8 @@ bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node)
} }
node = parseContext.handleAssign(loc, assignOp, node, rightNode); node = parseContext.handleAssign(loc, assignOp, node, rightNode);
node = parseContext.handleLvalue(loc, "assign", node);
if (node == nullptr) { if (node == nullptr) {
parseContext.error(loc, "could not create assignment", "", ""); parseContext.error(loc, "could not create assignment", "", "");
return false; return false;
...@@ -1946,6 +1948,7 @@ bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node) ...@@ -1946,6 +1948,7 @@ bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
return true; return true;
node = intermediate.addUnaryMath(unaryOp, node, loc); node = intermediate.addUnaryMath(unaryOp, node, loc);
node = parseContext.handleLvalue(loc, "unary operator", node);
return node != nullptr; return node != nullptr;
} }
...@@ -2061,6 +2064,7 @@ bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node) ...@@ -2061,6 +2064,7 @@ bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node)
case EOpPostDecrement: case EOpPostDecrement:
// DEC_OP // DEC_OP
node = intermediate.addUnaryMath(postOp, node, loc); node = intermediate.addUnaryMath(postOp, node, loc);
node = parseContext.handleLvalue(loc, "unary operator", node);
break; break;
default: default:
assert(0); assert(0);
......
...@@ -61,6 +61,7 @@ public: ...@@ -61,6 +61,7 @@ public:
void handlePragma(const TSourceLoc&, const TVector<TString>&); void handlePragma(const TSourceLoc&, const TVector<TString>&);
TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol, const TString* string); TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol, const TString* string);
TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
TIntermTyped* handleBracketOperator(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
void checkIndex(const TSourceLoc&, const TType&, int& index); void checkIndex(const TSourceLoc&, const TType&, int& index);
TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right); TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
...@@ -80,7 +81,7 @@ public: ...@@ -80,7 +81,7 @@ public:
void decomposeSampleMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments); void decomposeSampleMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*); TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
void addInputArgumentConversions(const TFunction&, TIntermNode*&) const; void addInputArgumentConversions(const TFunction&, TIntermNode*&) const;
TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const; TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&);
void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&); void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
TFunction* handleConstructorCall(const TSourceLoc&, const TType&); TFunction* handleConstructorCall(const TSourceLoc&, const TType&);
void handleSemantic(TSourceLoc, TQualifier&, const TString& semantic); void handleSemantic(TSourceLoc, TQualifier&, const TString& semantic);
...@@ -151,6 +152,10 @@ public: ...@@ -151,6 +152,10 @@ public:
void pushSwitchSequence(TIntermSequence* sequence) { switchSequenceStack.push_back(sequence); } void pushSwitchSequence(TIntermSequence* sequence) { switchSequenceStack.push_back(sequence); }
void popSwitchSequence() { switchSequenceStack.pop_back(); } void popSwitchSequence() { switchSequenceStack.pop_back(); }
// Apply L-value conversions. E.g, turning a write to a RWTexture into an ImageStore.
TIntermTyped* handleLvalue(const TSourceLoc&, const char* op, TIntermTyped* node);
bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
protected: protected:
void inheritGlobalDefaults(TQualifier& dst) const; void inheritGlobalDefaults(TQualifier& dst) const;
TVariable* makeInternalVariable(const char* name, const TType&) const; TVariable* makeInternalVariable(const char* name, const TType&) const;
...@@ -160,6 +165,9 @@ protected: ...@@ -160,6 +165,9 @@ protected:
TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer); TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer);
TOperator mapAtomicOp(const TSourceLoc& loc, TOperator op, bool isImage); TOperator mapAtomicOp(const TSourceLoc& loc, TOperator op, bool isImage);
// Return true if this node requires L-value conversion (e.g, to an imageStore).
bool shouldConvertLValue(const TIntermNode*) const;
// Array and struct flattening // Array and struct flattening
bool shouldFlatten(const TType& type) const { return shouldFlattenIO(type) || shouldFlattenUniform(type); } bool shouldFlatten(const TType& type) const { return shouldFlattenIO(type) || shouldFlattenUniform(type); }
TIntermTyped* flattenAccess(TIntermTyped* base, int member); TIntermTyped* flattenAccess(TIntermTyped* base, int member);
......
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