Commit ae37a5c8 by Olli Etuaho

Support equality between structs containing arrays in HLSL output

This requires sorting all equality functions together so that struct equality functions can have dependencies on array equality functions, but support for array equality functions that have dependencies on struct equality functions is also maintained. There's no automated test coverage for this specifically. The change was tested by manually inspecting shader output and ensuring that there were no test regressions in tests listed below. TEST=dEQP-GLES3.functional.shaders.* BUG=angleproject:954 Change-Id: If7199ab2446804afae50f103bb625101172882b9 Reviewed-on: https://chromium-review.googlesource.com/261550Reviewed-by: 's avatarOlli Etuaho <oetuaho@nvidia.com> Tested-by: 's avatarOlli Etuaho <oetuaho@nvidia.com>
parent 7fb4955d
...@@ -158,6 +158,14 @@ OutputHLSL::~OutputHLSL() ...@@ -158,6 +158,14 @@ OutputHLSL::~OutputHLSL()
SafeDelete(mUnfoldShortCircuit); SafeDelete(mUnfoldShortCircuit);
SafeDelete(mStructureHLSL); SafeDelete(mStructureHLSL);
SafeDelete(mUniformHLSL); SafeDelete(mUniformHLSL);
for (auto &eqFunction : mStructEqualityFunctions)
{
SafeDelete(eqFunction);
}
for (auto &eqFunction : mArrayEqualityFunctions)
{
SafeDelete(eqFunction);
}
} }
void OutputHLSL::output(TIntermNode *treeRoot, TInfoSinkBase &objSink) void OutputHLSL::output(TIntermNode *treeRoot, TInfoSinkBase &objSink)
...@@ -329,21 +337,12 @@ void OutputHLSL::header(const BuiltInFunctionEmulator *builtInFunctionEmulator) ...@@ -329,21 +337,12 @@ void OutputHLSL::header(const BuiltInFunctionEmulator *builtInFunctionEmulator)
out << mUniformHLSL->uniformsHeader(mOutputType, mReferencedUniforms); out << mUniformHLSL->uniformsHeader(mOutputType, mReferencedUniforms);
out << mUniformHLSL->interfaceBlocksHeader(mReferencedInterfaceBlocks); out << mUniformHLSL->interfaceBlocksHeader(mReferencedInterfaceBlocks);
if (!mStructEqualityFunctions.empty()) if (!mEqualityFunctions.empty())
{
out << "\n// Structure equality functions\n\n";
for (const auto &eqFunction : mStructEqualityFunctions)
{
out << eqFunction.functionDefinition << "\n";
}
}
if (!mArrayEqualityFunctions.empty())
{ {
out << "\n// Array equality functions\n\n"; out << "\n// Equality functions\n\n";
for (const auto &eqFunction : mArrayEqualityFunctions) for (const auto &eqFunction : mEqualityFunctions)
{ {
out << eqFunction.functionDefinition << "\n"; out << eqFunction->functionDefinition << "\n";
} }
} }
...@@ -2961,23 +2960,23 @@ TString OutputHLSL::addStructEqualityFunction(const TStructure &structure) ...@@ -2961,23 +2960,23 @@ TString OutputHLSL::addStructEqualityFunction(const TStructure &structure)
for (const auto &eqFunction : mStructEqualityFunctions) for (const auto &eqFunction : mStructEqualityFunctions)
{ {
if (eqFunction.structure == &structure) if (eqFunction->structure == &structure)
{ {
return eqFunction.functionName; return eqFunction->functionName;
} }
} }
const TString &structNameString = StructNameString(structure); const TString &structNameString = StructNameString(structure);
StructEqualityFunction function; StructEqualityFunction *function = new StructEqualityFunction();
function.structure = &structure; function->structure = &structure;
function.functionName = "angle_eq_" + structNameString; function->functionName = "angle_eq_" + structNameString;
TString &func = function.functionDefinition; TInfoSinkBase fnOut;
func = "bool " + function.functionName + "(" + structNameString + " a, " + structNameString + " b)\n" + fnOut << "bool " << function->functionName << "(" << structNameString << " a, " << structNameString + " b)\n"
"{\n" << "{\n"
" return "; " return ";
for (size_t i = 0; i < fields.size(); i++) for (size_t i = 0; i < fields.size(); i++)
{ {
...@@ -2987,67 +2986,55 @@ TString OutputHLSL::addStructEqualityFunction(const TStructure &structure) ...@@ -2987,67 +2986,55 @@ TString OutputHLSL::addStructEqualityFunction(const TStructure &structure)
const TString &fieldNameA = "a." + Decorate(field->name()); const TString &fieldNameA = "a." + Decorate(field->name());
const TString &fieldNameB = "b." + Decorate(field->name()); const TString &fieldNameB = "b." + Decorate(field->name());
// TODO (oetuaho): Use outputEqual() here instead
if (i > 0) if (i > 0)
{ {
func += " && "; fnOut << " && ";
} }
if (fieldType->isArray()) fnOut << "(";
{ outputEqual(PreVisit, *fieldType, EOpEqual, fnOut);
// TODO (oetuaho): This requires sorting array and struct equality functions together. fnOut << fieldNameA;
UNIMPLEMENTED(); outputEqual(InVisit, *fieldType, EOpEqual, fnOut);
} fnOut << fieldNameB;
else if (fieldType->getBasicType() == EbtStruct) outputEqual(PostVisit, *fieldType, EOpEqual, fnOut);
{ fnOut << ")";
const TStructure &fieldStruct = *fieldType->getStruct();
const TString &functionName = addStructEqualityFunction(fieldStruct);
func += functionName + "(" + fieldNameA + ", " + fieldNameB + ")";
}
else if (fieldType->isScalar())
{
func += "(" + fieldNameA + " == " + fieldNameB + ")";
}
else
{
ASSERT(fieldType->isMatrix() || fieldType->isVector());
func += "all(" + fieldNameA + " == " + fieldNameB + ")";
}
} }
func = func + ";\n" + "}\n"; fnOut << ";\n" << "}\n";
function->functionDefinition = fnOut.c_str();
mStructEqualityFunctions.push_back(function); mStructEqualityFunctions.push_back(function);
mEqualityFunctions.push_back(function);
return function.functionName; return function->functionName;
} }
TString OutputHLSL::addArrayEqualityFunction(const TType& type) TString OutputHLSL::addArrayEqualityFunction(const TType& type)
{ {
for (const auto &eqFunction : mArrayEqualityFunctions) for (const auto &eqFunction : mArrayEqualityFunctions)
{ {
if (eqFunction.type == type) if (eqFunction->type == type)
{ {
return eqFunction.functionName; return eqFunction->functionName;
} }
} }
const TString &typeName = TypeString(type); const TString &typeName = TypeString(type);
ArrayEqualityFunction function; ArrayEqualityFunction *function = new ArrayEqualityFunction();
function.type = type; function->type = type;
TInfoSinkBase fnNameOut; TInfoSinkBase fnNameOut;
fnNameOut << "angle_eq_" << type.getArraySize() << "_" << typeName; fnNameOut << "angle_eq_" << type.getArraySize() << "_" << typeName;
function.functionName = fnNameOut.c_str(); function->functionName = fnNameOut.c_str();
TType nonArrayType = type; TType nonArrayType = type;
nonArrayType.clearArrayness(); nonArrayType.clearArrayness();
TInfoSinkBase fnOut; TInfoSinkBase fnOut;
fnOut << "bool " << function.functionName << "(" fnOut << "bool " << function->functionName << "("
<< typeName << "[" << type.getArraySize() << "] a, " << typeName << "[" << type.getArraySize() << "] a, "
<< typeName << "[" << type.getArraySize() << "] b)\n" << typeName << "[" << type.getArraySize() << "] b)\n"
<< "{\n" << "{\n"
...@@ -3066,11 +3053,12 @@ TString OutputHLSL::addArrayEqualityFunction(const TType& type) ...@@ -3066,11 +3053,12 @@ TString OutputHLSL::addArrayEqualityFunction(const TType& type)
" return true;\n" " return true;\n"
"}\n"; "}\n";
function.functionDefinition = fnOut.c_str(); function->functionDefinition = fnOut.c_str();
mArrayEqualityFunctions.push_back(function); mArrayEqualityFunctions.push_back(function);
mEqualityFunctions.push_back(function);
return function.functionName; return function->functionName;
} }
} }
...@@ -186,25 +186,31 @@ class OutputHLSL : public TIntermTraverser ...@@ -186,25 +186,31 @@ class OutputHLSL : public TIntermTraverser
// these static globals after we initialize our other globals. // these static globals after we initialize our other globals.
std::vector<std::pair<TIntermSymbol*, TIntermTyped*>> mDeferredGlobalInitializers; std::vector<std::pair<TIntermSymbol*, TIntermTyped*>> mDeferredGlobalInitializers;
// A list of structure equality comparison functions. It's important to preserve the order at struct EqualityFunction
// which we add the functions, since nested structures call each other recursively.
struct StructEqualityFunction
{ {
const TStructure *structure;
TString functionName; TString functionName;
TString functionDefinition; TString functionDefinition;
virtual ~EqualityFunction() {}
}; };
std::vector<StructEqualityFunction> mStructEqualityFunctions; // A list of all equality comparison functions. It's important to preserve the order at
// which we add the functions, since nested structures call each other recursively, and
// structure equality functions may need to call array equality functions and vice versa.
// The ownership of the pointers is maintained by the type-specific arrays.
std::vector<EqualityFunction*> mEqualityFunctions;
struct ArrayEqualityFunction struct StructEqualityFunction : public EqualityFunction
{ {
TType type; const TStructure *structure;
TString functionName;
TString functionDefinition;
}; };
std::vector<StructEqualityFunction*> mStructEqualityFunctions;
std::vector<ArrayEqualityFunction> mArrayEqualityFunctions; struct ArrayEqualityFunction : public EqualityFunction
{
TType type;
};
std::vector<ArrayEqualityFunction*> mArrayEqualityFunctions;
}; };
} }
......
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