зеркало из https://github.com/AvaloniaUI/angle.git
Recursively write ConstantUnion to correctly construct structs.
Review URL: http://codereview.appspot.com/1108041 git-svn-id: https://angleproject.googlecode.com/svn/trunk@229 736b8ea6-26fd-11df-bfd4-992fa37f6226
This commit is contained in:
Родитель
256b751db2
Коммит
b3f7fb68c6
|
@ -43,7 +43,8 @@ TString getTypeName(const TType& type)
|
|||
TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink)
|
||||
: TIntermTraverser(true, true, true),
|
||||
mObjSink(objSink),
|
||||
mWriteFullSymbol(false)
|
||||
mWriteFullSymbol(false),
|
||||
mScopeSequences(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -64,6 +65,50 @@ void TOutputGLSL::writeTriplet(Visit visit, const char* preStr, const char* inSt
|
|||
}
|
||||
}
|
||||
|
||||
const ConstantUnion* TOutputGLSL::writeConstantUnion(const TType& type, const ConstantUnion* pConstUnion)
|
||||
{
|
||||
TInfoSinkBase& out = objSink();
|
||||
|
||||
if (type.getBasicType() == EbtStruct)
|
||||
{
|
||||
out << type.getTypeName() << "(";
|
||||
const TTypeList* structure = type.getStruct();
|
||||
ASSERT(structure != NULL);
|
||||
for (size_t i = 0; i < structure->size(); ++i)
|
||||
{
|
||||
const TType* fieldType = (*structure)[i].type;
|
||||
ASSERT(fieldType != NULL);
|
||||
pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
|
||||
if (i != structure->size() - 1) out << ", ";
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
int size = type.getObjectSize();
|
||||
bool writeType = size > 1;
|
||||
if (writeType) out << getTypeName(type) << "(";
|
||||
for (int i = 0; i < size; ++i, ++pConstUnion)
|
||||
{
|
||||
switch (pConstUnion->getType())
|
||||
{
|
||||
case EbtFloat: out << pConstUnion->getFConst(); break;
|
||||
case EbtInt: out << pConstUnion->getIConst(); break;
|
||||
case EbtBool:
|
||||
if (pConstUnion->getBConst())
|
||||
out << "true";
|
||||
else
|
||||
out << "false";
|
||||
break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
if (i != size - 1) out << ", ";
|
||||
}
|
||||
if (writeType) out << ")";
|
||||
}
|
||||
return pConstUnion;
|
||||
}
|
||||
|
||||
void TOutputGLSL::visitSymbol(TIntermSymbol* node)
|
||||
{
|
||||
TInfoSinkBase& out = objSink();
|
||||
|
@ -106,28 +151,7 @@ void TOutputGLSL::visitSymbol(TIntermSymbol* node)
|
|||
|
||||
void TOutputGLSL::visitConstantUnion(TIntermConstantUnion* node)
|
||||
{
|
||||
TInfoSinkBase& out = objSink();
|
||||
|
||||
const TType& type = node->getType();
|
||||
int size = type.getObjectSize();
|
||||
bool writeType = (size > 1) || (type.getBasicType() == EbtStruct);
|
||||
if (writeType)
|
||||
out << getTypeName(type) << "(";
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
const ConstantUnion& data = node->getUnionArrayPointer()[i];
|
||||
switch (data.getType())
|
||||
{
|
||||
case EbtFloat: out << data.getFConst(); break;
|
||||
case EbtInt: out << data.getIConst(); break;
|
||||
case EbtBool: out << data.getBConst(); break;
|
||||
default: UNREACHABLE(); break;
|
||||
}
|
||||
if (i != size - 1)
|
||||
out << ", ";
|
||||
}
|
||||
if (writeType)
|
||||
out << ")";
|
||||
writeConstantUnion(node->getType(), node->getUnionArrayPointer());
|
||||
}
|
||||
|
||||
bool TOutputGLSL::visitBinary(Visit visit, TIntermBinary* node)
|
||||
|
@ -331,13 +355,13 @@ bool TOutputGLSL::visitSelection(Visit visit, TIntermSelection* node)
|
|||
{
|
||||
node->getTrueBlock()->traverse(this);
|
||||
}
|
||||
out << "}";
|
||||
out << ";\n}";
|
||||
|
||||
if (node->getFalseBlock())
|
||||
{
|
||||
out << " else {\n";
|
||||
node->getFalseBlock()->traverse(this);
|
||||
out << "}";
|
||||
out << ";\n}";
|
||||
}
|
||||
decrementDepth();
|
||||
out << "\n";
|
||||
|
@ -347,11 +371,26 @@ bool TOutputGLSL::visitSelection(Visit visit, TIntermSelection* node)
|
|||
|
||||
bool TOutputGLSL::visitAggregate(Visit visit, TIntermAggregate* node)
|
||||
{
|
||||
bool visitChildren = true;
|
||||
TInfoSinkBase& out = objSink();
|
||||
switch (node->getOp())
|
||||
{
|
||||
case EOpSequence:
|
||||
writeTriplet(visit, NULL, ";\n", ";\n");
|
||||
if (visit == PreVisit)
|
||||
{
|
||||
if (mScopeSequences)
|
||||
out << "{\n";
|
||||
}
|
||||
else if (visit == InVisit)
|
||||
{
|
||||
out << ";\n";
|
||||
}
|
||||
else if (visit == PostVisit)
|
||||
{
|
||||
out << ";\n";
|
||||
if (mScopeSequences)
|
||||
out << "}\n";
|
||||
}
|
||||
break;
|
||||
case EOpPrototype:
|
||||
// Function declaration.
|
||||
|
@ -373,26 +412,47 @@ bool TOutputGLSL::visitAggregate(Visit visit, TIntermAggregate* node)
|
|||
mWriteFullSymbol = false;
|
||||
}
|
||||
break;
|
||||
case EOpFunction:
|
||||
case EOpFunction: {
|
||||
// Function definition.
|
||||
if (visit == PreVisit)
|
||||
TString returnType = getTypeName(node->getType());
|
||||
TString functionName = TFunction::unmangleName(node->getName());
|
||||
out << returnType << " " << functionName;
|
||||
|
||||
// Function definition node contains one or two children nodes
|
||||
// representing function parameters and function body. The latter
|
||||
// is not present in case of empty function bodies.
|
||||
const TIntermSequence& sequence = node->getSequence();
|
||||
ASSERT((sequence.size() == 1) || (sequence.size() == 2));
|
||||
TIntermSequence::const_iterator seqIter = sequence.begin();
|
||||
|
||||
// Traverse function parameters.
|
||||
TIntermAggregate* params = (*seqIter)->getAsAggregate();
|
||||
ASSERT(params != NULL);
|
||||
ASSERT(params->getOp() == EOpParameters);
|
||||
params->traverse(this);
|
||||
|
||||
// Traverse function body.
|
||||
TIntermAggregate* body = ++seqIter != sequence.end() ?
|
||||
(*seqIter)->getAsAggregate() : NULL;
|
||||
if (body != NULL)
|
||||
{
|
||||
TString returnType = getTypeName(node->getType());
|
||||
TString functionName = TFunction::unmangleName(node->getName());
|
||||
out << returnType << " " << functionName;
|
||||
ASSERT(body->getOp() == EOpSequence);
|
||||
// Sequences are scoped with {} inside function body so that
|
||||
// variables are declared in the correct scope.
|
||||
mScopeSequences = true;
|
||||
body->traverse(this);
|
||||
mScopeSequences = false;
|
||||
}
|
||||
else if (visit == InVisit)
|
||||
else
|
||||
{
|
||||
// Called after traversing function arguments (EOpParameters)
|
||||
// but before traversing function body (EOpSequence).
|
||||
out << "{\n";
|
||||
}
|
||||
else if (visit == PostVisit)
|
||||
{
|
||||
// Called after traversing function body (EOpSequence).
|
||||
out << "}\n";
|
||||
// Empty function body.
|
||||
out << "{}\n";
|
||||
}
|
||||
|
||||
// Fully processed; no need to visit children.
|
||||
visitChildren = false;
|
||||
break;
|
||||
}
|
||||
case EOpFunctionCall:
|
||||
// Function call.
|
||||
if (visit == PreVisit)
|
||||
|
@ -503,7 +563,7 @@ bool TOutputGLSL::visitAggregate(Visit visit, TIntermAggregate* node)
|
|||
|
||||
default: UNREACHABLE(); break;
|
||||
}
|
||||
return true;
|
||||
return visitChildren;
|
||||
}
|
||||
|
||||
bool TOutputGLSL::visitLoop(Visit visit, TIntermLoop* node)
|
||||
|
|
|
@ -18,6 +18,7 @@ public:
|
|||
protected:
|
||||
TInfoSinkBase& objSink() { return mObjSink; }
|
||||
void writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr);
|
||||
const ConstantUnion* writeConstantUnion(const TType& type, const ConstantUnion* pConstUnion);
|
||||
|
||||
virtual void visitSymbol(TIntermSymbol* node);
|
||||
virtual void visitConstantUnion(TIntermConstantUnion* node);
|
||||
|
@ -31,6 +32,7 @@ protected:
|
|||
private:
|
||||
TInfoSinkBase& mObjSink;
|
||||
bool mWriteFullSymbol;
|
||||
bool mScopeSequences;
|
||||
|
||||
// Structs are declared as the tree is traversed. This set contains all
|
||||
// the structs already declared. It is maintained so that a struct is
|
||||
|
|
Загрузка…
Ссылка в новой задаче