Commit 465835d6 by Olli Etuaho Committed by Commit Bot

Support arrays of arrays in the API

The ShaderVariable class that is used as an interface between the compiler and the rest of the code gets arrays of arrays support. Array of array variables are passed from the compiler just like any other variables. However, when stored in Program state each innermost array constitutes a separate variable. This is done to make the implementation match the GLES specification for program interface query APIs. This will be tested more fully once support for parsing arrays of arrays lands in the compiler. TEST=angle_end2end_tests, angle_unittests BUG=angleproject:2125 Change-Id: I0f7159000f039be92a87a52b3b68cd9a215a21cb Reviewed-on: https://chromium-review.googlesource.com/684742 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent acf2f3ad
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
// Version number for shader translation API. // Version number for shader translation API.
// It is incremented every time the API changes. // It is incremented every time the API changes.
#define ANGLE_SH_VERSION 189 #define ANGLE_SH_VERSION 190
enum ShShaderSpec enum ShShaderSpec
{ {
......
...@@ -68,13 +68,30 @@ struct ShaderVariable ...@@ -68,13 +68,30 @@ struct ShaderVariable
ShaderVariable(const ShaderVariable &other); ShaderVariable(const ShaderVariable &other);
ShaderVariable &operator=(const ShaderVariable &other); ShaderVariable &operator=(const ShaderVariable &other);
bool isArray() const { return arraySize > 0 || isUnsizedArray; } bool isArrayOfArrays() const { return arraySizes.size() >= 2u; }
unsigned int elementCount() const { return isUnsizedArray ? 0 : std::max(1u, arraySize); } bool isArray() const { return !arraySizes.empty(); }
bool isStruct() const { return !fields.empty(); } unsigned int getArraySizeProduct() const;
// Array size 0 means not an array when passed to or returned from these functions. // Array size 0 means not an array when passed to or returned from these functions.
unsigned int getOutermostArraySize() const { return arraySize; } // Note that setArraySize() is deprecated and should not be used inside ANGLE.
void setArraySize(unsigned int size) { arraySize = size; } unsigned int getOutermostArraySize() const { return isArray() ? arraySizes.back() : 0; }
void setArraySize(unsigned int size);
// Turn this ShaderVariable from an array into a specific element in that array. Will update
// flattenedOffsetInParentArrays.
void indexIntoArray(unsigned int arrayIndex);
// Get the nth nested array size from the top. Caller is responsible for range checking
// arrayNestingIndex.
unsigned int getNestedArraySize(unsigned int arrayNestingIndex) const;
// This function should only be used with variables that are of a basic type or an array of a
// basic type. Shader interface variables that are enumerated according to rules in GLES 3.1
// spec section 7.3.1.1 page 77 are fine. For those variables the return value should match the
// ARRAY_SIZE value that can be queried through the API.
unsigned int getBasicTypeElementCount() const;
bool isStruct() const { return !fields.empty(); }
// All of the shader's variables are described using nested data // All of the shader's variables are described using nested data
// structures. This is needed in order to disambiguate similar looking // structures. This is needed in order to disambiguate similar looking
...@@ -97,11 +114,21 @@ struct ShaderVariable ...@@ -97,11 +114,21 @@ struct ShaderVariable
GLenum precision; GLenum precision;
std::string name; std::string name;
std::string mappedName; std::string mappedName;
unsigned int arraySize;
// Used to make an array type. Outermost array size is stored at the end of the vector.
std::vector<unsigned int> arraySizes;
// Offset of this variable in parent arrays. In case the parent is an array of arrays, the
// offset is outerArrayElement * innerArraySize + innerArrayElement.
// For example, if there's a variable declared as size 3 array of size 4 array of int:
// int a[3][4];
// then the flattenedOffsetInParentArrays of a[2] would be 2.
// and flattenedOffsetInParentArrays of a[2][1] would be 2*4 + 1 = 9.
unsigned int flattenedOffsetInParentArrays;
bool staticUse; bool staticUse;
std::vector<ShaderVariable> fields; std::vector<ShaderVariable> fields;
std::string structName; std::string structName;
bool isUnsizedArray;
protected: protected:
bool isSameVariableAtLinkTime(const ShaderVariable &other, bool isSameVariableAtLinkTime(const ShaderVariable &other,
......
...@@ -560,9 +560,14 @@ void PrintVariable(const std::string &prefix, size_t index, const sh::ShaderVari ...@@ -560,9 +560,14 @@ void PrintVariable(const std::string &prefix, size_t index, const sh::ShaderVari
default: typeName = "UNKNOWN"; break; default: typeName = "UNKNOWN"; break;
} }
printf("%s %u : name=%s, mappedName=%s, type=%s, arraySize=%u\n", prefix.c_str(), printf("%s %u : name=%s, mappedName=%s, type=%s, arraySizes=", prefix.c_str(),
static_cast<unsigned int>(index), var.name.c_str(), var.mappedName.c_str(), static_cast<unsigned int>(index), var.name.c_str(), var.mappedName.c_str(),
typeName.c_str(), var.arraySize); typeName.c_str());
for (unsigned int arraySize : var.arraySizes)
{
printf("%u ", arraySize);
}
printf("\n");
if (var.fields.size()) if (var.fields.size())
{ {
std::string structPrefix; std::string structPrefix;
......
...@@ -770,6 +770,16 @@ std::string ParseResourceName(const std::string &name, std::vector<unsigned int> ...@@ -770,6 +770,16 @@ std::string ParseResourceName(const std::string &name, std::vector<unsigned int>
return name.substr(0, baseNameLength); return name.substr(0, baseNameLength);
} }
unsigned int ArraySizeProduct(const std::vector<unsigned int> &arraySizes)
{
unsigned int arraySizeProduct = 1u;
for (unsigned int arraySize : arraySizes)
{
arraySizeProduct *= arraySize;
}
return arraySizeProduct;
}
unsigned int ParseArrayIndex(const std::string &name, size_t *nameLengthWithoutArrayIndexOut) unsigned int ParseArrayIndex(const std::string &name, size_t *nameLengthWithoutArrayIndexOut)
{ {
ASSERT(nameLengthWithoutArrayIndexOut != nullptr); ASSERT(nameLengthWithoutArrayIndexOut != nullptr);
......
...@@ -70,6 +70,10 @@ GLuint GetPrimitiveRestartIndex(GLenum indexType); ...@@ -70,6 +70,10 @@ GLuint GetPrimitiveRestartIndex(GLenum indexType);
bool IsTriangleMode(GLenum drawMode); bool IsTriangleMode(GLenum drawMode);
bool IsIntegerFormat(GLenum unsizedFormat); bool IsIntegerFormat(GLenum unsizedFormat);
// Returns the product of the sizes in the vector, or 1 if the vector is empty. Doesn't currently
// perform overflow checks.
unsigned int ArraySizeProduct(const std::vector<unsigned int> &arraySizes);
// Return the array index at the end of name, and write the length of name before the final array // Return the array index at the end of name, and write the length of name before the final array
// index into nameLengthWithoutArrayIndexOut. In case name doesn't include an array index, return // index into nameLengthWithoutArrayIndexOut. In case name doesn't include an array index, return
// GL_INVALID_INDEX and write the length of the original string. // GL_INVALID_INDEX and write the length of the original string.
......
...@@ -262,8 +262,7 @@ void CollectVariablesTraverser::setBuiltInInfoFromSymbolTable(const char *name, ...@@ -262,8 +262,7 @@ void CollectVariablesTraverser::setBuiltInInfoFromSymbolTable(const char *name,
info->name = name; info->name = name;
info->mappedName = name; info->mappedName = name;
info->type = GLVariableType(type); info->type = GLVariableType(type);
ASSERT(!type.isArrayOfArrays()); info->arraySizes.assign(type.getArraySizes().begin(), type.getArraySizes().end());
info->arraySize = type.isArray() ? type.getOutermostArraySize() : 0;
info->precision = GLVariablePrecision(type); info->precision = GLVariablePrecision(type);
} }
...@@ -485,7 +484,8 @@ void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol) ...@@ -485,7 +484,8 @@ void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
setBuiltInInfoFromSymbolTable("gl_FragData", &info); setBuiltInInfoFromSymbolTable("gl_FragData", &info);
if (!IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers)) if (!IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))
{ {
info.arraySize = 1; ASSERT(info.arraySizes.size() == 1u);
info.arraySizes.back() = 1u;
} }
info.staticUse = true; info.staticUse = true;
mOutputVariables->push_back(info); mOutputVariables->push_back(info);
...@@ -581,10 +581,7 @@ void CollectVariablesTraverser::setCommonVariableProperties(const TType &type, ...@@ -581,10 +581,7 @@ void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
variableOut->name = name.getString().c_str(); variableOut->name = name.getString().c_str();
variableOut->mappedName = getMappedName(name); variableOut->mappedName = getMappedName(name);
// TODO(oetuaho@nvidia.com): Uniforms can be arrays of arrays, so this assert will need to be variableOut->arraySizes.assign(type.getArraySizes().begin(), type.getArraySizes().end());
// removed.
ASSERT(!type.isArrayOfArrays());
variableOut->arraySize = type.isArray() ? type.getOutermostArraySize() : 0;
} }
Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const
...@@ -677,7 +674,6 @@ void CollectVariablesTraverser::recordInterfaceBlock(const TType &interfaceBlock ...@@ -677,7 +674,6 @@ void CollectVariablesTraverser::recordInterfaceBlock(const TType &interfaceBlock
setCommonVariableProperties(fieldType, TName(field->name()), &fieldVariable); setCommonVariableProperties(fieldType, TName(field->name()), &fieldVariable);
fieldVariable.isRowMajorLayout = fieldVariable.isRowMajorLayout =
(fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor); (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
fieldVariable.isUnsizedArray = fieldType.isUnsizedArray();
interfaceBlock->fields.push_back(fieldVariable); interfaceBlock->fields.push_back(fieldVariable);
} }
} }
......
...@@ -119,7 +119,8 @@ void EmulateGLFragColorBroadcast(TIntermBlock *root, ...@@ -119,7 +119,8 @@ void EmulateGLFragColorBroadcast(TIntermBlock *root,
// TODO(zmo): Find a way to keep the original variable information. // TODO(zmo): Find a way to keep the original variable information.
var.name = "gl_FragData"; var.name = "gl_FragData";
var.mappedName = "gl_FragData"; var.mappedName = "gl_FragData";
var.arraySize = maxDrawBuffers; var.arraySizes.push_back(maxDrawBuffers);
ASSERT(var.arraySizes.size() == 1u);
} }
} }
} }
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <GLSLANG/ShaderLang.h> #include <GLSLANG/ShaderLang.h>
#include "common/debug.h" #include "common/debug.h"
#include "common/utilities.h"
namespace sh namespace sh
{ {
...@@ -31,19 +32,20 @@ bool InterpolationTypesMatch(InterpolationType a, InterpolationType b) ...@@ -31,19 +32,20 @@ bool InterpolationTypesMatch(InterpolationType a, InterpolationType b)
} }
ShaderVariable::ShaderVariable() ShaderVariable::ShaderVariable()
: type(0), precision(0), arraySize(0), staticUse(false), isUnsizedArray(false) : type(0), precision(0), flattenedOffsetInParentArrays(0), staticUse(false)
{ {
} }
ShaderVariable::ShaderVariable(GLenum typeIn) ShaderVariable::ShaderVariable(GLenum typeIn)
: type(typeIn), precision(0), arraySize(0), staticUse(false), isUnsizedArray(false) : type(typeIn), precision(0), flattenedOffsetInParentArrays(0), staticUse(false)
{ {
} }
ShaderVariable::ShaderVariable(GLenum typeIn, unsigned int arraySizeIn) ShaderVariable::ShaderVariable(GLenum typeIn, unsigned int arraySizeIn)
: type(typeIn), precision(0), arraySize(arraySizeIn), staticUse(false), isUnsizedArray(false) : type(typeIn), precision(0), flattenedOffsetInParentArrays(0), staticUse(false)
{ {
ASSERT(arraySizeIn != 0); ASSERT(arraySizeIn != 0);
arraySizes.push_back(arraySizeIn);
} }
ShaderVariable::~ShaderVariable() ShaderVariable::~ShaderVariable()
...@@ -55,11 +57,11 @@ ShaderVariable::ShaderVariable(const ShaderVariable &other) ...@@ -55,11 +57,11 @@ ShaderVariable::ShaderVariable(const ShaderVariable &other)
precision(other.precision), precision(other.precision),
name(other.name), name(other.name),
mappedName(other.mappedName), mappedName(other.mappedName),
arraySize(other.arraySize), arraySizes(other.arraySizes),
flattenedOffsetInParentArrays(other.flattenedOffsetInParentArrays),
staticUse(other.staticUse), staticUse(other.staticUse),
fields(other.fields), fields(other.fields),
structName(other.structName), structName(other.structName)
isUnsizedArray(other.isUnsizedArray)
{ {
} }
...@@ -69,20 +71,20 @@ ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other) ...@@ -69,20 +71,20 @@ ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other)
precision = other.precision; precision = other.precision;
name = other.name; name = other.name;
mappedName = other.mappedName; mappedName = other.mappedName;
arraySize = other.arraySize; arraySizes = other.arraySizes;
staticUse = other.staticUse; staticUse = other.staticUse;
flattenedOffsetInParentArrays = other.flattenedOffsetInParentArrays;
fields = other.fields; fields = other.fields;
structName = other.structName; structName = other.structName;
isUnsizedArray = other.isUnsizedArray;
return *this; return *this;
} }
bool ShaderVariable::operator==(const ShaderVariable &other) const bool ShaderVariable::operator==(const ShaderVariable &other) const
{ {
if (type != other.type || precision != other.precision || name != other.name || if (type != other.type || precision != other.precision || name != other.name ||
mappedName != other.mappedName || arraySize != other.arraySize || mappedName != other.mappedName || arraySizes != other.arraySizes ||
staticUse != other.staticUse || fields.size() != other.fields.size() || staticUse != other.staticUse || fields.size() != other.fields.size() ||
structName != other.structName || isUnsizedArray != other.isUnsizedArray) structName != other.structName)
{ {
return false; return false;
} }
...@@ -94,6 +96,49 @@ bool ShaderVariable::operator==(const ShaderVariable &other) const ...@@ -94,6 +96,49 @@ bool ShaderVariable::operator==(const ShaderVariable &other) const
return true; return true;
} }
void ShaderVariable::setArraySize(unsigned int size)
{
arraySizes.clear();
if (size != 0)
{
arraySizes.push_back(size);
}
}
unsigned int ShaderVariable::getArraySizeProduct() const
{
return gl::ArraySizeProduct(arraySizes);
}
void ShaderVariable::indexIntoArray(unsigned int arrayIndex)
{
ASSERT(isArray());
flattenedOffsetInParentArrays =
arrayIndex + getOutermostArraySize() * flattenedOffsetInParentArrays;
arraySizes.pop_back();
}
unsigned int ShaderVariable::getNestedArraySize(unsigned int arrayNestingIndex) const
{
ASSERT(arraySizes.size() > arrayNestingIndex);
return arraySizes[arraySizes.size() - 1u - arrayNestingIndex];
}
unsigned int ShaderVariable::getBasicTypeElementCount() const
{
// GLES 3.1 Nov 2016 section 7.3.1.1 page 77 specifies that a separate entry should be generated
// for each array element when dealing with an array of arrays or an array of structs.
ASSERT(!isArrayOfArrays());
ASSERT(!isStruct() || !isArray());
// GLES 3.1 Nov 2016 page 82.
if (isArray())
{
return getOutermostArraySize();
}
return 1u;
}
bool ShaderVariable::findInfoByMappedName(const std::string &mappedFullName, bool ShaderVariable::findInfoByMappedName(const std::string &mappedFullName,
const ShaderVariable **leafVar, const ShaderVariable **leafVar,
std::string *originalFullName) const std::string *originalFullName) const
...@@ -180,7 +225,7 @@ bool ShaderVariable::isSameVariableAtLinkTime(const ShaderVariable &other, ...@@ -180,7 +225,7 @@ bool ShaderVariable::isSameVariableAtLinkTime(const ShaderVariable &other,
if (matchName && name != other.name) if (matchName && name != other.name)
return false; return false;
ASSERT(!matchName || mappedName == other.mappedName); ASSERT(!matchName || mappedName == other.mappedName);
if (arraySize != other.arraySize) if (arraySizes != other.arraySizes)
return false; return false;
if (fields.size() != other.fields.size()) if (fields.size() != other.fields.size())
return false; return false;
...@@ -197,10 +242,6 @@ bool ShaderVariable::isSameVariableAtLinkTime(const ShaderVariable &other, ...@@ -197,10 +242,6 @@ bool ShaderVariable::isSameVariableAtLinkTime(const ShaderVariable &other,
} }
if (structName != other.structName) if (structName != other.structName)
return false; return false;
if (isUnsizedArray != other.isUnsizedArray)
{
return false;
}
return true; return true;
} }
......
...@@ -41,14 +41,24 @@ void ExpandStructVariable(const ShaderVariable &variable, ...@@ -41,14 +41,24 @@ void ExpandStructVariable(const ShaderVariable &variable,
} }
void ExpandStructArrayVariable(const ShaderVariable &variable, void ExpandStructArrayVariable(const ShaderVariable &variable,
unsigned int arrayNestingIndex,
const std::string &name, const std::string &name,
std::vector<ShaderVariable> *expanded) std::vector<ShaderVariable> *expanded)
{ {
for (unsigned int arrayElement = 0u; arrayElement < variable.getOutermostArraySize(); // Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the
++arrayElement) // innermost.
const unsigned int currentArraySize = variable.getNestedArraySize(arrayNestingIndex);
for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement)
{ {
const std::string elementName = name + ArrayString(arrayElement); const std::string elementName = name + ArrayString(arrayElement);
ExpandStructVariable(variable, elementName, expanded); if (arrayNestingIndex + 1u < variable.arraySizes.size())
{
ExpandStructArrayVariable(variable, arrayNestingIndex + 1u, elementName, expanded);
}
else
{
ExpandStructVariable(variable, elementName, expanded);
}
} }
} }
...@@ -60,7 +70,7 @@ void ExpandVariable(const ShaderVariable &variable, ...@@ -60,7 +70,7 @@ void ExpandVariable(const ShaderVariable &variable,
{ {
if (variable.isArray()) if (variable.isArray())
{ {
ExpandStructArrayVariable(variable, name, expanded); ExpandStructArrayVariable(variable, 0u, name, expanded);
} }
else else
{ {
...@@ -70,7 +80,6 @@ void ExpandVariable(const ShaderVariable &variable, ...@@ -70,7 +80,6 @@ void ExpandVariable(const ShaderVariable &variable,
else else
{ {
ShaderVariable expandedVar = variable; ShaderVariable expandedVar = variable;
expandedVar.name = name; expandedVar.name = name;
expanded->push_back(expandedVar); expanded->push_back(expandedVar);
...@@ -79,7 +88,7 @@ void ExpandVariable(const ShaderVariable &variable, ...@@ -79,7 +88,7 @@ void ExpandVariable(const ShaderVariable &variable,
int GetVariablePackingRows(const ShaderVariable &variable) int GetVariablePackingRows(const ShaderVariable &variable)
{ {
return GetTypePackingRows(variable.type) * variable.elementCount(); return GetTypePackingRows(variable.type) * variable.getArraySizeProduct();
} }
class VariablePacker class VariablePacker
...@@ -113,7 +122,7 @@ struct TVariableInfoComparer ...@@ -113,7 +122,7 @@ struct TVariableInfoComparer
return lhsSortOrder < rhsSortOrder; return lhsSortOrder < rhsSortOrder;
} }
// Sort by largest first. // Sort by largest first.
return lhs.arraySize > rhs.arraySize; return lhs.getArraySizeProduct() > rhs.getArraySizeProduct();
} }
}; };
...@@ -208,7 +217,7 @@ bool VariablePacker::checkExpandedVariablesWithinPackingLimits( ...@@ -208,7 +217,7 @@ bool VariablePacker::checkExpandedVariablesWithinPackingLimits(
{ {
// Structs should have been expanded before reaching here. // Structs should have been expanded before reaching here.
ASSERT(!variable.isStruct()); ASSERT(!variable.isStruct());
if (variable.elementCount() > maxVectors / GetTypePackingRows(variable.type)) if (variable.getArraySizeProduct() > maxVectors / GetTypePackingRows(variable.type))
{ {
return false; return false;
} }
......
...@@ -26,6 +26,46 @@ bool IsRowMajorLayout(const ShaderVariable &var) ...@@ -26,6 +26,46 @@ bool IsRowMajorLayout(const ShaderVariable &var)
{ {
return false; return false;
} }
template <typename VarT>
void GetUniformBlockStructMemberInfo(const std::vector<VarT> &fields,
const std::string &fieldName,
sh::BlockLayoutEncoder *encoder,
bool inRowMajorLayout,
BlockLayoutMap *blockInfoOut)
{
encoder->enterAggregateType();
GetUniformBlockInfo(fields, fieldName, encoder, inRowMajorLayout, blockInfoOut);
encoder->exitAggregateType();
}
template <typename VarT>
void GetUniformBlockStructArrayMemberInfo(const VarT &field,
unsigned int arrayNestingIndex,
const std::string &prefix,
sh::BlockLayoutEncoder *encoder,
bool inRowMajorLayout,
BlockLayoutMap *blockInfoOut)
{
// Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the
// innermost.
const unsigned int currentArraySize = field.getNestedArraySize(arrayNestingIndex);
for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++arrayElement)
{
const std::string elementName = prefix + ArrayString(arrayElement);
if (arrayNestingIndex + 1u < field.arraySizes.size())
{
GetUniformBlockStructArrayMemberInfo(field, arrayNestingIndex + 1u, elementName,
encoder, inRowMajorLayout, blockInfoOut);
}
else
{
GetUniformBlockStructMemberInfo(field.fields, elementName, encoder, inRowMajorLayout,
blockInfoOut);
}
}
}
} // anonymous namespace } // anonymous namespace
BlockLayoutEncoder::BlockLayoutEncoder() : mCurrentOffset(0) BlockLayoutEncoder::BlockLayoutEncoder() : mCurrentOffset(0)
...@@ -33,20 +73,20 @@ BlockLayoutEncoder::BlockLayoutEncoder() : mCurrentOffset(0) ...@@ -33,20 +73,20 @@ BlockLayoutEncoder::BlockLayoutEncoder() : mCurrentOffset(0)
} }
BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type,
unsigned int arraySize, const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix) bool isRowMajorMatrix)
{ {
int arrayStride; int arrayStride;
int matrixStride; int matrixStride;
getBlockLayoutInfo(type, arraySize, isRowMajorMatrix, &arrayStride, &matrixStride); getBlockLayoutInfo(type, arraySizes, isRowMajorMatrix, &arrayStride, &matrixStride);
const BlockMemberInfo memberInfo(static_cast<int>(mCurrentOffset * BytesPerComponent), const BlockMemberInfo memberInfo(static_cast<int>(mCurrentOffset * BytesPerComponent),
static_cast<int>(arrayStride * BytesPerComponent), static_cast<int>(arrayStride * BytesPerComponent),
static_cast<int>(matrixStride * BytesPerComponent), static_cast<int>(matrixStride * BytesPerComponent),
isRowMajorMatrix); isRowMajorMatrix);
advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride); advanceOffset(type, arraySizes, isRowMajorMatrix, arrayStride, matrixStride);
return memberInfo; return memberInfo;
} }
...@@ -83,7 +123,7 @@ void Std140BlockEncoder::exitAggregateType() ...@@ -83,7 +123,7 @@ void Std140BlockEncoder::exitAggregateType()
} }
void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, void Std140BlockEncoder::getBlockLayoutInfo(GLenum type,
unsigned int arraySize, const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix, bool isRowMajorMatrix,
int *arrayStrideOut, int *arrayStrideOut,
int *matrixStrideOut) int *matrixStrideOut)
...@@ -100,13 +140,13 @@ void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, ...@@ -100,13 +140,13 @@ void Std140BlockEncoder::getBlockLayoutInfo(GLenum type,
baseAlignment = ComponentsPerRegister; baseAlignment = ComponentsPerRegister;
matrixStride = ComponentsPerRegister; matrixStride = ComponentsPerRegister;
if (arraySize > 0) if (!arraySizes.empty())
{ {
const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
arrayStride = ComponentsPerRegister * numRegisters; arrayStride = ComponentsPerRegister * numRegisters;
} }
} }
else if (arraySize > 0) else if (!arraySizes.empty())
{ {
baseAlignment = ComponentsPerRegister; baseAlignment = ComponentsPerRegister;
arrayStride = ComponentsPerRegister; arrayStride = ComponentsPerRegister;
...@@ -124,14 +164,14 @@ void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, ...@@ -124,14 +164,14 @@ void Std140BlockEncoder::getBlockLayoutInfo(GLenum type,
} }
void Std140BlockEncoder::advanceOffset(GLenum type, void Std140BlockEncoder::advanceOffset(GLenum type,
unsigned int arraySize, const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix, bool isRowMajorMatrix,
int arrayStride, int arrayStride,
int matrixStride) int matrixStride)
{ {
if (arraySize > 0) if (!arraySizes.empty())
{ {
mCurrentOffset += arrayStride * arraySize; mCurrentOffset += arrayStride * gl::ArraySizeProduct(arraySizes);
} }
else if (gl::IsMatrixType(type)) else if (gl::IsMatrixType(type))
{ {
...@@ -148,13 +188,14 @@ void Std140BlockEncoder::advanceOffset(GLenum type, ...@@ -148,13 +188,14 @@ void Std140BlockEncoder::advanceOffset(GLenum type,
template <typename VarT> template <typename VarT>
void GetUniformBlockInfo(const std::vector<VarT> &fields, void GetUniformBlockInfo(const std::vector<VarT> &fields,
const std::string &prefix, const std::string &prefix,
BlockLayoutEncoder *encoder, sh::BlockLayoutEncoder *encoder,
bool inRowMajorLayout, bool inRowMajorLayout,
BlockLayoutMap *blockLayoutMap) BlockLayoutMap *blockInfoOut)
{ {
for (const VarT &field : fields) for (const VarT &field : fields)
{ {
// Skip samplers. // Skip samplers. On Vulkan we use this for the default uniform block, so samplers may be
// included.
if (gl::IsSamplerType(field.type)) if (gl::IsSamplerType(field.type))
{ {
continue; continue;
...@@ -166,25 +207,22 @@ void GetUniformBlockInfo(const std::vector<VarT> &fields, ...@@ -166,25 +207,22 @@ void GetUniformBlockInfo(const std::vector<VarT> &fields,
{ {
bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field)); bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++) if (field.isArray())
{ {
encoder->enterAggregateType(); GetUniformBlockStructArrayMemberInfo(field, 0u, fieldName, encoder, rowMajorLayout,
blockInfoOut);
const std::string uniformElementName = }
fieldName + (field.isArray() ? ArrayString(arrayElement) : ""); else
GetUniformBlockInfo(field.fields, uniformElementName, encoder, rowMajorLayout, {
blockLayoutMap); GetUniformBlockStructMemberInfo(field.fields, fieldName, encoder, rowMajorLayout,
blockInfoOut);
encoder->exitAggregateType();
} }
} }
else else
{ {
bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout); bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
const BlockMemberInfo &blockMemberInfo = (*blockInfoOut)[fieldName] =
encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix); encoder->encodeType(field.type, field.arraySizes, isRowMajorMatrix);
(*blockLayoutMap)[fieldName] = blockMemberInfo;
} }
} }
} }
......
...@@ -73,7 +73,9 @@ class BlockLayoutEncoder ...@@ -73,7 +73,9 @@ class BlockLayoutEncoder
BlockLayoutEncoder(); BlockLayoutEncoder();
virtual ~BlockLayoutEncoder() {} virtual ~BlockLayoutEncoder() {}
BlockMemberInfo encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix); BlockMemberInfo encodeType(GLenum type,
const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix);
size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; } size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; }
...@@ -92,15 +94,15 @@ class BlockLayoutEncoder ...@@ -92,15 +94,15 @@ class BlockLayoutEncoder
void nextRegister(); void nextRegister();
virtual void getBlockLayoutInfo(GLenum type, virtual void getBlockLayoutInfo(GLenum type,
unsigned int arraySize, const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix, bool isRowMajorMatrix,
int *arrayStrideOut, int *arrayStrideOut,
int *matrixStrideOut) = 0; int *matrixStrideOut) = 0;
virtual void advanceOffset(GLenum type, virtual void advanceOffset(GLenum type,
unsigned int arraySize, const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix, bool isRowMajorMatrix,
int arrayStride, int arrayStride,
int matrixStride) = 0; int matrixStride) = 0;
}; };
// Block layout according to the std140 block layout // Block layout according to the std140 block layout
...@@ -116,12 +118,12 @@ class Std140BlockEncoder : public BlockLayoutEncoder ...@@ -116,12 +118,12 @@ class Std140BlockEncoder : public BlockLayoutEncoder
protected: protected:
void getBlockLayoutInfo(GLenum type, void getBlockLayoutInfo(GLenum type,
unsigned int arraySize, const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix, bool isRowMajorMatrix,
int *arrayStrideOut, int *arrayStrideOut,
int *matrixStrideOut) override; int *matrixStrideOut) override;
void advanceOffset(GLenum type, void advanceOffset(GLenum type,
unsigned int arraySize, const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix, bool isRowMajorMatrix,
int arrayStride, int arrayStride,
int matrixStride) override; int matrixStride) override;
......
...@@ -30,7 +30,7 @@ void HLSLBlockEncoder::exitAggregateType() ...@@ -30,7 +30,7 @@ void HLSLBlockEncoder::exitAggregateType()
} }
void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn, void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn,
unsigned int arraySize, const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix, bool isRowMajorMatrix,
int *arrayStrideOut, int *arrayStrideOut,
int *matrixStrideOut) int *matrixStrideOut)
...@@ -46,7 +46,7 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn, ...@@ -46,7 +46,7 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn,
// if variables are not to be packed, or we're about to // if variables are not to be packed, or we're about to
// pack a matrix or array, skip to the start of the next // pack a matrix or array, skip to the start of the next
// register // register
if (!isPacked() || gl::IsMatrixType(type) || arraySize > 0) if (!isPacked() || gl::IsMatrixType(type) || !arraySizes.empty())
{ {
nextRegister(); nextRegister();
} }
...@@ -55,13 +55,13 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn, ...@@ -55,13 +55,13 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn,
{ {
matrixStride = ComponentsPerRegister; matrixStride = ComponentsPerRegister;
if (arraySize > 0) if (!arraySizes.empty())
{ {
const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
arrayStride = ComponentsPerRegister * numRegisters; arrayStride = ComponentsPerRegister * numRegisters;
} }
} }
else if (arraySize > 0) else if (!arraySizes.empty())
{ {
arrayStride = ComponentsPerRegister; arrayStride = ComponentsPerRegister;
} }
...@@ -79,16 +79,16 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn, ...@@ -79,16 +79,16 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn,
} }
void HLSLBlockEncoder::advanceOffset(GLenum typeIn, void HLSLBlockEncoder::advanceOffset(GLenum typeIn,
unsigned int arraySize, const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix, bool isRowMajorMatrix,
int arrayStride, int arrayStride,
int matrixStride) int matrixStride)
{ {
GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn); GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn);
if (arraySize > 0) if (!arraySizes.empty())
{ {
mCurrentOffset += arrayStride * (arraySize - 1); mCurrentOffset += arrayStride * (gl::ArraySizeProduct(arraySizes) - 1);
} }
if (gl::IsMatrixType(type)) if (gl::IsMatrixType(type))
...@@ -135,7 +135,7 @@ void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder * ...@@ -135,7 +135,7 @@ void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *
{ {
if (variable.isStruct()) if (variable.isStruct())
{ {
for (size_t arrayElement = 0; arrayElement < variable.elementCount(); arrayElement++) for (size_t arrayElement = 0; arrayElement < variable.getArraySizeProduct(); arrayElement++)
{ {
encoder->enterAggregateType(); encoder->enterAggregateType();
...@@ -150,7 +150,7 @@ void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder * ...@@ -150,7 +150,7 @@ void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *
else else
{ {
// We operate only on varyings and uniforms, which do not have matrix layout qualifiers // We operate only on varyings and uniforms, which do not have matrix layout qualifiers
encoder->encodeType(variable.type, variable.arraySize, false); encoder->encodeType(variable.type, variable.arraySizes, false);
} }
} }
......
...@@ -45,12 +45,12 @@ class HLSLBlockEncoder : public BlockLayoutEncoder ...@@ -45,12 +45,12 @@ class HLSLBlockEncoder : public BlockLayoutEncoder
protected: protected:
void getBlockLayoutInfo(GLenum type, void getBlockLayoutInfo(GLenum type,
unsigned int arraySize, const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix, bool isRowMajorMatrix,
int *arrayStrideOut, int *arrayStrideOut,
int *matrixStrideOut) override; int *matrixStrideOut) override;
void advanceOffset(GLenum type, void advanceOffset(GLenum type,
unsigned int arraySize, const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix, bool isRowMajorMatrix,
int arrayStride, int arrayStride,
int matrixStride) override; int matrixStride) override;
......
...@@ -42,7 +42,7 @@ void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var) ...@@ -42,7 +42,7 @@ void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
stream->writeInt(var.precision); stream->writeInt(var.precision);
stream->writeString(var.name); stream->writeString(var.name);
stream->writeString(var.mappedName); stream->writeString(var.mappedName);
stream->writeInt(var.arraySize); stream->writeIntVector(var.arraySizes);
stream->writeInt(var.staticUse); stream->writeInt(var.staticUse);
stream->writeString(var.structName); stream->writeString(var.structName);
ASSERT(var.fields.empty()); ASSERT(var.fields.empty());
...@@ -54,7 +54,7 @@ void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var) ...@@ -54,7 +54,7 @@ void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var)
var->precision = stream->readInt<GLenum>(); var->precision = stream->readInt<GLenum>();
var->name = stream->readString(); var->name = stream->readString();
var->mappedName = stream->readString(); var->mappedName = stream->readString();
var->arraySize = stream->readInt<unsigned int>(); stream->readIntVector<unsigned int>(&var->arraySizes);
var->staticUse = stream->readBool(); var->staticUse = stream->readBool();
var->structName = stream->readString(); var->structName = stream->readString();
} }
...@@ -334,7 +334,7 @@ LinkResult MemoryProgramCache::Deserialize(const Context *context, ...@@ -334,7 +334,7 @@ LinkResult MemoryProgramCache::Deserialize(const Context *context,
++transformFeedbackVaryingIndex) ++transformFeedbackVaryingIndex)
{ {
sh::Varying varying; sh::Varying varying;
stream.readInt(&varying.arraySize); stream.readIntVector<unsigned int>(&varying.arraySizes);
stream.readInt(&varying.type); stream.readInt(&varying.type);
stream.readString(&varying.name); stream.readString(&varying.name);
...@@ -508,7 +508,7 @@ void MemoryProgramCache::Serialize(const Context *context, ...@@ -508,7 +508,7 @@ void MemoryProgramCache::Serialize(const Context *context,
stream.writeInt(state.getLinkedTransformFeedbackVaryings().size()); stream.writeInt(state.getLinkedTransformFeedbackVaryings().size());
for (const auto &var : state.getLinkedTransformFeedbackVaryings()) for (const auto &var : state.getLinkedTransformFeedbackVaryings())
{ {
stream.writeInt(var.arraySize); stream.writeIntVector(var.arraySizes);
stream.writeInt(var.type); stream.writeInt(var.type);
stream.writeString(var.name); stream.writeString(var.name);
......
...@@ -106,7 +106,6 @@ void UniformStateQueryCastLoop(DestT *dataOut, const uint8_t *srcPointer, int co ...@@ -106,7 +106,6 @@ void UniformStateQueryCastLoop(DestT *dataOut, const uint8_t *srcPointer, int co
} }
} }
template <typename VarT> template <typename VarT>
GLuint GetResourceIndexFromName(const std::vector<VarT> &list, const std::string &name) GLuint GetResourceIndexFromName(const std::vector<VarT> &list, const std::string &name)
{ {
...@@ -1375,7 +1374,7 @@ void Program::getActiveUniform(GLuint index, ...@@ -1375,7 +1374,7 @@ void Program::getActiveUniform(GLuint index,
CopyStringToBuffer(name, string, bufsize, length); CopyStringToBuffer(name, string, bufsize, length);
} }
*size = uniform.elementCount(); *size = clampCast<GLint>(uniform.getBasicTypeElementCount());
*type = uniform.type; *type = uniform.type;
} }
else else
...@@ -2078,12 +2077,13 @@ void Program::linkSamplerAndImageBindings() ...@@ -2078,12 +2077,13 @@ void Program::linkSamplerAndImageBindings()
auto &imageUniform = mState.mUniforms[imageIndex]; auto &imageUniform = mState.mUniforms[imageIndex];
if (imageUniform.binding == -1) if (imageUniform.binding == -1)
{ {
mState.mImageBindings.emplace_back(ImageBinding(imageUniform.elementCount())); mState.mImageBindings.emplace_back(
ImageBinding(imageUniform.getBasicTypeElementCount()));
} }
else else
{ {
mState.mImageBindings.emplace_back( mState.mImageBindings.emplace_back(
ImageBinding(imageUniform.binding, imageUniform.elementCount())); ImageBinding(imageUniform.binding, imageUniform.getBasicTypeElementCount()));
} }
} }
...@@ -2103,7 +2103,7 @@ void Program::linkSamplerAndImageBindings() ...@@ -2103,7 +2103,7 @@ void Program::linkSamplerAndImageBindings()
const auto &samplerUniform = mState.mUniforms[samplerIndex]; const auto &samplerUniform = mState.mUniforms[samplerIndex];
GLenum textureType = SamplerTypeToTextureType(samplerUniform.type); GLenum textureType = SamplerTypeToTextureType(samplerUniform.type);
mState.mSamplerBindings.emplace_back( mState.mSamplerBindings.emplace_back(
SamplerBinding(textureType, samplerUniform.elementCount(), false)); SamplerBinding(textureType, samplerUniform.getBasicTypeElementCount(), false));
} }
} }
...@@ -2455,7 +2455,7 @@ bool Program::linkValidateVariablesBase(InfoLog &infoLog, const std::string &var ...@@ -2455,7 +2455,7 @@ bool Program::linkValidateVariablesBase(InfoLog &infoLog, const std::string &var
infoLog << "Types for " << variableName << " differ between vertex and fragment shaders"; infoLog << "Types for " << variableName << " differ between vertex and fragment shaders";
return false; return false;
} }
if (vertexVariable.arraySize != fragmentVariable.arraySize) if (vertexVariable.arraySizes != fragmentVariable.arraySizes)
{ {
infoLog << "Array sizes for " << variableName << " differ between vertex and fragment shaders"; infoLog << "Array sizes for " << variableName << " differ between vertex and fragment shaders";
return false; return false;
...@@ -2649,8 +2649,12 @@ bool Program::linkValidateTransformFeedback(const gl::Context *context, ...@@ -2649,8 +2649,12 @@ bool Program::linkValidateTransformFeedback(const gl::Context *context,
uniqueNames.insert(tfVaryingName); uniqueNames.insert(tfVaryingName);
// TODO(jmadill): Investigate implementation limits on D3D11 // TODO(jmadill): Investigate implementation limits on D3D11
// GLSL ES 3.10 section 4.3.6: A vertex output can't be an array of arrays.
ASSERT(!varying->isArrayOfArrays());
size_t elementCount = size_t elementCount =
((varying->isArray() && subscripts.empty()) ? varying->elementCount() : 1); ((varying->isArray() && subscripts.empty()) ? varying->getOutermostArraySize()
: 1);
size_t componentCount = VariableComponentCount(varying->type) * elementCount; size_t componentCount = VariableComponentCount(varying->type) * elementCount;
if (mState.mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS && if (mState.mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
componentCount > caps.maxTransformFeedbackSeparateComponents) componentCount > caps.maxTransformFeedbackSeparateComponents)
...@@ -2786,8 +2790,11 @@ void Program::linkOutputVariables(const Context *context) ...@@ -2786,8 +2790,11 @@ void Program::linkOutputVariables(const Context *context)
unsigned int baseLocation = unsigned int baseLocation =
(outputVariable.location == -1 ? 0u (outputVariable.location == -1 ? 0u
: static_cast<unsigned int>(outputVariable.location)); : static_cast<unsigned int>(outputVariable.location));
for (unsigned int elementIndex = 0; elementIndex < outputVariable.elementCount();
elementIndex++) // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
// structures, so we may use getBasicTypeElementCount().
unsigned int elementCount = outputVariable.getBasicTypeElementCount();
for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
{ {
const unsigned int location = baseLocation + elementIndex; const unsigned int location = baseLocation + elementIndex;
if (location >= mState.mOutputVariableTypes.size()) if (location >= mState.mOutputVariableTypes.size())
...@@ -2829,8 +2836,10 @@ void Program::linkOutputVariables(const Context *context) ...@@ -2829,8 +2836,10 @@ void Program::linkOutputVariables(const Context *context)
(outputVariable.location == -1 ? 0u (outputVariable.location == -1 ? 0u
: static_cast<unsigned int>(outputVariable.location)); : static_cast<unsigned int>(outputVariable.location));
for (unsigned int elementIndex = 0; elementIndex < outputVariable.elementCount(); // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
elementIndex++) // structures, so we may use getBasicTypeElementCount().
unsigned int elementCount = outputVariable.getBasicTypeElementCount();
for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
{ {
const unsigned int location = baseLocation + elementIndex; const unsigned int location = baseLocation + elementIndex;
if (location >= mState.mOutputLocations.size()) if (location >= mState.mOutputLocations.size())
...@@ -2863,8 +2872,8 @@ void Program::setUniformValuesFromBindingQualifiers() ...@@ -2863,8 +2872,8 @@ void Program::setUniformValuesFromBindingQualifiers()
GLint location = getUniformLocation(samplerUniform.name); GLint location = getUniformLocation(samplerUniform.name);
ASSERT(location != -1); ASSERT(location != -1);
std::vector<GLint> boundTextureUnits; std::vector<GLint> boundTextureUnits;
for (unsigned int elementIndex = 0; elementIndex < samplerUniform.elementCount(); for (unsigned int elementIndex = 0;
++elementIndex) elementIndex < samplerUniform.getBasicTypeElementCount(); ++elementIndex)
{ {
boundTextureUnits.push_back(samplerUniform.binding + elementIndex); boundTextureUnits.push_back(samplerUniform.binding + elementIndex);
} }
...@@ -2926,7 +2935,8 @@ GLsizei Program::clampUniformCount(const VariableLocation &locationInfo, ...@@ -2926,7 +2935,8 @@ GLsizei Program::clampUniformCount(const VariableLocation &locationInfo,
// OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
// element index used, as reported by GetActiveUniform, will be ignored by the GL." // element index used, as reported by GetActiveUniform, will be ignored by the GL."
unsigned int remainingElements = linkedUniform.elementCount() - locationInfo.arrayIndex; unsigned int remainingElements =
linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
GLsizei maxElementCount = GLsizei maxElementCount =
static_cast<GLsizei>(remainingElements * linkedUniform.getElementComponents()); static_cast<GLsizei>(remainingElements * linkedUniform.getElementComponents());
...@@ -2955,7 +2965,8 @@ GLsizei Program::clampMatrixUniformCount(GLint location, ...@@ -2955,7 +2965,8 @@ GLsizei Program::clampMatrixUniformCount(GLint location,
// OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
// element index used, as reported by GetActiveUniform, will be ignored by the GL." // element index used, as reported by GetActiveUniform, will be ignored by the GL."
unsigned int remainingElements = linkedUniform.elementCount() - locationInfo.arrayIndex; unsigned int remainingElements =
linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
return std::min(count, static_cast<GLsizei>(remainingElements)); return std::min(count, static_cast<GLsizei>(remainingElements));
} }
......
...@@ -199,6 +199,7 @@ struct TransformFeedbackVarying : public sh::Varying ...@@ -199,6 +199,7 @@ struct TransformFeedbackVarying : public sh::Varying
TransformFeedbackVarying(const sh::Varying &varyingIn, GLuint index) TransformFeedbackVarying(const sh::Varying &varyingIn, GLuint index)
: sh::Varying(varyingIn), arrayIndex(index) : sh::Varying(varyingIn), arrayIndex(index)
{ {
ASSERT(!isArrayOfArrays());
} }
std::string nameWithArrayIndex() const std::string nameWithArrayIndex() const
{ {
...@@ -210,7 +211,10 @@ struct TransformFeedbackVarying : public sh::Varying ...@@ -210,7 +211,10 @@ struct TransformFeedbackVarying : public sh::Varying
} }
return fullNameStr.str(); return fullNameStr.str();
} }
GLsizei size() const { return (arrayIndex == GL_INVALID_INDEX ? elementCount() : 1); } GLsizei size() const
{
return (isArray() && arrayIndex == GL_INVALID_INDEX ? getOutermostArraySize() : 1);
}
GLuint arrayIndex; GLuint arrayIndex;
}; };
......
...@@ -88,6 +88,44 @@ class UniformLinker ...@@ -88,6 +88,44 @@ class UniformLinker
std::vector<LinkedUniform> *atomicCounterUniforms, std::vector<LinkedUniform> *atomicCounterUniforms,
GLenum shaderType); GLenum shaderType);
ShaderUniformCount flattenArrayOfStructsUniform(
const sh::ShaderVariable &uniform,
unsigned int arrayNestingIndex,
const std::string &namePrefix,
const std::string &mappedNamePrefix,
std::vector<LinkedUniform> *samplerUniforms,
std::vector<LinkedUniform> *imageUniforms,
std::vector<LinkedUniform> *atomicCounterUniforms,
GLenum shaderType,
bool markStaticUse,
int binding,
int offset,
int *location);
ShaderUniformCount flattenStructUniform(const std::vector<sh::ShaderVariable> &fields,
const std::string &namePrefix,
const std::string &mappedNamePrefix,
std::vector<LinkedUniform> *samplerUniforms,
std::vector<LinkedUniform> *imageUniforms,
std::vector<LinkedUniform> *atomicCounterUniforms,
GLenum shaderType,
bool markStaticUse,
int binding,
int offset,
int *location);
ShaderUniformCount flattenArrayUniform(const sh::ShaderVariable &uniform,
const std::string &fullName,
const std::string &fullMappedName,
std::vector<LinkedUniform> *samplerUniforms,
std::vector<LinkedUniform> *imageUniforms,
std::vector<LinkedUniform> *atomicCounterUniforms,
GLenum shaderType,
bool markStaticUse,
int binding,
int offset,
int *location);
// markStaticUse is given as a separate parameter because it is tracked here at struct // markStaticUse is given as a separate parameter because it is tracked here at struct
// granularity. // granularity.
ShaderUniformCount flattenUniformImpl(const sh::ShaderVariable &uniform, ShaderUniformCount flattenUniformImpl(const sh::ShaderVariable &uniform,
...@@ -149,21 +187,40 @@ class InterfaceBlockLinker : angle::NonCopyable ...@@ -149,21 +187,40 @@ class InterfaceBlockLinker : angle::NonCopyable
const std::string &prefix, const std::string &prefix,
const std::string &mappedPrefix, const std::string &mappedPrefix,
int blockIndex, int blockIndex,
bool outsideTopLevelArray, bool singleEntryForTopLevelArray,
int topLevelArraySize) const; int topLevelArraySize) const;
template <typename VarT>
virtual void defineBlockMember(const sh::ShaderVariable &field, void defineBlockMember(const GetBlockMemberInfo &getMemberInfo,
const std::string &fullName, const VarT &field,
const std::string &fullMappedName, const std::string &fullName,
int blockIndex, const std::string &fullMappedName,
const sh::BlockMemberInfo &memberInfo, int blockIndex,
int topLevelArraySize) const = 0; bool singleEntryForTopLevelArray,
int topLevelArraySize) const;
virtual void defineBlockMemberImpl(const sh::ShaderVariable &field,
const std::string &fullName,
const std::string &fullMappedName,
int blockIndex,
const sh::BlockMemberInfo &memberInfo,
int topLevelArraySize) const = 0;
virtual size_t getCurrentBlockMemberIndex() const = 0; virtual size_t getCurrentBlockMemberIndex() const = 0;
using ShaderBlocks = std::pair<GLenum, const std::vector<sh::InterfaceBlock> *>; using ShaderBlocks = std::pair<GLenum, const std::vector<sh::InterfaceBlock> *>;
std::vector<ShaderBlocks> mShaderBlocks; std::vector<ShaderBlocks> mShaderBlocks;
std::vector<InterfaceBlock> *mBlocksOut; std::vector<InterfaceBlock> *mBlocksOut;
private:
template <typename VarT>
void defineArrayOfStructsBlockMembers(const GetBlockMemberInfo &getMemberInfo,
const VarT &field,
unsigned int arrayNestingIndex,
const std::string &prefix,
const std::string &mappedPrefix,
int blockIndex,
bool singleEntryForTopLevelArray,
int topLevelArraySize) const;
}; };
class UniformBlockLinker final : public InterfaceBlockLinker class UniformBlockLinker final : public InterfaceBlockLinker
...@@ -174,12 +231,12 @@ class UniformBlockLinker final : public InterfaceBlockLinker ...@@ -174,12 +231,12 @@ class UniformBlockLinker final : public InterfaceBlockLinker
~UniformBlockLinker() override; ~UniformBlockLinker() override;
private: private:
void defineBlockMember(const sh::ShaderVariable &field, void defineBlockMemberImpl(const sh::ShaderVariable &field,
const std::string &fullName, const std::string &fullName,
const std::string &fullMappedName, const std::string &fullMappedName,
int blockIndex, int blockIndex,
const sh::BlockMemberInfo &memberInfo, const sh::BlockMemberInfo &memberInfo,
int topLevelArraySize) const override; int topLevelArraySize) const override;
size_t getCurrentBlockMemberIndex() const override; size_t getCurrentBlockMemberIndex() const override;
std::vector<LinkedUniform> *mUniformsOut; std::vector<LinkedUniform> *mUniformsOut;
}; };
...@@ -192,12 +249,12 @@ class ShaderStorageBlockLinker final : public InterfaceBlockLinker ...@@ -192,12 +249,12 @@ class ShaderStorageBlockLinker final : public InterfaceBlockLinker
~ShaderStorageBlockLinker() override; ~ShaderStorageBlockLinker() override;
private: private:
void defineBlockMember(const sh::ShaderVariable &field, void defineBlockMemberImpl(const sh::ShaderVariable &field,
const std::string &fullName, const std::string &fullName,
const std::string &fullMappedName, const std::string &fullMappedName,
int blockIndex, int blockIndex,
const sh::BlockMemberInfo &memberInfo, const sh::BlockMemberInfo &memberInfo,
int topLevelArraySize) const override; int topLevelArraySize) const override;
size_t getCurrentBlockMemberIndex() const override; size_t getCurrentBlockMemberIndex() const override;
std::vector<BufferVariable> *mBufferVariablesOut; std::vector<BufferVariable> *mBufferVariablesOut;
}; };
......
...@@ -57,7 +57,7 @@ bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y) ...@@ -57,7 +57,7 @@ bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y)
{ {
if (x.type == y.type) if (x.type == y.type)
{ {
return x.arraySize > y.arraySize; return x.getArraySizeProduct() > y.getArraySizeProduct();
} }
// Special case for handling structs: we sort these to the end of the list // Special case for handling structs: we sort these to the end of the list
......
...@@ -61,7 +61,7 @@ LinkedUniform::LinkedUniform() ...@@ -61,7 +61,7 @@ LinkedUniform::LinkedUniform()
LinkedUniform::LinkedUniform(GLenum typeIn, LinkedUniform::LinkedUniform(GLenum typeIn,
GLenum precisionIn, GLenum precisionIn,
const std::string &nameIn, const std::string &nameIn,
unsigned int arraySizeIn, const std::vector<unsigned int> &arraySizesIn,
const int bindingIn, const int bindingIn,
const int offsetIn, const int offsetIn,
const int locationIn, const int locationIn,
...@@ -72,10 +72,12 @@ LinkedUniform::LinkedUniform(GLenum typeIn, ...@@ -72,10 +72,12 @@ LinkedUniform::LinkedUniform(GLenum typeIn,
type = typeIn; type = typeIn;
precision = precisionIn; precision = precisionIn;
name = nameIn; name = nameIn;
arraySize = arraySizeIn; arraySizes = arraySizesIn;
binding = bindingIn; binding = bindingIn;
offset = offsetIn; offset = offsetIn;
location = locationIn; location = locationIn;
ASSERT(!isArrayOfArrays());
ASSERT(!isArray() || !isStruct());
} }
LinkedUniform::LinkedUniform(const sh::Uniform &uniform) LinkedUniform::LinkedUniform(const sh::Uniform &uniform)
...@@ -84,6 +86,8 @@ LinkedUniform::LinkedUniform(const sh::Uniform &uniform) ...@@ -84,6 +86,8 @@ LinkedUniform::LinkedUniform(const sh::Uniform &uniform)
bufferIndex(-1), bufferIndex(-1),
blockInfo(sh::BlockMemberInfo::getDefaultBlockInfo()) blockInfo(sh::BlockMemberInfo::getDefaultBlockInfo())
{ {
ASSERT(!isArrayOfArrays());
ASSERT(!isArray() || !isStruct());
} }
LinkedUniform::LinkedUniform(const LinkedUniform &uniform) LinkedUniform::LinkedUniform(const LinkedUniform &uniform)
...@@ -152,7 +156,7 @@ BufferVariable::BufferVariable() ...@@ -152,7 +156,7 @@ BufferVariable::BufferVariable()
BufferVariable::BufferVariable(GLenum typeIn, BufferVariable::BufferVariable(GLenum typeIn,
GLenum precisionIn, GLenum precisionIn,
const std::string &nameIn, const std::string &nameIn,
unsigned int arraySizeIn, const std::vector<unsigned int> &arraySizesIn,
const int bufferIndexIn, const int bufferIndexIn,
const sh::BlockMemberInfo &blockInfoIn) const sh::BlockMemberInfo &blockInfoIn)
: bufferIndex(bufferIndexIn), blockInfo(blockInfoIn), topLevelArraySize(-1) : bufferIndex(bufferIndexIn), blockInfo(blockInfoIn), topLevelArraySize(-1)
...@@ -160,7 +164,7 @@ BufferVariable::BufferVariable(GLenum typeIn, ...@@ -160,7 +164,7 @@ BufferVariable::BufferVariable(GLenum typeIn,
type = typeIn; type = typeIn;
precision = precisionIn; precision = precisionIn;
name = nameIn; name = nameIn;
arraySize = arraySizeIn; arraySizes = arraySizesIn;
} }
BufferVariable::~BufferVariable() BufferVariable::~BufferVariable()
......
...@@ -43,7 +43,7 @@ struct LinkedUniform : public sh::Uniform, public StaticallyUsed ...@@ -43,7 +43,7 @@ struct LinkedUniform : public sh::Uniform, public StaticallyUsed
LinkedUniform(GLenum type, LinkedUniform(GLenum type,
GLenum precision, GLenum precision,
const std::string &name, const std::string &name,
unsigned int arraySize, const std::vector<unsigned int> &arraySizes,
const int binding, const int binding,
const int offset, const int offset,
const int location, const int location,
...@@ -75,7 +75,7 @@ struct BufferVariable : public sh::ShaderVariable, public StaticallyUsed ...@@ -75,7 +75,7 @@ struct BufferVariable : public sh::ShaderVariable, public StaticallyUsed
BufferVariable(GLenum type, BufferVariable(GLenum type,
GLenum precision, GLenum precision,
const std::string &name, const std::string &name,
unsigned int arraySize, const std::vector<unsigned int> &arraySizes,
const int bufferIndex, const int bufferIndex,
const sh::BlockMemberInfo &blockInfo); const sh::BlockMemberInfo &blockInfo);
~BufferVariable() override; ~BufferVariable() override;
......
...@@ -31,7 +31,7 @@ bool ComparePackedVarying(const PackedVarying &x, const PackedVarying &y) ...@@ -31,7 +31,7 @@ bool ComparePackedVarying(const PackedVarying &x, const PackedVarying &y)
if (x.isArrayElement()) if (x.isArrayElement())
{ {
vx = *x.varying; vx = *x.varying;
vx.arraySize = 0; vx.arraySizes.clear();
px = &vx; px = &vx;
} }
else else
...@@ -42,7 +42,7 @@ bool ComparePackedVarying(const PackedVarying &x, const PackedVarying &y) ...@@ -42,7 +42,7 @@ bool ComparePackedVarying(const PackedVarying &x, const PackedVarying &y)
if (y.isArrayElement()) if (y.isArrayElement())
{ {
vy = *y.varying; vy = *y.varying;
vy.arraySize = 0; vy.arraySizes.clear();
py = &vy; py = &vy;
} }
else else
...@@ -88,7 +88,10 @@ bool VaryingPacking::packVarying(const PackedVarying &packedVarying) ...@@ -88,7 +88,10 @@ bool VaryingPacking::packVarying(const PackedVarying &packedVarying)
} }
// "Arrays of size N are assumed to take N times the size of the base type" // "Arrays of size N are assumed to take N times the size of the base type"
varyingRows *= (packedVarying.isArrayElement() ? 1 : varying.elementCount()); // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
// structures, so we may use getBasicTypeElementCount().
const unsigned int elementCount = varying.getBasicTypeElementCount();
varyingRows *= (packedVarying.isArrayElement() ? 1 : elementCount);
unsigned int maxVaryingVectors = static_cast<unsigned int>(mRegisterMap.size()); unsigned int maxVaryingVectors = static_cast<unsigned int>(mRegisterMap.size());
...@@ -240,7 +243,10 @@ void VaryingPacking::insert(unsigned int registerRow, ...@@ -240,7 +243,10 @@ void VaryingPacking::insert(unsigned int registerRow,
registerInfo.packedVarying = &packedVarying; registerInfo.packedVarying = &packedVarying;
registerInfo.registerColumn = registerColumn; registerInfo.registerColumn = registerColumn;
for (unsigned int arrayElement = 0; arrayElement < varying.elementCount(); ++arrayElement) // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
// structures, so we may use getBasicTypeElementCount().
const unsigned int arrayElementCount = varying.getBasicTypeElementCount();
for (unsigned int arrayElement = 0; arrayElement < arrayElementCount; ++arrayElement)
{ {
if (packedVarying.isArrayElement() && arrayElement != packedVarying.arrayIndex) if (packedVarying.isArrayElement() && arrayElement != packedVarying.arrayIndex)
{ {
......
...@@ -71,7 +71,10 @@ std::vector<sh::Varying> MakeVaryings(GLenum type, size_t count, size_t arraySiz ...@@ -71,7 +71,10 @@ std::vector<sh::Varying> MakeVaryings(GLenum type, size_t count, size_t arraySiz
varying.precision = GL_MEDIUM_FLOAT; varying.precision = GL_MEDIUM_FLOAT;
varying.name = strstr.str(); varying.name = strstr.str();
varying.mappedName = strstr.str(); varying.mappedName = strstr.str();
varying.arraySize = static_cast<unsigned int>(arraySize); if (arraySize > 0)
{
varying.arraySizes.push_back(static_cast<unsigned int>(arraySize));
}
varying.staticUse = true; varying.staticUse = true;
varying.interpolation = sh::INTERPOLATION_FLAT; varying.interpolation = sh::INTERPOLATION_FLAT;
varying.isInvariant = false; varying.isInvariant = false;
......
...@@ -436,7 +436,7 @@ void QueryBufferParameterBase(const Buffer *buffer, GLenum pname, ParamType *par ...@@ -436,7 +436,7 @@ void QueryBufferParameterBase(const Buffer *buffer, GLenum pname, ParamType *par
} }
} }
GLint GetLocationVariableProperty(const sh::VariableWithLocation &var, GLenum prop) GLint GetCommonVariableProperty(const sh::ShaderVariable &var, GLenum prop)
{ {
switch (prop) switch (prop)
{ {
...@@ -444,21 +444,13 @@ GLint GetLocationVariableProperty(const sh::VariableWithLocation &var, GLenum pr ...@@ -444,21 +444,13 @@ GLint GetLocationVariableProperty(const sh::VariableWithLocation &var, GLenum pr
return clampCast<GLint>(var.type); return clampCast<GLint>(var.type);
case GL_ARRAY_SIZE: case GL_ARRAY_SIZE:
// TODO(jie.a.chen@intel.com): check array of array. // Queryable variables are guaranteed not to be arrays of arrays or arrays of structs,
if (var.isArray() && !var.isStruct()) // see GLES 3.1 spec section 7.3.1.1 page 77.
{ return clampCast<GLint>(var.getBasicTypeElementCount());
return clampCast<GLint>(var.elementCount());
}
return 1;
case GL_NAME_LENGTH: case GL_NAME_LENGTH:
{
// ES31 spec p84: This counts the terminating null char. // ES31 spec p84: This counts the terminating null char.
return clampCast<GLint>(var.name.size() + 1u); return clampCast<GLint>(var.name.size() + 1u);
}
case GL_LOCATION:
return var.location;
default: default:
UNREACHABLE(); UNREACHABLE();
...@@ -474,7 +466,7 @@ GLint GetInputResourceProperty(const Program *program, GLuint index, GLenum prop ...@@ -474,7 +466,7 @@ GLint GetInputResourceProperty(const Program *program, GLuint index, GLenum prop
case GL_TYPE: case GL_TYPE:
case GL_ARRAY_SIZE: case GL_ARRAY_SIZE:
case GL_NAME_LENGTH: case GL_NAME_LENGTH:
return GetLocationVariableProperty(attribute, prop); return GetCommonVariableProperty(attribute, prop);
case GL_LOCATION: case GL_LOCATION:
return program->getAttributeLocation(attribute.name); return program->getAttributeLocation(attribute.name);
...@@ -500,7 +492,7 @@ GLint GetOutputResourceProperty(const Program *program, GLuint index, const GLen ...@@ -500,7 +492,7 @@ GLint GetOutputResourceProperty(const Program *program, GLuint index, const GLen
case GL_TYPE: case GL_TYPE:
case GL_ARRAY_SIZE: case GL_ARRAY_SIZE:
case GL_NAME_LENGTH: case GL_NAME_LENGTH:
return GetLocationVariableProperty(outputVariable, prop); return GetCommonVariableProperty(outputVariable, prop);
case GL_LOCATION: case GL_LOCATION:
return program->getFragDataLocation(outputVariable.name); return program->getFragDataLocation(outputVariable.name);
...@@ -1369,7 +1361,7 @@ GLint GetUniformResourceProperty(const Program *program, GLuint index, const GLe ...@@ -1369,7 +1361,7 @@ GLint GetUniformResourceProperty(const Program *program, GLuint index, const GLe
case GL_TYPE: case GL_TYPE:
case GL_ARRAY_SIZE: case GL_ARRAY_SIZE:
case GL_NAME_LENGTH: case GL_NAME_LENGTH:
return GetLocationVariableProperty(uniform, resourceProp); return GetCommonVariableProperty(uniform, resourceProp);
case GL_LOCATION: case GL_LOCATION:
return program->getUniformLocation(uniform.name); return program->getUniformLocation(uniform.name);
...@@ -1413,18 +1405,13 @@ GLint GetBufferVariableResourceProperty(const Program *program, GLuint index, co ...@@ -1413,18 +1405,13 @@ GLint GetBufferVariableResourceProperty(const Program *program, GLuint index, co
switch (prop) switch (prop)
{ {
case GL_TYPE: case GL_TYPE:
return clampCast<GLint>(bufferVariable.type);
case GL_ARRAY_SIZE: case GL_ARRAY_SIZE:
return clampCast<GLint>(bufferVariable.elementCount()); case GL_NAME_LENGTH:
return GetCommonVariableProperty(bufferVariable, prop);
case GL_BLOCK_INDEX: case GL_BLOCK_INDEX:
return bufferVariable.bufferIndex; return bufferVariable.bufferIndex;
case GL_NAME_LENGTH:
// ES31 spec p84: This counts the terminating null char.
return clampCast<GLint>(bufferVariable.name.size() + 1u);
case GL_OFFSET: case GL_OFFSET:
return bufferVariable.blockInfo.offset; return bufferVariable.blockInfo.offset;
......
...@@ -36,11 +36,17 @@ class ShaderExecutableD3D; ...@@ -36,11 +36,17 @@ class ShaderExecutableD3D;
// register indices. // register indices.
struct D3DUniform : private angle::NonCopyable struct D3DUniform : private angle::NonCopyable
{ {
D3DUniform(GLenum type, const std::string &nameIn, unsigned int arraySizeIn, bool defaultBlock); D3DUniform(GLenum type,
const std::string &nameIn,
const std::vector<unsigned int> &arraySizesIn,
bool defaultBlock);
~D3DUniform(); ~D3DUniform();
bool isSampler() const; bool isSampler() const;
unsigned int elementCount() const { return std::max(1u, arraySize); }
bool isArray() const { return !arraySizes.empty(); }
unsigned int getArraySizeProduct() const;
bool isReferencedByVertexShader() const; bool isReferencedByVertexShader() const;
bool isReferencedByFragmentShader() const; bool isReferencedByFragmentShader() const;
bool isReferencedByComputeShader() const; bool isReferencedByComputeShader() const;
...@@ -51,7 +57,7 @@ struct D3DUniform : private angle::NonCopyable ...@@ -51,7 +57,7 @@ struct D3DUniform : private angle::NonCopyable
// Duplicated from the GL layer // Duplicated from the GL layer
const gl::UniformTypeInfo &typeInfo; const gl::UniformTypeInfo &typeInfo;
std::string name; // Names of arrays don't include [0], unlike at the GL layer. std::string name; // Names of arrays don't include [0], unlike at the GL layer.
unsigned int arraySize; std::vector<unsigned int> arraySizes;
// Pointer to a system copies of the data. Separate pointers for each uniform storage type. // Pointer to a system copies of the data. Separate pointers for each uniform storage type.
uint8_t *vsData; uint8_t *vsData;
...@@ -368,13 +374,29 @@ class ProgramD3D : public ProgramImpl ...@@ -368,13 +374,29 @@ class ProgramD3D : public ProgramImpl
void defineUniformBase(const gl::Shader *shader, void defineUniformBase(const gl::Shader *shader,
const sh::Uniform &uniform, const sh::Uniform &uniform,
D3DUniformMap *uniformMap); D3DUniformMap *uniformMap);
void defineStructUniformFields(GLenum shaderType,
const std::vector<sh::ShaderVariable> &fields,
const std::string &namePrefix,
sh::HLSLBlockEncoder *encoder,
D3DUniformMap *uniformMap);
void defineArrayOfStructsUniformFields(GLenum shaderType,
const sh::ShaderVariable &uniform,
unsigned int arrayNestingIndex,
const std::string &prefix,
sh::HLSLBlockEncoder *encoder,
D3DUniformMap *uniformMap);
void defineArrayUniformElements(GLenum shaderType,
const sh::ShaderVariable &uniform,
const std::string &fullName,
sh::HLSLBlockEncoder *encoder,
D3DUniformMap *uniformMap);
void defineUniform(GLenum shaderType, void defineUniform(GLenum shaderType,
const sh::ShaderVariable &uniform, const sh::ShaderVariable &uniform,
const std::string &fullName, const std::string &fullName,
sh::HLSLBlockEncoder *encoder, sh::HLSLBlockEncoder *encoder,
D3DUniformMap *uniformMap); D3DUniformMap *uniformMap);
void assignAllSamplerRegisters(); void assignAllSamplerRegisters();
void assignSamplerRegisters(D3DUniform *d3dUniform); void assignSamplerRegisters(size_t uniformIndex);
static void AssignSamplers(unsigned int startSamplerIndex, static void AssignSamplers(unsigned int startSamplerIndex,
const gl::UniformTypeInfo &typeInfo, const gl::UniformTypeInfo &typeInfo,
......
...@@ -182,9 +182,9 @@ ShCompileOptions ShaderD3D::prepareSourceAndReturnOptions(std::stringstream *sha ...@@ -182,9 +182,9 @@ ShCompileOptions ShaderD3D::prepareSourceAndReturnOptions(std::stringstream *sha
return additionalOptions; return additionalOptions;
} }
bool ShaderD3D::hasUniform(const D3DUniform *d3dUniform) const bool ShaderD3D::hasUniform(const std::string &name) const
{ {
return mUniformRegisterMap.find(d3dUniform->name) != mUniformRegisterMap.end(); return mUniformRegisterMap.find(name) != mUniformRegisterMap.end();
} }
const std::map<std::string, unsigned int> &GetUniformRegisterMap( const std::map<std::string, unsigned int> &GetUniformRegisterMap(
......
...@@ -47,7 +47,7 @@ class ShaderD3D : public ShaderImpl ...@@ -47,7 +47,7 @@ class ShaderD3D : public ShaderImpl
// D3D-specific methods // D3D-specific methods
void uncompile(); void uncompile();
bool hasUniform(const D3DUniform *d3dUniform) const; bool hasUniform(const std::string &name) const;
// Query regular uniforms with their name. Query sampler fields of structs with field selection // Query regular uniforms with their name. Query sampler fields of structs with field selection
// using dot (.) operator. // using dot (.) operator.
......
...@@ -149,7 +149,7 @@ gl::LinkResult GlslangWrapper::linkProgram(const gl::Context *glContext, ...@@ -149,7 +149,7 @@ gl::LinkResult GlslangWrapper::linkProgram(const gl::Context *glContext,
InsertLayoutSpecifierString(&fragmentSource, samplerUniform.name, setBindingString); InsertLayoutSpecifierString(&fragmentSource, samplerUniform.name, setBindingString);
} }
textureCount += samplerUniform.elementCount(); textureCount += samplerUniform.getBasicTypeElementCount();
} }
std::array<const char *, 2> strings = {{vertexSource.c_str(), fragmentSource.c_str()}}; std::array<const char *, 2> strings = {{vertexSource.c_str(), fragmentSource.c_str()}};
......
...@@ -623,7 +623,7 @@ vk::Error ProgramVk::initPipelineLayout(ContextVk *context) ...@@ -623,7 +623,7 @@ vk::Error ProgramVk::initPipelineLayout(ContextVk *context)
VkDescriptorSetLayoutBinding layoutBinding; VkDescriptorSetLayoutBinding layoutBinding;
uint32_t elementCount = samplerUniform.elementCount(); uint32_t elementCount = samplerUniform.getBasicTypeElementCount();
layoutBinding.binding = textureCount; layoutBinding.binding = textureCount;
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
......
...@@ -607,7 +607,8 @@ TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragData) ...@@ -607,7 +607,8 @@ TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragData)
const OutputVariable *outputVariable = nullptr; const OutputVariable *outputVariable = nullptr;
validateOutputVariableForShader(fragDataShader, 0u, "gl_FragData", &outputVariable); validateOutputVariableForShader(fragDataShader, 0u, "gl_FragData", &outputVariable);
ASSERT_NE(outputVariable, nullptr); ASSERT_NE(outputVariable, nullptr);
EXPECT_EQ(kMaxDrawBuffers, outputVariable->arraySize); ASSERT_EQ(1u, outputVariable->arraySizes.size());
EXPECT_EQ(kMaxDrawBuffers, outputVariable->arraySizes.back());
EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type); EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision); EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
} }
...@@ -742,7 +743,8 @@ TEST_F(CollectFragmentVariablesTest, OutputVarESSL1EXTBlendFuncExtendedSecondary ...@@ -742,7 +743,8 @@ TEST_F(CollectFragmentVariablesTest, OutputVarESSL1EXTBlendFuncExtendedSecondary
const OutputVariable *outputVariable = nullptr; const OutputVariable *outputVariable = nullptr;
validateOutputVariableForShader(secondaryFragDataShader, 0u, "gl_FragData", &outputVariable); validateOutputVariableForShader(secondaryFragDataShader, 0u, "gl_FragData", &outputVariable);
ASSERT_NE(outputVariable, nullptr); ASSERT_NE(outputVariable, nullptr);
EXPECT_EQ(kMaxDrawBuffers, outputVariable->arraySize); ASSERT_EQ(1u, outputVariable->arraySizes.size());
EXPECT_EQ(kMaxDrawBuffers, outputVariable->arraySizes.back());
EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type); EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision); EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
...@@ -750,7 +752,8 @@ TEST_F(CollectFragmentVariablesTest, OutputVarESSL1EXTBlendFuncExtendedSecondary ...@@ -750,7 +752,8 @@ TEST_F(CollectFragmentVariablesTest, OutputVarESSL1EXTBlendFuncExtendedSecondary
validateOutputVariableForShader(secondaryFragDataShader, 1u, "gl_SecondaryFragDataEXT", validateOutputVariableForShader(secondaryFragDataShader, 1u, "gl_SecondaryFragDataEXT",
&outputVariable); &outputVariable);
ASSERT_NE(outputVariable, nullptr); ASSERT_NE(outputVariable, nullptr);
EXPECT_EQ(kMaxDrawBuffers, outputVariable->arraySize); ASSERT_EQ(1u, outputVariable->arraySizes.size());
EXPECT_EQ(kMaxDrawBuffers, outputVariable->arraySizes.back());
EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type); EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type);
EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision); EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision);
} }
...@@ -1347,7 +1350,8 @@ TEST_F(CollectGeometryVariablesTest, CollectInputs) ...@@ -1347,7 +1350,8 @@ TEST_F(CollectGeometryVariablesTest, CollectInputs)
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, varying.precision); EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, varying.precision);
EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, varying.type); EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, varying.type);
EXPECT_FALSE(varying.isInvariant); EXPECT_FALSE(varying.isInvariant);
EXPECT_EQ(1u, varying.arraySize); ASSERT_EQ(1u, varying.arraySizes.size());
EXPECT_EQ(1u, varying.arraySizes.back());
} }
} }
...@@ -1376,7 +1380,8 @@ TEST_F(CollectGeometryVariablesTest, CollectInputArraySizeForUnsizedInput) ...@@ -1376,7 +1380,8 @@ TEST_F(CollectGeometryVariablesTest, CollectInputArraySizeForUnsizedInput)
const Varying *varying = &inputVaryings[0]; const Varying *varying = &inputVaryings[0];
EXPECT_EQ("texcoord", varying->name); EXPECT_EQ("texcoord", varying->name);
EXPECT_EQ(kArraySizeForInputPrimitives[i], varying->arraySize); ASSERT_EQ(1u, varying->arraySizes.size());
EXPECT_EQ(kArraySizeForInputPrimitives[i], varying->arraySizes.back());
} }
} }
......
...@@ -25,14 +25,12 @@ TEST(ShaderVariableTest, FindInfoByMappedName) ...@@ -25,14 +25,12 @@ TEST(ShaderVariableTest, FindInfoByMappedName)
// A a[3]; // A a[3];
// }; // };
// B uni[2]; // B uni[2];
ShaderVariable uni; ShaderVariable uni(0, 2);
uni.setArraySize(2);
uni.name = "uni"; uni.name = "uni";
uni.mappedName = "m_uni"; uni.mappedName = "m_uni";
uni.structName = "B"; uni.structName = "B";
{ {
ShaderVariable a; ShaderVariable a(0, 3);
a.setArraySize(3);
a.name = "a"; a.name = "a";
a.mappedName = "m_a"; a.mappedName = "m_a";
a.structName = "A"; a.structName = "A";
......
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