Refactor ProgramBinary uniform linking code.
This prepares us for moving most of the register assignment to the
ProgramBinary class itself, and cleans up the various methods.
BUG=angle:466
Change-Id: Ie2965ed41ac50617584fd7a6d7b0ec2784e7dfaf
Reviewed-on: https://chromium-review.googlesource.com/207252
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Nicolas Capens <capn@chromium.org>
diff --git a/src/libGLESv2/ProgramBinary.cpp b/src/libGLESv2/ProgramBinary.cpp
index 2c1bcac..14e90b8 100644
--- a/src/libGLESv2/ProgramBinary.cpp
+++ b/src/libGLESv2/ProgramBinary.cpp
@@ -37,6 +37,36 @@
namespace
{
+TextureType GetTextureType(GLenum samplerType)
+{
+ switch (samplerType)
+ {
+ case GL_SAMPLER_2D:
+ case GL_INT_SAMPLER_2D:
+ case GL_UNSIGNED_INT_SAMPLER_2D:
+ case GL_SAMPLER_2D_SHADOW:
+ return TEXTURE_2D;
+ case GL_SAMPLER_3D:
+ case GL_INT_SAMPLER_3D:
+ case GL_UNSIGNED_INT_SAMPLER_3D:
+ return TEXTURE_3D;
+ case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_CUBE_SHADOW:
+ return TEXTURE_CUBE;
+ case GL_INT_SAMPLER_CUBE:
+ case GL_UNSIGNED_INT_SAMPLER_CUBE:
+ return TEXTURE_CUBE;
+ case GL_SAMPLER_2D_ARRAY:
+ case GL_INT_SAMPLER_2D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_2D_ARRAY_SHADOW:
+ return TEXTURE_2D_ARRAY;
+ default: UNREACHABLE();
+ }
+
+ return TEXTURE_2D;
+}
+
unsigned int ParseAndStripArrayIndex(std::string* name)
{
unsigned int subscript = GL_INVALID_INDEX;
@@ -353,7 +383,7 @@
switch (type)
{
case SAMPLER_PIXEL:
- ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
+ ASSERT(samplerIndex < ArraySize(mSamplersPS));
if (mSamplersPS[samplerIndex].active)
{
@@ -361,7 +391,7 @@
}
break;
case SAMPLER_VERTEX:
- ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
+ ASSERT(samplerIndex < ArraySize(mSamplersVS));
if (mSamplersVS[samplerIndex].active)
{
@@ -386,11 +416,11 @@
switch (type)
{
case SAMPLER_PIXEL:
- ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
+ ASSERT(samplerIndex < ArraySize(mSamplersPS));
ASSERT(mSamplersPS[samplerIndex].active);
return mSamplersPS[samplerIndex].textureType;
case SAMPLER_VERTEX:
- ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
+ ASSERT(samplerIndex < ArraySize(mSamplersVS));
ASSERT(mSamplersVS[samplerIndex].active);
return mSamplersVS[samplerIndex].textureType;
default: UNREACHABLE();
@@ -1899,18 +1929,17 @@
for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++)
{
- if (!defineUniform(GL_VERTEX_SHADER, vertexUniforms[uniformIndex], infoLog))
- {
- return false;
- }
+ defineUniform(GL_VERTEX_SHADER, vertexUniforms[uniformIndex]);
}
for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++)
{
- if (!defineUniform(GL_FRAGMENT_SHADER, fragmentUniforms[uniformIndex], infoLog))
- {
- return false;
- }
+ defineUniform(GL_FRAGMENT_SHADER, fragmentUniforms[uniformIndex]);
+ }
+
+ if (!indexUniforms(infoLog))
+ {
+ return false;
}
initializeUniformStorage();
@@ -1918,37 +1947,7 @@
return true;
}
-TextureType ProgramBinary::getTextureType(GLenum samplerType, InfoLog &infoLog)
-{
- switch(samplerType)
- {
- case GL_SAMPLER_2D:
- case GL_INT_SAMPLER_2D:
- case GL_UNSIGNED_INT_SAMPLER_2D:
- case GL_SAMPLER_2D_SHADOW:
- return TEXTURE_2D;
- case GL_SAMPLER_3D:
- case GL_INT_SAMPLER_3D:
- case GL_UNSIGNED_INT_SAMPLER_3D:
- return TEXTURE_3D;
- case GL_SAMPLER_CUBE:
- case GL_SAMPLER_CUBE_SHADOW:
- return TEXTURE_CUBE;
- case GL_INT_SAMPLER_CUBE:
- case GL_UNSIGNED_INT_SAMPLER_CUBE:
- return TEXTURE_CUBE;
- case GL_SAMPLER_2D_ARRAY:
- case GL_INT_SAMPLER_2D_ARRAY:
- case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
- case GL_SAMPLER_2D_ARRAY_SHADOW:
- return TEXTURE_2D_ARRAY;
- default: UNREACHABLE();
- }
-
- return TEXTURE_2D;
-}
-
-bool ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog)
+void ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant)
{
if (constant.isStruct())
{
@@ -1970,10 +1969,8 @@
fieldRegisterIndex, field.elementIndex);
fieldUniform.fields = field.fields;
- if (!defineUniform(shader, fieldUniform, infoLog))
- {
- return false;
- }
+
+ defineUniform(shader, fieldUniform);
}
}
}
@@ -1989,118 +1986,131 @@
fieldUniform.fields = field.fields;
- if (!defineUniform(shader, fieldUniform, infoLog))
- {
- return false;
- }
+ defineUniform(shader, fieldUniform);
}
}
-
- return true;
}
-
- if (IsSampler(constant.type))
+ else // Not a struct
{
- unsigned int samplerIndex = constant.registerIndex;
+ LinkedUniform *linkedUniform = getUniformByName(constant.name);
- do
+ if (!linkedUniform)
{
- if (shader == GL_VERTEX_SHADER)
- {
- if (samplerIndex < mRenderer->getMaxVertexTextureImageUnits())
- {
- mSamplersVS[samplerIndex].active = true;
- mSamplersVS[samplerIndex].textureType = getTextureType(constant.type, infoLog);
- mSamplersVS[samplerIndex].logicalTextureUnit = 0;
- mUsedVertexSamplerRange = std::max(samplerIndex + 1, mUsedVertexSamplerRange);
- }
- else
- {
- infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).", mRenderer->getMaxVertexTextureImageUnits());
- return false;
- }
- }
- else if (shader == GL_FRAGMENT_SHADER)
- {
- if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
- {
- mSamplersPS[samplerIndex].active = true;
- mSamplersPS[samplerIndex].textureType = getTextureType(constant.type, infoLog);
- mSamplersPS[samplerIndex].logicalTextureUnit = 0;
- mUsedPixelSamplerRange = std::max(samplerIndex + 1, mUsedPixelSamplerRange);
- }
- else
- {
- infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS);
- return false;
- }
- }
- else UNREACHABLE();
-
- samplerIndex++;
+ linkedUniform = new LinkedUniform(constant.type, constant.precision, constant.name, constant.arraySize,
+ -1, sh::BlockMemberInfo::getDefaultBlockInfo());
+ ASSERT(linkedUniform);
+ linkedUniform->registerElement = constant.elementIndex;
+ mUniforms.push_back(linkedUniform);
}
- while (samplerIndex < constant.registerIndex + constant.arraySize);
- }
- LinkedUniform *uniform = NULL;
- GLint location = getUniformLocation(constant.name);
-
- if (location >= 0) // Previously defined, type and precision must match
- {
- uniform = mUniforms[mUniformIndex[location].index];
- }
- else
- {
- uniform = new LinkedUniform(constant.type, constant.precision, constant.name, constant.arraySize,
- -1, sh::BlockMemberInfo::getDefaultBlockInfo());
- uniform->registerElement = constant.elementIndex;
- }
-
- if (!uniform)
- {
- return false;
- }
-
- if (shader == GL_FRAGMENT_SHADER)
- {
- uniform->psRegisterIndex = constant.registerIndex;
- }
- else if (shader == GL_VERTEX_SHADER)
- {
- uniform->vsRegisterIndex = constant.registerIndex;
- }
- else UNREACHABLE();
-
- if (location >= 0)
- {
- return uniform->type == constant.type;
- }
-
- mUniforms.push_back(uniform);
- unsigned int uniformIndex = mUniforms.size() - 1;
-
- for (unsigned int arrayElementIndex = 0; arrayElementIndex < uniform->elementCount(); arrayElementIndex++)
- {
- mUniformIndex.push_back(VariableLocation(uniform->name, arrayElementIndex, uniformIndex));
- }
-
- if (shader == GL_VERTEX_SHADER)
- {
- if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedVertexUniformVectors() + mRenderer->getMaxVertexUniformVectors())
+ if (shader == GL_FRAGMENT_SHADER)
{
- infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", mRenderer->getMaxVertexUniformVectors());
+ linkedUniform->psRegisterIndex = constant.registerIndex;
+ }
+ else if (shader == GL_VERTEX_SHADER)
+ {
+ linkedUniform->vsRegisterIndex = constant.registerIndex;
+ }
+ else UNREACHABLE();
+ }
+}
+
+bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog)
+{
+ ASSERT(IsSampler(uniform.type));
+ ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX);
+
+ if (uniform.vsRegisterIndex != GL_INVALID_INDEX)
+ {
+ if (!assignSamplers(uniform.vsRegisterIndex, uniform.type, uniform.arraySize, mSamplersVS,
+ &mUsedVertexSamplerRange, mRenderer->getMaxVertexTextureImageUnits()))
+ {
+ infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).",
+ mRenderer->getMaxVertexTextureImageUnits());
+ return false;
+ }
+
+ unsigned int maxVertexVectors = mRenderer->getReservedVertexUniformVectors() +
+ mRenderer->getMaxVertexUniformVectors();
+ if (uniform.vsRegisterIndex + uniform.registerCount > maxVertexVectors)
+ {
+ infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)",
+ mRenderer->getMaxVertexUniformVectors());
return false;
}
}
- else if (shader == GL_FRAGMENT_SHADER)
+
+ if (uniform.psRegisterIndex != GL_INVALID_INDEX)
{
- if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedFragmentUniformVectors() + mRenderer->getMaxFragmentUniformVectors())
+ if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS,
+ &mUsedPixelSamplerRange, MAX_TEXTURE_IMAGE_UNITS))
{
- infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", mRenderer->getMaxFragmentUniformVectors());
+ infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).",
+ MAX_TEXTURE_IMAGE_UNITS);
+ return false;
+ }
+
+ unsigned int maxFragmentVectors = mRenderer->getReservedFragmentUniformVectors() +
+ mRenderer->getMaxFragmentUniformVectors();
+ if (uniform.psRegisterIndex + uniform.registerCount > maxFragmentVectors)
+ {
+ infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)",
+ mRenderer->getMaxFragmentUniformVectors());
return false;
}
}
- else UNREACHABLE();
+
+ return true;
+}
+
+bool ProgramBinary::indexUniforms(InfoLog &infoLog)
+{
+ for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
+ {
+ const LinkedUniform &uniform = *mUniforms[uniformIndex];
+
+ if (IsSampler(uniform.type))
+ {
+ if (!indexSamplerUniform(uniform, infoLog))
+ {
+ return false;
+ }
+ }
+
+ for (unsigned int arrayElementIndex = 0; arrayElementIndex < uniform.elementCount(); arrayElementIndex++)
+ {
+ mUniformIndex.push_back(VariableLocation(uniform.name, arrayElementIndex, uniformIndex));
+ }
+ }
+
+ return true;
+}
+
+bool ProgramBinary::assignSamplers(unsigned int startSamplerIndex,
+ GLenum samplerType,
+ unsigned int samplerCount,
+ Sampler *outArray,
+ GLuint *usedRange,
+ unsigned int limit)
+{
+ unsigned int samplerIndex = startSamplerIndex;
+
+ do
+ {
+ if (samplerIndex < limit)
+ {
+ outArray[samplerIndex].active = true;
+ outArray[samplerIndex].textureType = GetTextureType(samplerType);
+ outArray[samplerIndex].logicalTextureUnit = 0;
+ *usedRange = std::max(samplerIndex + 1, *usedRange);
+ }
+ else
+ {
+ return false;
+ }
+
+ samplerIndex++;
+ } while (samplerIndex < startSamplerIndex + samplerCount);
return true;
}
@@ -2538,6 +2548,19 @@
return mUniforms[mUniformIndex[location].index];
}
+LinkedUniform *ProgramBinary::getUniformByName(const std::string &name) const
+{
+ for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
+ {
+ if (mUniforms[uniformIndex]->name == name)
+ {
+ return mUniforms[uniformIndex];
+ }
+ }
+
+ return NULL;
+}
+
void ProgramBinary::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const
{
ASSERT(uniformBlockIndex < mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount()
diff --git a/src/libGLESv2/ProgramBinary.h b/src/libGLESv2/ProgramBinary.h
index 161afa1..56b58c6 100644
--- a/src/libGLESv2/ProgramBinary.h
+++ b/src/libGLESv2/ProgramBinary.h
@@ -146,6 +146,7 @@
GLint getActiveUniformi(GLuint index, GLenum pname) const;
bool isValidUniformLocation(GLint location) const;
LinkedUniform *getUniformByLocation(GLint location) const;
+ LinkedUniform *getUniformByName(const std::string &name) const;
void getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const;
void getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const;
@@ -177,6 +178,15 @@
private:
DISALLOW_COPY_AND_ASSIGN(ProgramBinary);
+ struct Sampler
+ {
+ Sampler();
+
+ bool active;
+ GLint logicalTextureUnit;
+ TextureType textureType;
+ };
+
void reset();
bool linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShader, VertexShader *vertexShader);
@@ -192,7 +202,11 @@
bool linkValidateVariables(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying);
bool linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform);
bool linkUniforms(InfoLog &infoLog, const std::vector<sh::Uniform> &vertexUniforms, const std::vector<sh::Uniform> &fragmentUniforms);
- bool defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog);
+ void defineUniform(GLenum shader, const sh::Uniform &constant);
+ bool indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog);
+ bool indexUniforms(InfoLog &infoLog);
+ static bool assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount,
+ Sampler *outArray, GLuint *usedRange, unsigned int limit);
bool areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock);
bool linkUniformBlocks(InfoLog &infoLog, const VertexShader &vertexShader, const FragmentShader &fragmentShader);
bool gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings,
@@ -214,8 +228,6 @@
template <typename T>
bool getUniformv(GLint location, GLsizei *bufSize, T *params, GLenum uniformType);
- static TextureType getTextureType(GLenum samplerType, InfoLog &infoLog);
-
class VertexExecutable
{
public:
@@ -276,15 +288,6 @@
GLenum mTransformFeedbackBufferMode;
std::vector<LinkedVarying> mTransformFeedbackLinkedVaryings;
- struct Sampler
- {
- Sampler();
-
- bool active;
- GLint logicalTextureUnit;
- TextureType textureType;
- };
-
Sampler mSamplersPS[MAX_TEXTURE_IMAGE_UNITS];
Sampler mSamplersVS[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
GLuint mUsedVertexSamplerRange;