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 @@
// Version number for shader translation API.
// It is incremented every time the API changes.
#define ANGLE_SH_VERSION 180
#define ANGLE_SH_VERSION 181
enum ShShaderSpec
{
......@@ -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;
// 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;
// Set to initialize uninitialized local variables. Should only be used with GLSL output. In HLSL
......
......@@ -218,6 +218,7 @@ struct InterfaceBlock
// Fields from blocks with non-empty instance names are prefixed with the block name.
std::string fieldPrefix() const;
std::string fieldMappedPrefix() const;
// Decide whether two interface blocks are the same at shader link time.
bool isSameInterfaceBlockAtLinkTime(const InterfaceBlock &other) const;
......
......@@ -108,8 +108,10 @@ class CollectVariablesTraverser : public TIntermTraverser
bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
private:
std::string getMappedName(const TName &name) const;
void setCommonVariableProperties(const TType &type,
const TString &name,
const TName &name,
ShaderVariable *variableOut) const;
Attribute recordAttribute(const TIntermSymbol &variable) const;
......@@ -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,
ShaderVariable *info)
{
......@@ -535,7 +542,7 @@ void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
}
void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
const TString &name,
const TName &name,
ShaderVariable *variableOut) const
{
ASSERT(variableOut);
......@@ -560,12 +567,12 @@ void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
// Regardless of the variable type (uniform, in/out etc.) its fields are always plain
// ShaderVariable objects.
ShaderVariable fieldVariable;
setCommonVariableProperties(*field->type(), field->name(), &fieldVariable);
setCommonVariableProperties(*field->type(), TName(field->name()), &fieldVariable);
variableOut->fields.push_back(fieldVariable);
}
}
variableOut->name = name.c_str();
variableOut->mappedName = HashName(name, mHashFunction).c_str();
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.
......@@ -579,7 +586,7 @@ Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variab
ASSERT(!type.getStruct());
Attribute attribute;
setCommonVariableProperties(type, variable.getSymbol(), &attribute);
setCommonVariableProperties(type, variable.getName(), &attribute);
attribute.location = type.getLayoutQualifier().location;
return attribute;
......@@ -591,7 +598,7 @@ OutputVariable CollectVariablesTraverser::recordOutputVariable(const TIntermSymb
ASSERT(!type.getStruct());
OutputVariable outputVariable;
setCommonVariableProperties(type, variable.getSymbol(), &outputVariable);
setCommonVariableProperties(type, variable.getName(), &outputVariable);
outputVariable.location = type.getLayoutQualifier().location;
return outputVariable;
......@@ -602,7 +609,7 @@ Varying CollectVariablesTraverser::recordVarying(const TIntermSymbol &variable)
const TType &type = variable.getType();
Varying varying;
setCommonVariableProperties(type, variable.getSymbol(), &varying);
setCommonVariableProperties(type, variable.getName(), &varying);
switch (type.getQualifier())
{
......@@ -637,7 +644,7 @@ void CollectVariablesTraverser::recordInterfaceBlock(const TType &interfaceBlock
ASSERT(blockType);
interfaceBlock->name = blockType->name().c_str();
interfaceBlock->mappedName = HashName(blockType->name().c_str(), mHashFunction).c_str();
interfaceBlock->mappedName = getMappedName(TName(blockType->name()));
interfaceBlock->instanceName =
(blockType->hasInstanceName() ? blockType->instanceName().c_str() : "");
ASSERT(!interfaceBlockType.isArrayOfArrays()); // Disallowed by GLSL ES 3.10 section 4.3.9
......@@ -658,7 +665,7 @@ void CollectVariablesTraverser::recordInterfaceBlock(const TType &interfaceBlock
const TType &fieldType = *field->type();
InterfaceBlockField fieldVariable;
setCommonVariableProperties(fieldType, field->name(), &fieldVariable);
setCommonVariableProperties(fieldType, TName(field->name()), &fieldVariable);
fieldVariable.isRowMajorLayout =
(fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
interfaceBlock->fields.push_back(fieldVariable);
......@@ -668,7 +675,7 @@ void CollectVariablesTraverser::recordInterfaceBlock(const TType &interfaceBlock
Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const
{
Uniform uniform;
setCommonVariableProperties(variable.getType(), variable.getSymbol(), &uniform);
setCommonVariableProperties(variable.getType(), variable.getName(), &uniform);
uniform.binding = variable.getType().getLayoutQualifier().binding;
uniform.location = variable.getType().getLayoutQualifier().location;
uniform.offset = variable.getType().getLayoutQualifier().offset;
......
......@@ -6,18 +6,67 @@
#include "compiler/translator/HashNames.h"
#include "compiler/translator/IntermNode.h"
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)
{
if (hashFunction == nullptr || name.empty())
return name;
ASSERT(!name.empty());
ASSERT(hashFunction);
khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length());
TStringStream stream;
stream << HASHED_NAME_PREFIX << std::hex << number;
stream << kHashedNamePrefix << std::hex << number;
TString hashedName = stream.str();
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
......@@ -12,16 +12,16 @@
#include "GLSLANG/ShaderLang.h"
#include "compiler/translator/Common.h"
#define HASHED_NAME_PREFIX "webgl_"
namespace sh
{
typedef std::map<TPersistString, TPersistString> NameMap;
// Return the original name if hash function pointer is NULL;
// otherwise return the hashed name.
TString HashName(const TString &name, ShHashFunction64 hashFunction);
class TName;
// 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
......
......@@ -1142,35 +1142,13 @@ TString TOutputGLSLBase::getTypeName(const TType &type)
TString TOutputGLSLBase::hashName(const TName &name)
{
if (name.getString().empty())
{
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;
return HashName(name, mHashFunction, &mNameMap);
}
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 &&
name.getString() == "gl_ViewID_OVR")
......@@ -1186,10 +1164,8 @@ TString TOutputGLSLBase::hashVariableName(const TName &name)
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();
}
else
......
......@@ -417,6 +417,11 @@ std::string InterfaceBlock::fieldPrefix() const
return instanceName.empty() ? "" : name;
}
std::string InterfaceBlock::fieldMappedPrefix() const
{
return instanceName.empty() ? "" : mappedName;
}
bool InterfaceBlock::isSameInterfaceBlockAtLinkTime(const InterfaceBlock &other) const
{
if (name != other.name || mappedName != other.mappedName || arraySize != other.arraySize ||
......
......@@ -231,6 +231,7 @@ LinkResult MemoryProgramCache::Deserialize(const Context *context,
{
UniformBlock uniformBlock;
stream.readString(&uniformBlock.name);
stream.readString(&uniformBlock.mappedName);
stream.readBool(&uniformBlock.isArray);
stream.readInt(&uniformBlock.arrayElement);
......@@ -411,6 +412,7 @@ void MemoryProgramCache::Serialize(const Context *context,
for (const UniformBlock &uniformBlock : state.getUniformBlocks())
{
stream.writeString(uniformBlock.name);
stream.writeString(uniformBlock.mappedName);
stream.writeInt(uniformBlock.isArray);
stream.writeInt(uniformBlock.arrayElement);
......
......@@ -2799,32 +2799,40 @@ void Program::gatherInterfaceBlockInfo(const Context *context)
template <typename VarT>
void Program::defineUniformBlockMembers(const std::vector<VarT> &fields,
const std::string &prefix,
const std::string &mappedPrefix,
int blockIndex)
{
for (const VarT &field : fields)
{
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())
{
for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++)
{
const std::string uniformElementName =
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
{
// If getBlockMemberInfo returns false, the uniform is optimized out.
sh::BlockMemberInfo memberInfo;
if (!mProgram->getUniformBlockMemberInfo(fullName, &memberInfo))
if (!mProgram->getUniformBlockMemberInfo(fullName, fullMappedName, &memberInfo))
{
continue;
}
LinkedUniform newUniform(field.type, field.precision, fullName, field.arraySize, -1, -1,
-1, blockIndex, memberInfo);
newUniform.mappedName = fullMappedName;
// Since block uniforms have no location, we don't need to store them in the uniform
// locations list.
......@@ -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
// block.
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();
std::vector<unsigned int> blockUniformIndexes;
......@@ -2859,12 +2868,13 @@ void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenu
for (unsigned int arrayElement = 0; arrayElement < interfaceBlock.arraySize; ++arrayElement)
{
// Don't define this block at all if it's not active in the implementation.
if (!mProgram->getUniformBlockSize(interfaceBlock.name + ArrayString(arrayElement),
&blockSize))
if (!mProgram->getUniformBlockSize(
interfaceBlock.name + ArrayString(arrayElement),
interfaceBlock.mappedName + ArrayString(arrayElement), &blockSize))
{
continue;
}
UniformBlock block(interfaceBlock.name, true, arrayElement,
UniformBlock block(interfaceBlock.name, interfaceBlock.mappedName, true, arrayElement,
blockBinding + arrayElement);
block.memberIndexes = blockUniformIndexes;
......@@ -2898,11 +2908,12 @@ void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenu
}
else
{
if (!mProgram->getUniformBlockSize(interfaceBlock.name, &blockSize))
if (!mProgram->getUniformBlockSize(interfaceBlock.name, interfaceBlock.mappedName,
&blockSize))
{
return;
}
UniformBlock block(interfaceBlock.name, false, 0, blockBinding);
UniformBlock block(interfaceBlock.name, interfaceBlock.mappedName, false, 0, blockBinding);
block.memberIndexes = blockUniformIndexes;
switch (shaderType)
......
......@@ -610,6 +610,7 @@ class Program final : angle::NonCopyable, public LabeledObject
template <typename VarT>
void defineUniformBlockMembers(const std::vector<VarT> &fields,
const std::string &prefix,
const std::string &mappedPrefix,
int blockIndex);
void defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType);
......
......@@ -477,6 +477,38 @@ const std::vector<sh::OutputVariable> &Shader::getActiveOutputVariables(const Co
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)
{
resolveCompile(context);
......
......@@ -158,6 +158,12 @@ class Shader final : angle::NonCopyable, public LabeledObject
const std::vector<sh::Attribute> &getActiveAttributes(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);
int getNumViews(const Context *context);
......
......@@ -147,10 +147,11 @@ UniformBlock::UniformBlock() : isArray(false), arrayElement(0)
}
UniformBlock::UniformBlock(const std::string &nameIn,
const std::string &mappedNameIn,
bool isArrayIn,
unsigned int arrayElementIn,
int bindingIn)
: name(nameIn), isArray(isArrayIn), arrayElement(arrayElementIn)
: name(nameIn), mappedName(mappedNameIn), isArray(isArrayIn), arrayElement(arrayElementIn)
{
binding = bindingIn;
}
......@@ -166,4 +167,16 @@ std::string UniformBlock::nameWithArrayIndex() const
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
{
UniformBlock();
UniformBlock(const std::string &nameIn,
const std::string &mappedNameIn,
bool isArrayIn,
unsigned int arrayElementIn,
int bindingIn);
......@@ -101,8 +102,10 @@ struct UniformBlock : public ShaderVariableBuffer
UniformBlock &operator=(const UniformBlock &other) = default;
std::string nameWithArrayIndex() const;
std::string mappedNameWithArrayIndex() const;
std::string name;
std::string mappedName;
bool isArray;
unsigned int arrayElement;
};
......
......@@ -453,8 +453,8 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniform(
{
int location = uniform.location;
ShaderUniformCount shaderUniformCount = flattenUniformImpl(
uniform, uniform.name, samplerUniforms, imageUniforms, atomicCounterUniforms,
uniform.staticUse, uniform.binding, uniform.offset, &location);
uniform, uniform.name, uniform.mappedName, samplerUniforms, imageUniforms,
atomicCounterUniforms, uniform.staticUse, uniform.binding, uniform.offset, &location);
if (uniform.staticUse)
{
return shaderUniformCount;
......@@ -465,6 +465,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniform(
UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl(
const sh::ShaderVariable &uniform,
const std::string &fullName,
const std::string &fullMappedName,
std::vector<LinkedUniform> *samplerUniforms,
std::vector<LinkedUniform> *imageUniforms,
std::vector<LinkedUniform> *atomicCounterUniforms,
......@@ -486,10 +487,12 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl(
{
const sh::ShaderVariable &field = uniform.fields[fieldIndex];
const std::string &fieldFullName = (fullName + elementString + "." + field.name);
const std::string &fieldFullMappedName =
(fullMappedName + elementString + "." + field.mappedName);
shaderUniformCount +=
flattenUniformImpl(field, fieldFullName, samplerUniforms, imageUniforms,
atomicCounterUniforms, markStaticUse, -1, -1, location);
shaderUniformCount += flattenUniformImpl(
field, fieldFullName, fieldFullMappedName, samplerUniforms, imageUniforms,
atomicCounterUniforms, markStaticUse, -1, -1, location);
}
}
......@@ -538,6 +541,7 @@ UniformLinker::ShaderUniformCount UniformLinker::flattenUniformImpl(
LinkedUniform linkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize,
binding, -1, *location, -1,
sh::BlockMemberInfo::getDefaultBlockInfo());
linkedUniform.mappedName = fullMappedName;
linkedUniform.staticUse = markStaticUse;
uniformList->push_back(linkedUniform);
......
......@@ -87,6 +87,7 @@ class UniformLinker
// granularity.
ShaderUniformCount flattenUniformImpl(const sh::ShaderVariable &uniform,
const std::string &fullName,
const std::string &fullMappedName,
std::vector<LinkedUniform> *samplerUniforms,
std::vector<LinkedUniform> *imageUniforms,
std::vector<LinkedUniform> *atomicCounterUniforms,
......
......@@ -86,11 +86,14 @@ class ProgramImpl : angle::NonCopyable
// May only be called after a successful link operation.
// 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.
// Returns false for inactive members.
virtual bool getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const = 0;
// CHROMIUM_path_rendering
// Set parameters to control fragment shader input variable interpolation
......
......@@ -60,8 +60,10 @@ class MockProgramImpl : public rx::ProgramImpl
MOCK_CONST_METHOD3(getUniformuiv, void(const gl::Context *, GLint, GLuint *));
MOCK_METHOD2(setUniformBlockBinding, void(GLuint, GLuint));
MOCK_CONST_METHOD2(getUniformBlockSize, bool(const std::string &, size_t *));
MOCK_CONST_METHOD2(getUniformBlockMemberInfo, bool(const std::string &, sh::BlockMemberInfo *));
MOCK_CONST_METHOD3(getUniformBlockSize,
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,
void(const std::string &, GLenum, GLint, const GLfloat *));
......
......@@ -2525,7 +2525,9 @@ D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
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;
gl::ParseAndStripArrayIndex(&baseName);
......@@ -2542,6 +2544,7 @@ bool ProgramD3D::getUniformBlockSize(const std::string &blockName, size_t *sizeO
}
bool ProgramD3D::getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string & /* memberUniformMappedName */,
sh::BlockMemberInfo *memberInfoOut) const
{
auto infoIter = mBlockInfo.find(memberUniformName);
......
......@@ -184,8 +184,11 @@ class ProgramD3D : public ProgramImpl
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,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const override;
void setPathFragmentInputGen(const std::string &inputName,
GLenum genMode,
......
......@@ -144,13 +144,16 @@ gl::LinkResult ProgramGL::link(const gl::Context *context,
else
{
// Set the transform feedback state
std::vector<const GLchar *> transformFeedbackVaryings;
std::vector<std::string> transformFeedbackVaryingMappedNames;
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)
{
......@@ -161,8 +164,13 @@ gl::LinkResult ProgramGL::link(const gl::Context *context,
else
{
ASSERT(mFunctions->transformFeedbackVaryings);
std::vector<const GLchar *> transformFeedbackVaryings;
for (const auto &varying : transformFeedbackVaryingMappedNames)
{
transformFeedbackVaryings.push_back(varying.c_str());
}
mFunctions->transformFeedbackVaryings(
mProgramID, static_cast<GLsizei>(transformFeedbackVaryings.size()),
mProgramID, static_cast<GLsizei>(transformFeedbackVaryingMappedNames.size()),
&transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode());
}
......@@ -181,7 +189,8 @@ gl::LinkResult ProgramGL::link(const gl::Context *context,
continue;
}
mFunctions->bindAttribLocation(mProgramID, attribute.location, attribute.name.c_str());
mFunctions->bindAttribLocation(mProgramID, attribute.location,
attribute.mappedName.c_str());
}
// Link and verify
......@@ -501,8 +510,9 @@ void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformB
mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size());
for (const gl::UniformBlock &uniformBlock : mState.getUniformBlocks())
{
const std::string &nameWithIndex = uniformBlock.nameWithArrayIndex();
GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, nameWithIndex.c_str());
const std::string &mappedNameWithIndex = uniformBlock.mappedNameWithArrayIndex();
GLuint blockIndex =
mFunctions->getUniformBlockIndex(mProgramID, mappedNameWithIndex.c_str());
mUniformBlockRealLocationMap.push_back(blockIndex);
}
}
......@@ -519,11 +529,13 @@ GLuint ProgramGL::getProgramID() const
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);
GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockName.c_str());
GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockMappedName.c_str());
if (blockIndex == GL_INVALID_INDEX)
{
*sizeOut = 0;
......@@ -537,11 +549,12 @@ bool ProgramGL::getUniformBlockSize(const std::string &blockName, size_t *sizeOu
return true;
}
bool ProgramGL::getUniformBlockMemberInfo(const std::string &memberUniformName,
bool ProgramGL::getUniformBlockMemberInfo(const std::string & /* memberUniformName */,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const
{
GLuint uniformIndex;
const GLchar *memberNameGLStr = memberUniformName.c_str();
const GLchar *memberNameGLStr = memberUniformMappedName.c_str();
mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);
if (uniformIndex == GL_INVALID_INDEX)
......@@ -574,7 +587,7 @@ void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
for (const auto &input : mPathRenderingFragmentInputs)
{
if (input.name == inputName)
if (input.mappedName == inputName)
{
mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode,
components, coeffs);
......@@ -650,7 +663,7 @@ void ProgramGL::postLink()
// "Locations for sequential array indices are not required to be sequential."
const gl::LinkedUniform &uniform = uniforms[entry.index];
std::stringstream fullNameStr;
fullNameStr << uniform.name;
fullNameStr << uniform.mappedName;
if (uniform.isArray())
{
fullNameStr << "[" << entry.element << "]";
......@@ -664,7 +677,7 @@ void ProgramGL::postLink()
if (mState.usesMultiview())
{
mMultiviewBaseViewLayerIndexUniformLocation =
mFunctions->getUniformLocation(mProgramID, "webgl_angle_multiviewBaseViewLayerIndex");
mFunctions->getUniformLocation(mProgramID, "multiviewBaseViewLayerIndex");
ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
}
......@@ -685,16 +698,16 @@ void ProgramGL::postLink()
for (GLint i = 0; i < numFragmentInputs; ++i)
{
std::string name;
name.resize(maxNameLength);
std::string mappedName;
mappedName.resize(maxNameLength);
GLsizei nameLen = 0;
mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength,
&nameLen, &name[0]);
name.resize(nameLen);
&nameLen, &mappedName[0]);
mappedName.resize(nameLen);
// Ignore built-ins
if (angle::BeginsWith(name, "gl_"))
if (angle::BeginsWith(mappedName, "gl_"))
continue;
const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE};
......@@ -709,16 +722,16 @@ void ProgramGL::postLink()
ASSERT(queryLength == static_cast<GLsizei>(ArraySize(kQueryProperties)));
PathRenderingFragmentInput baseElementInput;
baseElementInput.name = name;
baseElementInput.mappedName = mappedName;
baseElementInput.location = queryResults[0];
mPathRenderingFragmentInputs.push_back(std::move(baseElementInput));
// 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
if (angle::EndsWith(name, "[0]"))
if (angle::EndsWith(mappedName, "[0]"))
{
// drop the suffix
name.resize(name.size() - 3);
mappedName.resize(mappedName.size() - 3);
const auto arraySize = queryResults[1];
const auto baseLocation = queryResults[0];
......@@ -726,7 +739,7 @@ void ProgramGL::postLink()
for (GLint arrayIndex = 1; arrayIndex < arraySize; ++arrayIndex)
{
PathRenderingFragmentInput arrayElementInput;
arrayElementInput.name = name + "[" + ToString(arrayIndex) + "]";
arrayElementInput.mappedName = mappedName + "[" + ToString(arrayIndex) + "]";
arrayElementInput.location = baseLocation + arrayIndex;
mPathRenderingFragmentInputs.push_back(std::move(arrayElementInput));
}
......
......@@ -71,8 +71,11 @@ class ProgramGL : public ProgramImpl
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,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const override;
void setPathFragmentInputGen(const std::string &inputName,
......@@ -105,7 +108,7 @@ class ProgramGL : public ProgramImpl
struct PathRenderingFragmentInput
{
std::string name;
std::string mappedName;
GLint location;
};
std::vector<PathRenderingFragmentInput> mPathRenderingFragmentInputs;
......
......@@ -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?
*sizeOut = 0;
......@@ -191,6 +193,7 @@ bool ProgramNULL::getUniformBlockSize(const std::string &blockName, size_t *size
}
bool ProgramNULL::getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const
{
// TODO(geofflang): Compute reasonable values?
......
......@@ -91,11 +91,14 @@ class ProgramNULL : public ProgramImpl
// May only be called after a successful link operation.
// 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.
// Returns false for inactive members.
bool getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const override;
// CHROMIUM_path_rendering
// Set parameters to control fragment shader input variable interpolation
......
......@@ -259,13 +259,16 @@ void ProgramVk::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformB
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();
return bool();
}
bool ProgramVk::getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const
{
UNIMPLEMENTED();
......
......@@ -93,11 +93,14 @@ class ProgramVk : public ProgramImpl
// May only be called after a successful link operation.
// 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.
// Returns false for inactive members.
bool getUniformBlockMemberInfo(const std::string &memberUniformName,
const std::string &memberUniformMappedName,
sh::BlockMemberInfo *memberInfoOut) const override;
void setPathFragmentInputGen(const std::string &inputName,
......
......@@ -19,6 +19,16 @@ using namespace sh;
#define EXPECT_GLENUM_EQ(expected, 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
{
public:
......@@ -358,6 +368,7 @@ TEST_F(CollectVertexVariablesTest, StructInterfaceBlock)
EXPECT_FALSE(interfaceBlock.isRowMajorLayout);
EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
EXPECT_EQ("b", interfaceBlock.name);
EXPECT_EQ(DecorateName("b"), interfaceBlock.mappedName);
EXPECT_TRUE(interfaceBlock.staticUse);
ASSERT_EQ(1u, interfaceBlock.fields.size());
......@@ -367,6 +378,7 @@ TEST_F(CollectVertexVariablesTest, StructInterfaceBlock)
EXPECT_TRUE(field.isStruct());
EXPECT_TRUE(field.staticUse);
EXPECT_EQ("s", field.name);
EXPECT_EQ(DecorateName("s"), field.mappedName);
EXPECT_FALSE(field.isRowMajorLayout);
const ShaderVariable &member = field.fields[0];
......@@ -374,6 +386,7 @@ TEST_F(CollectVertexVariablesTest, StructInterfaceBlock)
// NOTE: we don't currently mark struct members as statically used or not
EXPECT_FALSE(member.isStruct());
EXPECT_EQ("f", member.name);
EXPECT_EQ(DecorateName("f"), member.mappedName);
EXPECT_GLENUM_EQ(GL_FLOAT, member.type);
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision);
}
......@@ -401,6 +414,7 @@ TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock)
EXPECT_FALSE(interfaceBlock.isRowMajorLayout);
EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
EXPECT_EQ("b", interfaceBlock.name);
EXPECT_EQ(DecorateName("b"), interfaceBlock.mappedName);
EXPECT_EQ("instanceName", interfaceBlock.instanceName);
EXPECT_TRUE(interfaceBlock.staticUse);
......@@ -411,6 +425,7 @@ TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock)
EXPECT_TRUE(field.isStruct());
EXPECT_TRUE(field.staticUse);
EXPECT_EQ("s", field.name);
EXPECT_EQ(DecorateName("s"), field.mappedName);
EXPECT_FALSE(field.isRowMajorLayout);
const ShaderVariable &member = field.fields[0];
......@@ -418,6 +433,7 @@ TEST_F(CollectVertexVariablesTest, StructInstancedInterfaceBlock)
// NOTE: we don't currently mark struct members as statically used or not
EXPECT_FALSE(member.isStruct());
EXPECT_EQ("f", member.name);
EXPECT_EQ(DecorateName("f"), member.mappedName);
EXPECT_GLENUM_EQ(GL_FLOAT, member.type);
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision);
}
......@@ -445,6 +461,7 @@ TEST_F(CollectVertexVariablesTest, NestedStructRowMajorInterfaceBlock)
EXPECT_TRUE(interfaceBlock.isRowMajorLayout);
EXPECT_EQ(BLOCKLAYOUT_SHARED, interfaceBlock.layout);
EXPECT_EQ("b", interfaceBlock.name);
EXPECT_EQ(DecorateName("b"), interfaceBlock.mappedName);
EXPECT_TRUE(interfaceBlock.staticUse);
ASSERT_EQ(1u, interfaceBlock.fields.size());
......@@ -454,6 +471,7 @@ TEST_F(CollectVertexVariablesTest, NestedStructRowMajorInterfaceBlock)
EXPECT_TRUE(field.isStruct());
EXPECT_TRUE(field.staticUse);
EXPECT_EQ("s", field.name);
EXPECT_EQ(DecorateName("s"), field.mappedName);
EXPECT_TRUE(field.isRowMajorLayout);
const ShaderVariable &member = field.fields[0];
......@@ -461,6 +479,7 @@ TEST_F(CollectVertexVariablesTest, NestedStructRowMajorInterfaceBlock)
// NOTE: we don't currently mark struct members as statically used or not
EXPECT_FALSE(member.isStruct());
EXPECT_EQ("m", member.name);
EXPECT_EQ(DecorateName("m"), member.mappedName);
EXPECT_GLENUM_EQ(GL_FLOAT_MAT2, member.type);
EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision);
}
......@@ -493,6 +512,7 @@ TEST_F(CollectVertexVariablesTest, VaryingInterpolation)
EXPECT_TRUE(varying->staticUse);
EXPECT_GLENUM_EQ(GL_FLOAT, varying->type);
EXPECT_EQ("vary", varying->name);
EXPECT_EQ(DecorateName("vary"), varying->mappedName);
EXPECT_EQ(INTERPOLATION_CENTROID, varying->interpolation);
}
......
......@@ -37,8 +37,10 @@ TEST_F(PruneEmptyDeclarationsTest, EmptyDeclarationStartsDeclaratorList)
" gl_Position = vec4(u * f);\n"
"}\n";
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 _u, _uf"));
}
TEST_F(PruneEmptyDeclarationsTest, EmptyStructDeclarationWithQualifiers)
......@@ -52,9 +54,9 @@ TEST_F(PruneEmptyDeclarationsTest, EmptyStructDeclarationWithQualifiers)
" gl_Position = vec4(s.f);\n"
"}\n";
compile(shaderString);
ASSERT_TRUE(foundInCode("struct S"));
ASSERT_TRUE(foundInCode("uniform S"));
ASSERT_TRUE(notFoundInCode("const struct S"));
ASSERT_TRUE(foundInCode("struct _uS"));
ASSERT_TRUE(foundInCode("uniform _uS"));
ASSERT_TRUE(notFoundInCode("const struct _uS"));
}
} // namespace
......@@ -33,7 +33,7 @@ TEST_F(RecordConstantPrecisionTest, HigherPrecisionConstantAsParameter)
" gl_FragColor = vec4(b);\n"
"}\n";
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"));
}
......@@ -51,7 +51,7 @@ TEST_F(RecordConstantPrecisionTest, EqualPrecisionConstantAsParameter)
" gl_FragColor = vec4(b);\n"
"}\n";
compile(shaderString);
ASSERT_FALSE(foundInCode("const mediump float webgl_angle_s"));
ASSERT_FALSE(foundInCode("const mediump float s"));
ASSERT_TRUE(foundInCode("fract((4096.5"));
}
......@@ -69,7 +69,7 @@ TEST_F(RecordConstantPrecisionTest, FoldedBinaryConstantPrecisionIsHigher)
" gl_FragColor = vec4(b);\n"
"}\n";
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"));
}
......@@ -89,7 +89,7 @@ TEST_F(RecordConstantPrecisionTest, FoldedUnaryConstantPrecisionIsHigher)
" gl_FragColor = vec4(b);\n"
"}\n";
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"));
}
......@@ -752,8 +752,8 @@ TEST_F(WEBGLMultiviewVertexShaderOutputCodeTest, ViewIDAndInstanceIDHaveCorrectV
requestHLSLOutput();
compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW);
EXPECT_TRUE(foundInAllGLSLCode("webgl_angle_ViewID_OVR = (uint(gl_InstanceID) % 3u)"));
EXPECT_TRUE(foundInAllGLSLCode("webgl_angle_InstanceID = (gl_InstanceID / 3)"));
EXPECT_TRUE(foundInAllGLSLCode("ViewID_OVR = (uint(gl_InstanceID) % 3u)"));
EXPECT_TRUE(foundInAllGLSLCode("InstanceID = (gl_InstanceID / 3)"));
EXPECT_TRUE(foundInHLSLCode("ViewID_OVR = (uvec1(gl_InstanceID) % 3)"));
EXPECT_TRUE(foundInHLSLCode("InstanceID = (gl_InstanceID / 3)"));
......@@ -914,13 +914,13 @@ TEST_F(WEBGLMultiviewVertexShaderOutputCodeTest, GlViewportIndexIsSet)
"}\n";
compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW |
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.
EXPECT_TRUE(foundInAllGLSLCode(glViewportIndexAssignment));
// 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 glViewportIndexAssignmentLoc =
findInCode(SH_GLSL_COMPATIBILITY_OUTPUT, glViewportIndexAssignment);
......@@ -944,14 +944,13 @@ TEST_F(WEBGLMultiviewVertexShaderOutputCodeTest, GlLayerIsSet)
"}\n";
compile(shaderString, SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW |
SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER);
const char glLayerAssignment[] =
"gl_Layer = (int(webgl_angle_ViewID_OVR) + webgl_angle_multiviewBaseViewLayerIndex)";
const char glLayerAssignment[] = "gl_Layer = (int(ViewID_OVR) + multiviewBaseViewLayerIndex)";
// Check that the layer is selected.
EXPECT_TRUE(foundInAllGLSLCode(glLayerAssignment));
// 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 glLayerAssignmentLoc = findInCode(SH_GLSL_COMPATIBILITY_OUTPUT, glLayerAssignment);
EXPECT_LT(viewIDOVRAssignmentLoc, glLayerAssignmentLoc);
......
......@@ -1238,6 +1238,64 @@ TEST_P(TransformFeedbackTest, NonExistentTransformFeedbackVarying)
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
// tests should be run against.
ANGLE_INSTANTIATE_TEST(TransformFeedbackTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
......
......@@ -963,6 +963,72 @@ TEST_P(UniformBufferTest, GetUniformBlockIndexDefaultReturn)
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.
ANGLE_INSTANTIATE_TEST(UniformBufferTest,
ES3_D3D11(),
......
......@@ -946,6 +946,37 @@ TEST_P(UniformTestES3, StructWithNonSquareMatrixAndBool)
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.
ANGLE_INSTANTIATE_TEST(UniformTest,
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