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(
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)
{
TInfoSinkBase &out = objSink();
......@@ -722,7 +744,6 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
{
bool visitChildren = true;
TInfoSinkBase &out = objSink();
TString preString;
bool useEmulatedFunction = (visit == PreVisit && node->getUseEmulatedFunction());
switch (node->getOp())
{
......@@ -854,66 +875,58 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
visitChildren = false;
break;
case EOpConstructFloat:
writeTriplet(visit, "float(", NULL, ")");
writeConstructorTriplet(visit, node->getType(), "float");
break;
case EOpConstructVec2:
writeBuiltInFunctionTriplet(visit, "vec2(", false);
writeConstructorTriplet(visit, node->getType(), "vec2");
break;
case EOpConstructVec3:
writeBuiltInFunctionTriplet(visit, "vec3(", false);
writeConstructorTriplet(visit, node->getType(), "vec3");
break;
case EOpConstructVec4:
writeBuiltInFunctionTriplet(visit, "vec4(", false);
writeConstructorTriplet(visit, node->getType(), "vec4");
break;
case EOpConstructBool:
writeTriplet(visit, "bool(", NULL, ")");
writeConstructorTriplet(visit, node->getType(), "bool");
break;
case EOpConstructBVec2:
writeBuiltInFunctionTriplet(visit, "bvec2(", false);
writeConstructorTriplet(visit, node->getType(), "bvec2");
break;
case EOpConstructBVec3:
writeBuiltInFunctionTriplet(visit, "bvec3(", false);
writeConstructorTriplet(visit, node->getType(), "bvec3");
break;
case EOpConstructBVec4:
writeBuiltInFunctionTriplet(visit, "bvec4(", false);
writeConstructorTriplet(visit, node->getType(), "bvec4");
break;
case EOpConstructInt:
writeTriplet(visit, "int(", NULL, ")");
writeConstructorTriplet(visit, node->getType(), "int");
break;
case EOpConstructIVec2:
writeBuiltInFunctionTriplet(visit, "ivec2(", false);
writeConstructorTriplet(visit, node->getType(), "ivec2");
break;
case EOpConstructIVec3:
writeBuiltInFunctionTriplet(visit, "ivec3(", false);
writeConstructorTriplet(visit, node->getType(), "ivec3");
break;
case EOpConstructIVec4:
writeBuiltInFunctionTriplet(visit, "ivec4(", false);
writeConstructorTriplet(visit, node->getType(), "ivec4");
break;
case EOpConstructMat2:
writeBuiltInFunctionTriplet(visit, "mat2(", false);
writeConstructorTriplet(visit, node->getType(), "mat2");
break;
case EOpConstructMat3:
writeBuiltInFunctionTriplet(visit, "mat3(", false);
writeConstructorTriplet(visit, node->getType(), "mat3");
break;
case EOpConstructMat4:
writeBuiltInFunctionTriplet(visit, "mat4(", false);
writeConstructorTriplet(visit, node->getType(), "mat4");
break;
case EOpConstructStruct:
if (visit == PreVisit)
{
const TType &type = node->getType();
ASSERT(type.getBasicType() == EbtStruct);
out << hashName(type.getStruct()->name()) << "(";
}
else if (visit == InVisit)
{
out << ", ";
}
else
{
out << ")";
TString constructorName = hashName(type.getStruct()->name());
writeConstructorTriplet(visit, node->getType(), constructorName.c_str());
break;
}
break;
case EOpOuterProduct:
writeBuiltInFunctionTriplet(visit, "outerProduct(", useEmulatedFunction);
......
......@@ -36,6 +36,7 @@ class TOutputGLSLBase : public TIntermTraverser
virtual bool writeVariablePrecision(TPrecision precision) = 0;
void writeFunctionParameters(const TIntermSequence &args);
const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *pConstUnion);
void writeConstructorTriplet(Visit visit, const TType &type, const char *constructorBaseType);
TString getTypeName(const TType &type);
virtual void visitSymbol(TIntermSymbol *node);
......
......@@ -2202,6 +2202,10 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpConstructMat4: outputConstructor(visit, node->getType(), "mat4", node->getSequence()); break;
case EOpConstructStruct:
{
if (node->getType().isArray())
{
UNIMPLEMENTED();
}
const TString &structName = StructNameString(*node->getType().getStruct());
mStructureHLSL->addConstructor(node->getType(), structName, node->getSequence());
outputTriplet(visit, (structName + "_ctor(").c_str(), ", ", ")");
......@@ -2829,6 +2833,10 @@ TString OutputHLSL::initializer(const TType &type)
void OutputHLSL::outputConstructor(Visit visit, const TType &type, const char *name, const TIntermSequence *parameters)
{
if (type.isArray())
{
UNIMPLEMENTED();
}
TInfoSinkBase &out = getInfoSink();
if (visit == PreVisit)
......
......@@ -1651,7 +1651,24 @@ TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, TType *type,
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();
TIntermSequence *args = aggregateArguments->getSequence();
......@@ -1689,7 +1706,8 @@ TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, 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);
if (canBeFolded) {
bool returnVal = false;
......
......@@ -358,7 +358,10 @@ function_call_header
// Grammar Note: Constructors look like functions, but are recognized as types.
function_identifier
: type_specifier_nonarray {
: type_specifier_no_prec {
if ($1.array) {
ES3_ONLY("[]", @1, "array constructor");
}
$$ = context->addConstructorFunc($1);
}
| IDENTIFIER {
......@@ -929,9 +932,10 @@ fully_specified_type
$$ = $1;
if ($1.array) {
context->error(@1, "not supported", "first-class array");
context->recover();
$1.setArray(false);
ES3_ONLY("[]", @1, "first-class-array");
if (context->shaderVersion != 300) {
$1.setArray(false);
}
}
}
| type_qualifier type_specifier {
......
......@@ -22,7 +22,7 @@
#line 25 "./glslang_lex.cpp"
#line 26 "./glslang_lex.cpp"
#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