Commit 96f6adfa by Olli Etuaho Committed by Commit Bot

Add support for arrays of arrays in AST processing

Data concerning arrays of arrays is added in TType. Parsing arrays of arrays and support for arrays of arrays in TPublicType are still left to be implemented later. ShaderVariable interface for arrays of arrays is also left to be implemented later. We rely on existing test coverage to make sure that arrays of arrays are not accidentally exposed. BUG=angleproject:2125 TEST=angle_unittests, angle_end2end_tests, angle_deqp_gles31_tests Change-Id: Ie17d5ac9b8d33958e9126dc0fb40bf1c81ddeec9 Reviewed-on: https://chromium-review.googlesource.com/616146Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 5e424fae
......@@ -219,8 +219,9 @@ void CollectVariablesTraverser::setBuiltInInfoFromSymbolTable(const char *name,
info->name = name;
info->mappedName = name;
info->type = GLVariableType(type);
info->arraySize = type.isArray() ? type.getArraySize() : 0;
info->precision = GLVariablePrecision(type);
ASSERT(!type.isArrayOfArrays());
info->arraySize = type.isArray() ? type.getOutermostArraySize() : 0;
info->precision = GLVariablePrecision(type);
}
void CollectVariablesTraverser::recordBuiltInVaryingUsed(const char *name,
......@@ -511,7 +512,11 @@ void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
}
variableOut->name = name.c_str();
variableOut->mappedName = HashName(name, mHashFunction).c_str();
variableOut->arraySize = type.getArraySize();
// TODO(oetuaho@nvidia.com): Uniforms can be arrays of arrays, so this assert will need to be
// removed.
ASSERT(!type.isArrayOfArrays());
variableOut->arraySize = type.isArray() ? type.getOutermostArraySize() : 0;
}
Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const
......@@ -581,7 +586,8 @@ void CollectVariablesTraverser::recordInterfaceBlock(const TType &interfaceBlock
interfaceBlock->mappedName = HashName(blockType->name().c_str(), mHashFunction).c_str();
interfaceBlock->instanceName =
(blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
interfaceBlock->arraySize = interfaceBlockType.getArraySize();
ASSERT(!interfaceBlockType.isArrayOfArrays()); // Disallowed by GLSL ES 3.10 section 4.3.9
interfaceBlock->arraySize = interfaceBlockType.isArray() ? interfaceBlockType.getOutermostArraySize() : 0;
interfaceBlock->blockType = GetBlockType(interfaceBlockType.getQualifier());
if (interfaceBlock->blockType == BlockType::BLOCK_UNIFORM ||
......
......@@ -816,11 +816,11 @@ void IdentifyBuiltIns(sh::GLenum type,
TType fragData(EbtFloat, EbpMedium, EvqFragData, 4);
if (spec != SH_WEBGL2_SPEC && spec != SH_WEBGL3_SPEC)
{
fragData.setArraySize(resources.MaxDrawBuffers);
fragData.makeArray(resources.MaxDrawBuffers);
}
else
{
fragData.setArraySize(1u);
fragData.makeArray(1u);
}
symbolTable.insertVariable(ESSL1_BUILTINS, "gl_FragData", fragData);
......@@ -829,8 +829,8 @@ void IdentifyBuiltIns(sh::GLenum type,
symbolTable.insertVariableExt(
ESSL1_BUILTINS, "GL_EXT_blend_func_extended", "gl_SecondaryFragColorEXT",
TType(EbtFloat, EbpMedium, EvqSecondaryFragColorEXT, 4));
TType secondaryFragData(EbtFloat, EbpMedium, EvqSecondaryFragDataEXT, 4, 1, true);
secondaryFragData.setArraySize(resources.MaxDualSourceDrawBuffers);
TType secondaryFragData(EbtFloat, EbpMedium, EvqSecondaryFragDataEXT, 4, 1);
secondaryFragData.makeArray(resources.MaxDualSourceDrawBuffers);
symbolTable.insertVariableExt(ESSL1_BUILTINS, "GL_EXT_blend_func_extended",
"gl_SecondaryFragDataEXT", secondaryFragData);
}
......@@ -848,8 +848,8 @@ void IdentifyBuiltIns(sh::GLenum type,
if (resources.EXT_shader_framebuffer_fetch || resources.NV_shader_framebuffer_fetch)
{
TType lastFragData(EbtFloat, EbpMedium, EvqLastFragData, 4, 1, true);
lastFragData.setArraySize(resources.MaxDrawBuffers);
TType lastFragData(EbtFloat, EbpMedium, EvqLastFragData, 4, 1);
lastFragData.makeArray(resources.MaxDrawBuffers);
if (resources.EXT_shader_framebuffer_fetch)
{
......@@ -928,8 +928,8 @@ void IdentifyBuiltIns(sh::GLenum type,
// The array size of gl_in is undefined until we get a valid input primitive
// declaration.
TType glInType(glInBlock, EvqPerVertexIn, TLayoutQualifier::create(), 0);
glInType.setArrayUnsized();
TType glInType(glInBlock, EvqPerVertexIn, TLayoutQualifier::create());
glInType.makeArray(0u);
symbolTable.insertVariableExt(ESSL3_1_BUILTINS, extension, "gl_in", glInType);
break;
......
......@@ -68,11 +68,15 @@ void AddArrayZeroInitSequence(const TIntermTyped *initializedNode, TIntermSequen
// doesn't have array assignment.
// Note that it is important to have the array init in the right order to workaround
// http://crbug.com/709317
for (unsigned int i = 0; i < initializedNode->getArraySize(); ++i)
for (unsigned int i = 0; i < initializedNode->getOutermostArraySize(); ++i)
{
TIntermBinary *element =
new TIntermBinary(EOpIndexDirect, initializedNode->deepCopy(), CreateIndexNode(i));
if (element->getType().isStructureContainingArrays())
if (element->isArray())
{
AddArrayZeroInitSequence(element, initSequenceOut);
}
else if (element->getType().isStructureContainingArrays())
{
AddStructZeroInitSequence(element, initSequenceOut);
}
......
......@@ -502,7 +502,7 @@ void TIntermDeclaration::appendDeclarator(TIntermTyped *declarator)
(declarator->getAsBinaryNode() != nullptr &&
declarator->getAsBinaryNode()->getOp() == EOpInitialize));
ASSERT(mDeclarators.empty() ||
declarator->getType().sameElementType(mDeclarators.back()->getAsTyped()->getType()));
declarator->getType().sameNonArrayType(mDeclarators.back()->getAsTyped()->getType()));
mDeclarators.push_back(declarator);
}
......@@ -1063,7 +1063,7 @@ void TIntermBinary::promote()
case EOpIndexIndirect:
if (mLeft->isArray())
{
mType.clearArrayness();
mType.toArrayElementType();
}
else if (mLeft->isMatrix())
{
......@@ -1242,9 +1242,9 @@ const TConstantUnion *TIntermConstantUnion::foldIndexing(int index)
{
if (isArray())
{
ASSERT(index < static_cast<int>(getType().getArraySize()));
ASSERT(index < static_cast<int>(getType().getOutermostArraySize()));
TType arrayElementType = getType();
arrayElementType.clearArrayness();
arrayElementType.toArrayElementType();
size_t arrayElementSize = arrayElementType.getObjectSize();
return &mUnionArrayPointer[arrayElementSize * index];
}
......
......@@ -176,7 +176,7 @@ class TIntermTyped : public TIntermNode
const char *getBasicString() const { return mType.getBasicString(); }
TString getCompleteString() const { return mType.getCompleteString(); }
unsigned int getArraySize() const { return mType.getArraySize(); }
unsigned int getOutermostArraySize() const { return mType.getOutermostArraySize(); }
bool isConstructorWithOnlyConstantUnionParameters();
......
......@@ -116,7 +116,10 @@ TIntermTyped *CreateZeroNode(const TType &type)
// Void array. This happens only on error condition, similarly to the case above. We don't
// have a constructor operator for void, so this needs special handling. We'll end up with a
// value without the array type, but that should not be a problem.
constType.clearArrayness();
while (constType.isArray())
{
constType.toArrayElementType();
}
return CreateZeroNode(constType);
}
......@@ -125,9 +128,9 @@ TIntermTyped *CreateZeroNode(const TType &type)
if (type.isArray())
{
TType elementType(type);
elementType.clearArrayness();
elementType.toArrayElementType();
size_t arraySize = type.getArraySize();
size_t arraySize = type.getOutermostArraySize();
for (size_t i = 0; i < arraySize; ++i)
{
arguments->push_back(CreateZeroNode(elementType));
......
......@@ -10,6 +10,7 @@
#include "common/debug.h"
#include "common/mathutil.h"
#include "compiler/translator/Compiler.h"
#include "compiler/translator/util.h"
#include <cfloat>
......@@ -18,13 +19,6 @@ namespace sh
namespace
{
TString arrayBrackets(const TType &type)
{
ASSERT(type.isArray());
TInfoSinkBase out;
out << "[" << type.getArraySize() << "]";
return TString(out.c_str());
}
bool isSingleStatement(TIntermNode *node)
{
......@@ -382,7 +376,7 @@ void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence &args)
if (!arg->getName().getString().empty())
out << " " << hashName(arg->getName());
if (type.isArray())
out << arrayBrackets(type);
out << ArrayString(type);
// Put a comma if this is not the last argument.
if (iter != args.end() - 1)
......@@ -456,7 +450,7 @@ void TOutputGLSLBase::writeConstructorTriplet(Visit visit, const TType &type)
if (type.isArray())
{
out << getTypeName(type);
out << arrayBrackets(type);
out << ArrayString(type);
out << "(";
}
else
......@@ -476,7 +470,7 @@ void TOutputGLSLBase::visitSymbol(TIntermSymbol *node)
out << hashVariableName(node->getName());
if (mDeclaringVariables && node->getType().isArray())
out << arrayBrackets(node->getType());
out << ArrayString(node->getType());
}
void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion *node)
......@@ -573,7 +567,7 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
if (left->isArray())
{
// The shader will fail validation if the array length is not > 0.
maxSize = static_cast<int>(leftType.getArraySize()) - 1;
maxSize = static_cast<int>(leftType.getOutermostArraySize()) - 1;
}
else
{
......@@ -931,7 +925,7 @@ bool TOutputGLSLBase::visitFunctionPrototype(Visit visit, TIntermFunctionPrototy
const TType &type = node->getType();
writeVariableType(type);
if (type.isArray())
out << arrayBrackets(type);
out << ArrayString(type);
out << " " << hashFunctionNameIfNeeded(*node->getFunctionSymbolInfo());
......@@ -1226,7 +1220,7 @@ void TOutputGLSLBase::declareStruct(const TStructure *structure)
out << " ";
out << getTypeName(*field->type()) << " " << hashName(TName(field->name()));
if (field->type()->isArray())
out << arrayBrackets(*field->type());
out << ArrayString(*field->type());
out << ";\n";
}
out << "}";
......@@ -1294,7 +1288,7 @@ void TOutputGLSLBase::declareInterfaceBlock(const TInterfaceBlock *interfaceBloc
out << " ";
out << getTypeName(*field->type()) << " " << hashName(TName(field->name()));
if (field->type()->isArray())
out << arrayBrackets(*field->type());
out << ArrayString(*field->type());
out << ";\n";
}
out << "}";
......
......@@ -108,6 +108,7 @@ class OutputHLSL : public TIntermTraverser
const TConstantUnion *constUnion);
void outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out);
void outputAssign(Visit visit, const TType &type, TInfoSinkBase &out);
void writeEmulatedFunctionTriplet(TInfoSinkBase &out, Visit visit, TOperator op);
void makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flaggedStructs);
......
......@@ -484,8 +484,12 @@ class TParseContext : angle::NonCopyable
void checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type);
void checkBindingIsNotSpecified(const TSourceLoc &location, int binding);
void checkOffsetIsNotSpecified(const TSourceLoc &location, int offset);
void checkImageBindingIsValid(const TSourceLoc &location, int binding, int arraySize);
void checkSamplerBindingIsValid(const TSourceLoc &location, int binding, int arraySize);
void checkImageBindingIsValid(const TSourceLoc &location,
int binding,
int arrayTotalElementCount);
void checkSamplerBindingIsValid(const TSourceLoc &location,
int binding,
int arrayTotalElementCount);
void checkBlockBindingIsValid(const TSourceLoc &location,
const TQualifier &qualifier,
int binding,
......@@ -498,6 +502,10 @@ class TParseContext : angle::NonCopyable
void checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv);
bool checkUnsizedArrayConstructorArgumentDimensionality(TIntermSequence *arguments,
TType type,
const TSourceLoc &line);
TIntermTyped *addBinaryMathInternal(TOperator op,
TIntermTyped *left,
TIntermTyped *right,
......
......@@ -236,7 +236,10 @@ TString StructureHLSL::addConstructor(const TType &type,
}
TType ctorType = type;
ctorType.clearArrayness();
while (ctorType.isArray())
{
ctorType.toArrayElementType();
}
ctorType.setPrecision(EbpHigh);
ctorType.setQualifier(EvqTemporary);
......
......@@ -122,13 +122,15 @@ TType::TType(const TPublicType &p)
layoutQualifier(p.layoutQualifier),
primarySize(p.getPrimarySize()),
secondarySize(p.getSecondarySize()),
array(p.array),
arraySize(p.arraySize),
interfaceBlock(0),
structure(0)
{
ASSERT(primarySize <= 4);
ASSERT(secondarySize <= 4);
if (p.array)
{
makeArray(p.arraySize);
}
if (p.getUserDef())
structure = p.getUserDef();
}
......@@ -279,8 +281,11 @@ TString TType::getCompleteString() const
stream << getQualifierString() << " ";
if (precision != EbpUndefined)
stream << getPrecisionString() << " ";
if (array)
stream << "array[" << getArraySize() << "] of ";
for (auto arraySizeIter = mArraySizes.rbegin(); arraySizeIter != mArraySizes.rend();
++arraySizeIter)
{
stream << "array[" << (*arraySizeIter) << "] of ";
}
if (isMatrix())
stream << getCols() << "X" << getRows() << " matrix of ";
else if (isVector())
......@@ -442,7 +447,7 @@ TString TType::buildMangledName() const
mangledName += static_cast<char>('0' + getNominalSize());
}
if (isArray())
for (unsigned int arraySize : mArraySizes)
{
char buf[20];
snprintf(buf, sizeof(buf), "%d", arraySize);
......@@ -462,16 +467,15 @@ size_t TType::getObjectSize() const
else
totalSize = primarySize * secondarySize;
if (isArray())
{
if (totalSize == 0)
return 0;
if (totalSize == 0)
return 0;
size_t currentArraySize = getArraySize();
if (currentArraySize > INT_MAX / totalSize)
for (size_t arraySize : mArraySizes)
{
if (arraySize > INT_MAX / totalSize)
totalSize = INT_MAX;
else
totalSize *= currentArraySize;
totalSize *= arraySize;
}
return totalSize;
......@@ -486,27 +490,93 @@ int TType::getLocationCount() const
count = structure->getLocationCount();
}
if (isArray())
if (count == 0)
{
if (count == 0)
{
return 0;
}
return 0;
}
unsigned int currentArraySize = getArraySize();
if (currentArraySize > static_cast<unsigned int>(std::numeric_limits<int>::max() / count))
for (unsigned int arraySize : mArraySizes)
{
if (arraySize > static_cast<unsigned int>(std::numeric_limits<int>::max() / count))
{
count = std::numeric_limits<int>::max();
}
else
{
count *= static_cast<int>(currentArraySize);
count *= static_cast<int>(arraySize);
}
}
return count;
}
unsigned int TType::getArraySizeProduct() const
{
unsigned int product = 1u;
for (unsigned int arraySize : mArraySizes)
{
product *= arraySize;
}
return product;
}
bool TType::isUnsizedArray() const
{
for (unsigned int arraySize : mArraySizes)
{
if (arraySize == 0u)
{
return true;
}
}
return false;
}
bool TType::sameNonArrayType(const TType &right) const
{
return (type == right.type && primarySize == right.primarySize &&
secondarySize == right.secondarySize && structure == right.structure);
}
bool TType::isElementTypeOf(const TType &arrayType) const
{
if (!sameNonArrayType(arrayType))
{
return false;
}
if (arrayType.mArraySizes.size() != mArraySizes.size() + 1u)
{
return false;
}
for (size_t i = 0; i < mArraySizes.size(); ++i)
{
if (mArraySizes[i] != arrayType.mArraySizes[i])
{
return false;
}
}
return true;
}
void TType::sizeUnsizedArrays(const TVector<unsigned int> &arraySizes)
{
for (size_t i = 0u; i < mArraySizes.size(); ++i)
{
if (mArraySizes[i] == 0)
{
if (i < arraySizes.size())
{
mArraySizes[i] = arraySizes[i];
}
else
{
mArraySizes[i] = 1u;
}
}
}
invalidateMangledName();
}
TStructure::TStructure(TSymbolTable *symbolTable, const TString *name, TFieldList *fields)
: TFieldListCollection(name, fields),
mDeepestNesting(0),
......@@ -558,8 +628,8 @@ void TType::createSamplerSymbols(const TString &namePrefix,
if (isArray())
{
TType elementType(*this);
elementType.clearArrayness();
for (unsigned int arrayIndex = 0u; arrayIndex < getArraySize(); ++arrayIndex)
elementType.toArrayElementType();
for (unsigned int arrayIndex = 0u; arrayIndex < getOutermostArraySize(); ++arrayIndex)
{
TStringStream elementName;
elementName << namePrefix << "_" << arrayIndex;
......
......@@ -193,8 +193,6 @@ class TType
layoutQualifier(TLayoutQualifier::create()),
primarySize(0),
secondarySize(0),
array(false),
arraySize(0),
interfaceBlock(nullptr),
structure(nullptr)
{
......@@ -208,8 +206,6 @@ class TType
layoutQualifier(TLayoutQualifier::create()),
primarySize(ps),
secondarySize(ss),
array(false),
arraySize(0),
interfaceBlock(0),
structure(0)
{
......@@ -218,8 +214,7 @@ class TType
TPrecision p,
TQualifier q = EvqTemporary,
unsigned char ps = 1,
unsigned char ss = 1,
bool a = false)
unsigned char ss = 1)
: type(t),
precision(p),
qualifier(q),
......@@ -228,8 +223,6 @@ class TType
layoutQualifier(TLayoutQualifier::create()),
primarySize(ps),
secondarySize(ss),
array(a),
arraySize(0),
interfaceBlock(0),
structure(0)
{
......@@ -244,16 +237,13 @@ class TType
layoutQualifier(TLayoutQualifier::create()),
primarySize(1),
secondarySize(1),
array(false),
arraySize(0),
interfaceBlock(0),
structure(userDef)
{
}
TType(TInterfaceBlock *interfaceBlockIn,
TQualifier qualifierIn,
TLayoutQualifier layoutQualifierIn,
unsigned int arraySizeIn)
TLayoutQualifier layoutQualifierIn)
: type(EbtInterfaceBlock),
precision(EbpUndefined),
qualifier(qualifierIn),
......@@ -262,8 +252,6 @@ class TType
layoutQualifier(layoutQualifierIn),
primarySize(1),
secondarySize(1),
array(arraySizeIn > 0),
arraySize(arraySizeIn),
interfaceBlock(interfaceBlockIn),
structure(0)
{
......@@ -337,25 +325,38 @@ class TType
bool isMatrix() const { return primarySize > 1 && secondarySize > 1; }
bool isNonSquareMatrix() const { return isMatrix() && primarySize != secondarySize; }
bool isArray() const { return array; }
bool isUnsizedArray() const { return array && arraySize == 0u; }
unsigned int getArraySize() const { return arraySize; }
void setArraySize(unsigned int s)
{
if (!array || arraySize != s)
bool isArray() const { return !mArraySizes.empty(); }
bool isArrayOfArrays() const { return mArraySizes.size() > 1u; }
const TVector<unsigned int> &getArraySizes() const { return mArraySizes; }
unsigned int getArraySizeProduct() const;
bool isUnsizedArray() const;
unsigned int getOutermostArraySize() const { return mArraySizes.back(); }
void makeArray(unsigned int s)
{
mArraySizes.push_back(s);
invalidateMangledName();
}
// Here, the array dimension value 0 corresponds to the innermost array.
void setArraySize(size_t arrayDimension, unsigned int s)
{
ASSERT(arrayDimension < mArraySizes.size());
if (mArraySizes.at(arrayDimension) != s)
{
array = true;
arraySize = s;
mArraySizes[arrayDimension] = s;
invalidateMangledName();
}
}
void setArrayUnsized() { setArraySize(0u); }
void clearArrayness()
// Will set unsized array sizes according to arraySizes. In case there are more unsized arrays
// than there are sizes in arraySizes, defaults to setting array sizes to 1.
void sizeUnsizedArrays(const TVector<unsigned int> &arraySizes);
// Note that the array element type might still be an array type in GLSL ES version >= 3.10.
void toArrayElementType()
{
if (array)
if (mArraySizes.size() > 0)
{
array = false;
arraySize = 0u;
mArraySizes.pop_back();
invalidateMangledName();
}
}
......@@ -372,7 +373,10 @@ class TType
bool isInterfaceBlock() const { return type == EbtInterfaceBlock; }
bool isVector() const { return primarySize > 1 && secondarySize == 1; }
bool isScalar() const { return primarySize == 1 && secondarySize == 1 && !structure && !array; }
bool isScalar() const
{
return primarySize == 1 && secondarySize == 1 && !structure && !isArray();
}
bool isScalarFloat() const { return isScalar() && type == EbtFloat; }
bool isScalarInt() const { return isScalar() && (type == EbtInt || type == EbtUInt); }
......@@ -399,16 +403,16 @@ class TType
return mangled;
}
bool sameElementType(const TType &right) const
{
return type == right.type && primarySize == right.primarySize &&
secondarySize == right.secondarySize && structure == right.structure;
}
bool sameNonArrayType(const TType &right) const;
// Returns true if arrayType is an array made of this type.
bool isElementTypeOf(const TType &arrayType) const;
bool operator==(const TType &right) const
{
return type == right.type && primarySize == right.primarySize &&
secondarySize == right.secondarySize && array == right.array &&
(!array || arraySize == right.arraySize) && structure == right.structure;
secondarySize == right.secondarySize && mArraySizes == right.mArraySizes &&
structure == right.structure;
// don't check the qualifier, it's not ever what's being sought after
}
bool operator!=(const TType &right) const { return !operator==(right); }
......@@ -420,10 +424,13 @@ class TType
return primarySize < right.primarySize;
if (secondarySize != right.secondarySize)
return secondarySize < right.secondarySize;
if (array != right.array)
return array < right.array;
if (arraySize != right.arraySize)
return arraySize < right.arraySize;
if (mArraySizes.size() != right.mArraySizes.size())
return mArraySizes.size() < right.mArraySizes.size();
for (size_t i = 0; i < mArraySizes.size(); ++i)
{
if (mArraySizes[i] != right.mArraySizes[i])
return mArraySizes[i] < right.mArraySizes[i];
}
if (structure != right.structure)
return structure < right.structure;
......@@ -488,8 +495,10 @@ class TType
TLayoutQualifier layoutQualifier;
unsigned char primarySize; // size of vector or cols matrix
unsigned char secondarySize; // rows of a matrix
bool array;
unsigned int arraySize;
// Used to make an array type. Outermost array size is stored at the end of the vector. Having 0
// in this vector means an unsized array.
TVector<unsigned int> mArraySizes;
// This is set only in the following two cases:
// 1) Represents an interface block.
......
......@@ -18,6 +18,9 @@
namespace sh
{
namespace
{
static const char *UniformRegisterPrefix(const TType &type)
{
if (IsSampler(type.getBasicType()))
......@@ -61,6 +64,34 @@ static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock)
return DecoratePrivate(interfaceBlock.name()) + "_type";
}
void OutputSamplerIndexArrayInitializer(TInfoSinkBase &out,
const TType &type,
unsigned int startIndex)
{
out << "{";
TType elementType(type);
elementType.toArrayElementType();
for (unsigned int i = 0u; i < type.getOutermostArraySize(); ++i)
{
if (i > 0u)
{
out << ", ";
}
if (elementType.isArray())
{
OutputSamplerIndexArrayInitializer(out, elementType,
startIndex + i * elementType.getArraySizeProduct());
}
else
{
out << (startIndex + i);
}
}
out << "}";
}
} // anonymous namespace
UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL,
ShShaderOutput outputType,
const std::vector<Uniform> &uniforms)
......@@ -133,7 +164,7 @@ unsigned int UniformHLSL::assignSamplerInStructUniformRegister(const TType &type
ASSERT(IsSampler(type.getBasicType()));
unsigned int registerIndex = mSamplerRegister;
mUniformRegisterMap[std::string(name.c_str())] = registerIndex;
unsigned int registerCount = type.isArray() ? type.getArraySize() : 1u;
unsigned int registerCount = type.isArray() ? type.getArraySizeProduct() : 1u;
mSamplerRegister += registerCount;
if (outRegisterCount)
{
......@@ -179,14 +210,9 @@ void UniformHLSL::outputHLSLSamplerUniformGroup(
if (type.isArray())
{
out << "static const uint " << DecorateVariableIfNeeded(uniform->getName())
<< ArrayString(type) << " = {";
for (unsigned int i = 0u; i < type.getArraySize(); ++i)
{
if (i > 0u)
out << ", ";
out << (samplerArrayIndex + i);
}
out << "};\n";
<< ArrayString(type) << " = ";
OutputSamplerIndexArrayInitializer(out, type, samplerArrayIndex);
out << ";\n";
}
else
{
......@@ -365,8 +391,11 @@ TString UniformHLSL::uniformBlocksHeader(const ReferencedSymbols &referencedInte
// nodeType.isInterfaceBlock() == false means the node is a field of a uniform block which
// doesn't have instance name, so this block cannot be an array.
unsigned int interfaceBlockArraySize =
nodeType.isInterfaceBlock() ? nodeType.getArraySize() : 0;
unsigned int interfaceBlockArraySize = 0u;
if (nodeType.isInterfaceBlock() && nodeType.isArray())
{
interfaceBlockArraySize = nodeType.getOutermostArraySize();
}
unsigned int activeRegister = mUniformBlockRegister;
mUniformBlockRegisterMap[interfaceBlock.name().c_str()] = activeRegister;
......
......@@ -95,7 +95,9 @@ void ValidateOutputsTraverser::validate(TDiagnostics *diagnostics) const
for (const auto &symbol : mOutputs)
{
const TType &type = symbol->getType();
const size_t elementCount = static_cast<size_t>(type.isArray() ? type.getArraySize() : 1u);
ASSERT(!type.isArrayOfArrays()); // Disallowed in GLSL ES 3.10 section 4.3.6.
const size_t elementCount =
static_cast<size_t>(type.isArray() ? type.getOutermostArraySize() : 1u);
const size_t location = static_cast<size_t>(type.getLayoutQualifier().location);
ASSERT(type.getLayoutQualifier().location != -1);
......
......@@ -437,12 +437,14 @@ GLenum GLVariablePrecision(const TType &type)
TString ArrayString(const TType &type)
{
if (!type.isArray())
TStringStream arrayString;
const TVector<unsigned int> &arraySizes = type.getArraySizes();
for (auto arraySizeIter = arraySizes.rbegin(); arraySizeIter != arraySizes.rend();
++arraySizeIter)
{
return "";
arrayString << "[" << (*arraySizeIter) << "]";
}
return "[" + str(type.getArraySize()) + "]";
return arrayString.str();
}
bool IsVaryingOut(TQualifier qualifier)
......
......@@ -39,6 +39,9 @@ bool IsVaryingIn(TQualifier qualifier);
bool IsVaryingOut(TQualifier qualifier);
bool IsVarying(TQualifier qualifier);
InterpolationType GetInterpolationType(TQualifier qualifier);
// Returns array brackets including size with outermost array size first, as specified in GLSL ES
// 3.10 section 4.1.9.
TString ArrayString(const TType &type);
TType GetShaderVariableBasicType(const sh::ShaderVariable &var);
......
......@@ -71,7 +71,7 @@ ExpectedLValues CreateIndexedLValueNodeList(const TString &lValueName,
unsigned arraySize)
{
ASSERT(elementType.isArray() == false);
elementType.setArraySize(arraySize);
elementType.makeArray(arraySize);
ExpectedLValues expected(arraySize);
for (unsigned index = 0u; index < arraySize; ++index)
......
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