Commit 9638c352 by Olli Etuaho

Support assigning array constructors in HLSL output

This adds support to the following type of shader code, where an array constructor is used as a source of assignment: float a[3]; a = float[3](0.0, 1.0, 2.0); The assignment gets replaced in the HLSL code by a function call where the array is an out parameter and the constructor parameters are regular parameters. Constructors cannot yet be used in initializers. With this change in place, some of the relevant dEQP tests start passing. TEST=dEQP-GLES3.functional.shaders.arrays.constructor.* BUG=angleproject:941 Change-Id: I13ed603c02a30d9f9950a61c4d562ae9fac058ec Reviewed-on: https://chromium-review.googlesource.com/263403Reviewed-by: 's avatarOlli Etuaho <oetuaho@nvidia.com> Tested-by: 's avatarOlli Etuaho <oetuaho@nvidia.com>
parent f40319e9
...@@ -353,6 +353,14 @@ void OutputHLSL::header(const BuiltInFunctionEmulator *builtInFunctionEmulator) ...@@ -353,6 +353,14 @@ void OutputHLSL::header(const BuiltInFunctionEmulator *builtInFunctionEmulator)
out << assignmentFunction.functionDefinition << "\n"; out << assignmentFunction.functionDefinition << "\n";
} }
} }
if (!mArrayConstructIntoFunctions.empty())
{
out << "\n// Array constructor functions\n\n";
for (const auto &constructIntoFunction : mArrayConstructIntoFunctions)
{
out << constructIntoFunction.functionDefinition << "\n";
}
}
if (mUsesDiscardRewriting) if (mUsesDiscardRewriting)
{ {
...@@ -1451,8 +1459,26 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) ...@@ -1451,8 +1459,26 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
case EOpAssign: case EOpAssign:
if (node->getLeft()->isArray()) if (node->getLeft()->isArray())
{ {
const TString &functionName = addArrayAssignmentFunction(node->getType()); TIntermAggregate *rightAgg = node->getRight()->getAsAggregate();
outputTriplet(visit, (functionName + "(").c_str(), ", ", ")"); if (rightAgg != nullptr && rightAgg->isConstructor())
{
const TString &functionName = addArrayConstructIntoFunction(node->getType());
out << functionName << "(";
node->getLeft()->traverse(this);
TIntermSequence *seq = rightAgg->getSequence();
for (auto &arrayElement : *seq)
{
out << ", ";
arrayElement->traverse(this);
}
out << ")";
return false;
}
else
{
const TString &functionName = addArrayAssignmentFunction(node->getType());
outputTriplet(visit, (functionName + "(").c_str(), ", ", ")");
}
} }
else else
{ {
...@@ -3116,4 +3142,48 @@ TString OutputHLSL::addArrayAssignmentFunction(const TType& type) ...@@ -3116,4 +3142,48 @@ TString OutputHLSL::addArrayAssignmentFunction(const TType& type)
return function.functionName; return function.functionName;
} }
TString OutputHLSL::addArrayConstructIntoFunction(const TType& type)
{
for (const auto &constructIntoFunction : mArrayConstructIntoFunctions)
{
if (constructIntoFunction.type == type)
{
return constructIntoFunction.functionName;
}
}
const TString &typeName = TypeString(type);
ArrayHelperFunction function;
function.type = type;
TInfoSinkBase fnNameOut;
fnNameOut << "angle_construct_into_" << type.getArraySize() << "_" << typeName;
function.functionName = fnNameOut.c_str();
TInfoSinkBase fnOut;
fnOut << "void " << function.functionName << "(out "
<< typeName << " a[" << type.getArraySize() << "]";
for (int i = 0; i < type.getArraySize(); ++i)
{
fnOut << ", " << typeName << " b" << i;
}
fnOut << ")\n"
"{\n";
for (int i = 0; i < type.getArraySize(); ++i)
{
fnOut << " a[" << i << "] = b" << i << ";\n";
}
fnOut << "}\n";
function.functionDefinition = fnOut.c_str();
mArrayConstructIntoFunctions.push_back(function);
return function.functionName;
}
} }
...@@ -90,6 +90,7 @@ class OutputHLSL : public TIntermTraverser ...@@ -90,6 +90,7 @@ class OutputHLSL : public TIntermTraverser
TString addStructEqualityFunction(const TStructure &structure); TString addStructEqualityFunction(const TStructure &structure);
TString addArrayEqualityFunction(const TType &type); TString addArrayEqualityFunction(const TType &type);
TString addArrayAssignmentFunction(const TType &type); TString addArrayAssignmentFunction(const TType &type);
TString addArrayConstructIntoFunction(const TType &type);
sh::GLenum mShaderType; sh::GLenum mShaderType;
int mShaderVersion; int mShaderVersion;
...@@ -214,6 +215,11 @@ class OutputHLSL : public TIntermTraverser ...@@ -214,6 +215,11 @@ class OutputHLSL : public TIntermTraverser
std::vector<ArrayHelperFunction*> mArrayEqualityFunctions; std::vector<ArrayHelperFunction*> mArrayEqualityFunctions;
std::vector<ArrayHelperFunction> mArrayAssignmentFunctions; std::vector<ArrayHelperFunction> mArrayAssignmentFunctions;
// The construct-into functions are functions that fill an N-element array passed as an out parameter
// with the other N parameters of the function. This is used to work around that arrays can't be
// return values in HLSL.
std::vector<ArrayHelperFunction> mArrayConstructIntoFunctions;
}; };
} }
......
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