Implement scoped structure declarations

TRAC# 12110 Signed-off-by: Shannon Woods Singed-off-by: Daniel Koch Author: Nicolas Capens git-svn-id: https://angleproject.googlecode.com/svn/trunk@310 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 8026c677
...@@ -62,6 +62,8 @@ OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, tr ...@@ -62,6 +62,8 @@ OutputHLSL::OutputHLSL(TParseContext &context) : TIntermTraverser(true, true, tr
mUsesEqualBVec4 = false; mUsesEqualBVec4 = false;
mUsesAtan2 = false; mUsesAtan2 = false;
mScopeDepth = 0;
mArgumentIndex = 0; mArgumentIndex = 0;
} }
...@@ -97,165 +99,14 @@ void OutputHLSL::header() ...@@ -97,165 +99,14 @@ void OutputHLSL::header()
EShLanguage language = mContext.language; EShLanguage language = mContext.language;
TInfoSinkBase &out = mHeader; TInfoSinkBase &out = mHeader;
// Output structure declarations for (StructDeclarations::iterator structDeclaration = mStructDeclarations.begin(); structDeclaration != mStructDeclarations.end(); structDeclaration++)
for (StructureArray::iterator structure = mStructures.begin(); structure != mStructures.end(); structure++)
{
const TTypeList &fields = *structure->getStruct();
out << "struct " + decorate(structure->getTypeName()) + "\n"
"{\n";
for (unsigned int i = 0; i < fields.size(); i++)
{
const TType &field = *fields[i].type;
out << " " + typeString(field) + " " + field.getFieldName() + arrayString(field) + ";\n";
}
out << "};\n";
}
// Output type constructors
for (ConstructorSet::iterator constructor = mConstructors.begin(); constructor != mConstructors.end(); constructor++)
{
out << typeString(constructor->type) + " " + constructor->name + "(";
for (unsigned int parameter = 0; parameter < constructor->parameters.size(); parameter++)
{
const TType &type = constructor->parameters[parameter];
out << typeString(type) + " x" + str(parameter) + arrayString(type);
if (parameter < constructor->parameters.size() - 1)
{
out << ", ";
}
}
out << ")\n"
"{\n";
if (constructor->type.getStruct())
{
out << " " + decorate(constructor->type.getTypeName()) + " structure = {";
}
else
{
out << " return " + typeString(constructor->type) + "(";
}
if (constructor->type.isMatrix() && constructor->parameters.size() == 1)
{
int dim = constructor->type.getNominalSize();
const TType &parameter = constructor->parameters[0];
if (parameter.isScalar())
{
for (int row = 0; row < dim; row++)
{
for (int col = 0; col < dim; col++)
{
out << TString((row == col) ? "x0" : "0.0");
if (row < dim - 1 || col < dim - 1)
{
out << ", ";
}
}
}
}
else if (parameter.isMatrix())
{
for (int row = 0; row < dim; row++)
{
for (int col = 0; col < dim; col++)
{
if (row < parameter.getNominalSize() && col < parameter.getNominalSize())
{ {
out << TString("x0") + "[" + str(row) + "]" + "[" + str(col) + "]"; out << *structDeclaration;
}
else
{
out << TString((row == col) ? "1.0" : "0.0");
} }
if (row < dim - 1 || col < dim - 1) for (Constructors::iterator constructor = mConstructors.begin(); constructor != mConstructors.end(); constructor++)
{ {
out << ", "; out << *constructor;
}
}
}
}
else UNREACHABLE();
}
else
{
int remainingComponents = constructor->type.getObjectSize();
int parameterIndex = 0;
while (remainingComponents > 0)
{
const TType &parameter = constructor->parameters[parameterIndex];
bool moreParameters = parameterIndex < (int)constructor->parameters.size() - 1;
out << "x" + str(parameterIndex);
if (parameter.isScalar())
{
remainingComponents -= parameter.getObjectSize();
}
else if (parameter.isVector())
{
if (remainingComponents == parameter.getObjectSize() || moreParameters)
{
remainingComponents -= parameter.getObjectSize();
}
else if (remainingComponents < parameter.getNominalSize())
{
switch (remainingComponents)
{
case 1: out << ".x"; break;
case 2: out << ".xy"; break;
case 3: out << ".xyz"; break;
case 4: out << ".xyzw"; break;
default: UNREACHABLE();
}
remainingComponents = 0;
}
else UNREACHABLE();
}
else if (parameter.isMatrix() || parameter.getStruct())
{
ASSERT(remainingComponents == parameter.getObjectSize() || moreParameters);
remainingComponents -= parameter.getObjectSize();
}
else UNREACHABLE();
if (moreParameters)
{
parameterIndex++;
}
if (remainingComponents)
{
out << ", ";
}
}
}
if (constructor->type.getStruct())
{
out << "};\n"
" return structure;\n"
"}\n";
}
else
{
out << ");\n"
"}\n";
}
} }
if (language == EShLangFragment) if (language == EShLangFragment)
...@@ -1105,6 +956,17 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -1105,6 +956,17 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
if (mInsideFunction) if (mInsideFunction)
{ {
out << "{\n"; out << "{\n";
mScopeDepth++;
if (mScopeBracket.size() < mScopeDepth)
{
mScopeBracket.push_back(0); // New scope level
}
else
{
mScopeBracket[mScopeDepth - 1]++; // New scope at existing level
}
} }
for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++) for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++)
...@@ -1122,6 +984,8 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -1122,6 +984,8 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
if (mInsideFunction) if (mInsideFunction)
{ {
out << "}\n"; out << "}\n";
mScopeDepth--;
} }
return false; return false;
...@@ -1137,7 +1001,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -1137,7 +1001,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
{ {
if (variable->getType().getStruct()) if (variable->getType().getStruct())
{ {
addConstructor(variable->getType(), variable->getType().getTypeName() + "_ctor", NULL); addConstructor(variable->getType(), scopedStruct(variable->getType().getTypeName()), NULL);
} }
if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration
...@@ -1413,8 +1277,8 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -1413,8 +1277,8 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
outputTriplet(visit, "mat4(", ", ", ")"); outputTriplet(visit, "mat4(", ", ", ")");
break; break;
case EOpConstructStruct: case EOpConstructStruct:
addConstructor(node->getType(), node->getType().getTypeName() + "_ctor", &node->getSequence()); addConstructor(node->getType(), scopedStruct(node->getType().getTypeName()), &node->getSequence());
outputTriplet(visit, node->getType().getTypeName() + "_ctor(", ", ", ")"); outputTriplet(visit, structLookup(node->getType().getTypeName()) + "_ctor(", ", ", ")");
break; break;
case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break; case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break;
case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break; case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break;
...@@ -1877,7 +1741,7 @@ TString OutputHLSL::typeString(const TType &type) ...@@ -1877,7 +1741,7 @@ TString OutputHLSL::typeString(const TType &type)
{ {
if (type.getTypeName() != "") if (type.getTypeName() != "")
{ {
return decorate(type.getTypeName()); return structLookup(type.getTypeName());
} }
else // Nameless structure, define in place else // Nameless structure, define in place
{ {
...@@ -1975,72 +1839,209 @@ TString OutputHLSL::initializer(const TType &type) ...@@ -1975,72 +1839,209 @@ TString OutputHLSL::initializer(const TType &type)
return "{" + string + "}"; return "{" + string + "}";
} }
bool OutputHLSL::CompareConstructor::operator()(const Constructor &x, const Constructor &y) const void OutputHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters)
{ {
if (x.name != y.name) if (name == "")
{
return; // Nameless structures don't have constructors
}
TType ctorType = type;
ctorType.clearArrayness();
ctorType.changePrecision(EbpHigh);
ctorType.changeQualifier(EvqTemporary);
TString ctorName = type.getStruct() ? decorate(name) : name;
typedef std::vector<TType> ParameterArray;
ParameterArray ctorParameters;
if (parameters)
{
for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++)
{ {
return x.name < y.name; ctorParameters.push_back((*parameter)->getAsTyped()->getType());
} }
}
else if (type.getStruct())
{
mStructNames.insert(decorate(name));
TString structure;
structure += "struct " + decorate(name) + "\n"
"{\n";
if (x.type != y.type) const TTypeList &fields = *type.getStruct();
for (unsigned int i = 0; i < fields.size(); i++)
{ {
return x.type < y.type; const TType &field = *fields[i].type;
structure += " " + typeString(field) + " " + field.getFieldName() + arrayString(field) + ";\n";
} }
if (x.parameters.size() != y.parameters.size()) structure += "};\n";
if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structure) == mStructDeclarations.end())
{ {
return x.parameters.size() < y.parameters.size(); mStructDeclarations.push_back(structure);
} }
for (unsigned int i = 0; i < x.parameters.size(); i++) for (unsigned int i = 0; i < fields.size(); i++)
{ {
if (x.parameters[i] != y.parameters[i]) ctorParameters.push_back(*fields[i].type);
}
}
else UNREACHABLE();
TString constructor;
if (ctorType.getStruct())
{ {
return x.parameters[i] < y.parameters[i]; constructor += ctorName + " " + ctorName + "_ctor(";
} }
else // Built-in type
{
constructor += typeString(ctorType) + " " + ctorName + "(";
} }
return false; for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++)
} {
const TType &type = ctorParameters[parameter];
void OutputHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters) constructor += typeString(type) + " x" + str(parameter) + arrayString(type);
{
if (name == "") if (parameter < ctorParameters.size() - 1)
{ {
return; // Nameless structures don't have constructors constructor += ", ";
}
} }
Constructor constructor; constructor += ")\n"
"{\n";
constructor.type = type; if (ctorType.getStruct())
constructor.type.clearArrayness(); {
constructor.type.changePrecision(EbpHigh); constructor += " " + ctorName + " structure = {";
constructor.type.changeQualifier(EvqTemporary); }
constructor.name = name; else
{
constructor += " return " + typeString(ctorType) + "(";
}
if (parameters) if (ctorType.isMatrix() && ctorParameters.size() == 1)
{ {
for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++) int dim = ctorType.getNominalSize();
const TType &parameter = ctorParameters[0];
if (parameter.isScalar())
{
for (int row = 0; row < dim; row++)
{
for (int col = 0; col < dim; col++)
{ {
constructor.parameters.push_back((*parameter)->getAsTyped()->getType()); constructor += TString((row == col) ? "x0" : "0.0");
if (row < dim - 1 || col < dim - 1)
{
constructor += ", ";
} }
} }
else if (type.getStruct()) }
}
else if (parameter.isMatrix())
{
for (int row = 0; row < dim; row++)
{
for (int col = 0; col < dim; col++)
{
if (row < parameter.getNominalSize() && col < parameter.getNominalSize())
{ {
if (std::find(mStructures.begin(), mStructures.end(), constructor.type) == mStructures.end()) constructor += TString("x0") + "[" + str(row) + "]" + "[" + str(col) + "]";
}
else
{ {
mStructures.push_back(constructor.type); constructor += TString((row == col) ? "1.0" : "0.0");
} }
const TTypeList *structure = type.getStruct(); if (row < dim - 1 || col < dim - 1)
{
constructor += ", ";
}
}
}
}
else UNREACHABLE();
}
else
{
int remainingComponents = ctorType.getObjectSize();
int parameterIndex = 0;
for (unsigned int i = 0; i < structure->size(); i++) while (remainingComponents > 0)
{ {
constructor.parameters.push_back(*(*structure)[i].type); const TType &parameter = ctorParameters[parameterIndex];
bool moreParameters = parameterIndex < (int)ctorParameters.size() - 1;
constructor += "x" + str(parameterIndex);
if (parameter.isScalar())
{
remainingComponents -= parameter.getObjectSize();
}
else if (parameter.isVector())
{
if (remainingComponents == parameter.getObjectSize() || moreParameters)
{
remainingComponents -= parameter.getObjectSize();
}
else if (remainingComponents < parameter.getNominalSize())
{
switch (remainingComponents)
{
case 1: constructor += ".x"; break;
case 2: constructor += ".xy"; break;
case 3: constructor += ".xyz"; break;
case 4: constructor += ".xyzw"; break;
default: UNREACHABLE();
}
remainingComponents = 0;
}
else UNREACHABLE();
} }
else if (parameter.isMatrix() || parameter.getStruct())
{
ASSERT(remainingComponents == parameter.getObjectSize() || moreParameters);
remainingComponents -= parameter.getObjectSize();
} }
else UNREACHABLE(); else UNREACHABLE();
if (moreParameters)
{
parameterIndex++;
}
if (remainingComponents)
{
constructor += ", ";
}
}
}
if (ctorType.getStruct())
{
constructor += "};\n"
" return structure;\n"
"}\n";
}
else
{
constructor += ");\n"
"}\n";
}
mConstructors.insert(constructor); mConstructors.insert(constructor);
} }
...@@ -2050,7 +2051,7 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con ...@@ -2050,7 +2051,7 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con
if (type.getBasicType() == EbtStruct) if (type.getBasicType() == EbtStruct)
{ {
out << type.getTypeName() + "_ctor("; out << structLookup(type.getTypeName()) + "_ctor(";
const TTypeList *structure = type.getStruct(); const TTypeList *structure = type.getStruct();
...@@ -2112,6 +2113,48 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con ...@@ -2112,6 +2113,48 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con
return constUnion; return constUnion;
} }
TString OutputHLSL::scopeString(unsigned int depthLimit)
{
TString string;
for (unsigned int i = 0; i < mScopeBracket.size() && i < depthLimit; i++)
{
string += "_" + str(i);
}
return string;
}
TString OutputHLSL::scopedStruct(const TString &typeName)
{
if (typeName == "")
{
return typeName;
}
return typeName + scopeString(mScopeDepth);
}
TString OutputHLSL::structLookup(const TString &typeName)
{
for (int depth = mScopeDepth; depth >= 0; depth--)
{
TString scopedName = decorate(typeName + scopeString(depth));
for (StructNames::iterator structName = mStructNames.begin(); structName != mStructNames.end(); structName++)
{
if (*structName == scopedName)
{
return scopedName;
}
}
}
UNREACHABLE(); // Should have found a matching constructor
return typeName;
}
TString OutputHLSL::decorate(const TString &string) TString OutputHLSL::decorate(const TString &string)
{ {
if (string.substr(0, 3) != "gl_" && string.substr(0, 3) != "dx_") if (string.substr(0, 3) != "gl_" && string.substr(0, 3) != "dx_")
......
...@@ -27,8 +27,8 @@ class OutputHLSL : public TIntermTraverser ...@@ -27,8 +27,8 @@ class OutputHLSL : public TIntermTraverser
TInfoSinkBase &getBodyStream(); TInfoSinkBase &getBodyStream();
TString typeString(const TType &type);
static TString qualifierString(TQualifier qualifier); static TString qualifierString(TQualifier qualifier);
static TString typeString(const TType &type);
static TString arrayString(const TType &type); static TString arrayString(const TType &type);
static TString initializer(const TType &type); static TString initializer(const TType &type);
static TString decorate(const TString &string); // Prepend an underscore to avoid naming clashes static TString decorate(const TString &string); // Prepend an underscore to avoid naming clashes
...@@ -55,6 +55,10 @@ class OutputHLSL : public TIntermTraverser ...@@ -55,6 +55,10 @@ class OutputHLSL : public TIntermTraverser
void addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters); void addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters);
const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *constUnion); const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *constUnion);
TString scopeString(unsigned int depthLimit);
TString scopedStruct(const TString &typeName);
TString structLookup(const TString &typeName);
TParseContext &mContext; TParseContext &mContext;
UnfoldSelect *mUnfoldSelect; UnfoldSelect *mUnfoldSelect;
bool mInsideFunction; bool mInsideFunction;
...@@ -103,25 +107,18 @@ class OutputHLSL : public TIntermTraverser ...@@ -103,25 +107,18 @@ class OutputHLSL : public TIntermTraverser
bool mUsesEqualBVec4; bool mUsesEqualBVec4;
bool mUsesAtan2; bool mUsesAtan2;
struct Constructor // Describes a constructor signature typedef std::set<TString> Constructors;
{ Constructors mConstructors;
TType type;
TString name;
typedef std::vector<TType> ParameterArray;
ParameterArray parameters;
};
struct CompareConstructor typedef std::set<TString> StructNames;
{ StructNames mStructNames;
bool operator()(const Constructor &x, const Constructor &y) const;
};
typedef std::set<Constructor, CompareConstructor> ConstructorSet; typedef std::list<TString> StructDeclarations;
ConstructorSet mConstructors; StructDeclarations mStructDeclarations;
typedef std::list<TType> StructureArray; typedef std::vector<int> ScopeBracket;
StructureArray mStructures; ScopeBracket mScopeBracket;
unsigned int mScopeDepth;
int mArgumentIndex; // For creating unique argument names int mArgumentIndex; // For creating unique argument names
}; };
......
...@@ -32,7 +32,7 @@ bool UnfoldSelect::visitSelection(Visit visit, TIntermSelection *node) ...@@ -32,7 +32,7 @@ bool UnfoldSelect::visitSelection(Visit visit, TIntermSelection *node)
{ {
int i = mTemporaryIndex++; int i = mTemporaryIndex++;
out << OutputHLSL::typeString(node->getType()) << " t" << i << ";\n"; out << mOutputHLSL->typeString(node->getType()) << " t" << i << ";\n";
node->getCondition()->traverse(this); node->getCondition()->traverse(this);
out << "if("; out << "if(";
......
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