mirror of
https://github.com/godotengine/godot-angle-static.git
synced 2026-01-03 14:09:33 +03:00
Pack and reduce Program::mProgramInput size
Right now mProgramInput is std::vector<sh::ShaderVariable>. It really only need a subset of ShaderVariable struct. This CL adds a ProgramInput struct so that we can add data members that actually required. This CL also makes bools into bitfield and some variables to uint16_t to further compact the size. This CL also groups the data memebers other than string to basicDataTypeStruct which only contains basic data types and the entire struct is memcpied during program binary load and save. This not just reduces number of memcpy calls, but also improves reliability so that when someone adds a new member into the struct, it will automatically load/save correctly. Bug: b/275102061 Change-Id: Ic055c986453ed46e56057a0122c9926245fef4d1 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4776267 Reviewed-by: Roman Lavrov <romanl@google.com> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Commit-Queue: Charlie Lao <cclao@google.com>
This commit is contained in:
committed by
Angle LUCI CQ
parent
124e90af14
commit
1e1c9d9de8
@@ -327,6 +327,54 @@ void InitShaderStorageBlockLinker(const Context *context,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
GLuint GetResourceMaxNameSize(const T &resource, GLint max)
|
||||
{
|
||||
if (resource.isArray())
|
||||
{
|
||||
return std::max(max, clampCast<GLint>((resource.name + "[0]").size()));
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::max(max, clampCast<GLint>((resource.name).size()));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
GLuint GetResourceLocation(const GLchar *name, const T &variable, GLint location)
|
||||
{
|
||||
if (variable.isBuiltIn())
|
||||
{
|
||||
return GL_INVALID_INDEX;
|
||||
}
|
||||
|
||||
if (variable.isArray())
|
||||
{
|
||||
size_t nameLengthWithoutArrayIndexOut;
|
||||
size_t arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndexOut);
|
||||
// The 'name' string may not contain the array notation "[0]"
|
||||
if (arrayIndex != GL_INVALID_INDEX)
|
||||
{
|
||||
location += arrayIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const std::string GetResourceName(const T &resource)
|
||||
{
|
||||
std::string resourceName = resource.name;
|
||||
|
||||
if (resource.isArray())
|
||||
{
|
||||
resourceName += "[0]";
|
||||
}
|
||||
|
||||
return resourceName;
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
const char *GetLinkMismatchErrorString(LinkMismatchError linkError)
|
||||
@@ -379,7 +427,8 @@ const char *GetLinkMismatchErrorString(LinkMismatchError linkError)
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateInterfaceVariable(std::vector<sh::ShaderVariable> *block, const sh::ShaderVariable &var)
|
||||
template <typename T>
|
||||
void UpdateInterfaceVariable(std::vector<T> *block, const sh::ShaderVariable &var)
|
||||
{
|
||||
if (!var.isStruct())
|
||||
{
|
||||
@@ -471,7 +520,7 @@ void LoadShaderVariableBuffer(BinaryInputStream *stream, ShaderVariableBuffer *v
|
||||
{
|
||||
var->memberIndexes.resize(numMembers);
|
||||
stream->readBytes(reinterpret_cast<unsigned char *>(var->memberIndexes.data()),
|
||||
sizeof(unsigned int) * var->memberIndexes.size());
|
||||
sizeof(*var->memberIndexes.data()) * var->memberIndexes.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -660,6 +709,46 @@ void LoadBlockMemberInfo(BinaryInputStream *stream, sh::BlockMemberInfo *var)
|
||||
var->topLevelArrayStride = stream->readInt<int>();
|
||||
}
|
||||
|
||||
// ProgramInput implementation.
|
||||
ProgramInput::ProgramInput() {}
|
||||
|
||||
ProgramInput::ProgramInput(const sh::ShaderVariable &var)
|
||||
{
|
||||
ASSERT(!var.isStruct());
|
||||
|
||||
name = var.name;
|
||||
mappedName = var.mappedName;
|
||||
|
||||
SetBitField(basicDataTypeStruct.type, var.type);
|
||||
basicDataTypeStruct.location = var.hasImplicitLocation ? -1 : var.location;
|
||||
SetBitField(basicDataTypeStruct.interpolation, var.interpolation);
|
||||
basicDataTypeStruct.flagBitsAsUByte = 0;
|
||||
basicDataTypeStruct.flagBits.active = var.active;
|
||||
basicDataTypeStruct.flagBits.isPatch = var.isPatch;
|
||||
basicDataTypeStruct.flagBits.hasImplicitLocation = var.hasImplicitLocation;
|
||||
basicDataTypeStruct.flagBits.isArray = var.isArray();
|
||||
basicDataTypeStruct.flagBits.isBuiltIn = IsBuiltInName(var.name);
|
||||
SetBitField(basicDataTypeStruct.basicTypeElementCount, var.getBasicTypeElementCount());
|
||||
basicDataTypeStruct.id = var.id;
|
||||
SetBitField(basicDataTypeStruct.arraySizeProduct, var.getArraySizeProduct());
|
||||
}
|
||||
|
||||
ProgramInput::ProgramInput(const ProgramInput &other)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
ProgramInput &ProgramInput::operator=(const ProgramInput &rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
name = rhs.name;
|
||||
mappedName = rhs.mappedName;
|
||||
basicDataTypeStruct = rhs.basicDataTypeStruct;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// VariableLocation implementation.
|
||||
VariableLocation::VariableLocation() : arrayIndex(0), index(kUnused), ignored(false) {}
|
||||
|
||||
@@ -935,11 +1024,11 @@ GLuint ProgramState::getImageIndexFromUniformIndex(GLuint uniformIndex) const
|
||||
|
||||
GLuint ProgramState::getAttributeLocation(const std::string &name) const
|
||||
{
|
||||
for (const sh::ShaderVariable &attribute : mExecutable->mProgramInputs)
|
||||
for (const ProgramInput &attribute : mExecutable->mProgramInputs)
|
||||
{
|
||||
if (attribute.name == name)
|
||||
{
|
||||
return attribute.location;
|
||||
return attribute.getLocation();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1718,7 +1807,7 @@ void Program::getActiveAttribute(GLuint index,
|
||||
}
|
||||
|
||||
ASSERT(index < mState.mExecutable->getProgramInputs().size());
|
||||
const sh::ShaderVariable &attrib = mState.mExecutable->getProgramInputs()[index];
|
||||
const ProgramInput &attrib = mState.mExecutable->getProgramInputs()[index];
|
||||
|
||||
if (bufsize > 0)
|
||||
{
|
||||
@@ -1727,7 +1816,7 @@ void Program::getActiveAttribute(GLuint index,
|
||||
|
||||
// Always a single 'type' instance
|
||||
*size = 1;
|
||||
*type = attrib.type;
|
||||
*type = attrib.getType();
|
||||
}
|
||||
|
||||
GLint Program::getActiveAttributeCount() const
|
||||
@@ -1751,7 +1840,7 @@ GLint Program::getActiveAttributeMaxLength() const
|
||||
|
||||
size_t maxLength = 0;
|
||||
|
||||
for (const sh::ShaderVariable &attrib : mState.mExecutable->getProgramInputs())
|
||||
for (const ProgramInput &attrib : mState.mExecutable->getProgramInputs())
|
||||
{
|
||||
maxLength = std::max(attrib.name.length() + 1, maxLength);
|
||||
}
|
||||
@@ -1759,7 +1848,7 @@ GLint Program::getActiveAttributeMaxLength() const
|
||||
return static_cast<GLint>(maxLength);
|
||||
}
|
||||
|
||||
const std::vector<sh::ShaderVariable> &Program::getAttributes() const
|
||||
const std::vector<ProgramInput> &Program::getAttributes() const
|
||||
{
|
||||
ASSERT(!mLinkingState);
|
||||
return mState.mExecutable->getProgramInputs();
|
||||
@@ -1822,7 +1911,7 @@ GLenum Program::getTessGenVertexOrder() const
|
||||
return mState.mExecutable->mTessGenVertexOrder;
|
||||
}
|
||||
|
||||
const sh::ShaderVariable &Program::getInputResource(size_t index) const
|
||||
const ProgramInput &Program::getInputResource(size_t index) const
|
||||
{
|
||||
ASSERT(!mLinkingState);
|
||||
ASSERT(index < mState.mExecutable->getProgramInputs().size());
|
||||
@@ -1836,7 +1925,7 @@ GLuint Program::getInputResourceIndex(const GLchar *name) const
|
||||
|
||||
for (size_t index = 0; index < mState.mExecutable->getProgramInputs().size(); index++)
|
||||
{
|
||||
sh::ShaderVariable resource = getInputResource(index);
|
||||
ProgramInput resource = getInputResource(index);
|
||||
if (resource.name == nameString)
|
||||
{
|
||||
return static_cast<GLuint>(index);
|
||||
@@ -1846,25 +1935,13 @@ GLuint Program::getInputResourceIndex(const GLchar *name) const
|
||||
return GL_INVALID_INDEX;
|
||||
}
|
||||
|
||||
GLuint Program::getResourceMaxNameSize(const sh::ShaderVariable &resource, GLint max) const
|
||||
{
|
||||
if (resource.isArray())
|
||||
{
|
||||
return std::max(max, clampCast<GLint>((resource.name + "[0]").size()));
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::max(max, clampCast<GLint>((resource.name).size()));
|
||||
}
|
||||
}
|
||||
|
||||
GLuint Program::getInputResourceMaxNameSize() const
|
||||
{
|
||||
GLint max = 0;
|
||||
|
||||
for (const sh::ShaderVariable &resource : mState.mExecutable->getProgramInputs())
|
||||
for (const ProgramInput &resource : mState.mExecutable->getProgramInputs())
|
||||
{
|
||||
max = getResourceMaxNameSize(resource, max);
|
||||
max = GetResourceMaxNameSize(resource, max);
|
||||
}
|
||||
|
||||
return max;
|
||||
@@ -1876,34 +1953,12 @@ GLuint Program::getOutputResourceMaxNameSize() const
|
||||
|
||||
for (const sh::ShaderVariable &resource : mState.mExecutable->getOutputVariables())
|
||||
{
|
||||
max = getResourceMaxNameSize(resource, max);
|
||||
max = GetResourceMaxNameSize(resource, max);
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
GLuint Program::getResourceLocation(const GLchar *name, const sh::ShaderVariable &variable) const
|
||||
{
|
||||
if (variable.isBuiltIn())
|
||||
{
|
||||
return GL_INVALID_INDEX;
|
||||
}
|
||||
|
||||
GLint location = variable.location;
|
||||
if (variable.isArray())
|
||||
{
|
||||
size_t nameLengthWithoutArrayIndexOut;
|
||||
size_t arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndexOut);
|
||||
// The 'name' string may not contain the array notation "[0]"
|
||||
if (arrayIndex != GL_INVALID_INDEX)
|
||||
{
|
||||
location += arrayIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
GLuint Program::getInputResourceLocation(const GLchar *name) const
|
||||
{
|
||||
const GLuint index = getInputResourceIndex(name);
|
||||
@@ -1912,9 +1967,9 @@ GLuint Program::getInputResourceLocation(const GLchar *name) const
|
||||
return index;
|
||||
}
|
||||
|
||||
const sh::ShaderVariable &variable = getInputResource(index);
|
||||
const ProgramInput &variable = getInputResource(index);
|
||||
|
||||
return getResourceLocation(name, variable);
|
||||
return GetResourceLocation(name, variable, variable.getLocation());
|
||||
}
|
||||
|
||||
GLuint Program::getOutputResourceLocation(const GLchar *name) const
|
||||
@@ -1927,7 +1982,7 @@ GLuint Program::getOutputResourceLocation(const GLchar *name) const
|
||||
|
||||
const sh::ShaderVariable &variable = getOutputResource(index);
|
||||
|
||||
return getResourceLocation(name, variable);
|
||||
return GetResourceLocation(name, variable, variable.location);
|
||||
}
|
||||
|
||||
GLuint Program::getOutputResourceIndex(const GLchar *name) const
|
||||
@@ -2016,24 +2071,12 @@ void Program::getBufferVariableResourceName(GLuint index,
|
||||
getResourceName(mState.mBufferVariables[index].name, bufSize, length, name);
|
||||
}
|
||||
|
||||
const std::string Program::getResourceName(const sh::ShaderVariable &resource) const
|
||||
{
|
||||
std::string resourceName = resource.name;
|
||||
|
||||
if (resource.isArray())
|
||||
{
|
||||
resourceName += "[0]";
|
||||
}
|
||||
|
||||
return resourceName;
|
||||
}
|
||||
|
||||
const std::string Program::getInputResourceName(GLuint index) const
|
||||
{
|
||||
ASSERT(!mLinkingState);
|
||||
const sh::ShaderVariable &resource = getInputResource(index);
|
||||
const ProgramInput &resource = getInputResource(index);
|
||||
|
||||
return getResourceName(resource);
|
||||
return GetResourceName(resource);
|
||||
}
|
||||
|
||||
const std::string Program::getOutputResourceName(GLuint index) const
|
||||
@@ -2041,7 +2084,7 @@ const std::string Program::getOutputResourceName(GLuint index) const
|
||||
ASSERT(!mLinkingState);
|
||||
const sh::ShaderVariable &resource = getOutputResource(index);
|
||||
|
||||
return getResourceName(resource);
|
||||
return GetResourceName(resource);
|
||||
}
|
||||
|
||||
const sh::ShaderVariable &Program::getOutputResource(size_t index) const
|
||||
@@ -3158,54 +3201,56 @@ bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
|
||||
return true;
|
||||
}
|
||||
|
||||
// In GLSL ES 3.00.6, aliasing checks should be done with all declared attributes -
|
||||
// see GLSL ES 3.00.6 section 12.46. Inactive attributes will be pruned after
|
||||
// aliasing checks.
|
||||
// In GLSL ES 1.00.17 we only do aliasing checks for active attributes.
|
||||
shaderVersion = vertexShader->getShaderVersion(context);
|
||||
if (shaderVersion >= 300)
|
||||
{
|
||||
// In GLSL ES 3.00.6, aliasing checks should be done with all declared attributes -
|
||||
// see GLSL ES 3.00.6 section 12.46. Inactive attributes will be pruned after
|
||||
// aliasing checks.
|
||||
mState.mExecutable->mProgramInputs = vertexShader->getAllAttributes(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
// In GLSL ES 1.00.17 we only do aliasing checks for active attributes.
|
||||
mState.mExecutable->mProgramInputs = vertexShader->getActiveAttributes(context);
|
||||
}
|
||||
const std::vector<sh::ShaderVariable> &shaderAttributes =
|
||||
shaderVersion >= 300 ? vertexShader->getAllAttributes(context)
|
||||
: vertexShader->getActiveAttributes(context);
|
||||
|
||||
ASSERT(mState.mExecutable->mProgramInputs.empty());
|
||||
mState.mExecutable->mProgramInputs.reserve(shaderAttributes.size());
|
||||
|
||||
GLuint maxAttribs = static_cast<GLuint>(caps.maxVertexAttributes);
|
||||
std::vector<sh::ShaderVariable *> usedAttribMap(maxAttribs, nullptr);
|
||||
std::vector<ProgramInput *> usedAttribMap(maxAttribs, nullptr);
|
||||
|
||||
// Assign locations to attributes that have a binding location and check for attribute aliasing.
|
||||
for (sh::ShaderVariable &attribute : mState.mExecutable->mProgramInputs)
|
||||
for (const sh::ShaderVariable &shaderAttribute : shaderAttributes)
|
||||
{
|
||||
// GLSL ES 3.10 January 2016 section 4.3.4: Vertex shader inputs can't be arrays or
|
||||
// structures, so we don't need to worry about adjusting their names or generating entries
|
||||
// for each member/element (unlike uniforms for example).
|
||||
ASSERT(!attribute.isArray() && !attribute.isStruct());
|
||||
ASSERT(!shaderAttribute.isArray() && !shaderAttribute.isStruct());
|
||||
|
||||
int bindingLocation = mAttributeBindings.getBinding(attribute);
|
||||
if (attribute.location == -1 && bindingLocation != -1)
|
||||
mState.mExecutable->mProgramInputs.emplace_back(shaderAttribute);
|
||||
|
||||
// Assign locations to attributes that have a binding location and check for attribute
|
||||
// aliasing.
|
||||
ProgramInput &attribute = mState.mExecutable->mProgramInputs.back();
|
||||
int bindingLocation = mAttributeBindings.getBinding(attribute);
|
||||
if (attribute.getLocation() == -1 && bindingLocation != -1)
|
||||
{
|
||||
attribute.location = bindingLocation;
|
||||
attribute.setLocation(bindingLocation);
|
||||
}
|
||||
|
||||
if (attribute.location != -1)
|
||||
if (attribute.getLocation() != -1)
|
||||
{
|
||||
// Location is set by glBindAttribLocation or by location layout qualifier
|
||||
const int regs = VariableRegisterCount(attribute.type);
|
||||
const int regs = VariableRegisterCount(attribute.getType());
|
||||
|
||||
if (static_cast<GLuint>(regs + attribute.location) > maxAttribs)
|
||||
if (static_cast<GLuint>(regs + attribute.getLocation()) > maxAttribs)
|
||||
{
|
||||
infoLog << "Attribute (" << attribute.name << ") at location " << attribute.location
|
||||
<< " is too big to fit";
|
||||
infoLog << "Attribute (" << attribute.name << ") at location "
|
||||
<< attribute.getLocation() << " is too big to fit";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int reg = 0; reg < regs; reg++)
|
||||
{
|
||||
const int regLocation = attribute.location + reg;
|
||||
sh::ShaderVariable *linkedAttribute = usedAttribMap[regLocation];
|
||||
const int regLocation = attribute.getLocation() + reg;
|
||||
ProgramInput *linkedAttribute = usedAttribMap[regLocation];
|
||||
|
||||
// In GLSL ES 3.00.6 and in WebGL, attribute aliasing produces a link error.
|
||||
// In non-WebGL GLSL ES 1.00.17, attribute aliasing is allowed with some
|
||||
@@ -3232,12 +3277,12 @@ bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
|
||||
}
|
||||
|
||||
// Assign locations to attributes that don't have a binding location.
|
||||
for (sh::ShaderVariable &attribute : mState.mExecutable->mProgramInputs)
|
||||
for (ProgramInput &attribute : mState.mExecutable->mProgramInputs)
|
||||
{
|
||||
// Not set by glBindAttribLocation or by location layout qualifier
|
||||
if (attribute.location == -1)
|
||||
if (attribute.getLocation() == -1)
|
||||
{
|
||||
int regs = VariableRegisterCount(attribute.type);
|
||||
int regs = VariableRegisterCount(attribute.getType());
|
||||
int availableIndex = AllocateFirstFreeBits(&usedLocations, regs, maxAttribs);
|
||||
|
||||
if (availableIndex == -1 || static_cast<GLuint>(availableIndex + regs) > maxAttribs)
|
||||
@@ -3246,7 +3291,7 @@ bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
|
||||
return false;
|
||||
}
|
||||
|
||||
attribute.location = availableIndex;
|
||||
attribute.setLocation(availableIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3260,7 +3305,7 @@ bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
|
||||
for (auto attributeIter = mState.mExecutable->getProgramInputs().begin();
|
||||
attributeIter != mState.mExecutable->getProgramInputs().end();)
|
||||
{
|
||||
if (attributeIter->active)
|
||||
if (attributeIter->isActive())
|
||||
{
|
||||
++attributeIter;
|
||||
}
|
||||
@@ -3271,13 +3316,13 @@ bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
|
||||
}
|
||||
}
|
||||
|
||||
for (const sh::ShaderVariable &attribute : mState.mExecutable->getProgramInputs())
|
||||
for (const ProgramInput &attribute : mState.mExecutable->getProgramInputs())
|
||||
{
|
||||
ASSERT(attribute.active);
|
||||
ASSERT(attribute.location != -1);
|
||||
unsigned int regs = static_cast<unsigned int>(VariableRegisterCount(attribute.type));
|
||||
ASSERT(attribute.isActive());
|
||||
ASSERT(attribute.getLocation() != -1);
|
||||
unsigned int regs = static_cast<unsigned int>(VariableRegisterCount(attribute.getType()));
|
||||
|
||||
unsigned int location = static_cast<unsigned int>(attribute.location);
|
||||
unsigned int location = static_cast<unsigned int>(attribute.getLocation());
|
||||
for (unsigned int r = 0; r < regs; r++)
|
||||
{
|
||||
// Built-in active program inputs don't have a bound attribute.
|
||||
@@ -3288,7 +3333,7 @@ bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
|
||||
std::max(mState.mExecutable->mMaxActiveAttribLocation, location + 1);
|
||||
|
||||
ComponentType componentType =
|
||||
GLenumToComponentType(VariableComponentType(attribute.type));
|
||||
GLenumToComponentType(VariableComponentType(attribute.getType()));
|
||||
|
||||
SetComponentTypeMask(componentType, location,
|
||||
&mState.mExecutable->mAttributesTypeMask);
|
||||
|
||||
@@ -244,7 +244,7 @@ class ProgramState final : angle::NonCopyable
|
||||
{
|
||||
return mExecutable->getActiveUniformBlockBindings();
|
||||
}
|
||||
const std::vector<sh::ShaderVariable> &getProgramInputs() const
|
||||
const std::vector<ProgramInput> &getProgramInputs() const
|
||||
{
|
||||
return mExecutable->getProgramInputs();
|
||||
}
|
||||
@@ -508,7 +508,7 @@ class Program final : public LabeledObject, public angle::Subject
|
||||
GLchar *name) const;
|
||||
GLint getActiveAttributeCount() const;
|
||||
GLint getActiveAttributeMaxLength() const;
|
||||
const std::vector<sh::ShaderVariable> &getAttributes() const;
|
||||
const std::vector<ProgramInput> &getAttributes() const;
|
||||
|
||||
GLint getFragDataLocation(const std::string &name) const;
|
||||
size_t getOutputResourceCount() const;
|
||||
@@ -734,14 +734,11 @@ class Program final : public LabeledObject, public angle::Subject
|
||||
GLsizei bufSize,
|
||||
GLsizei *length,
|
||||
GLchar *name) const;
|
||||
const sh::ShaderVariable &getInputResource(size_t index) const;
|
||||
GLuint getResourceMaxNameSize(const sh::ShaderVariable &resource, GLint max) const;
|
||||
const ProgramInput &getInputResource(size_t index) const;
|
||||
GLuint getInputResourceMaxNameSize() const;
|
||||
GLuint getOutputResourceMaxNameSize() const;
|
||||
GLuint getResourceLocation(const GLchar *name, const sh::ShaderVariable &variable) const;
|
||||
GLuint getInputResourceLocation(const GLchar *name) const;
|
||||
GLuint getOutputResourceLocation(const GLchar *name) const;
|
||||
const std::string getResourceName(const sh::ShaderVariable &resource) const;
|
||||
const std::string getInputResourceName(GLuint index) const;
|
||||
const std::string getOutputResourceName(GLuint index) const;
|
||||
const sh::ShaderVariable &getOutputResource(size_t index) const;
|
||||
|
||||
@@ -194,6 +194,35 @@ void AppendActiveBlocks(ShaderType shaderType,
|
||||
}
|
||||
}
|
||||
|
||||
void SaveProgramInputs(BinaryOutputStream *stream, const std::vector<ProgramInput> &programInputs)
|
||||
{
|
||||
stream->writeInt(programInputs.size());
|
||||
for (const ProgramInput &attrib : programInputs)
|
||||
{
|
||||
stream->writeString(attrib.name);
|
||||
stream->writeString(attrib.mappedName);
|
||||
stream->writeBytes(reinterpret_cast<const unsigned char *>(&attrib.basicDataTypeStruct),
|
||||
sizeof(attrib.basicDataTypeStruct));
|
||||
}
|
||||
}
|
||||
void LoadProgramInputs(BinaryInputStream *stream, std::vector<ProgramInput> *programInputs)
|
||||
{
|
||||
size_t attribCount = stream->readInt<size_t>();
|
||||
ASSERT(programInputs->empty());
|
||||
if (attribCount > 0)
|
||||
{
|
||||
programInputs->resize(attribCount);
|
||||
for (size_t attribIndex = 0; attribIndex < attribCount; ++attribIndex)
|
||||
{
|
||||
ProgramInput &attrib = (*programInputs)[attribIndex];
|
||||
stream->readString(&attrib.name);
|
||||
stream->readString(&attrib.mappedName);
|
||||
stream->readBytes(reinterpret_cast<unsigned char *>(&attrib.basicDataTypeStruct),
|
||||
sizeof(attrib.basicDataTypeStruct));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SaveUniforms(BinaryOutputStream *stream,
|
||||
const std::vector<LinkedUniform> &uniforms,
|
||||
const std::vector<std::string> &uniformNames,
|
||||
@@ -417,16 +446,7 @@ void ProgramExecutable::load(bool isSeparable, gl::BinaryInputStream *stream)
|
||||
mTessGenVertexOrder = stream->readInt<GLenum>();
|
||||
mTessGenPointMode = stream->readInt<GLenum>();
|
||||
|
||||
size_t attribCount = stream->readInt<size_t>();
|
||||
ASSERT(mProgramInputs.empty());
|
||||
mProgramInputs.resize(attribCount);
|
||||
for (size_t attribIndex = 0; attribIndex < attribCount; ++attribIndex)
|
||||
{
|
||||
sh::ShaderVariable &attrib = mProgramInputs[attribIndex];
|
||||
LoadShaderVar(stream, &attrib);
|
||||
attrib.location = stream->readInt<int>();
|
||||
}
|
||||
|
||||
LoadProgramInputs(stream, &mProgramInputs);
|
||||
LoadUniforms(stream, &mUniforms, &mUniformNames, &mUniformMappedNames);
|
||||
|
||||
size_t uniformBlockCount = stream->readInt<size_t>();
|
||||
@@ -633,13 +653,7 @@ void ProgramExecutable::save(bool isSeparable, gl::BinaryOutputStream *stream) c
|
||||
stream->writeInt(mTessGenVertexOrder);
|
||||
stream->writeInt(mTessGenPointMode);
|
||||
|
||||
stream->writeInt(getProgramInputs().size());
|
||||
for (const sh::ShaderVariable &attrib : getProgramInputs())
|
||||
{
|
||||
WriteShaderVar(stream, attrib);
|
||||
stream->writeInt(attrib.location);
|
||||
}
|
||||
|
||||
SaveProgramInputs(stream, mProgramInputs);
|
||||
SaveUniforms(stream, mUniforms, mUniformNames, mUniformMappedNames);
|
||||
|
||||
stream->writeInt(getUniformBlocks().size());
|
||||
|
||||
@@ -60,6 +60,72 @@ struct ImageBinding
|
||||
std::vector<GLuint> boundImageUnits;
|
||||
};
|
||||
|
||||
ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
|
||||
struct ProgramInput
|
||||
{
|
||||
ProgramInput();
|
||||
ProgramInput(const sh::ShaderVariable &var);
|
||||
ProgramInput(const ProgramInput &other);
|
||||
ProgramInput &operator=(const ProgramInput &rhs);
|
||||
|
||||
GLenum getType() const { return basicDataTypeStruct.type; }
|
||||
bool isBuiltIn() const { return basicDataTypeStruct.flagBits.isBuiltIn; }
|
||||
bool isArray() const { return basicDataTypeStruct.flagBits.isArray; }
|
||||
bool isActive() const { return basicDataTypeStruct.flagBits.active; }
|
||||
bool isPatch() const { return basicDataTypeStruct.flagBits.isPatch; }
|
||||
int getLocation() const { return basicDataTypeStruct.location; }
|
||||
unsigned int getBasicTypeElementCount() const
|
||||
{
|
||||
return basicDataTypeStruct.basicTypeElementCount;
|
||||
}
|
||||
unsigned int getArraySizeProduct() const { return basicDataTypeStruct.arraySizeProduct; }
|
||||
uint32_t getId() const { return basicDataTypeStruct.id; }
|
||||
sh::InterpolationType getInterpolation() const
|
||||
{
|
||||
return static_cast<sh::InterpolationType>(basicDataTypeStruct.interpolation);
|
||||
}
|
||||
|
||||
void setLocation(int location) { basicDataTypeStruct.location = location; }
|
||||
void resetEffectiveLocation()
|
||||
{
|
||||
if (basicDataTypeStruct.flagBits.hasImplicitLocation)
|
||||
{
|
||||
basicDataTypeStruct.location = -1;
|
||||
}
|
||||
}
|
||||
|
||||
std::string name;
|
||||
std::string mappedName;
|
||||
|
||||
// The struct bellow must only contain data of basic type so that entire struct can memcpy-able.
|
||||
struct
|
||||
{
|
||||
uint16_t type; // GLenum
|
||||
uint16_t arraySizeProduct;
|
||||
|
||||
int location;
|
||||
|
||||
uint8_t interpolation; // sh::InterpolationType
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8_t active : 1;
|
||||
uint8_t isPatch : 1;
|
||||
uint8_t hasImplicitLocation : 1;
|
||||
uint8_t isArray : 1;
|
||||
uint8_t isBuiltIn : 1;
|
||||
uint8_t padding : 3;
|
||||
} flagBits;
|
||||
uint8_t flagBitsAsUByte;
|
||||
};
|
||||
int16_t basicTypeElementCount;
|
||||
|
||||
uint32_t id;
|
||||
} basicDataTypeStruct;
|
||||
};
|
||||
ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
|
||||
|
||||
// A varying with transform feedback enabled. If it's an array, either the whole array or one of its
|
||||
// elements specified by 'arrayIndex' can set to be enabled.
|
||||
struct TransformFeedbackVarying : public sh::ShaderVariable
|
||||
@@ -214,7 +280,7 @@ class ProgramExecutable final : public angle::Subject
|
||||
void updateCanDrawWith();
|
||||
bool hasVertexShader() const { return mCanDrawWith; }
|
||||
|
||||
const std::vector<sh::ShaderVariable> &getProgramInputs() const { return mProgramInputs; }
|
||||
const std::vector<ProgramInput> &getProgramInputs() const { return mProgramInputs; }
|
||||
const std::vector<sh::ShaderVariable> &getOutputVariables() const { return mOutputVariables; }
|
||||
const std::vector<VariableLocation> &getOutputLocations() const { return mOutputLocations; }
|
||||
const std::vector<VariableLocation> &getSecondaryOutputLocations() const
|
||||
@@ -454,7 +520,7 @@ class ProgramExecutable final : public angle::Subject
|
||||
std::vector<VariableLocation> mSecondaryOutputLocations;
|
||||
bool mYUVOutput;
|
||||
// Vertex attributes, Fragment input varyings, etc.
|
||||
std::vector<sh::ShaderVariable> mProgramInputs;
|
||||
std::vector<ProgramInput> mProgramInputs;
|
||||
std::vector<TransformFeedbackVarying> mLinkedTransformFeedbackVaryings;
|
||||
// The size of the data written to each transform feedback buffer per vertex.
|
||||
std::vector<GLsizei> mTransformFeedbackStrides;
|
||||
|
||||
@@ -3407,7 +3407,7 @@ void GenerateLinkedProgram(const gl::Context *context,
|
||||
|
||||
// Force the attributes to be bound the same way as in the existing program.
|
||||
// This can affect attributes that are optimized out in some implementations.
|
||||
for (const sh::ShaderVariable &attrib : program->getState().getProgramInputs())
|
||||
for (const gl::ProgramInput &attrib : program->getState().getProgramInputs())
|
||||
{
|
||||
if (gl::IsBuiltInName(attrib.name))
|
||||
{
|
||||
@@ -3418,9 +3418,9 @@ void GenerateLinkedProgram(const gl::Context *context,
|
||||
// Separable programs may not have a VS, meaning it may not have attributes.
|
||||
if (program->getExecutable().hasLinkedShaderStage(gl::ShaderType::Vertex))
|
||||
{
|
||||
ASSERT(attrib.location != -1);
|
||||
ASSERT(attrib.getLocation() != -1);
|
||||
Capture(setupCalls, CaptureBindAttribLocation(replayState, true, id,
|
||||
static_cast<GLuint>(attrib.location),
|
||||
static_cast<GLuint>(attrib.getLocation()),
|
||||
attrib.name.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -719,19 +719,20 @@ GLint GetCommonVariableProperty(const T &var, GLenum prop)
|
||||
|
||||
GLint GetInputResourceProperty(const Program *program, GLuint index, GLenum prop)
|
||||
{
|
||||
const sh::ShaderVariable &variable = program->getInputResource(index);
|
||||
const ProgramInput &variable = program->getInputResource(index);
|
||||
|
||||
switch (prop)
|
||||
{
|
||||
case GL_TYPE:
|
||||
return clampCast<GLint>(variable.getType());
|
||||
case GL_ARRAY_SIZE:
|
||||
return GetCommonVariableProperty(variable, prop);
|
||||
return clampCast<GLint>(variable.getBasicTypeElementCount());
|
||||
|
||||
case GL_NAME_LENGTH:
|
||||
return clampCast<GLint>(program->getInputResourceName(index).size() + 1u);
|
||||
|
||||
case GL_LOCATION:
|
||||
return variable.isBuiltIn() ? GL_INVALID_INDEX : variable.location;
|
||||
return variable.isBuiltIn() ? GL_INVALID_INDEX : variable.getLocation();
|
||||
|
||||
// The query is targeted at the set of active input variables used by the first shader stage
|
||||
// of program. If program contains multiple shader stages then input variables from any
|
||||
@@ -751,7 +752,7 @@ GLint GetInputResourceProperty(const Program *program, GLuint index, GLenum prop
|
||||
return program->getState().getFirstAttachedShaderStageType() ==
|
||||
ShaderType::TessEvaluation;
|
||||
case GL_IS_PER_PATCH_EXT:
|
||||
return variable.isPatch;
|
||||
return variable.isPatch();
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
||||
@@ -181,7 +181,7 @@ DynamicHLSL::DynamicHLSL(RendererD3D *const renderer) : mRenderer(renderer) {}
|
||||
std::string DynamicHLSL::generateVertexShaderForInputLayout(
|
||||
const std::string &sourceShader,
|
||||
const InputLayout &inputLayout,
|
||||
const std::vector<sh::ShaderVariable> &shaderAttributes,
|
||||
const std::vector<gl::ProgramInput> &shaderAttributes,
|
||||
const std::vector<rx::ShaderStorageBlock> &shaderStorageBlocks,
|
||||
size_t baseUAVRegister) const
|
||||
{
|
||||
@@ -217,7 +217,7 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(
|
||||
|
||||
for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); ++attributeIndex)
|
||||
{
|
||||
const sh::ShaderVariable &shaderAttribute = shaderAttributes[attributeIndex];
|
||||
const gl::ProgramInput &shaderAttribute = shaderAttributes[attributeIndex];
|
||||
if (!shaderAttribute.name.empty())
|
||||
{
|
||||
ASSERT(inputIndex < MAX_VERTEX_ATTRIBS);
|
||||
@@ -225,11 +225,12 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(
|
||||
inputIndex < inputLayout.size() ? inputLayout[inputIndex] : angle::FormatID::NONE;
|
||||
|
||||
// HLSL code for input structure
|
||||
if (IsMatrixType(shaderAttribute.type))
|
||||
if (IsMatrixType(shaderAttribute.getType()))
|
||||
{
|
||||
// Matrix types are always transposed
|
||||
structStream << " "
|
||||
<< HLSLMatrixTypeString(TransposeMatrixType(shaderAttribute.type));
|
||||
<< HLSLMatrixTypeString(
|
||||
TransposeMatrixType(shaderAttribute.getType()));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -246,7 +247,7 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(
|
||||
|
||||
structStream << " ";
|
||||
HLSLComponentTypeString(structStream, componentType,
|
||||
VariableComponentCount(shaderAttribute.type));
|
||||
VariableComponentCount(shaderAttribute.getType()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,7 +264,7 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(
|
||||
else
|
||||
{
|
||||
structStream << "TEXCOORD" << semanticIndex;
|
||||
semanticIndex += VariableRegisterCount(shaderAttribute.type);
|
||||
semanticIndex += VariableRegisterCount(shaderAttribute.getType());
|
||||
}
|
||||
|
||||
structStream << ";\n";
|
||||
@@ -274,7 +275,7 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(
|
||||
// Mismatched vertex attribute to vertex input may result in an undefined
|
||||
// data reinterpretation (eg for pure integer->float, float->pure integer)
|
||||
// TODO: issue warning with gl debug info extension, when supported
|
||||
if (IsMatrixType(shaderAttribute.type) ||
|
||||
if (IsMatrixType(shaderAttribute.getType()) ||
|
||||
(mRenderer->getVertexConversionType(vertexFormatID) & VERTEX_CONVERT_GPU) != 0)
|
||||
{
|
||||
GenerateAttributeConversionHLSL(vertexFormatID, shaderAttribute, initStream);
|
||||
@@ -292,7 +293,7 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(
|
||||
|
||||
initStream << ";\n";
|
||||
|
||||
inputIndex += VariableRowCount(TransposeMatrixType(shaderAttribute.type));
|
||||
inputIndex += VariableRowCount(TransposeMatrixType(shaderAttribute.getType()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1464,18 +1465,18 @@ std::string DynamicHLSL::generateGeometryShaderHLSL(const gl::Caps &caps,
|
||||
|
||||
// static
|
||||
void DynamicHLSL::GenerateAttributeConversionHLSL(angle::FormatID vertexFormatID,
|
||||
const sh::ShaderVariable &shaderAttrib,
|
||||
const gl::ProgramInput &shaderAttrib,
|
||||
std::ostringstream &outStream)
|
||||
{
|
||||
// Matrix
|
||||
if (IsMatrixType(shaderAttrib.type))
|
||||
if (IsMatrixType(shaderAttrib.getType()))
|
||||
{
|
||||
outStream << "transpose(input." << DecorateVariable(shaderAttrib.name) << ")";
|
||||
return;
|
||||
}
|
||||
|
||||
GLenum shaderComponentType = VariableComponentType(shaderAttrib.type);
|
||||
int shaderComponentCount = VariableComponentCount(shaderAttrib.type);
|
||||
GLenum shaderComponentType = VariableComponentType(shaderAttrib.getType());
|
||||
int shaderComponentCount = VariableComponentCount(shaderAttrib.getType());
|
||||
const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromID(vertexFormatID);
|
||||
|
||||
// Perform integer to float conversion (if necessary)
|
||||
|
||||
@@ -152,7 +152,7 @@ class DynamicHLSL : angle::NonCopyable
|
||||
std::string generateVertexShaderForInputLayout(
|
||||
const std::string &sourceShader,
|
||||
const gl::InputLayout &inputLayout,
|
||||
const std::vector<sh::ShaderVariable> &shaderAttributes,
|
||||
const std::vector<gl::ProgramInput> &shaderAttributes,
|
||||
const std::vector<rx::ShaderStorageBlock> &shaderStorageBlocks,
|
||||
size_t baseUAVRegister) const;
|
||||
std::string generatePixelShaderForOutputSignature(
|
||||
@@ -207,7 +207,7 @@ class DynamicHLSL : angle::NonCopyable
|
||||
std::ostringstream &hlslStream) const;
|
||||
|
||||
static void GenerateAttributeConversionHLSL(angle::FormatID vertexFormatID,
|
||||
const sh::ShaderVariable &shaderAttrib,
|
||||
const gl::ProgramInput &shaderAttrib,
|
||||
std::ostringstream &outStream);
|
||||
};
|
||||
|
||||
|
||||
@@ -30,21 +30,21 @@ namespace rx
|
||||
namespace
|
||||
{
|
||||
|
||||
GLenum GetGLSLAttributeType(const std::vector<sh::ShaderVariable> &shaderAttributes, size_t index)
|
||||
GLenum GetGLSLAttributeType(const std::vector<gl::ProgramInput> &shaderAttributes, size_t index)
|
||||
{
|
||||
// Count matrices differently
|
||||
for (const sh::ShaderVariable &attrib : shaderAttributes)
|
||||
for (const gl::ProgramInput &attrib : shaderAttributes)
|
||||
{
|
||||
if (attrib.location == -1)
|
||||
if (attrib.getLocation() == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
GLenum transposedType = gl::TransposeMatrixType(attrib.type);
|
||||
GLenum transposedType = gl::TransposeMatrixType(attrib.getType());
|
||||
int rows = gl::VariableRowCount(transposedType);
|
||||
int intIndex = static_cast<int>(index);
|
||||
|
||||
if (intIndex >= attrib.location && intIndex < attrib.location + rows)
|
||||
if (intIndex >= attrib.getLocation() && intIndex < attrib.getLocation() + rows)
|
||||
{
|
||||
return transposedType;
|
||||
}
|
||||
|
||||
@@ -290,14 +290,14 @@ std::unique_ptr<LinkEvent> ProgramGL::link(const gl::Context *context,
|
||||
}
|
||||
|
||||
// Bind attribute locations to match the GL layer.
|
||||
for (const sh::ShaderVariable &attribute : mState.getProgramInputs())
|
||||
for (const gl::ProgramInput &attribute : mState.getProgramInputs())
|
||||
{
|
||||
if (!attribute.active || attribute.isBuiltIn())
|
||||
if (!attribute.isActive() || attribute.isBuiltIn())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
mFunctions->bindAttribLocation(mProgramID, attribute.location,
|
||||
mFunctions->bindAttribLocation(mProgramID, attribute.getLocation(),
|
||||
attribute.mappedName.c_str());
|
||||
}
|
||||
|
||||
|
||||
@@ -676,7 +676,7 @@ void ProgramMtl::linkUpdateHasFlatAttributes(const gl::Context *context)
|
||||
const auto &programInputs = mState.getProgramInputs();
|
||||
for (auto &attribute : programInputs)
|
||||
{
|
||||
if (attribute.interpolation == sh::INTERPOLATION_FLAT)
|
||||
if (attribute.getInterpolation() == sh::INTERPOLATION_FLAT)
|
||||
{
|
||||
mProgramHasFlatAttributes = true;
|
||||
return;
|
||||
|
||||
@@ -71,7 +71,7 @@ class VertexArrayMtl : public VertexArrayImpl
|
||||
private:
|
||||
void reset(ContextMtl *context);
|
||||
|
||||
void getVertexAttribFormatAndArraySize(const sh::ShaderVariable &var,
|
||||
void getVertexAttribFormatAndArraySize(const gl::ProgramInput &var,
|
||||
MTLVertexFormat *formatOut,
|
||||
uint32_t *arraySizeOut);
|
||||
|
||||
|
||||
@@ -328,14 +328,14 @@ angle::Result VertexArrayMtl::syncState(const gl::Context *context,
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
ANGLE_INLINE void VertexArrayMtl::getVertexAttribFormatAndArraySize(const sh::ShaderVariable &var,
|
||||
ANGLE_INLINE void VertexArrayMtl::getVertexAttribFormatAndArraySize(const gl::ProgramInput &var,
|
||||
MTLVertexFormat *formatOut,
|
||||
uint32_t *arraySizeOut)
|
||||
{
|
||||
uint32_t arraySize = var.getArraySizeProduct();
|
||||
|
||||
MTLVertexFormat format;
|
||||
switch (var.type)
|
||||
switch (var.getType())
|
||||
{
|
||||
case GL_INT:
|
||||
case GL_INT_VEC2:
|
||||
@@ -437,11 +437,11 @@ angle::Result VertexArrayMtl::setupDraw(const gl::Context *glContext,
|
||||
// Use default attribute
|
||||
// Need to find the attribute having the exact binding location = v in the program
|
||||
// inputs list to retrieve its coresponding data type:
|
||||
const std::vector<sh::ShaderVariable> &programInputs =
|
||||
const std::vector<gl::ProgramInput> &programInputs =
|
||||
programState.getProgramInputs();
|
||||
std::vector<sh::ShaderVariable>::const_iterator attribInfoIte = std::find_if(
|
||||
begin(programInputs), end(programInputs), [v](const sh::ShaderVariable &sv) {
|
||||
return static_cast<uint32_t>(sv.location) == v;
|
||||
std::vector<gl::ProgramInput>::const_iterator attribInfoIte = std::find_if(
|
||||
begin(programInputs), end(programInputs), [v](const gl::ProgramInput &sv) {
|
||||
return static_cast<uint32_t>(sv.getLocation()) == v;
|
||||
});
|
||||
|
||||
if (attribInfoIte == end(programInputs))
|
||||
|
||||
@@ -173,7 +173,7 @@ std::string updateShaderAttributes(std::string shaderSourceIn, const gl::Program
|
||||
std::unordered_map<std::string, uint32_t> attributeBindings;
|
||||
for (auto &attribute : programAttributes)
|
||||
{
|
||||
const int regs = gl::VariableRegisterCount(attribute.type);
|
||||
const int regs = gl::VariableRegisterCount(attribute.getType());
|
||||
if (regs > 1)
|
||||
{
|
||||
for (int i = 0; i < regs; i++)
|
||||
@@ -181,7 +181,7 @@ std::string updateShaderAttributes(std::string shaderSourceIn, const gl::Program
|
||||
stream.str("");
|
||||
stream << " " << kUserDefinedNamePrefix << attribute.name << "_"
|
||||
<< std::to_string(i) << sh::kUnassignedAttributeString;
|
||||
attributeBindings.insert({std::string(stream.str()), i + attribute.location});
|
||||
attributeBindings.insert({std::string(stream.str()), i + attribute.getLocation()});
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -189,7 +189,7 @@ std::string updateShaderAttributes(std::string shaderSourceIn, const gl::Program
|
||||
stream.str("");
|
||||
stream << " " << kUserDefinedNamePrefix << attribute.name
|
||||
<< sh::kUnassignedAttributeString;
|
||||
attributeBindings.insert({std::string(stream.str()), attribute.location});
|
||||
attributeBindings.insert({std::string(stream.str()), attribute.getLocation()});
|
||||
stream.str("");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,9 +283,9 @@ void AssignAttributeLocations(const gl::ProgramExecutable &programExecutable,
|
||||
bool hasAliasingAttributes = false;
|
||||
|
||||
// Assign attribute locations for the vertex shader.
|
||||
for (const sh::ShaderVariable &attribute : programExecutable.getProgramInputs())
|
||||
for (const gl::ProgramInput &attribute : programExecutable.getProgramInputs())
|
||||
{
|
||||
ASSERT(attribute.active);
|
||||
ASSERT(attribute.isActive());
|
||||
|
||||
if (std::find(implicitInputs.begin(), implicitInputs.end(), attribute.name) !=
|
||||
implicitInputs.end())
|
||||
@@ -293,14 +293,14 @@ void AssignAttributeLocations(const gl::ProgramExecutable &programExecutable,
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint8_t colCount = static_cast<uint8_t>(gl::VariableColumnCount(attribute.type));
|
||||
const uint8_t rowCount = static_cast<uint8_t>(gl::VariableRowCount(attribute.type));
|
||||
const uint8_t colCount = static_cast<uint8_t>(gl::VariableColumnCount(attribute.getType()));
|
||||
const uint8_t rowCount = static_cast<uint8_t>(gl::VariableRowCount(attribute.getType()));
|
||||
const bool isMatrix = colCount > 1 && rowCount > 1;
|
||||
|
||||
const uint8_t componentCount = isMatrix ? rowCount : colCount;
|
||||
const uint8_t locationCount = isMatrix ? colCount : rowCount;
|
||||
|
||||
AddLocationInfo(variableInfoMapOut, shaderType, attribute.id, attribute.location,
|
||||
AddLocationInfo(variableInfoMapOut, shaderType, attribute.getId(), attribute.getLocation(),
|
||||
ShaderInterfaceVariableInfo::kInvalid, componentCount, locationCount);
|
||||
|
||||
// Detect if there are aliasing attributes.
|
||||
@@ -309,7 +309,7 @@ void AssignAttributeLocations(const gl::ProgramExecutable &programExecutable,
|
||||
{
|
||||
for (uint8_t offset = 0; offset < locationCount; ++offset)
|
||||
{
|
||||
uint32_t location = attribute.location + offset;
|
||||
uint32_t location = attribute.getLocation() + offset;
|
||||
|
||||
// If there's aliasing, no need for futher processing.
|
||||
if (isLocationAssigned.test(location))
|
||||
|
||||
Reference in New Issue
Block a user