Commit f40319e9 by Olli Etuaho

Add basic support for array constructors

Add limited support for parsing array constructors and writing them out as GLSL code. Still missing from this version: HLSL output, array support in initializer lists, arrays with implicit size. BUG=angleproject:941 Change-Id: I7febf80923c4cd0b730399f1f49f9456cf3668e9 Reviewed-on: https://chromium-review.googlesource.com/260572Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarOlli Etuaho <oetuaho@nvidia.com>
parent 51a1db16
...@@ -221,6 +221,28 @@ const ConstantUnion *TOutputGLSLBase::writeConstantUnion( ...@@ -221,6 +221,28 @@ const ConstantUnion *TOutputGLSLBase::writeConstantUnion(
return pConstUnion; return pConstUnion;
} }
void TOutputGLSLBase::writeConstructorTriplet(Visit visit, const TType &type, const char *constructorBaseType)
{
TInfoSinkBase &out = objSink();
if (visit == PreVisit)
{
if (type.isArray())
{
out << constructorBaseType;
out << arrayBrackets(type);
out << "(";
}
else
{
out << constructorBaseType << "(";
}
}
else
{
writeTriplet(visit, nullptr, ", ", ")");
}
}
void TOutputGLSLBase::visitSymbol(TIntermSymbol *node) void TOutputGLSLBase::visitSymbol(TIntermSymbol *node)
{ {
TInfoSinkBase &out = objSink(); TInfoSinkBase &out = objSink();
...@@ -722,7 +744,6 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -722,7 +744,6 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
{ {
bool visitChildren = true; bool visitChildren = true;
TInfoSinkBase &out = objSink(); TInfoSinkBase &out = objSink();
TString preString;
bool useEmulatedFunction = (visit == PreVisit && node->getUseEmulatedFunction()); bool useEmulatedFunction = (visit == PreVisit && node->getUseEmulatedFunction());
switch (node->getOp()) switch (node->getOp())
{ {
...@@ -854,66 +875,58 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -854,66 +875,58 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
visitChildren = false; visitChildren = false;
break; break;
case EOpConstructFloat: case EOpConstructFloat:
writeTriplet(visit, "float(", NULL, ")"); writeConstructorTriplet(visit, node->getType(), "float");
break; break;
case EOpConstructVec2: case EOpConstructVec2:
writeBuiltInFunctionTriplet(visit, "vec2(", false); writeConstructorTriplet(visit, node->getType(), "vec2");
break; break;
case EOpConstructVec3: case EOpConstructVec3:
writeBuiltInFunctionTriplet(visit, "vec3(", false); writeConstructorTriplet(visit, node->getType(), "vec3");
break; break;
case EOpConstructVec4: case EOpConstructVec4:
writeBuiltInFunctionTriplet(visit, "vec4(", false); writeConstructorTriplet(visit, node->getType(), "vec4");
break; break;
case EOpConstructBool: case EOpConstructBool:
writeTriplet(visit, "bool(", NULL, ")"); writeConstructorTriplet(visit, node->getType(), "bool");
break; break;
case EOpConstructBVec2: case EOpConstructBVec2:
writeBuiltInFunctionTriplet(visit, "bvec2(", false); writeConstructorTriplet(visit, node->getType(), "bvec2");
break; break;
case EOpConstructBVec3: case EOpConstructBVec3:
writeBuiltInFunctionTriplet(visit, "bvec3(", false); writeConstructorTriplet(visit, node->getType(), "bvec3");
break; break;
case EOpConstructBVec4: case EOpConstructBVec4:
writeBuiltInFunctionTriplet(visit, "bvec4(", false); writeConstructorTriplet(visit, node->getType(), "bvec4");
break; break;
case EOpConstructInt: case EOpConstructInt:
writeTriplet(visit, "int(", NULL, ")"); writeConstructorTriplet(visit, node->getType(), "int");
break; break;
case EOpConstructIVec2: case EOpConstructIVec2:
writeBuiltInFunctionTriplet(visit, "ivec2(", false); writeConstructorTriplet(visit, node->getType(), "ivec2");
break; break;
case EOpConstructIVec3: case EOpConstructIVec3:
writeBuiltInFunctionTriplet(visit, "ivec3(", false); writeConstructorTriplet(visit, node->getType(), "ivec3");
break; break;
case EOpConstructIVec4: case EOpConstructIVec4:
writeBuiltInFunctionTriplet(visit, "ivec4(", false); writeConstructorTriplet(visit, node->getType(), "ivec4");
break; break;
case EOpConstructMat2: case EOpConstructMat2:
writeBuiltInFunctionTriplet(visit, "mat2(", false); writeConstructorTriplet(visit, node->getType(), "mat2");
break; break;
case EOpConstructMat3: case EOpConstructMat3:
writeBuiltInFunctionTriplet(visit, "mat3(", false); writeConstructorTriplet(visit, node->getType(), "mat3");
break; break;
case EOpConstructMat4: case EOpConstructMat4:
writeBuiltInFunctionTriplet(visit, "mat4(", false); writeConstructorTriplet(visit, node->getType(), "mat4");
break; break;
case EOpConstructStruct: case EOpConstructStruct:
if (visit == PreVisit)
{ {
const TType &type = node->getType(); const TType &type = node->getType();
ASSERT(type.getBasicType() == EbtStruct); ASSERT(type.getBasicType() == EbtStruct);
out << hashName(type.getStruct()->name()) << "("; TString constructorName = hashName(type.getStruct()->name());
} writeConstructorTriplet(visit, node->getType(), constructorName.c_str());
else if (visit == InVisit) break;
{
out << ", ";
}
else
{
out << ")";
} }
break;
case EOpOuterProduct: case EOpOuterProduct:
writeBuiltInFunctionTriplet(visit, "outerProduct(", useEmulatedFunction); writeBuiltInFunctionTriplet(visit, "outerProduct(", useEmulatedFunction);
......
...@@ -36,6 +36,7 @@ class TOutputGLSLBase : public TIntermTraverser ...@@ -36,6 +36,7 @@ class TOutputGLSLBase : public TIntermTraverser
virtual bool writeVariablePrecision(TPrecision precision) = 0; virtual bool writeVariablePrecision(TPrecision precision) = 0;
void writeFunctionParameters(const TIntermSequence &args); void writeFunctionParameters(const TIntermSequence &args);
const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *pConstUnion); const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *pConstUnion);
void writeConstructorTriplet(Visit visit, const TType &type, const char *constructorBaseType);
TString getTypeName(const TType &type); TString getTypeName(const TType &type);
virtual void visitSymbol(TIntermSymbol *node); virtual void visitSymbol(TIntermSymbol *node);
......
...@@ -2202,6 +2202,10 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -2202,6 +2202,10 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpConstructMat4: outputConstructor(visit, node->getType(), "mat4", node->getSequence()); break; case EOpConstructMat4: outputConstructor(visit, node->getType(), "mat4", node->getSequence()); break;
case EOpConstructStruct: case EOpConstructStruct:
{ {
if (node->getType().isArray())
{
UNIMPLEMENTED();
}
const TString &structName = StructNameString(*node->getType().getStruct()); const TString &structName = StructNameString(*node->getType().getStruct());
mStructureHLSL->addConstructor(node->getType(), structName, node->getSequence()); mStructureHLSL->addConstructor(node->getType(), structName, node->getSequence());
outputTriplet(visit, (structName + "_ctor(").c_str(), ", ", ")"); outputTriplet(visit, (structName + "_ctor(").c_str(), ", ", ")");
...@@ -2829,6 +2833,10 @@ TString OutputHLSL::initializer(const TType &type) ...@@ -2829,6 +2833,10 @@ TString OutputHLSL::initializer(const TType &type)
void OutputHLSL::outputConstructor(Visit visit, const TType &type, const char *name, const TIntermSequence *parameters) void OutputHLSL::outputConstructor(Visit visit, const TType &type, const char *name, const TIntermSequence *parameters)
{ {
if (type.isArray())
{
UNIMPLEMENTED();
}
TInfoSinkBase &out = getInfoSink(); TInfoSinkBase &out = getInfoSink();
if (visit == PreVisit) if (visit == PreVisit)
......
...@@ -1651,7 +1651,24 @@ TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, TType *type, ...@@ -1651,7 +1651,24 @@ TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, TType *type,
aggregateArguments->getSequence()->push_back(arguments); aggregateArguments->getSequence()->push_back(arguments);
} }
if (op == EOpConstructStruct) if (type->isArray())
{
// GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of the array.
TIntermSequence *args = aggregateArguments->getSequence();
for (size_t i = 0; i < args->size(); i++)
{
const TType &argType = (*args)[i]->getAsTyped()->getType();
// It has already been checked that the argument is not an array.
ASSERT(!argType.isArray());
if (!argType.sameElementType(*type))
{
error(line, "Array constructor argument has an incorrect type", "Error");
recover();
return nullptr;
}
}
}
else if (op == EOpConstructStruct)
{ {
const TFieldList &fields = type->getStruct()->fields(); const TFieldList &fields = type->getStruct()->fields();
TIntermSequence *args = aggregateArguments->getSequence(); TIntermSequence *args = aggregateArguments->getSequence();
...@@ -1689,7 +1706,8 @@ TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, TType *type, ...@@ -1689,7 +1706,8 @@ TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, TType *type,
TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type) TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type)
{ {
bool canBeFolded = areAllChildConst(aggrNode); // TODO: Add support for folding array constructors
bool canBeFolded = areAllChildConst(aggrNode) && !type.isArray();
aggrNode->setType(type); aggrNode->setType(type);
if (canBeFolded) { if (canBeFolded) {
bool returnVal = false; bool returnVal = false;
......
...@@ -358,7 +358,10 @@ function_call_header ...@@ -358,7 +358,10 @@ function_call_header
// Grammar Note: Constructors look like functions, but are recognized as types. // Grammar Note: Constructors look like functions, but are recognized as types.
function_identifier function_identifier
: type_specifier_nonarray { : type_specifier_no_prec {
if ($1.array) {
ES3_ONLY("[]", @1, "array constructor");
}
$$ = context->addConstructorFunc($1); $$ = context->addConstructorFunc($1);
} }
| IDENTIFIER { | IDENTIFIER {
...@@ -929,9 +932,10 @@ fully_specified_type ...@@ -929,9 +932,10 @@ fully_specified_type
$$ = $1; $$ = $1;
if ($1.array) { if ($1.array) {
context->error(@1, "not supported", "first-class array"); ES3_ONLY("[]", @1, "first-class-array");
context->recover(); if (context->shaderVersion != 300) {
$1.setArray(false); $1.setArray(false);
}
} }
} }
| type_qualifier type_specifier { | type_qualifier type_specifier {
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#line 25 "./glslang_lex.cpp" #line 26 "./glslang_lex.cpp"
#define YY_INT_ALIGNED short int #define YY_INT_ALIGNED short int
......
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