Commit 855d964b by Olli Etuaho Committed by Commit Bot

Prefix user-defined names in GLSL output

Now user-defined names are prefixed by _u in GLSL output in case name hashing is not on. Internal names such as names of temporary variables created in AST transformations are written out as such. This makes handling of internal function names and internal variable names consistent. It also removes the possibility of name conflicts between user-defined names and internal names in case name hashing is not on. In the same vein, it makes it safe to use GLSL reserved words that are not reserved in ESSL as variable names in case name hashing is not on. This also makes the GLSL output more consistent with how names are handled in HLSL output. Name hashing code is shared between VariableInfo and OutputGLSLBase to ensure names are handled consistently in both. The name that's used in the shader source for a given interface variable is written out to ShaderVariable::mappedName. An exception needs to be made for identifiers close to the length limit, since adding any prefix would take them over the limit. But they can be just written out as such, since we don't have any builtins or ANGLE internal variables that have as long names and could create a conflict. BUG=angleproject:2139 BUG=angleproject:2038 TEST=angle_unittests, angle_end2end_tests, WebGL conformance tests Change-Id: Id6ed052c4fab2d091227dc9a3668083053b67a38 Reviewed-on: https://chromium-review.googlesource.com/507647 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent ced5c86c
...@@ -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 180 #define ANGLE_SH_VERSION 181
enum ShShaderSpec enum ShShaderSpec
{ {
...@@ -215,7 +215,7 @@ const ShCompileOptions SH_REWRITE_FLOAT_UNARY_MINUS_OPERATOR = UINT64_C(1) << 29 ...@@ -215,7 +215,7 @@ const ShCompileOptions SH_REWRITE_FLOAT_UNARY_MINUS_OPERATOR = UINT64_C(1) << 29
const ShCompileOptions SH_EMULATE_ATAN2_FLOAT_FUNCTION = UINT64_C(1) << 30; const ShCompileOptions SH_EMULATE_ATAN2_FLOAT_FUNCTION = UINT64_C(1) << 30;
// Set to 1 to translate gl_ViewID_OVR to an uniform so that the extension can be emulated. // Set to 1 to translate gl_ViewID_OVR to an uniform so that the extension can be emulated.
// "uniform highp uint webgl_angle_ViewID_OVR". // "uniform highp uint ViewID_OVR".
const ShCompileOptions SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM = UINT64_C(1) << 31; const ShCompileOptions SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM = UINT64_C(1) << 31;
// Set to initialize uninitialized local variables. Should only be used with GLSL output. In HLSL // Set to initialize uninitialized local variables. Should only be used with GLSL output. In HLSL
......
...@@ -218,6 +218,7 @@ struct InterfaceBlock ...@@ -218,6 +218,7 @@ struct InterfaceBlock
// Fields from blocks with non-empty instance names are prefixed with the block name. // Fields from blocks with non-empty instance names are prefixed with the block name.
std::string fieldPrefix() const; std::string fieldPrefix() const;
std::string fieldMappedPrefix() const;
// Decide whether two interface blocks are the same at shader link time. // Decide whether two interface blocks are the same at shader link time.
bool isSameInterfaceBlockAtLinkTime(const InterfaceBlock &other) const; bool isSameInterfaceBlockAtLinkTime(const InterfaceBlock &other) const;
......
...@@ -108,8 +108,10 @@ class CollectVariablesTraverser : public TIntermTraverser ...@@ -108,8 +108,10 @@ class CollectVariablesTraverser : public TIntermTraverser
bool visitBinary(Visit visit, TIntermBinary *binaryNode) override; bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
private: private:
std::string getMappedName(const TName &name) const;
void setCommonVariableProperties(const TType &type, void setCommonVariableProperties(const TType &type,
const TString &name, const TName &name,
ShaderVariable *variableOut) const; ShaderVariable *variableOut) const;
Attribute recordAttribute(const TIntermSymbol &variable) const; Attribute recordAttribute(const TIntermSymbol &variable) const;
...@@ -229,6 +231,11 @@ CollectVariablesTraverser::CollectVariablesTraverser( ...@@ -229,6 +231,11 @@ CollectVariablesTraverser::CollectVariablesTraverser(
{ {
} }
std::string CollectVariablesTraverser::getMappedName(const TName &name) const
{
return HashName(name, mHashFunction, nullptr).c_str();
}
void CollectVariablesTraverser::setBuiltInInfoFromSymbolTable(const char *name, void CollectVariablesTraverser::setBuiltInInfoFromSymbolTable(const char *name,
ShaderVariable *info) ShaderVariable *info)
{ {
...@@ -535,7 +542,7 @@ void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol) ...@@ -535,7 +542,7 @@ void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
} }
void CollectVariablesTraverser::setCommonVariableProperties(const TType &type, void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
const TString &name, const TName &name,
ShaderVariable *variableOut) const ShaderVariable *variableOut) const
{ {
ASSERT(variableOut); ASSERT(variableOut);
...@@ -560,12 +567,12 @@ void CollectVariablesTraverser::setCommonVariableProperties(const TType &type, ...@@ -560,12 +567,12 @@ void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
// Regardless of the variable type (uniform, in/out etc.) its fields are always plain // Regardless of the variable type (uniform, in/out etc.) its fields are always plain
// ShaderVariable objects. // ShaderVariable objects.
ShaderVariable fieldVariable; ShaderVariable fieldVariable;
setCommonVariableProperties(*field->type(), field->name(), &fieldVariable); setCommonVariableProperties(*field->type(), TName(field->name()), &fieldVariable);
variableOut->fields.push_back(fieldVariable); variableOut->fields.push_back(fieldVariable);
} }
} }
variableOut->name = name.c_str(); variableOut->name = name.getString().c_str();
variableOut->mappedName = HashName(name, mHashFunction).c_str(); variableOut->mappedName = getMappedName(name);
// TODO(oetuaho@nvidia.com): Uniforms can be arrays of arrays, so this assert will need to be // TODO(oetuaho@nvidia.com): Uniforms can be arrays of arrays, so this assert will need to be
// removed. // removed.
...@@ -579,7 +586,7 @@ Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variab ...@@ -579,7 +586,7 @@ Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variab
ASSERT(!type.getStruct()); ASSERT(!type.getStruct());
Attribute attribute; Attribute attribute;
setCommonVariableProperties(type, variable.getSymbol(), &attribute); setCommonVariableProperties(type, variable.getName(), &attribute);
attribute.location = type.getLayoutQualifier().location; attribute.location = type.getLayoutQualifier().location;
return attribute; return attribute;
...@@ -591,7 +598,7 @@ OutputVariable CollectVariablesTraverser::recordOutputVariable(const TIntermSymb ...@@ -591,7 +598,7 @@ OutputVariable CollectVariablesTraverser::recordOutputVariable(const TIntermSymb
ASSERT(!type.getStruct()); ASSERT(!type.getStruct());
OutputVariable outputVariable; OutputVariable outputVariable;
setCommonVariableProperties(type, variable.getSymbol(), &outputVariable); setCommonVariableProperties(type, variable.getName(), &outputVariable);
outputVariable.location = type.getLayoutQualifier().location; outputVariable.location = type.getLayoutQualifier().location;
return outputVariable; return outputVariable;
...@@ -602,7 +609,7 @@ Varying CollectVariablesTraverser::recordVarying(const TIntermSymbol &variable) ...@@ -602,7 +609,7 @@ Varying CollectVariablesTraverser::recordVarying(const TIntermSymbol &variable)
const TType &type = variable.getType(); const TType &type = variable.getType();
Varying varying; Varying varying;
setCommonVariableProperties(type, variable.getSymbol(), &varying); setCommonVariableProperties(type, variable.getName(), &varying);
switch (type.getQualifier()) switch (type.getQualifier())
{ {
...@@ -637,7 +644,7 @@ void CollectVariablesTraverser::recordInterfaceBlock(const TType &interfaceBlock ...@@ -637,7 +644,7 @@ void CollectVariablesTraverser::recordInterfaceBlock(const TType &interfaceBlock
ASSERT(blockType); ASSERT(blockType);
interfaceBlock->name = blockType->name().c_str(); interfaceBlock->name = blockType->name().c_str();
interfaceBlock->mappedName = HashName(blockType->name().c_str(), mHashFunction).c_str(); interfaceBlock->mappedName = getMappedName(TName(blockType->name()));
interfaceBlock->instanceName = interfaceBlock->instanceName =
(blockType->hasInstanceName() ? blockType->instanceName().c_str() : ""); (blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
ASSERT(!interfaceBlockType.isArrayOfArrays()); // Disallowed by GLSL ES 3.10 section 4.3.9 ASSERT(!interfaceBlockType.isArrayOfArrays()); // Disallowed by GLSL ES 3.10 section 4.3.9
...@@ -658,7 +665,7 @@ void CollectVariablesTraverser::recordInterfaceBlock(const TType &interfaceBlock ...@@ -658,7 +665,7 @@ void CollectVariablesTraverser::recordInterfaceBlock(const TType &interfaceBlock
const TType &fieldType = *field->type(); const TType &fieldType = *field->type();
InterfaceBlockField fieldVariable; InterfaceBlockField fieldVariable;
setCommonVariableProperties(fieldType, field->name(), &fieldVariable); setCommonVariableProperties(fieldType, TName(field->name()), &fieldVariable);
fieldVariable.isRowMajorLayout = fieldVariable.isRowMajorLayout =
(fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor); (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
interfaceBlock->fields.push_back(fieldVariable); interfaceBlock->fields.push_back(fieldVariable);
...@@ -668,7 +675,7 @@ void CollectVariablesTraverser::recordInterfaceBlock(const TType &interfaceBlock ...@@ -668,7 +675,7 @@ void CollectVariablesTraverser::recordInterfaceBlock(const TType &interfaceBlock
Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const
{ {
Uniform uniform; Uniform uniform;
setCommonVariableProperties(variable.getType(), variable.getSymbol(), &uniform); setCommonVariableProperties(variable.getType(), variable.getName(), &uniform);
uniform.binding = variable.getType().getLayoutQualifier().binding; uniform.binding = variable.getType().getLayoutQualifier().binding;
uniform.location = variable.getType().getLayoutQualifier().location; uniform.location = variable.getType().getLayoutQualifier().location;
uniform.offset = variable.getType().getLayoutQualifier().offset; uniform.offset = variable.getType().getLayoutQualifier().offset;
......
...@@ -6,18 +6,67 @@ ...@@ -6,18 +6,67 @@
#include "compiler/translator/HashNames.h" #include "compiler/translator/HashNames.h"
#include "compiler/translator/IntermNode.h"
namespace sh namespace sh
{ {
namespace
{
// GLSL ES 3.00.6 section 3.9: the maximum length of an identifier is 1024 characters.
static const unsigned int kESSLMaxIdentifierLength = 1024u;
static const char *kHashedNamePrefix = "webgl_";
// Can't prefix with just _ because then we might introduce a double underscore, which is not safe
// in GLSL (ESSL 3.00.6 section 3.8: All identifiers containing a double underscore are reserved for
// use by the underlying implementation). u is short for user-defined.
static const char *kUnhashedNamePrefix = "_u";
static const unsigned int kUnhashedNamePrefixLength = 2u;
TString HashName(const TString &name, ShHashFunction64 hashFunction) TString HashName(const TString &name, ShHashFunction64 hashFunction)
{ {
if (hashFunction == nullptr || name.empty()) ASSERT(!name.empty());
return name; ASSERT(hashFunction);
khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length()); khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length());
TStringStream stream; TStringStream stream;
stream << HASHED_NAME_PREFIX << std::hex << number; stream << kHashedNamePrefix << std::hex << number;
TString hashedName = stream.str(); TString hashedName = stream.str();
return hashedName; return hashedName;
} }
} // anonymous namespace
TString HashName(const TName &name, ShHashFunction64 hashFunction, NameMap *nameMap)
{
if (name.getString().empty() || name.isInternal())
{
return name.getString();
}
if (hashFunction == nullptr)
{
if (name.getString().length() + kUnhashedNamePrefixLength > kESSLMaxIdentifierLength)
{
// If the identifier length is already close to the limit, we can't prefix it. This is
// not a problem since there are no builtins or ANGLE's internal variables that would
// have as long names and could conflict.
return name.getString();
}
return kUnhashedNamePrefix + name.getString();
}
if (nameMap)
{
NameMap::const_iterator it = nameMap->find(name.getString().c_str());
if (it != nameMap->end())
return it->second.c_str();
}
TString hashedName = HashName(name.getString(), hashFunction);
if (nameMap)
{
(*nameMap)[name.getString().c_str()] = hashedName.c_str();
}
return hashedName;
}
} // namespace sh } // namespace sh
...@@ -12,16 +12,16 @@ ...@@ -12,16 +12,16 @@
#include "GLSLANG/ShaderLang.h" #include "GLSLANG/ShaderLang.h"
#include "compiler/translator/Common.h" #include "compiler/translator/Common.h"
#define HASHED_NAME_PREFIX "webgl_"
namespace sh namespace sh
{ {
typedef std::map<TPersistString, TPersistString> NameMap; typedef std::map<TPersistString, TPersistString> NameMap;
// Return the original name if hash function pointer is NULL; class TName;
// otherwise return the hashed name.
TString HashName(const TString &name, ShHashFunction64 hashFunction); // Hash user-defined name for GLSL output, with special handling for internal names.
// The nameMap parameter is optional and is used to cache hashed names if set.
TString HashName(const TName &name, ShHashFunction64 hashFunction, NameMap *nameMap);
} // namespace sh } // namespace sh
......
...@@ -1142,35 +1142,13 @@ TString TOutputGLSLBase::getTypeName(const TType &type) ...@@ -1142,35 +1142,13 @@ TString TOutputGLSLBase::getTypeName(const TType &type)
TString TOutputGLSLBase::hashName(const TName &name) TString TOutputGLSLBase::hashName(const TName &name)
{ {
if (name.getString().empty()) return HashName(name, mHashFunction, &mNameMap);
{
ASSERT(!name.isInternal());
return name.getString();
}
if (name.isInternal())
{
// TODO(oetuaho): Would be nicer to prefix non-internal names with "_" instead, like is
// done in the HLSL output, but that requires fairly complex changes elsewhere in the code
// as well.
// We need to use a prefix that is reserved in WebGL in order to guarantee that the internal
// names don't conflict with user-defined names from WebGL.
return "webgl_angle_" + name.getString();
}
if (mHashFunction == nullptr)
{
return name.getString();
}
NameMap::const_iterator it = mNameMap.find(name.getString().c_str());
if (it != mNameMap.end())
return it->second.c_str();
TString hashedName = HashName(name.getString(), mHashFunction);
mNameMap[name.getString().c_str()] = hashedName.c_str();
return hashedName;
} }
TString TOutputGLSLBase::hashVariableName(const TName &name) TString TOutputGLSLBase::hashVariableName(const TName &name)
{ {
if (mSymbolTable->findBuiltIn(name.getString(), mShaderVersion) != nullptr) if (mSymbolTable->findBuiltIn(name.getString(), mShaderVersion) != nullptr ||
name.getString().substr(0, 3) == "gl_")
{ {
if (mCompileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM && if (mCompileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM &&
name.getString() == "gl_ViewID_OVR") name.getString() == "gl_ViewID_OVR")
...@@ -1186,10 +1164,8 @@ TString TOutputGLSLBase::hashVariableName(const TName &name) ...@@ -1186,10 +1164,8 @@ TString TOutputGLSLBase::hashVariableName(const TName &name)
TString TOutputGLSLBase::hashFunctionNameIfNeeded(const TFunctionSymbolInfo &info) TString TOutputGLSLBase::hashFunctionNameIfNeeded(const TFunctionSymbolInfo &info)
{ {
if (info.isMain() || info.getNameObj().isInternal()) if (info.isMain())
{ {
// Internal function names are outputted as-is - they may refer to functions manually added
// to the output shader source that are not included in the AST at all.
return info.getName(); return info.getName();
} }
else else
......
...@@ -417,6 +417,11 @@ std::string InterfaceBlock::fieldPrefix() const ...@@ -417,6 +417,11 @@ std::string InterfaceBlock::fieldPrefix() const
return instanceName.empty() ? "" : name; return instanceName.empty() ? "" : name;
} }
std::string InterfaceBlock::fieldMappedPrefix() const
{
return instanceName.empty() ? "" : mappedName;
}
bool InterfaceBlock::isSameInterfaceBlockAtLinkTime(const InterfaceBlock &other) const bool InterfaceBlock::isSameInterfaceBlockAtLinkTime(const InterfaceBlock &other) const
{ {
if (name != other.name || mappedName != other.mappedName || arraySize != other.arraySize || if (name != other.name || mappedName != other.mappedName || arraySize != other.arraySize ||
......
...@@ -231,6 +231,7 @@ LinkResult MemoryProgramCache::Deserialize(const Context *context, ...@@ -231,6 +231,7 @@ LinkResult MemoryProgramCache::Deserialize(const Context *context,
{ {
UniformBlock uniformBlock; UniformBlock uniformBlock;
stream.readString(&uniformBlock.name); stream.readString(&uniformBlock.name);
stream.readString(&uniformBlock.mappedName);
stream.readBool(&uniformBlock.isArray); stream.readBool(&uniformBlock.isArray);
stream.readInt(&uniformBlock.arrayElement); stream.readInt(&uniformBlock.arrayElement);
...@@ -411,6 +412,7 @@ void MemoryProgramCache::Serialize(const Context *context, ...@@ -411,6 +412,7 @@ void MemoryProgramCache::Serialize(const Context *context,
for (const UniformBlock &uniformBlock : state.getUniformBlocks()) for (const UniformBlock &uniformBlock : state.getUniformBlocks())
{ {
stream.writeString(uniformBlock.name); stream.writeString(uniformBlock.name);
stream.writeString(uniformBlock.mappedName);
stream.writeInt(uniformBlock.isArray); stream.writeInt(uniformBlock.isArray);
stream.writeInt(uniformBlock.arrayElement); stream.writeInt(uniformBlock.arrayElement);
......
...@@ -2799,32 +2799,40 @@ void Program::gatherInterfaceBlockInfo(const Context *context) ...@@ -2799,32 +2799,40 @@ void Program::gatherInterfaceBlockInfo(const Context *context)
template <typename VarT> template <typename VarT>
void Program::defineUniformBlockMembers(const std::vector<VarT> &fields, void Program::defineUniformBlockMembers(const std::vector<VarT> &fields,
const std::string &prefix, const std::string &prefix,
const std::string &mappedPrefix,
int blockIndex) int blockIndex)
{ {
for (const VarT &field : fields) for (const VarT &field : fields)
{ {
const std::string &fullName = (prefix.empty() ? field.name : prefix + "." + field.name); const std::string &fullName = (prefix.empty() ? field.name : prefix + "." + field.name);
const std::string &fullMappedName =
(mappedPrefix.empty() ? field.mappedName : mappedPrefix + "." + field.mappedName);
if (field.isStruct()) if (field.isStruct())
{ {
for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++) for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
{ {
const std::string uniformElementName = const std::string uniformElementName =
fullName + (field.isArray() ? ArrayString(arrayElement) : ""); fullName + (field.isArray() ? ArrayString(arrayElement) : "");
defineUniformBlockMembers(field.fields, uniformElementName, blockIndex); const std::string uniformElementMappedName =
fullMappedName + (field.isArray() ? ArrayString(arrayElement) : "");
defineUniformBlockMembers(field.fields, uniformElementName,
uniformElementMappedName, blockIndex);
} }
} }
else else
{ {
// If getBlockMemberInfo returns false, the uniform is optimized out. // If getBlockMemberInfo returns false, the uniform is optimized out.
sh::BlockMemberInfo memberInfo; sh::BlockMemberInfo memberInfo;
if (!mProgram->getUniformBlockMemberInfo(fullName, &memberInfo)) if (!mProgram->getUniformBlockMemberInfo(fullName, fullMappedName, &memberInfo))
{ {
continue; continue;
} }
LinkedUniform newUniform(field.type, field.precision, fullName, field.arraySize, -1, -1, LinkedUniform newUniform(field.type, field.precision, fullName, field.arraySize, -1, -1,
-1, blockIndex, memberInfo); -1, blockIndex, memberInfo);
newUniform.mappedName = fullMappedName;
// Since block uniforms have no location, we don't need to store them in the uniform // Since block uniforms have no location, we don't need to store them in the uniform
// locations list. // locations list.
...@@ -2841,7 +2849,8 @@ void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenu ...@@ -2841,7 +2849,8 @@ void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenu
// Track the first and last uniform index to determine the range of active uniforms in the // Track the first and last uniform index to determine the range of active uniforms in the
// block. // block.
size_t firstBlockUniformIndex = mState.mUniforms.size(); size_t firstBlockUniformIndex = mState.mUniforms.size();
defineUniformBlockMembers(interfaceBlock.fields, interfaceBlock.fieldPrefix(), blockIndex); defineUniformBlockMembers(interfaceBlock.fields, interfaceBlock.fieldPrefix(),
interfaceBlock.fieldMappedPrefix(), blockIndex);
size_t lastBlockUniformIndex = mState.mUniforms.size(); size_t lastBlockUniformIndex = mState.mUniforms.size();
std::vector<unsigned int> blockUniformIndexes; std::vector<unsigned int> blockUniformIndexes;
...@@ -2859,12 +2868,13 @@ void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenu ...@@ -2859,12 +2868,13 @@ void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenu
for (unsigned int arrayElement = 0; arrayElement < interfaceBlock.arraySize; ++arrayElement) for (unsigned int arrayElement = 0; arrayElement < interfaceBlock.arraySize; ++arrayElement)
{ {
// Don't define this block at all if it's not active in the implementation. // Don't define this block at all if it's not active in the implementation.
if (!mProgram->getUniformBlockSize(interfaceBlock.name + ArrayString(arrayElement), if (!mProgram->getUniformBlockSize(
&blockSize)) interfaceBlock.name + ArrayString(arrayElement),
interfaceBlock.mappedName + ArrayString(arrayElement), &blockSize))
{ {
continue; continue;
} }
UniformBlock block(interfaceBlock.name, true, arrayElement, UniformBlock block(interfaceBlock.name, interfaceBlock.mappedName, true, arrayElement,
blockBinding + arrayElement); blockBinding + arrayElement);
block.memberIndexes = blockUniformIndexes; block.memberIndexes = blockUniformIndexes;
...@@ -2898,11 +2908,12 @@ void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenu ...@@ -2898,11 +2908,12 @@ void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenu
} }
else else
{ {
if (!mProgram->getUniformBlockSize(interfaceBlock.name, &blockSize)) if (!mProgram->getUniformBlockSize(interfaceBlock.name, interfaceBlock.mappedName,
&blockSize))
{ {
return; return;
} }
UniformBlock block(interfaceBlock.name, false, 0, blockBinding); UniformBlock block(interfaceBlock.name, interfaceBlock.mappedName, false, 0, blockBinding);
block.memberIndexes = blockUniformIndexes; block.memberIndexes = blockUniformIndexes;
switch (shaderType) switch (shaderType)
......
...@@ -610,6 +610,7 @@ class Program final : angle::NonCopyable, public LabeledObject ...@@ -610,6 +610,7 @@ class Program final : angle::NonCopyable, public LabeledObject
template <typename VarT> template <typename VarT>
void defineUniformBlockMembers(const std::vector<VarT> &fields, void defineUniformBlockMembers(const std::vector<VarT> &fields,
const std::string &prefix, const std::string &prefix,
const std::string &mappedPrefix,
int blockIndex); int blockIndex);
void defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType); void defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType);
......
...@@ -477,6 +477,38 @@ const std::vector<sh::OutputVariable> &Shader::getActiveOutputVariables(const Co ...@@ -477,6 +477,38 @@ const std::vector<sh::OutputVariable> &Shader::getActiveOutputVariables(const Co
return mState.getActiveOutputVariables(); return mState.getActiveOutputVariables();
} }
std::string Shader::getTransformFeedbackVaryingMappedName(const std::string &tfVaryingName,
const Context *context)
{
const auto &varyings = getVaryings(context);
auto bracketPos = tfVaryingName.find("[");
if (bracketPos != std::string::npos)
{
auto tfVaryingBaseName = tfVaryingName.substr(0, bracketPos);
for (const auto &varying : varyings)
{
if (varying.name == tfVaryingBaseName)
{
std::string mappedNameWithArrayIndex =
varying.mappedName + tfVaryingName.substr(bracketPos);
return mappedNameWithArrayIndex;
}
}
}
else
{
for (const auto &varying : varyings)
{
if (varying.name == tfVaryingName)
{
return varying.mappedName;
}
}
}
UNREACHABLE();
return std::string();
}
const sh::WorkGroupSize &Shader::getWorkGroupSize(const Context *context) const sh::WorkGroupSize &Shader::getWorkGroupSize(const Context *context)
{ {
resolveCompile(context); resolveCompile(context);
......
...@@ -158,6 +158,12 @@ class Shader final : angle::NonCopyable, public LabeledObject ...@@ -158,6 +158,12 @@ class Shader final : angle::NonCopyable, public LabeledObject
const std::vector<sh::Attribute> &getActiveAttributes(const Context *context); const std::vector<sh::Attribute> &getActiveAttributes(const Context *context);
const std::vector<sh::OutputVariable> &getActiveOutputVariables(const Context *context); const std::vector<sh::OutputVariable> &getActiveOutputVariables(const Context *context);
// Returns mapped name of a transform feedback varying. The original name may contain array
// brackets with an index inside, which will get copied to the mapped name. The varying must be
// known to be declared in the shader.
std::string getTransformFeedbackVaryingMappedName(const std::string &tfVaryingName,
const Context *context);
const sh::WorkGroupSize &getWorkGroupSize(const Context *context); const sh::WorkGroupSize &getWorkGroupSize(const Context *context);
int getNumViews(const Context *context); int getNumViews(const Context *context);
......
...@@ -147,10 +147,11 @@ UniformBlock::UniformBlock() : isArray(false), arrayElement(0) ...@@ -147,10 +147,11 @@ UniformBlock::UniformBlock() : isArray(false), arrayElement(0)
} }
UniformBlock::UniformBlock(const std::string &nameIn, UniformBlock::UniformBlock(const std::string &nameIn,
const std::string &mappedNameIn,
bool isArrayIn, bool isArrayIn,
unsigned int arrayElementIn, unsigned int arrayElementIn,
int bindingIn) int bindingIn)
: name(nameIn), isArray(isArrayIn), arrayElement(arrayElementIn) : name(nameIn), mappedName(mappedNameIn), isArray(isArrayIn), arrayElement(arrayElementIn)
{ {
binding = bindingIn; binding = bindingIn;
} }
...@@ -166,4 +167,16 @@ std::string UniformBlock::nameWithArrayIndex() const ...@@ -166,4 +167,16 @@ std::string UniformBlock::nameWithArrayIndex() const
return fullNameStr.str(); return fullNameStr.str();
} }
std::string UniformBlock::mappedNameWithArrayIndex() const
{
std::stringstream fullNameStr;
fullNameStr << mappedName;
if (isArray)
{
fullNameStr << "[" << arrayElement << "]";
}
return fullNameStr.str();
}
} }
...@@ -94,6 +94,7 @@ struct UniformBlock : public ShaderVariableBuffer ...@@ -94,6 +94,7 @@ struct UniformBlock : public ShaderVariableBuffer
{ {
UniformBlock(); UniformBlock();
UniformBlock(const std::string &nameIn, UniformBlock(const std::string &nameIn,
const std::string &mappedNameIn,
bool isArrayIn, bool isArrayIn,
unsigned int arrayElementIn, unsigned int arrayElementIn,
int bindingIn); int bindingIn);
...@@ -101,8 +102,10 @@ struct UniformBlock : public ShaderVariableBuffer ...@@ -101,8 +102,10 @@ struct UniformBlock : public ShaderVariableBuffer
UniformBlock &operator=(const UniformBlock &other) = default; UniformBlock &operator=(const UniformBlock &other) = default;
std::string nameWithArrayIndex() const; std::string nameWithArrayIndex() const;
std::string mappedNameWithArrayIndex() const;
std::string name; std::string name;
std::string mappedName;
bool isArray; bool isArray;
unsigned int arrayElement; unsigned int arrayElement;
}; };
......
...@@ -453,8 +453,8 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniform( ...@@ -453,8 +453,8 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniform(
{ {
int location = uniform.location; int location = uniform.location;
ShaderUniformCount shaderUniformCount = flattenUniformImpl( ShaderUniformCount shaderUniformCount = flattenUniformImpl(
uniform, uniform.name, samplerUniforms, imageUniforms, atomicCounterUniforms, uniform, uniform.name, uniform.mappedName, samplerUniforms, imageUniforms,
uniform.staticUse, uniform.binding, uniform.offset, &location); atomicCounterUniforms, uniform.staticUse, uniform.binding, uniform.offset, &location);
if (uniform.staticUse) if (uniform.staticUse)
{ {
return shaderUniformCount; return shaderUniformCount;
...@@ -465,6 +465,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniform( ...@@ -465,6 +465,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniform(
UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl( UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl(
const sh::ShaderVariable &uniform, const sh::ShaderVariable &uniform,
const std::string &fullName, const std::string &fullName,
const std::string &fullMappedName,
std::vector<LinkedUniform> *samplerUniforms, std::vector<LinkedUniform> *samplerUniforms,
std::vector<LinkedUniform> *imageUniforms, std::vector<LinkedUniform> *imageUniforms,
std::vector<LinkedUniform> *atomicCounterUniforms, std::vector<LinkedUniform> *atomicCounterUniforms,
...@@ -486,10 +487,12 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl( ...@@ -486,10 +487,12 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl(
{ {
const sh::ShaderVariable &field = uniform.fields[fieldIndex]; const sh::ShaderVariable &field = uniform.fields[fieldIndex];
const std::string &fieldFullName = (fullName + elementString + "." + field.name); const std::string &fieldFullName = (fullName + elementString + "." + field.name);
const std::string &fieldFullMappedName =
(fullMappedName + elementString + "." + field.mappedName);
shaderUniformCount += shaderUniformCount += flattenUniformImpl(
flattenUniformImpl(field, fieldFullName, samplerUniforms, imageUniforms, field, fieldFullName, fieldFullMappedName, samplerUniforms, imageUniforms,
atomicCounterUniforms, markStaticUse, -1, -1, location); atomicCounterUniforms, markStaticUse, -1, -1, location);
} }
} }
...@@ -538,6 +541,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl( ...@@ -538,6 +541,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl(
LinkedUniform linkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize, LinkedUniform linkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize,
binding, -1, *location, -1, binding, -1, *location, -1,
sh::BlockMemberInfo::getDefaultBlockInfo()); sh::BlockMemberInfo::getDefaultBlockInfo());
linkedUniform.mappedName = fullMappedName;
linkedUniform.staticUse = markStaticUse; linkedUniform.staticUse = markStaticUse;
uniformList->push_back(linkedUniform); uniformList->push_back(linkedUniform);
......
...@@ -87,6 +87,7 @@ class UniformLinker ...@@ -87,6 +87,7 @@ class UniformLinker
// granularity. // granularity.
ShaderUniformCount flattenUniformImpl(const sh::ShaderVariable &uniform, ShaderUniformCount flattenUniformImpl(const sh::ShaderVariable &uniform,
const std::string &fullName, const std::string &fullName,
const std::string &fullMappedName,
std::vector<LinkedUniform> *samplerUniforms, std::vector<LinkedUniform> *samplerUniforms,
std::vector<LinkedUniform> *imageUniforms, std::vector<LinkedUniform> *imageUniforms,
std::vector<LinkedUniform> *atomicCounterUniforms, std::vector<LinkedUniform> *atomicCounterUniforms,
......
...@@ -86,11 +86,14 @@ class ProgramImpl : angle::NonCopyable ...@@ -86,11 +86,14 @@ class ProgramImpl : angle::NonCopyable
// May only be called after a successful link operation. // May only be called after a successful link operation.
// Return false for inactive blocks. // Return false for inactive blocks.
virtual bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const = 0; virtual bool getUniformBlockSize(const std::string &blockName,
const std::string &blockMappedName,
size_t *sizeOut) const = 0;
// May only be called after a successful link operation. // May only be called after a successful link operation.
// Returns false for inactive members. // Returns false for inactive members.
virtual bool getUniformBlockMemberInfo(const std::string &memberUniformName, virtual bool getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const = 0; sh::BlockMemberInfo *memberInfoOut) const = 0;
// CHROMIUM_path_rendering // CHROMIUM_path_rendering
// Set parameters to control fragment shader input variable interpolation // Set parameters to control fragment shader input variable interpolation
......
...@@ -60,8 +60,10 @@ class MockProgramImpl : public rx::ProgramImpl ...@@ -60,8 +60,10 @@ class MockProgramImpl : public rx::ProgramImpl
MOCK_CONST_METHOD3(getUniformuiv, void(const gl::Context *, GLint, GLuint *)); MOCK_CONST_METHOD3(getUniformuiv, void(const gl::Context *, GLint, GLuint *));
MOCK_METHOD2(setUniformBlockBinding, void(GLuint, GLuint)); MOCK_METHOD2(setUniformBlockBinding, void(GLuint, GLuint));
MOCK_CONST_METHOD2(getUniformBlockSize, bool(const std::string &, size_t *)); MOCK_CONST_METHOD3(getUniformBlockSize,
MOCK_CONST_METHOD2(getUniformBlockMemberInfo, bool(const std::string &, sh::BlockMemberInfo *)); bool(const std::string &, const std::string &, size_t *));
MOCK_CONST_METHOD3(getUniformBlockMemberInfo,
bool(const std::string &, const std::string &, sh::BlockMemberInfo *));
MOCK_METHOD4(setPathFragmentInputGen, MOCK_METHOD4(setPathFragmentInputGen,
void(const std::string &, GLenum, GLint, const GLfloat *)); void(const std::string &, GLenum, GLint, const GLfloat *));
......
...@@ -2525,7 +2525,9 @@ D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location) ...@@ -2525,7 +2525,9 @@ D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
return mD3DUniforms[mState.getUniformLocations()[location].index]; return mD3DUniforms[mState.getUniformLocations()[location].index];
} }
bool ProgramD3D::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const bool ProgramD3D::getUniformBlockSize(const std::string &blockName,
const std::string & /* blockMappedName */,
size_t *sizeOut) const
{ {
std::string baseName = blockName; std::string baseName = blockName;
gl::ParseAndStripArrayIndex(&baseName); gl::ParseAndStripArrayIndex(&baseName);
...@@ -2542,6 +2544,7 @@ bool ProgramD3D::getUniformBlockSize(const std::string &blockName, size_t *sizeO ...@@ -2542,6 +2544,7 @@ bool ProgramD3D::getUniformBlockSize(const std::string &blockName, size_t *sizeO
} }
bool ProgramD3D::getUniformBlockMemberInfo(const std::string &memberUniformName, bool ProgramD3D::getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string & /* memberUniformMappedName */,
sh::BlockMemberInfo *memberInfoOut) const sh::BlockMemberInfo *memberInfoOut) const
{ {
auto infoIter = mBlockInfo.find(memberUniformName); auto infoIter = mBlockInfo.find(memberUniformName);
......
...@@ -184,8 +184,11 @@ class ProgramD3D : public ProgramImpl ...@@ -184,8 +184,11 @@ class ProgramD3D : public ProgramImpl
gl::InfoLog &infoLog) override; gl::InfoLog &infoLog) override;
GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override; GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override; bool getUniformBlockSize(const std::string &blockName,
const std::string &blockMappedName,
size_t *sizeOut) const override;
bool getUniformBlockMemberInfo(const std::string &memberUniformName, bool getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const override; sh::BlockMemberInfo *memberInfoOut) const override;
void setPathFragmentInputGen(const std::string &inputName, void setPathFragmentInputGen(const std::string &inputName,
GLenum genMode, GLenum genMode,
......
...@@ -144,13 +144,16 @@ gl::LinkResult ProgramGL::link(const gl::Context *context, ...@@ -144,13 +144,16 @@ gl::LinkResult ProgramGL::link(const gl::Context *context,
else else
{ {
// Set the transform feedback state // Set the transform feedback state
std::vector<const GLchar *> transformFeedbackVaryings; std::vector<std::string> transformFeedbackVaryingMappedNames;
for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames()) for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames())
{ {
transformFeedbackVaryings.push_back(tfVarying.c_str()); std::string tfVaryingMappedName =
mState.getAttachedVertexShader()->getTransformFeedbackVaryingMappedName(tfVarying,
context);
transformFeedbackVaryingMappedNames.push_back(tfVaryingMappedName);
} }
if (transformFeedbackVaryings.empty()) if (transformFeedbackVaryingMappedNames.empty())
{ {
if (mFunctions->transformFeedbackVaryings) if (mFunctions->transformFeedbackVaryings)
{ {
...@@ -161,8 +164,13 @@ gl::LinkResult ProgramGL::link(const gl::Context *context, ...@@ -161,8 +164,13 @@ gl::LinkResult ProgramGL::link(const gl::Context *context,
else else
{ {
ASSERT(mFunctions->transformFeedbackVaryings); ASSERT(mFunctions->transformFeedbackVaryings);
std::vector<const GLchar *> transformFeedbackVaryings;
for (const auto &varying : transformFeedbackVaryingMappedNames)
{
transformFeedbackVaryings.push_back(varying.c_str());
}
mFunctions->transformFeedbackVaryings( mFunctions->transformFeedbackVaryings(
mProgramID, static_cast<GLsizei>(transformFeedbackVaryings.size()), mProgramID, static_cast<GLsizei>(transformFeedbackVaryingMappedNames.size()),
&transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode()); &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode());
} }
...@@ -181,7 +189,8 @@ gl::LinkResult ProgramGL::link(const gl::Context *context, ...@@ -181,7 +189,8 @@ gl::LinkResult ProgramGL::link(const gl::Context *context,
continue; continue;
} }
mFunctions->bindAttribLocation(mProgramID, attribute.location, attribute.name.c_str()); mFunctions->bindAttribLocation(mProgramID, attribute.location,
attribute.mappedName.c_str());
} }
// Link and verify // Link and verify
...@@ -501,8 +510,9 @@ void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformB ...@@ -501,8 +510,9 @@ void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformB
mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size()); mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size());
for (const gl::UniformBlock &uniformBlock : mState.getUniformBlocks()) for (const gl::UniformBlock &uniformBlock : mState.getUniformBlocks())
{ {
const std::string &nameWithIndex = uniformBlock.nameWithArrayIndex(); const std::string &mappedNameWithIndex = uniformBlock.mappedNameWithArrayIndex();
GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, nameWithIndex.c_str()); GLuint blockIndex =
mFunctions->getUniformBlockIndex(mProgramID, mappedNameWithIndex.c_str());
mUniformBlockRealLocationMap.push_back(blockIndex); mUniformBlockRealLocationMap.push_back(blockIndex);
} }
} }
...@@ -519,11 +529,13 @@ GLuint ProgramGL::getProgramID() const ...@@ -519,11 +529,13 @@ GLuint ProgramGL::getProgramID() const
return mProgramID; return mProgramID;
} }
bool ProgramGL::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const bool ProgramGL::getUniformBlockSize(const std::string & /* blockName */,
const std::string &blockMappedName,
size_t *sizeOut) const
{ {
ASSERT(mProgramID != 0u); ASSERT(mProgramID != 0u);
GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockName.c_str()); GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockMappedName.c_str());
if (blockIndex == GL_INVALID_INDEX) if (blockIndex == GL_INVALID_INDEX)
{ {
*sizeOut = 0; *sizeOut = 0;
...@@ -537,11 +549,12 @@ bool ProgramGL::getUniformBlockSize(const std::string &blockName, size_t *sizeOu ...@@ -537,11 +549,12 @@ bool ProgramGL::getUniformBlockSize(const std::string &blockName, size_t *sizeOu
return true; return true;
} }
bool ProgramGL::getUniformBlockMemberInfo(const std::string &memberUniformName, bool ProgramGL::getUniformBlockMemberInfo(const std::string & /* memberUniformName */,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const sh::BlockMemberInfo *memberInfoOut) const
{ {
GLuint uniformIndex; GLuint uniformIndex;
const GLchar *memberNameGLStr = memberUniformName.c_str(); const GLchar *memberNameGLStr = memberUniformMappedName.c_str();
mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex); mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);
if (uniformIndex == GL_INVALID_INDEX) if (uniformIndex == GL_INVALID_INDEX)
...@@ -574,7 +587,7 @@ void ProgramGL::setPathFragmentInputGen(const std::string &inputName, ...@@ -574,7 +587,7 @@ void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
for (const auto &input : mPathRenderingFragmentInputs) for (const auto &input : mPathRenderingFragmentInputs)
{ {
if (input.name == inputName) if (input.mappedName == inputName)
{ {
mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode, mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode,
components, coeffs); components, coeffs);
...@@ -650,7 +663,7 @@ void ProgramGL::postLink() ...@@ -650,7 +663,7 @@ void ProgramGL::postLink()
// "Locations for sequential array indices are not required to be sequential." // "Locations for sequential array indices are not required to be sequential."
const gl::LinkedUniform &uniform = uniforms[entry.index]; const gl::LinkedUniform &uniform = uniforms[entry.index];
std::stringstream fullNameStr; std::stringstream fullNameStr;
fullNameStr << uniform.name; fullNameStr << uniform.mappedName;
if (uniform.isArray()) if (uniform.isArray())
{ {
fullNameStr << "[" << entry.element << "]"; fullNameStr << "[" << entry.element << "]";
...@@ -664,7 +677,7 @@ void ProgramGL::postLink() ...@@ -664,7 +677,7 @@ void ProgramGL::postLink()
if (mState.usesMultiview()) if (mState.usesMultiview())
{ {
mMultiviewBaseViewLayerIndexUniformLocation = mMultiviewBaseViewLayerIndexUniformLocation =
mFunctions->getUniformLocation(mProgramID, "webgl_angle_multiviewBaseViewLayerIndex"); mFunctions->getUniformLocation(mProgramID, "multiviewBaseViewLayerIndex");
ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1); ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
} }
...@@ -685,16 +698,16 @@ void ProgramGL::postLink() ...@@ -685,16 +698,16 @@ void ProgramGL::postLink()
for (GLint i = 0; i < numFragmentInputs; ++i) for (GLint i = 0; i < numFragmentInputs; ++i)
{ {
std::string name; std::string mappedName;
name.resize(maxNameLength); mappedName.resize(maxNameLength);
GLsizei nameLen = 0; GLsizei nameLen = 0;
mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength, mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength,
&nameLen, &name[0]); &nameLen, &mappedName[0]);
name.resize(nameLen); mappedName.resize(nameLen);
// Ignore built-ins // Ignore built-ins
if (angle::BeginsWith(name, "gl_")) if (angle::BeginsWith(mappedName, "gl_"))
continue; continue;
const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE}; const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE};
...@@ -709,16 +722,16 @@ void ProgramGL::postLink() ...@@ -709,16 +722,16 @@ void ProgramGL::postLink()
ASSERT(queryLength == static_cast<GLsizei>(ArraySize(kQueryProperties))); ASSERT(queryLength == static_cast<GLsizei>(ArraySize(kQueryProperties)));
PathRenderingFragmentInput baseElementInput; PathRenderingFragmentInput baseElementInput;
baseElementInput.name = name; baseElementInput.mappedName = mappedName;
baseElementInput.location = queryResults[0]; baseElementInput.location = queryResults[0];
mPathRenderingFragmentInputs.push_back(std::move(baseElementInput)); mPathRenderingFragmentInputs.push_back(std::move(baseElementInput));
// If the input is an array it's denoted by [0] suffix on the variable // If the input is an array it's denoted by [0] suffix on the variable
// name. We'll then create an entry per each array index where index > 0 // name. We'll then create an entry per each array index where index > 0
if (angle::EndsWith(name, "[0]")) if (angle::EndsWith(mappedName, "[0]"))
{ {
// drop the suffix // drop the suffix
name.resize(name.size() - 3); mappedName.resize(mappedName.size() - 3);
const auto arraySize = queryResults[1]; const auto arraySize = queryResults[1];
const auto baseLocation = queryResults[0]; const auto baseLocation = queryResults[0];
...@@ -726,7 +739,7 @@ void ProgramGL::postLink() ...@@ -726,7 +739,7 @@ void ProgramGL::postLink()
for (GLint arrayIndex = 1; arrayIndex < arraySize; ++arrayIndex) for (GLint arrayIndex = 1; arrayIndex < arraySize; ++arrayIndex)
{ {
PathRenderingFragmentInput arrayElementInput; PathRenderingFragmentInput arrayElementInput;
arrayElementInput.name = name + "[" + ToString(arrayIndex) + "]"; arrayElementInput.mappedName = mappedName + "[" + ToString(arrayIndex) + "]";
arrayElementInput.location = baseLocation + arrayIndex; arrayElementInput.location = baseLocation + arrayIndex;
mPathRenderingFragmentInputs.push_back(std::move(arrayElementInput)); mPathRenderingFragmentInputs.push_back(std::move(arrayElementInput));
} }
......
...@@ -71,8 +71,11 @@ class ProgramGL : public ProgramImpl ...@@ -71,8 +71,11 @@ class ProgramGL : public ProgramImpl
void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override; void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override;
bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override; bool getUniformBlockSize(const std::string &blockName,
const std::string &blockMappedName,
size_t *sizeOut) const override;
bool getUniformBlockMemberInfo(const std::string &memberUniformName, bool getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const override; sh::BlockMemberInfo *memberInfoOut) const override;
void setPathFragmentInputGen(const std::string &inputName, void setPathFragmentInputGen(const std::string &inputName,
...@@ -105,7 +108,7 @@ class ProgramGL : public ProgramImpl ...@@ -105,7 +108,7 @@ class ProgramGL : public ProgramImpl
struct PathRenderingFragmentInput struct PathRenderingFragmentInput
{ {
std::string name; std::string mappedName;
GLint location; GLint location;
}; };
std::vector<PathRenderingFragmentInput> mPathRenderingFragmentInputs; std::vector<PathRenderingFragmentInput> mPathRenderingFragmentInputs;
......
...@@ -183,7 +183,9 @@ void ProgramNULL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint unifor ...@@ -183,7 +183,9 @@ void ProgramNULL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint unifor
{ {
} }
bool ProgramNULL::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const bool ProgramNULL::getUniformBlockSize(const std::string &blockName,
const std::string &blockMappedName,
size_t *sizeOut) const
{ {
// TODO(geofflang): Compute reasonable sizes? // TODO(geofflang): Compute reasonable sizes?
*sizeOut = 0; *sizeOut = 0;
...@@ -191,6 +193,7 @@ bool ProgramNULL::getUniformBlockSize(const std::string &blockName, size_t *size ...@@ -191,6 +193,7 @@ bool ProgramNULL::getUniformBlockSize(const std::string &blockName, size_t *size
} }
bool ProgramNULL::getUniformBlockMemberInfo(const std::string &memberUniformName, bool ProgramNULL::getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const sh::BlockMemberInfo *memberInfoOut) const
{ {
// TODO(geofflang): Compute reasonable values? // TODO(geofflang): Compute reasonable values?
......
...@@ -91,11 +91,14 @@ class ProgramNULL : public ProgramImpl ...@@ -91,11 +91,14 @@ class ProgramNULL : public ProgramImpl
// May only be called after a successful link operation. // May only be called after a successful link operation.
// Return false for inactive blocks. // Return false for inactive blocks.
bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override; bool getUniformBlockSize(const std::string &blockName,
const std::string &blockMappedName,
size_t *sizeOut) const override;
// May only be called after a successful link operation. // May only be called after a successful link operation.
// Returns false for inactive members. // Returns false for inactive members.
bool getUniformBlockMemberInfo(const std::string &memberUniformName, bool getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const override; sh::BlockMemberInfo *memberInfoOut) const override;
// CHROMIUM_path_rendering // CHROMIUM_path_rendering
// Set parameters to control fragment shader input variable interpolation // Set parameters to control fragment shader input variable interpolation
......
...@@ -259,13 +259,16 @@ void ProgramVk::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformB ...@@ -259,13 +259,16 @@ void ProgramVk::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformB
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
bool ProgramVk::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const bool ProgramVk::getUniformBlockSize(const std::string &blockName,
const std::string &blockMappedName,
size_t *sizeOut) const
{ {
UNIMPLEMENTED(); UNIMPLEMENTED();
return bool(); return bool();
} }
bool ProgramVk::getUniformBlockMemberInfo(const std::string &memberUniformName, bool ProgramVk::getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const sh::BlockMemberInfo *memberInfoOut) const
{ {
UNIMPLEMENTED(); UNIMPLEMENTED();
......
...@@ -93,11 +93,14 @@ class ProgramVk : public ProgramImpl ...@@ -93,11 +93,14 @@ class ProgramVk : public ProgramImpl
// May only be called after a successful link operation. // May only be called after a successful link operation.
// Return false for inactive blocks. // Return false for inactive blocks.
bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override; bool getUniformBlockSize(const std::string &blockName,
const std::string &blockMappedName,
size_t *sizeOut) const override;
// May only be called after a successful link operation. // May only be called after a successful link operation.
// Returns false for inactive members. // Returns false for inactive members.
bool getUniformBlockMemberInfo(const std::string &memberUniformName, bool getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const override; sh::BlockMemberInfo *memberInfoOut) const override;
void setPathFragmentInputGen(const std::string &inputName, void setPathFragmentInputGen(const std::string &inputName,
......
...@@ -19,6 +19,16 @@ using namespace sh; ...@@ -19,6 +19,16 @@ using namespace sh;
#define EXPECT_GLENUM_EQ(expected, actual) \ #define EXPECT_GLENUM_EQ(expected, actual) \
EXPECT_EQ(static_cast<::GLenum>(expected), static_cast<::GLenum>(actual)) EXPECT_EQ(static_cast<::GLenum>(expected), static_cast<::GLenum>(actual))
namespace
{
std::string DecorateName(const char *name)
{
return std::string("_u") + name;
}
} // anonymous namespace
class CollectVariablesTest : public testing::Test class CollectVariablesTest : public testing::Test
{ {
public: public:
...@@ -358,6 +368,7 @@ TEST_F(CollectVertexVariablesTest, StructInterfaceBlock) ...@@ -358,6 +368,7 @@ TEST_F(CollectVertexVariablesTest, StructInterfaceBlock)
EXPECT_FALSE(interfaceBlock.isRowMajorLayout); EXPECT_FALSE(interfaceBlock.isRowMajorLayout);
EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout); EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
EXPECT_EQ("b", interfaceBlock.name); EXPECT_EQ("b", interfaceBlock.name);
EXPECT_EQ(DecorateName("b"), interfaceBlock.mappedName);
EXPECT_TRUE(interfaceBlock.staticUse); EXPECT_TRUE(interfaceBlock.staticUse);
ASSERT_EQ(1u, interfaceBlock.fields.size()); ASSERT_EQ(1u, interfaceBlock.fields.size());
...@@ -367,6 +378,7 @@ TEST_F(CollectVertexVariablesTest, StructInterfaceBlock) ...@@ -367,6 +378,7 @@ TEST_F(CollectVertexVariablesTest, StructInterfaceBlock)
EXPECT_TRUE(field.isStruct()); EXPECT_TRUE(field.isStruct());
EXPECT_TRUE(field.staticUse); EXPECT_TRUE(field.staticUse);
EXPECT_EQ("s", field.name); EXPECT_EQ("s", field.name);
EXPECT_EQ(DecorateName("s"), field.mappedName);
EXPECT_FALSE(field.isRowMajorLayout); EXPECT_FALSE(field.isRowMajorLayout);
const ShaderVariable &member = field.fields[0]; const ShaderVariable &member = field.fields[0];
...@@ -374,6 +386,7 @@ TEST_F(CollectVertexVariablesTest, StructInterfaceBlock) ...@@ -374,6 +386,7 @@ TEST_F(CollectVertexVariablesTest, StructInterfaceBlock)
// NOTE: we don't currently mark struct members as statically used or not // NOTE: we don't currently mark struct members as statically used or not
EXPECT_FALSE(member.isStruct()); EXPECT_FALSE(member.isStruct());
EXPECT_EQ("f", member.name); EXPECT_EQ("f", member.name);
EXPECT_EQ(DecorateName("f"), member.mappedName);
EXPECT_GLENUM_EQ(GL_FLOAT, member.type); EXPECT_GLENUM_EQ(GL_FLOAT, member.type);
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision); EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision);
} }
...@@ -401,6 +414,7 @@ TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock) ...@@ -401,6 +414,7 @@ TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock)
EXPECT_FALSE(interfaceBlock.isRowMajorLayout); EXPECT_FALSE(interfaceBlock.isRowMajorLayout);
EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout); EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
EXPECT_EQ("b", interfaceBlock.name); EXPECT_EQ("b", interfaceBlock.name);
EXPECT_EQ(DecorateName("b"), interfaceBlock.mappedName);
EXPECT_EQ("instanceName", interfaceBlock.instanceName); EXPECT_EQ("instanceName", interfaceBlock.instanceName);
EXPECT_TRUE(interfaceBlock.staticUse); EXPECT_TRUE(interfaceBlock.staticUse);
...@@ -411,6 +425,7 @@ TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock) ...@@ -411,6 +425,7 @@ TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock)
EXPECT_TRUE(field.isStruct()); EXPECT_TRUE(field.isStruct());
EXPECT_TRUE(field.staticUse); EXPECT_TRUE(field.staticUse);
EXPECT_EQ("s", field.name); EXPECT_EQ("s", field.name);
EXPECT_EQ(DecorateName("s"), field.mappedName);
EXPECT_FALSE(field.isRowMajorLayout); EXPECT_FALSE(field.isRowMajorLayout);
const ShaderVariable &member = field.fields[0]; const ShaderVariable &member = field.fields[0];
...@@ -418,6 +433,7 @@ TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock) ...@@ -418,6 +433,7 @@ TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock)
// NOTE: we don't currently mark struct members as statically used or not // NOTE: we don't currently mark struct members as statically used or not
EXPECT_FALSE(member.isStruct()); EXPECT_FALSE(member.isStruct());
EXPECT_EQ("f", member.name); EXPECT_EQ("f", member.name);
EXPECT_EQ(DecorateName("f"), member.mappedName);
EXPECT_GLENUM_EQ(GL_FLOAT, member.type); EXPECT_GLENUM_EQ(GL_FLOAT, member.type);
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision); EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision);
} }
...@@ -445,6 +461,7 @@ TEST_F(CollectVertexVariablesTest, NestedStructRowMajorInterfaceBlock) ...@@ -445,6 +461,7 @@ TEST_F(CollectVertexVariablesTest, NestedStructRowMajorInterfaceBlock)
EXPECT_TRUE(interfaceBlock.isRowMajorLayout); EXPECT_TRUE(interfaceBlock.isRowMajorLayout);
EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout); EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
EXPECT_EQ("b", interfaceBlock.name); EXPECT_EQ("b", interfaceBlock.name);
EXPECT_EQ(DecorateName("b"), interfaceBlock.mappedName);
EXPECT_TRUE(interfaceBlock.staticUse); EXPECT_TRUE(interfaceBlock.staticUse);
ASSERT_EQ(1u, interfaceBlock.fields.size()); ASSERT_EQ(1u, interfaceBlock.fields.size());
...@@ -454,6 +471,7 @@ TEST_F(CollectVertexVariablesTest, NestedStructRowMajorInterfaceBlock) ...@@ -454,6 +471,7 @@ TEST_F(CollectVertexVariablesTest, NestedStructRowMajorInterfaceBlock)
EXPECT_TRUE(field.isStruct()); EXPECT_TRUE(field.isStruct());
EXPECT_TRUE(field.staticUse); EXPECT_TRUE(field.staticUse);
EXPECT_EQ("s", field.name); EXPECT_EQ("s", field.name);
EXPECT_EQ(DecorateName("s"), field.mappedName);
EXPECT_TRUE(field.isRowMajorLayout); EXPECT_TRUE(field.isRowMajorLayout);
const ShaderVariable &member = field.fields[0]; const ShaderVariable &member = field.fields[0];
...@@ -461,6 +479,7 @@ TEST_F(CollectVertexVariablesTest, NestedStructRowMajorInterfaceBlock) ...@@ -461,6 +479,7 @@ TEST_F(CollectVertexVariablesTest, NestedStructRowMajorInterfaceBlock)
// NOTE: we don't currently mark struct members as statically used or not // NOTE: we don't currently mark struct members as statically used or not
EXPECT_FALSE(member.isStruct()); EXPECT_FALSE(member.isStruct());
EXPECT_EQ("m", member.name); EXPECT_EQ("m", member.name);
EXPECT_EQ(DecorateName("m"), member.mappedName);
EXPECT_GLENUM_EQ(GL_FLOAT_MAT2, member.type); EXPECT_GLENUM_EQ(GL_FLOAT_MAT2, member.type);
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision); EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision);
} }
...@@ -493,6 +512,7 @@ TEST_F(CollectVertexVariablesTest, VaryingInterpolation) ...@@ -493,6 +512,7 @@ TEST_F(CollectVertexVariablesTest, VaryingInterpolation)
EXPECT_TRUE(varying->staticUse); EXPECT_TRUE(varying->staticUse);
EXPECT_GLENUM_EQ(GL_FLOAT, varying->type); EXPECT_GLENUM_EQ(GL_FLOAT, varying->type);
EXPECT_EQ("vary", varying->name); EXPECT_EQ("vary", varying->name);
EXPECT_EQ(DecorateName("vary"), varying->mappedName);
EXPECT_EQ(INTERPOLATION_CENTROID, varying->interpolation); EXPECT_EQ(INTERPOLATION_CENTROID, varying->interpolation);
} }
......
...@@ -37,8 +37,10 @@ TEST_F(PruneEmptyDeclarationsTest, EmptyDeclarationStartsDeclaratorList) ...@@ -37,8 +37,10 @@ TEST_F(PruneEmptyDeclarationsTest, EmptyDeclarationStartsDeclaratorList)
" gl_Position = vec4(u * f);\n" " gl_Position = vec4(u * f);\n"
"}\n"; "}\n";
compile(shaderString); compile(shaderString);
ASSERT_TRUE(foundInCode("float f")); ASSERT_TRUE(foundInCode("float _uf"));
ASSERT_TRUE(notFoundInCode("float, _uf"));
ASSERT_TRUE(notFoundInCode("float, f")); ASSERT_TRUE(notFoundInCode("float, f"));
ASSERT_TRUE(notFoundInCode("float _u, _uf"));
} }
TEST_F(PruneEmptyDeclarationsTest, EmptyStructDeclarationWithQualifiers) TEST_F(PruneEmptyDeclarationsTest, EmptyStructDeclarationWithQualifiers)
...@@ -52,9 +54,9 @@ TEST_F(PruneEmptyDeclarationsTest, EmptyStructDeclarationWithQualifiers) ...@@ -52,9 +54,9 @@ TEST_F(PruneEmptyDeclarationsTest, EmptyStructDeclarationWithQualifiers)
" gl_Position = vec4(s.f);\n" " gl_Position = vec4(s.f);\n"
"}\n"; "}\n";
compile(shaderString); compile(shaderString);
ASSERT_TRUE(foundInCode("struct S")); ASSERT_TRUE(foundInCode("struct _uS"));
ASSERT_TRUE(foundInCode("uniform S")); ASSERT_TRUE(foundInCode("uniform _uS"));
ASSERT_TRUE(notFoundInCode("const struct S")); ASSERT_TRUE(notFoundInCode("const struct _uS"));
} }
} // namespace } // namespace
...@@ -33,7 +33,7 @@ TEST_F(RecordConstantPrecisionTest, HigherPrecisionConstantAsParameter) ...@@ -33,7 +33,7 @@ TEST_F(RecordConstantPrecisionTest, HigherPrecisionConstantAsParameter)
" gl_FragColor = vec4(b);\n" " gl_FragColor = vec4(b);\n"
"}\n"; "}\n";
compile(shaderString); compile(shaderString);
ASSERT_TRUE(foundInCode("const highp float webgl_angle_s")); ASSERT_TRUE(foundInCode("const highp float s"));
ASSERT_FALSE(foundInCode("fract(4096.5")); ASSERT_FALSE(foundInCode("fract(4096.5"));
ASSERT_FALSE(foundInCode("fract((4096.5")); ASSERT_FALSE(foundInCode("fract((4096.5"));
} }
...@@ -51,7 +51,7 @@ TEST_F(RecordConstantPrecisionTest, EqualPrecisionConstantAsParameter) ...@@ -51,7 +51,7 @@ TEST_F(RecordConstantPrecisionTest, EqualPrecisionConstantAsParameter)
" gl_FragColor = vec4(b);\n" " gl_FragColor = vec4(b);\n"
"}\n"; "}\n";
compile(shaderString); compile(shaderString);
ASSERT_FALSE(foundInCode("const mediump float webgl_angle_s")); ASSERT_FALSE(foundInCode("const mediump float s"));
ASSERT_TRUE(foundInCode("fract((4096.5")); ASSERT_TRUE(foundInCode("fract((4096.5"));
} }
...@@ -69,7 +69,7 @@ TEST_F(RecordConstantPrecisionTest, FoldedBinaryConstantPrecisionIsHigher) ...@@ -69,7 +69,7 @@ TEST_F(RecordConstantPrecisionTest, FoldedBinaryConstantPrecisionIsHigher)
" gl_FragColor = vec4(b);\n" " gl_FragColor = vec4(b);\n"
"}\n"; "}\n";
compile(shaderString); compile(shaderString);
ASSERT_TRUE(foundInCode("const highp float webgl_angle_s")); ASSERT_TRUE(foundInCode("const highp float s"));
ASSERT_FALSE(foundInCode("fract(4096.5")); ASSERT_FALSE(foundInCode("fract(4096.5"));
ASSERT_FALSE(foundInCode("fract((4096.5")); ASSERT_FALSE(foundInCode("fract((4096.5"));
} }
...@@ -89,7 +89,7 @@ TEST_F(RecordConstantPrecisionTest, FoldedUnaryConstantPrecisionIsHigher) ...@@ -89,7 +89,7 @@ TEST_F(RecordConstantPrecisionTest, FoldedUnaryConstantPrecisionIsHigher)
" gl_FragColor = vec4(b);\n" " gl_FragColor = vec4(b);\n"
"}\n"; "}\n";
compile(shaderString); compile(shaderString);
ASSERT_TRUE(foundInCode("const highp float webgl_angle_s")); ASSERT_TRUE(foundInCode("const highp float s"));
ASSERT_FALSE(foundInCode("sin(0.5")); ASSERT_FALSE(foundInCode("sin(0.5"));
ASSERT_FALSE(foundInCode("sin((0.5")); ASSERT_FALSE(foundInCode("sin((0.5"));
} }
...@@ -752,8 +752,8 @@ TEST_F(WEBGLMultiviewVertexShaderOutputCodeTest, ViewIDAndInstanceIDHaveCorrectV ...@@ -752,8 +752,8 @@ TEST_F(WEBGLMultiviewVertexShaderOutputCodeTest, ViewIDAndInstanceIDHaveCorrectV
requestHLSLOutput(); requestHLSLOutput();
compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW); compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW);
EXPECT_TRUE(foundInAllGLSLCode("webgl_angle_ViewID_OVR = (uint(gl_InstanceID) % 3u)")); EXPECT_TRUE(foundInAllGLSLCode("ViewID_OVR = (uint(gl_InstanceID) % 3u)"));
EXPECT_TRUE(foundInAllGLSLCode("webgl_angle_InstanceID = (gl_InstanceID / 3)")); EXPECT_TRUE(foundInAllGLSLCode("InstanceID = (gl_InstanceID / 3)"));
EXPECT_TRUE(foundInHLSLCode("ViewID_OVR = (uvec1(gl_InstanceID) % 3)")); EXPECT_TRUE(foundInHLSLCode("ViewID_OVR = (uvec1(gl_InstanceID) % 3)"));
EXPECT_TRUE(foundInHLSLCode("InstanceID = (gl_InstanceID / 3)")); EXPECT_TRUE(foundInHLSLCode("InstanceID = (gl_InstanceID / 3)"));
...@@ -914,13 +914,13 @@ TEST_F(WEBGLMultiviewVertexShaderOutputCodeTest, GlViewportIndexIsSet) ...@@ -914,13 +914,13 @@ TEST_F(WEBGLMultiviewVertexShaderOutputCodeTest, GlViewportIndexIsSet)
"}\n"; "}\n";
compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW | compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW |
SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER); SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER);
const char glViewportIndexAssignment[] = "gl_ViewportIndex = int(webgl_angle_ViewID_OVR)"; const char glViewportIndexAssignment[] = "gl_ViewportIndex = int(ViewID_OVR)";
// Check that the viewport index is selected. // Check that the viewport index is selected.
EXPECT_TRUE(foundInAllGLSLCode(glViewportIndexAssignment)); EXPECT_TRUE(foundInAllGLSLCode(glViewportIndexAssignment));
// Setting gl_ViewportIndex must happen after ViewID_OVR's initialization. // Setting gl_ViewportIndex must happen after ViewID_OVR's initialization.
const char viewIDOVRAssignment[] = "webgl_angle_ViewID_OVR = (uint(gl_InstanceID) % 3u)"; const char viewIDOVRAssignment[] = "ViewID_OVR = (uint(gl_InstanceID) % 3u)";
size_t viewIDOVRAssignmentLoc = findInCode(SH_GLSL_COMPATIBILITY_OUTPUT, viewIDOVRAssignment); size_t viewIDOVRAssignmentLoc = findInCode(SH_GLSL_COMPATIBILITY_OUTPUT, viewIDOVRAssignment);
size_t glViewportIndexAssignmentLoc = size_t glViewportIndexAssignmentLoc =
findInCode(SH_GLSL_COMPATIBILITY_OUTPUT, glViewportIndexAssignment); findInCode(SH_GLSL_COMPATIBILITY_OUTPUT, glViewportIndexAssignment);
...@@ -944,14 +944,13 @@ TEST_F(WEBGLMultiviewVertexShaderOutputCodeTest, GlLayerIsSet) ...@@ -944,14 +944,13 @@ TEST_F(WEBGLMultiviewVertexShaderOutputCodeTest, GlLayerIsSet)
"}\n"; "}\n";
compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW | compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW |
SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER); SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER);
const char glLayerAssignment[] = const char glLayerAssignment[] = "gl_Layer = (int(ViewID_OVR) + multiviewBaseViewLayerIndex)";
"gl_Layer = (int(webgl_angle_ViewID_OVR) + webgl_angle_multiviewBaseViewLayerIndex)";
// Check that the layer is selected. // Check that the layer is selected.
EXPECT_TRUE(foundInAllGLSLCode(glLayerAssignment)); EXPECT_TRUE(foundInAllGLSLCode(glLayerAssignment));
// Setting gl_Layer must happen after ViewID_OVR's initialization. // Setting gl_Layer must happen after ViewID_OVR's initialization.
const char viewIDOVRAssignment[] = "webgl_angle_ViewID_OVR = (uint(gl_InstanceID) % 3u)"; const char viewIDOVRAssignment[] = "ViewID_OVR = (uint(gl_InstanceID) % 3u)";
size_t viewIDOVRAssignmentLoc = findInCode(SH_GLSL_COMPATIBILITY_OUTPUT, viewIDOVRAssignment); size_t viewIDOVRAssignmentLoc = findInCode(SH_GLSL_COMPATIBILITY_OUTPUT, viewIDOVRAssignment);
size_t glLayerAssignmentLoc = findInCode(SH_GLSL_COMPATIBILITY_OUTPUT, glLayerAssignment); size_t glLayerAssignmentLoc = findInCode(SH_GLSL_COMPATIBILITY_OUTPUT, glLayerAssignment);
EXPECT_LT(viewIDOVRAssignmentLoc, glLayerAssignmentLoc); EXPECT_LT(viewIDOVRAssignmentLoc, glLayerAssignmentLoc);
......
...@@ -1238,6 +1238,64 @@ TEST_P(TransformFeedbackTest, NonExistentTransformFeedbackVarying) ...@@ -1238,6 +1238,64 @@ TEST_P(TransformFeedbackTest, NonExistentTransformFeedbackVarying)
ASSERT_EQ(0u, mProgram); ASSERT_EQ(0u, mProgram);
} }
// Test transform feedback names can be reserved names in GLSL, as long as they're not reserved in
// GLSL ES.
TEST_P(TransformFeedbackTest, VaryingReservedOpenGLName)
{
const std::string &vertexShaderSource =
"#version 300 es\n"
"in vec3 position;\n"
"out vec3 buffer;\n"
"void main() {\n"
" buffer = position;\n"
" gl_Position = vec4(position, 1);\n"
"}";
const std::string &fragmentShaderSource =
"#version 300 es\n"
"precision highp float;\n"
"out vec4 color;\n"
"in vec3 buffer;\n"
"void main() {\n"
" color = vec4(0);\n"
"}";
std::vector<std::string> tfVaryings;
tfVaryings.push_back("buffer");
mProgram = CompileProgramWithTransformFeedback(vertexShaderSource, fragmentShaderSource,
tfVaryings, GL_INTERLEAVED_ATTRIBS);
ASSERT_NE(0u, mProgram);
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mTransformFeedbackBuffer);
glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(Vector3) * 6, nullptr, GL_STREAM_DRAW);
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, mTransformFeedback);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, mTransformFeedbackBuffer);
glUseProgram(mProgram);
glBeginTransformFeedback(GL_TRIANGLES);
drawQuad(mProgram, "position", 0.5f);
glEndTransformFeedback();
glUseProgram(0);
ASSERT_GL_NO_ERROR();
const GLvoid *mapPointer =
glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(Vector3) * 6, GL_MAP_READ_BIT);
ASSERT_NE(nullptr, mapPointer);
const auto &quadVertices = GetQuadVertices();
const Vector3 *vecPointer = static_cast<const Vector3 *>(mapPointer);
for (unsigned int vectorIndex = 0; vectorIndex < 3; ++vectorIndex)
{
EXPECT_EQ(quadVertices[vectorIndex], vecPointer[vectorIndex]);
}
glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
ASSERT_GL_NO_ERROR();
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these // Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against. // tests should be run against.
ANGLE_INSTANTIATE_TEST(TransformFeedbackTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES()); ANGLE_INSTANTIATE_TEST(TransformFeedbackTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
......
...@@ -963,6 +963,72 @@ TEST_P(UniformBufferTest, GetUniformBlockIndexDefaultReturn) ...@@ -963,6 +963,72 @@ TEST_P(UniformBufferTest, GetUniformBlockIndexDefaultReturn)
EXPECT_GL_ERROR(GL_INVALID_VALUE); EXPECT_GL_ERROR(GL_INVALID_VALUE);
} }
// Block names can be reserved names in GLSL, as long as they're not reserved in GLSL ES.
TEST_P(UniformBufferTest, UniformBlockReservedOpenGLName)
{
const std::string &fragmentShader =
"#version 300 es\n"
"precision highp float;\n"
"out vec4 my_FragColor;\n"
"layout(std140) uniform buffer { vec4 color; };\n"
"void main()\n"
"{\n"
" my_FragColor = color;\n"
"}\n";
ANGLE_GL_PROGRAM(program, mVertexShaderSource, fragmentShader);
GLint uniformBufferIndex = glGetUniformBlockIndex(program, "buffer");
glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
const GLsizei kElementsPerVector = 4;
const GLsizei kBytesPerElement = 4;
const GLsizei kDataSize = kElementsPerVector * kBytesPerElement;
std::vector<GLubyte> v(kDataSize, 0);
float *vAsFloat = reinterpret_cast<float *>(v.data());
vAsFloat[1] = 1.0f;
vAsFloat[3] = 1.0f;
glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
glUniformBlockBinding(program, uniformBufferIndex, 0);
drawQuad(program.get(), "position", 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
// Block instance names can be reserved names in GLSL, as long as they're not reserved in GLSL ES.
TEST_P(UniformBufferTest, UniformBlockInstanceReservedOpenGLName)
{
const std::string &fragmentShader =
"#version 300 es\n"
"precision highp float;\n"
"out vec4 my_FragColor;\n"
"layout(std140) uniform dmat2 { vec4 color; } buffer;\n"
"void main()\n"
"{\n"
" my_FragColor = buffer.color;\n"
"}\n";
ANGLE_GL_PROGRAM(program, mVertexShaderSource, fragmentShader);
GLint uniformBufferIndex = glGetUniformBlockIndex(program, "dmat2");
glBindBuffer(GL_UNIFORM_BUFFER, mUniformBuffer);
const GLsizei kElementsPerVector = 4;
const GLsizei kBytesPerElement = 4;
const GLsizei kDataSize = kElementsPerVector * kBytesPerElement;
std::vector<GLubyte> v(kDataSize, 0);
float *vAsFloat = reinterpret_cast<float *>(v.data());
vAsFloat[1] = 1.0f;
vAsFloat[3] = 1.0f;
glBufferData(GL_UNIFORM_BUFFER, kDataSize, v.data(), GL_STATIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, mUniformBuffer);
glUniformBlockBinding(program, uniformBufferIndex, 0);
drawQuad(program.get(), "position", 0.5f);
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against. // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_INSTANTIATE_TEST(UniformBufferTest, ANGLE_INSTANTIATE_TEST(UniformBufferTest,
ES3_D3D11(), ES3_D3D11(),
......
...@@ -946,6 +946,37 @@ TEST_P(UniformTestES3, StructWithNonSquareMatrixAndBool) ...@@ -946,6 +946,37 @@ TEST_P(UniformTestES3, StructWithNonSquareMatrixAndBool)
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
} }
// Test that uniforms with reserved OpenGL names that aren't reserved in GL ES 2 work correctly.
TEST_P(UniformTest, UniformWithReservedOpenGLName)
{
const char *vertexShader =
"attribute highp vec4 a_position;\n"
"void main()\n"
"{\n"
" gl_Position = a_position;\n"
"}\n";
const char *fragShader =
"precision mediump float;\n"
"uniform float buffer;"
"void main() {\n"
" gl_FragColor = vec4(buffer);\n"
"}";
mProgram = CompileProgram(vertexShader, fragShader);
ASSERT_NE(mProgram, 0u);
GLint location = glGetUniformLocation(mProgram, "buffer");
ASSERT_NE(-1, location);
glUseProgram(mProgram);
glUniform1f(location, 1.0f);
drawQuad(mProgram, "a_position", 0.0f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against. // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_INSTANTIATE_TEST(UniformTest, ANGLE_INSTANTIATE_TEST(UniformTest,
ES2_D3D9(), ES2_D3D9(),
......
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