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 @@
// Version number for shader translation API.
// It is incremented every time the API changes.
#define ANGLE_SH_VERSION 189
#define ANGLE_SH_VERSION 190
enum ShShaderSpec
{
......
......@@ -68,13 +68,30 @@ struct ShaderVariable
ShaderVariable(const ShaderVariable &other);
ShaderVariable &operator=(const ShaderVariable &other);
bool isArray() const { return arraySize > 0 || isUnsizedArray; }
unsigned int elementCount() const { return isUnsizedArray ? 0 : std::max(1u, arraySize); }
bool isStruct() const { return !fields.empty(); }
bool isArrayOfArrays() const { return arraySizes.size() >= 2u; }
bool isArray() const { return !arraySizes.empty(); }
unsigned int getArraySizeProduct() const;
// Array size 0 means not an array when passed to or returned from these functions.
unsigned int getOutermostArraySize() const { return arraySize; }
void setArraySize(unsigned int size) { arraySize = size; }
// Note that setArraySize() is deprecated and should not be used inside ANGLE.
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
// structures. This is needed in order to disambiguate similar looking
......@@ -97,11 +114,21 @@ struct ShaderVariable
GLenum precision;
std::string name;
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;
std::vector<ShaderVariable> fields;
std::string structName;
bool isUnsizedArray;
protected:
bool isSameVariableAtLinkTime(const ShaderVariable &other,
......
......@@ -560,9 +560,14 @@ void PrintVariable(const std::string &prefix, size_t index, const sh::ShaderVari
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(),
typeName.c_str(), var.arraySize);
typeName.c_str());
for (unsigned int arraySize : var.arraySizes)
{
printf("%u ", arraySize);
}
printf("\n");
if (var.fields.size())
{
std::string structPrefix;
......
......@@ -770,6 +770,16 @@ std::string ParseResourceName(const std::string &name, std::vector<unsigned int>
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)
{
ASSERT(nameLengthWithoutArrayIndexOut != nullptr);
......
......@@ -70,6 +70,10 @@ GLuint GetPrimitiveRestartIndex(GLenum indexType);
bool IsTriangleMode(GLenum drawMode);
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
// index into nameLengthWithoutArrayIndexOut. In case name doesn't include an array index, return
// GL_INVALID_INDEX and write the length of the original string.
......
......@@ -262,8 +262,7 @@ void CollectVariablesTraverser::setBuiltInInfoFromSymbolTable(const char *name,
info->name = name;
info->mappedName = name;
info->type = GLVariableType(type);
ASSERT(!type.isArrayOfArrays());
info->arraySize = type.isArray() ? type.getOutermostArraySize() : 0;
info->arraySizes.assign(type.getArraySizes().begin(), type.getArraySizes().end());
info->precision = GLVariablePrecision(type);
}
......@@ -485,7 +484,8 @@ void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
setBuiltInInfoFromSymbolTable("gl_FragData", &info);
if (!IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))
{
info.arraySize = 1;
ASSERT(info.arraySizes.size() == 1u);
info.arraySizes.back() = 1u;
}
info.staticUse = true;
mOutputVariables->push_back(info);
......@@ -581,10 +581,7 @@ void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
variableOut->name = name.getString().c_str();
variableOut->mappedName = getMappedName(name);
// 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;
variableOut->arraySizes.assign(type.getArraySizes().begin(), type.getArraySizes().end());
}
Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const
......@@ -677,7 +674,6 @@ void CollectVariablesTraverser::recordInterfaceBlock(const TType &interfaceBlock
setCommonVariableProperties(fieldType, TName(field->name()), &fieldVariable);
fieldVariable.isRowMajorLayout =
(fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
fieldVariable.isUnsizedArray = fieldType.isUnsizedArray();
interfaceBlock->fields.push_back(fieldVariable);
}
}
......
......@@ -119,7 +119,8 @@ void EmulateGLFragColorBroadcast(TIntermBlock *root,
// TODO(zmo): Find a way to keep the original variable information.
var.name = "gl_FragData";
var.mappedName = "gl_FragData";
var.arraySize = maxDrawBuffers;
var.arraySizes.push_back(maxDrawBuffers);
ASSERT(var.arraySizes.size() == 1u);
}
}
}
......
......@@ -10,6 +10,7 @@
#include <GLSLANG/ShaderLang.h>
#include "common/debug.h"
#include "common/utilities.h"
namespace sh
{
......@@ -31,19 +32,20 @@ bool InterpolationTypesMatch(InterpolationType a, InterpolationType b)
}
ShaderVariable::ShaderVariable()
: type(0), precision(0), arraySize(0), staticUse(false), isUnsizedArray(false)
: type(0), precision(0), flattenedOffsetInParentArrays(0), staticUse(false)
{
}
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)
: type(typeIn), precision(0), arraySize(arraySizeIn), staticUse(false), isUnsizedArray(false)
: type(typeIn), precision(0), flattenedOffsetInParentArrays(0), staticUse(false)
{
ASSERT(arraySizeIn != 0);
arraySizes.push_back(arraySizeIn);
}
ShaderVariable::~ShaderVariable()
......@@ -55,11 +57,11 @@ ShaderVariable::ShaderVariable(const ShaderVariable &other)
precision(other.precision),
name(other.name),
mappedName(other.mappedName),
arraySize(other.arraySize),
arraySizes(other.arraySizes),
flattenedOffsetInParentArrays(other.flattenedOffsetInParentArrays),
staticUse(other.staticUse),
fields(other.fields),
structName(other.structName),
isUnsizedArray(other.isUnsizedArray)
structName(other.structName)
{
}
......@@ -69,20 +71,20 @@ ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other)
precision = other.precision;
name = other.name;
mappedName = other.mappedName;
arraySize = other.arraySize;
arraySizes = other.arraySizes;
staticUse = other.staticUse;
flattenedOffsetInParentArrays = other.flattenedOffsetInParentArrays;
fields = other.fields;
structName = other.structName;
isUnsizedArray = other.isUnsizedArray;
return *this;
}
bool ShaderVariable::operator==(const ShaderVariable &other) const
{
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() ||
structName != other.structName || isUnsizedArray != other.isUnsizedArray)
structName != other.structName)
{
return false;
}
......@@ -94,6 +96,49 @@ bool ShaderVariable::operator==(const ShaderVariable &other) const
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,
const ShaderVariable **leafVar,
std::string *originalFullName) const
......@@ -180,7 +225,7 @@ bool ShaderVariable::isSameVariableAtLinkTime(const ShaderVariable &other,
if (matchName && name != other.name)
return false;
ASSERT(!matchName || mappedName == other.mappedName);
if (arraySize != other.arraySize)
if (arraySizes != other.arraySizes)
return false;
if (fields.size() != other.fields.size())
return false;
......@@ -197,10 +242,6 @@ bool ShaderVariable::isSameVariableAtLinkTime(const ShaderVariable &other,
}
if (structName != other.structName)
return false;
if (isUnsizedArray != other.isUnsizedArray)
{
return false;
}
return true;
}
......
......@@ -41,14 +41,24 @@ void ExpandStructVariable(const ShaderVariable &variable,
}
void ExpandStructArrayVariable(const ShaderVariable &variable,
unsigned int arrayNestingIndex,
const std::string &name,
std::vector<ShaderVariable> *expanded)
{
for (unsigned int arrayElement = 0u; arrayElement < variable.getOutermostArraySize();
++arrayElement)
// Nested arrays are processed starting from outermost (arrayNestingIndex 0u) and ending at the
// innermost.
const unsigned int currentArraySize = variable.getNestedArraySize(arrayNestingIndex);
for (unsigned int arrayElement = 0u; arrayElement < currentArraySize; ++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,
{
if (variable.isArray())
{
ExpandStructArrayVariable(variable, name, expanded);
ExpandStructArrayVariable(variable, 0u, name, expanded);
}
else
{
......@@ -70,7 +80,6 @@ void ExpandVariable(const ShaderVariable &variable,
else
{
ShaderVariable expandedVar = variable;
expandedVar.name = name;
expanded->push_back(expandedVar);
......@@ -79,7 +88,7 @@ void ExpandVariable(const ShaderVariable &variable,
int GetVariablePackingRows(const ShaderVariable &variable)
{
return GetTypePackingRows(variable.type) * variable.elementCount();
return GetTypePackingRows(variable.type) * variable.getArraySizeProduct();
}
class VariablePacker
......@@ -113,7 +122,7 @@ struct TVariableInfoComparer
return lhsSortOrder < rhsSortOrder;
}
// Sort by largest first.
return lhs.arraySize > rhs.arraySize;
return lhs.getArraySizeProduct() > rhs.getArraySizeProduct();
}
};
......@@ -208,7 +217,7 @@ bool VariablePacker::checkExpandedVariablesWithinPackingLimits(
{
// Structs should have been expanded before reaching here.
ASSERT(!variable.isStruct());
if (variable.elementCount() > maxVectors / GetTypePackingRows(variable.type))
if (variable.getArraySizeProduct() > maxVectors / GetTypePackingRows(variable.type))
{
return false;
}
......
......@@ -26,6 +26,46 @@ bool IsRowMajorLayout(const ShaderVariable &var)
{
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
BlockLayoutEncoder::BlockLayoutEncoder() : mCurrentOffset(0)
......@@ -33,20 +73,20 @@ BlockLayoutEncoder::BlockLayoutEncoder() : mCurrentOffset(0)
}
BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type,
unsigned int arraySize,
const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix)
{
int arrayStride;
int matrixStride;
getBlockLayoutInfo(type, arraySize, isRowMajorMatrix, &arrayStride, &matrixStride);
getBlockLayoutInfo(type, arraySizes, isRowMajorMatrix, &arrayStride, &matrixStride);
const BlockMemberInfo memberInfo(static_cast<int>(mCurrentOffset * BytesPerComponent),
static_cast<int>(arrayStride * BytesPerComponent),
static_cast<int>(matrixStride * BytesPerComponent),
isRowMajorMatrix);
advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride);
advanceOffset(type, arraySizes, isRowMajorMatrix, arrayStride, matrixStride);
return memberInfo;
}
......@@ -83,7 +123,7 @@ void Std140BlockEncoder::exitAggregateType()
}
void Std140BlockEncoder::getBlockLayoutInfo(GLenum type,
unsigned int arraySize,
const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix,
int *arrayStrideOut,
int *matrixStrideOut)
......@@ -100,13 +140,13 @@ void Std140BlockEncoder::getBlockLayoutInfo(GLenum type,
baseAlignment = ComponentsPerRegister;
matrixStride = ComponentsPerRegister;
if (arraySize > 0)
if (!arraySizes.empty())
{
const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
arrayStride = ComponentsPerRegister * numRegisters;
}
}
else if (arraySize > 0)
else if (!arraySizes.empty())
{
baseAlignment = ComponentsPerRegister;
arrayStride = ComponentsPerRegister;
......@@ -124,14 +164,14 @@ void Std140BlockEncoder::getBlockLayoutInfo(GLenum type,
}
void Std140BlockEncoder::advanceOffset(GLenum type,
unsigned int arraySize,
const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix,
int arrayStride,
int matrixStride)
{
if (arraySize > 0)
if (!arraySizes.empty())
{
mCurrentOffset += arrayStride * arraySize;
mCurrentOffset += arrayStride * gl::ArraySizeProduct(arraySizes);
}
else if (gl::IsMatrixType(type))
{
......@@ -148,13 +188,14 @@ void Std140BlockEncoder::advanceOffset(GLenum type,
template <typename VarT>
void GetUniformBlockInfo(const std::vector<VarT> &fields,
const std::string &prefix,
BlockLayoutEncoder *encoder,
sh::BlockLayoutEncoder *encoder,
bool inRowMajorLayout,
BlockLayoutMap *blockLayoutMap)
BlockLayoutMap *blockInfoOut)
{
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))
{
continue;
......@@ -166,25 +207,22 @@ void GetUniformBlockInfo(const std::vector<VarT> &fields,
{
bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field));
for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
if (field.isArray())
{
encoder->enterAggregateType();
const std::string uniformElementName =
fieldName + (field.isArray() ? ArrayString(arrayElement) : "");
GetUniformBlockInfo(field.fields, uniformElementName, encoder, rowMajorLayout,
blockLayoutMap);
encoder->exitAggregateType();
GetUniformBlockStructArrayMemberInfo(field, 0u, fieldName, encoder, rowMajorLayout,
blockInfoOut);
}
else
{
GetUniformBlockStructMemberInfo(field.fields, fieldName, encoder, rowMajorLayout,
blockInfoOut);
}
}
else
{
bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
const BlockMemberInfo &blockMemberInfo =
encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix);
(*blockLayoutMap)[fieldName] = blockMemberInfo;
(*blockInfoOut)[fieldName] =
encoder->encodeType(field.type, field.arraySizes, isRowMajorMatrix);
}
}
}
......
......@@ -73,7 +73,9 @@ class BlockLayoutEncoder
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; }
......@@ -92,15 +94,15 @@ class BlockLayoutEncoder
void nextRegister();
virtual void getBlockLayoutInfo(GLenum type,
unsigned int arraySize,
const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix,
int *arrayStrideOut,
int *matrixStrideOut) = 0;
virtual void advanceOffset(GLenum type,
unsigned int arraySize,
const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix,
int arrayStride,
int matrixStride) = 0;
int matrixStride) = 0;
};
// Block layout according to the std140 block layout
......@@ -116,12 +118,12 @@ class Std140BlockEncoder : public BlockLayoutEncoder
protected:
void getBlockLayoutInfo(GLenum type,
unsigned int arraySize,
const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix,
int *arrayStrideOut,
int *matrixStrideOut) override;
void advanceOffset(GLenum type,
unsigned int arraySize,
const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix,
int arrayStride,
int matrixStride) override;
......
......@@ -30,7 +30,7 @@ void HLSLBlockEncoder::exitAggregateType()
}
void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn,
unsigned int arraySize,
const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix,
int *arrayStrideOut,
int *matrixStrideOut)
......@@ -46,7 +46,7 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn,
// if variables are not to be packed, or we're about to
// pack a matrix or array, skip to the start of the next
// register
if (!isPacked() || gl::IsMatrixType(type) || arraySize > 0)
if (!isPacked() || gl::IsMatrixType(type) || !arraySizes.empty())
{
nextRegister();
}
......@@ -55,13 +55,13 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn,
{
matrixStride = ComponentsPerRegister;
if (arraySize > 0)
if (!arraySizes.empty())
{
const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
arrayStride = ComponentsPerRegister * numRegisters;
}
}
else if (arraySize > 0)
else if (!arraySizes.empty())
{
arrayStride = ComponentsPerRegister;
}
......@@ -79,16 +79,16 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn,
}
void HLSLBlockEncoder::advanceOffset(GLenum typeIn,
unsigned int arraySize,
const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix,
int arrayStride,
int matrixStride)
{
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))
......@@ -135,7 +135,7 @@ void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *
{
if (variable.isStruct())
{
for (size_t arrayElement = 0; arrayElement < variable.elementCount(); arrayElement++)
for (size_t arrayElement = 0; arrayElement < variable.getArraySizeProduct(); arrayElement++)
{
encoder->enterAggregateType();
......@@ -150,7 +150,7 @@ void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *
else
{
// 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
protected:
void getBlockLayoutInfo(GLenum type,
unsigned int arraySize,
const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix,
int *arrayStrideOut,
int *matrixStrideOut) override;
void advanceOffset(GLenum type,
unsigned int arraySize,
const std::vector<unsigned int> &arraySizes,
bool isRowMajorMatrix,
int arrayStride,
int matrixStride) override;
......
......@@ -42,7 +42,7 @@ void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
stream->writeInt(var.precision);
stream->writeString(var.name);
stream->writeString(var.mappedName);
stream->writeInt(var.arraySize);
stream->writeIntVector(var.arraySizes);
stream->writeInt(var.staticUse);
stream->writeString(var.structName);
ASSERT(var.fields.empty());
......@@ -54,7 +54,7 @@ void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var)
var->precision = stream->readInt<GLenum>();
var->name = stream->readString();
var->mappedName = stream->readString();
var->arraySize = stream->readInt<unsigned int>();
stream->readIntVector<unsigned int>(&var->arraySizes);
var->staticUse = stream->readBool();
var->structName = stream->readString();
}
......@@ -334,7 +334,7 @@ LinkResult MemoryProgramCache::Deserialize(const Context *context,
++transformFeedbackVaryingIndex)
{
sh::Varying varying;
stream.readInt(&varying.arraySize);
stream.readIntVector<unsigned int>(&varying.arraySizes);
stream.readInt(&varying.type);
stream.readString(&varying.name);
......@@ -508,7 +508,7 @@ void MemoryProgramCache::Serialize(const Context *context,
stream.writeInt(state.getLinkedTransformFeedbackVaryings().size());
for (const auto &var : state.getLinkedTransformFeedbackVaryings())
{
stream.writeInt(var.arraySize);
stream.writeIntVector(var.arraySizes);
stream.writeInt(var.type);
stream.writeString(var.name);
......
......@@ -106,7 +106,6 @@ void UniformStateQueryCastLoop(DestT *dataOut, const uint8_t *srcPointer, int co
}
}
template <typename VarT>
GLuint GetResourceIndexFromName(const std::vector<VarT> &list, const std::string &name)
{
......@@ -1375,7 +1374,7 @@ void Program::getActiveUniform(GLuint index,
CopyStringToBuffer(name, string, bufsize, length);
}
*size = uniform.elementCount();
*size = clampCast<GLint>(uniform.getBasicTypeElementCount());
*type = uniform.type;
}
else
......@@ -2078,12 +2077,13 @@ void Program::linkSamplerAndImageBindings()
auto &imageUniform = mState.mUniforms[imageIndex];
if (imageUniform.binding == -1)
{
mState.mImageBindings.emplace_back(ImageBinding(imageUniform.elementCount()));
mState.mImageBindings.emplace_back(
ImageBinding(imageUniform.getBasicTypeElementCount()));
}
else
{
mState.mImageBindings.emplace_back(
ImageBinding(imageUniform.binding, imageUniform.elementCount()));
ImageBinding(imageUniform.binding, imageUniform.getBasicTypeElementCount()));
}
}
......@@ -2103,7 +2103,7 @@ void Program::linkSamplerAndImageBindings()
const auto &samplerUniform = mState.mUniforms[samplerIndex];
GLenum textureType = SamplerTypeToTextureType(samplerUniform.type);
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
infoLog << "Types for " << variableName << " differ between vertex and fragment shaders";
return false;
}
if (vertexVariable.arraySize != fragmentVariable.arraySize)
if (vertexVariable.arraySizes != fragmentVariable.arraySizes)
{
infoLog << "Array sizes for " << variableName << " differ between vertex and fragment shaders";
return false;
......@@ -2649,8 +2649,12 @@ bool Program::linkValidateTransformFeedback(const gl::Context *context,
uniqueNames.insert(tfVaryingName);
// 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 =
((varying->isArray() && subscripts.empty()) ? varying->elementCount() : 1);
((varying->isArray() && subscripts.empty()) ? varying->getOutermostArraySize()
: 1);
size_t componentCount = VariableComponentCount(varying->type) * elementCount;
if (mState.mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
componentCount > caps.maxTransformFeedbackSeparateComponents)
......@@ -2786,8 +2790,11 @@ void Program::linkOutputVariables(const Context *context)
unsigned int baseLocation =
(outputVariable.location == -1 ? 0u
: 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;
if (location >= mState.mOutputVariableTypes.size())
......@@ -2829,8 +2836,10 @@ void Program::linkOutputVariables(const Context *context)
(outputVariable.location == -1 ? 0u
: 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;
if (location >= mState.mOutputLocations.size())
......@@ -2863,8 +2872,8 @@ void Program::setUniformValuesFromBindingQualifiers()
GLint location = getUniformLocation(samplerUniform.name);
ASSERT(location != -1);
std::vector<GLint> boundTextureUnits;
for (unsigned int elementIndex = 0; elementIndex < samplerUniform.elementCount();
++elementIndex)
for (unsigned int elementIndex = 0;
elementIndex < samplerUniform.getBasicTypeElementCount(); ++elementIndex)
{
boundTextureUnits.push_back(samplerUniform.binding + elementIndex);
}
......@@ -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
// 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 =
static_cast<GLsizei>(remainingElements * linkedUniform.getElementComponents());
......@@ -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
// 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));
}
......
......@@ -199,6 +199,7 @@ struct TransformFeedbackVarying : public sh::Varying
TransformFeedbackVarying(const sh::Varying &varyingIn, GLuint index)
: sh::Varying(varyingIn), arrayIndex(index)
{
ASSERT(!isArrayOfArrays());
}
std::string nameWithArrayIndex() const
{
......@@ -210,7 +211,10 @@ struct TransformFeedbackVarying : public sh::Varying
}
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;
};
......
......@@ -88,6 +88,44 @@ class UniformLinker
std::vector<LinkedUniform> *atomicCounterUniforms,
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
// granularity.
ShaderUniformCount flattenUniformImpl(const sh::ShaderVariable &uniform,
......@@ -149,21 +187,40 @@ class InterfaceBlockLinker : angle::NonCopyable
const std::string &prefix,
const std::string &mappedPrefix,
int blockIndex,
bool outsideTopLevelArray,
bool singleEntryForTopLevelArray,
int topLevelArraySize) const;
virtual void defineBlockMember(const sh::ShaderVariable &field,
const std::string &fullName,
const std::string &fullMappedName,
int blockIndex,
const sh::BlockMemberInfo &memberInfo,
int topLevelArraySize) const = 0;
template <typename VarT>
void defineBlockMember(const GetBlockMemberInfo &getMemberInfo,
const VarT &field,
const std::string &fullName,
const std::string &fullMappedName,
int blockIndex,
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;
using ShaderBlocks = std::pair<GLenum, const std::vector<sh::InterfaceBlock> *>;
std::vector<ShaderBlocks> mShaderBlocks;
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
......@@ -174,12 +231,12 @@ class UniformBlockLinker final : public InterfaceBlockLinker
~UniformBlockLinker() override;
private:
void defineBlockMember(const sh::ShaderVariable &field,
const std::string &fullName,
const std::string &fullMappedName,
int blockIndex,
const sh::BlockMemberInfo &memberInfo,
int topLevelArraySize) const override;
void defineBlockMemberImpl(const sh::ShaderVariable &field,
const std::string &fullName,
const std::string &fullMappedName,
int blockIndex,
const sh::BlockMemberInfo &memberInfo,
int topLevelArraySize) const override;
size_t getCurrentBlockMemberIndex() const override;
std::vector<LinkedUniform> *mUniformsOut;
};
......@@ -192,12 +249,12 @@ class ShaderStorageBlockLinker final : public InterfaceBlockLinker
~ShaderStorageBlockLinker() override;
private:
void defineBlockMember(const sh::ShaderVariable &field,
const std::string &fullName,
const std::string &fullMappedName,
int blockIndex,
const sh::BlockMemberInfo &memberInfo,
int topLevelArraySize) const override;
void defineBlockMemberImpl(const sh::ShaderVariable &field,
const std::string &fullName,
const std::string &fullMappedName,
int blockIndex,
const sh::BlockMemberInfo &memberInfo,
int topLevelArraySize) const override;
size_t getCurrentBlockMemberIndex() const override;
std::vector<BufferVariable> *mBufferVariablesOut;
};
......
......@@ -57,7 +57,7 @@ bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y)
{
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
......
......@@ -61,7 +61,7 @@ LinkedUniform::LinkedUniform()
LinkedUniform::LinkedUniform(GLenum typeIn,
GLenum precisionIn,
const std::string &nameIn,
unsigned int arraySizeIn,
const std::vector<unsigned int> &arraySizesIn,
const int bindingIn,
const int offsetIn,
const int locationIn,
......@@ -72,10 +72,12 @@ LinkedUniform::LinkedUniform(GLenum typeIn,
type = typeIn;
precision = precisionIn;
name = nameIn;
arraySize = arraySizeIn;
arraySizes = arraySizesIn;
binding = bindingIn;
offset = offsetIn;
location = locationIn;
ASSERT(!isArrayOfArrays());
ASSERT(!isArray() || !isStruct());
}
LinkedUniform::LinkedUniform(const sh::Uniform &uniform)
......@@ -84,6 +86,8 @@ LinkedUniform::LinkedUniform(const sh::Uniform &uniform)
bufferIndex(-1),
blockInfo(sh::BlockMemberInfo::getDefaultBlockInfo())
{
ASSERT(!isArrayOfArrays());
ASSERT(!isArray() || !isStruct());
}
LinkedUniform::LinkedUniform(const LinkedUniform &uniform)
......@@ -152,7 +156,7 @@ BufferVariable::BufferVariable()
BufferVariable::BufferVariable(GLenum typeIn,
GLenum precisionIn,
const std::string &nameIn,
unsigned int arraySizeIn,
const std::vector<unsigned int> &arraySizesIn,
const int bufferIndexIn,
const sh::BlockMemberInfo &blockInfoIn)
: bufferIndex(bufferIndexIn), blockInfo(blockInfoIn), topLevelArraySize(-1)
......@@ -160,7 +164,7 @@ BufferVariable::BufferVariable(GLenum typeIn,
type = typeIn;
precision = precisionIn;
name = nameIn;
arraySize = arraySizeIn;
arraySizes = arraySizesIn;
}
BufferVariable::~BufferVariable()
......
......@@ -43,7 +43,7 @@ struct LinkedUniform : public sh::Uniform, public StaticallyUsed
LinkedUniform(GLenum type,
GLenum precision,
const std::string &name,
unsigned int arraySize,
const std::vector<unsigned int> &arraySizes,
const int binding,
const int offset,
const int location,
......@@ -75,7 +75,7 @@ struct BufferVariable : public sh::ShaderVariable, public StaticallyUsed
BufferVariable(GLenum type,
GLenum precision,
const std::string &name,
unsigned int arraySize,
const std::vector<unsigned int> &arraySizes,
const int bufferIndex,
const sh::BlockMemberInfo &blockInfo);
~BufferVariable() override;
......
......@@ -31,7 +31,7 @@ bool ComparePackedVarying(const PackedVarying &x, const PackedVarying &y)
if (x.isArrayElement())
{
vx = *x.varying;
vx.arraySize = 0;
vx.arraySizes.clear();
px = &vx;
}
else
......@@ -42,7 +42,7 @@ bool ComparePackedVarying(const PackedVarying &x, const PackedVarying &y)
if (y.isArrayElement())
{
vy = *y.varying;
vy.arraySize = 0;
vy.arraySizes.clear();
py = &vy;
}
else
......@@ -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"
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());
......@@ -240,7 +243,10 @@ void VaryingPacking::insert(unsigned int registerRow,
registerInfo.packedVarying = &packedVarying;
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)
{
......
......@@ -71,7 +71,10 @@ std::vector<sh::Varying> MakeVaryings(GLenum type, size_t count, size_t arraySiz
varying.precision = GL_MEDIUM_FLOAT;
varying.name = 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.interpolation = sh::INTERPOLATION_FLAT;
varying.isInvariant = false;
......
......@@ -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)
{
......@@ -444,21 +444,13 @@ GLint GetLocationVariableProperty(const sh::VariableWithLocation &var, GLenum pr
return clampCast<GLint>(var.type);
case GL_ARRAY_SIZE:
// TODO(jie.a.chen@intel.com): check array of array.
if (var.isArray() && !var.isStruct())
{
return clampCast<GLint>(var.elementCount());
}
return 1;
// Queryable variables are guaranteed not to be arrays of arrays or arrays of structs,
// see GLES 3.1 spec section 7.3.1.1 page 77.
return clampCast<GLint>(var.getBasicTypeElementCount());
case GL_NAME_LENGTH:
{
// ES31 spec p84: This counts the terminating null char.
return clampCast<GLint>(var.name.size() + 1u);
}
case GL_LOCATION:
return var.location;
default:
UNREACHABLE();
......@@ -474,7 +466,7 @@ GLint GetInputResourceProperty(const Program *program, GLuint index, GLenum prop
case GL_TYPE:
case GL_ARRAY_SIZE:
case GL_NAME_LENGTH:
return GetLocationVariableProperty(attribute, prop);
return GetCommonVariableProperty(attribute, prop);
case GL_LOCATION:
return program->getAttributeLocation(attribute.name);
......@@ -500,7 +492,7 @@ GLint GetOutputResourceProperty(const Program *program, GLuint index, const GLen
case GL_TYPE:
case GL_ARRAY_SIZE:
case GL_NAME_LENGTH:
return GetLocationVariableProperty(outputVariable, prop);
return GetCommonVariableProperty(outputVariable, prop);
case GL_LOCATION:
return program->getFragDataLocation(outputVariable.name);
......@@ -1369,7 +1361,7 @@ GLint GetUniformResourceProperty(const Program *program, GLuint index, const GLe
case GL_TYPE:
case GL_ARRAY_SIZE:
case GL_NAME_LENGTH:
return GetLocationVariableProperty(uniform, resourceProp);
return GetCommonVariableProperty(uniform, resourceProp);
case GL_LOCATION:
return program->getUniformLocation(uniform.name);
......@@ -1413,18 +1405,13 @@ GLint GetBufferVariableResourceProperty(const Program *program, GLuint index, co
switch (prop)
{
case GL_TYPE:
return clampCast<GLint>(bufferVariable.type);
case GL_ARRAY_SIZE:
return clampCast<GLint>(bufferVariable.elementCount());
case GL_NAME_LENGTH:
return GetCommonVariableProperty(bufferVariable, prop);
case GL_BLOCK_INDEX:
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:
return bufferVariable.blockInfo.offset;
......
......@@ -36,11 +36,17 @@ class ShaderExecutableD3D;
// register indices.
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();
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 isReferencedByFragmentShader() const;
bool isReferencedByComputeShader() const;
......@@ -51,7 +57,7 @@ struct D3DUniform : private angle::NonCopyable
// Duplicated from the GL layer
const gl::UniformTypeInfo &typeInfo;
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.
uint8_t *vsData;
......@@ -368,13 +374,29 @@ class ProgramD3D : public ProgramImpl
void defineUniformBase(const gl::Shader *shader,
const sh::Uniform &uniform,
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,
const sh::ShaderVariable &uniform,
const std::string &fullName,
sh::HLSLBlockEncoder *encoder,
D3DUniformMap *uniformMap);
void assignAllSamplerRegisters();
void assignSamplerRegisters(D3DUniform *d3dUniform);
void assignSamplerRegisters(size_t uniformIndex);
static void AssignSamplers(unsigned int startSamplerIndex,
const gl::UniformTypeInfo &typeInfo,
......
......@@ -182,9 +182,9 @@ ShCompileOptions ShaderD3D::prepareSourceAndReturnOptions(std::stringstream *sha
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(
......
......@@ -47,7 +47,7 @@ class ShaderD3D : public ShaderImpl
// D3D-specific methods
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
// using dot (.) operator.
......
......@@ -149,7 +149,7 @@ gl::LinkResult GlslangWrapper::linkProgram(const gl::Context *glContext,
InsertLayoutSpecifierString(&fragmentSource, samplerUniform.name, setBindingString);
}
textureCount += samplerUniform.elementCount();
textureCount += samplerUniform.getBasicTypeElementCount();
}
std::array<const char *, 2> strings = {{vertexSource.c_str(), fragmentSource.c_str()}};
......
......@@ -623,7 +623,7 @@ vk::Error ProgramVk::initPipelineLayout(ContextVk *context)
VkDescriptorSetLayoutBinding layoutBinding;
uint32_t elementCount = samplerUniform.elementCount();
uint32_t elementCount = samplerUniform.getBasicTypeElementCount();
layoutBinding.binding = textureCount;
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
......
......@@ -607,7 +607,8 @@ TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragData)
const OutputVariable *outputVariable = nullptr;
validateOutputVariableForShader(fragDataShader, 0u, "gl_FragData", &outputVariable);
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_MEDIUM_FLOAT, outputVariable->precision);
}
......@@ -742,7 +743,8 @@ TEST_F(CollectFragmentVariablesTest, OutputVarESSL1EXTBlendFuncExtendedSecondary
const OutputVariable *outputVariable = nullptr;
validateOutputVariableForShader(secondaryFragDataShader, 0u, "gl_FragData", &outputVariable);
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_MEDIUM_FLOAT, outputVariable->precision);
......@@ -750,7 +752,8 @@ TEST_F(CollectFragmentVariablesTest, OutputVarESSL1EXTBlendFuncExtendedSecondary
validateOutputVariableForShader(secondaryFragDataShader, 1u, "gl_SecondaryFragDataEXT",
&outputVariable);
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_MEDIUM_FLOAT, outputVariable->precision);
}
......@@ -1347,7 +1350,8 @@ TEST_F(CollectGeometryVariablesTest, CollectInputs)
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, varying.precision);
EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, varying.type);
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)
const Varying *varying = &inputVaryings[0];
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)
// A a[3];
// };
// B uni[2];
ShaderVariable uni;
uni.setArraySize(2);
ShaderVariable uni(0, 2);
uni.name = "uni";
uni.mappedName = "m_uni";
uni.structName = "B";
{
ShaderVariable a;
a.setArraySize(3);
ShaderVariable a(0, 3);
a.name = "a";
a.mappedName = "m_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