Commit 66d43d24 by Jamie Madill

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/207252Tested-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarNicolas Capens <capn@chromium.org>
parent cd68fe79
...@@ -37,6 +37,36 @@ namespace gl ...@@ -37,6 +37,36 @@ namespace gl
namespace 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 ParseAndStripArrayIndex(std::string* name)
{ {
unsigned int subscript = GL_INVALID_INDEX; unsigned int subscript = GL_INVALID_INDEX;
...@@ -353,7 +383,7 @@ GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerInd ...@@ -353,7 +383,7 @@ GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerInd
switch (type) switch (type)
{ {
case SAMPLER_PIXEL: case SAMPLER_PIXEL:
ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0])); ASSERT(samplerIndex < ArraySize(mSamplersPS));
if (mSamplersPS[samplerIndex].active) if (mSamplersPS[samplerIndex].active)
{ {
...@@ -361,7 +391,7 @@ GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerInd ...@@ -361,7 +391,7 @@ GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerInd
} }
break; break;
case SAMPLER_VERTEX: case SAMPLER_VERTEX:
ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0])); ASSERT(samplerIndex < ArraySize(mSamplersVS));
if (mSamplersVS[samplerIndex].active) if (mSamplersVS[samplerIndex].active)
{ {
...@@ -386,11 +416,11 @@ TextureType ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int ...@@ -386,11 +416,11 @@ TextureType ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int
switch (type) switch (type)
{ {
case SAMPLER_PIXEL: case SAMPLER_PIXEL:
ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0])); ASSERT(samplerIndex < ArraySize(mSamplersPS));
ASSERT(mSamplersPS[samplerIndex].active); ASSERT(mSamplersPS[samplerIndex].active);
return mSamplersPS[samplerIndex].textureType; return mSamplersPS[samplerIndex].textureType;
case SAMPLER_VERTEX: case SAMPLER_VERTEX:
ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0])); ASSERT(samplerIndex < ArraySize(mSamplersVS));
ASSERT(mSamplersVS[samplerIndex].active); ASSERT(mSamplersVS[samplerIndex].active);
return mSamplersVS[samplerIndex].textureType; return mSamplersVS[samplerIndex].textureType;
default: UNREACHABLE(); default: UNREACHABLE();
...@@ -1899,56 +1929,25 @@ bool ProgramBinary::linkUniforms(InfoLog &infoLog, const std::vector<sh::Uniform ...@@ -1899,56 +1929,25 @@ bool ProgramBinary::linkUniforms(InfoLog &infoLog, const std::vector<sh::Uniform
for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++) for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++)
{ {
if (!defineUniform(GL_VERTEX_SHADER, vertexUniforms[uniformIndex], infoLog)) defineUniform(GL_VERTEX_SHADER, vertexUniforms[uniformIndex]);
{
return false;
}
} }
for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++) for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++)
{ {
if (!defineUniform(GL_FRAGMENT_SHADER, fragmentUniforms[uniformIndex], infoLog)) defineUniform(GL_FRAGMENT_SHADER, fragmentUniforms[uniformIndex]);
{
return false;
}
} }
initializeUniformStorage(); if (!indexUniforms(infoLog))
return true;
}
TextureType ProgramBinary::getTextureType(GLenum samplerType, InfoLog &infoLog)
{
switch(samplerType)
{ {
case GL_SAMPLER_2D: return false;
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; initializeUniformStorage();
return true;
} }
bool ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog) void ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant)
{ {
if (constant.isStruct()) if (constant.isStruct())
{ {
...@@ -1970,10 +1969,8 @@ bool ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant, In ...@@ -1970,10 +1969,8 @@ bool ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant, In
fieldRegisterIndex, field.elementIndex); fieldRegisterIndex, field.elementIndex);
fieldUniform.fields = field.fields; fieldUniform.fields = field.fields;
if (!defineUniform(shader, fieldUniform, infoLog))
{ defineUniform(shader, fieldUniform);
return false;
}
} }
} }
} }
...@@ -1989,118 +1986,131 @@ bool ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant, In ...@@ -1989,118 +1986,131 @@ bool ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant, In
fieldUniform.fields = field.fields; fieldUniform.fields = field.fields;
if (!defineUniform(shader, fieldUniform, infoLog)) defineUniform(shader, fieldUniform);
{
return false;
}
} }
} }
return true;
} }
else // Not a struct
if (IsSampler(constant.type))
{ {
unsigned int samplerIndex = constant.registerIndex; LinkedUniform *linkedUniform = getUniformByName(constant.name);
do if (!linkedUniform)
{ {
if (shader == GL_VERTEX_SHADER) linkedUniform = new LinkedUniform(constant.type, constant.precision, constant.name, constant.arraySize,
{ -1, sh::BlockMemberInfo::getDefaultBlockInfo());
if (samplerIndex < mRenderer->getMaxVertexTextureImageUnits()) ASSERT(linkedUniform);
{ linkedUniform->registerElement = constant.elementIndex;
mSamplersVS[samplerIndex].active = true; mUniforms.push_back(linkedUniform);
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++; if (shader == GL_FRAGMENT_SHADER)
{
linkedUniform->psRegisterIndex = constant.registerIndex;
}
else if (shader == GL_VERTEX_SHADER)
{
linkedUniform->vsRegisterIndex = constant.registerIndex;
} }
while (samplerIndex < constant.registerIndex + constant.arraySize); else UNREACHABLE();
} }
}
LinkedUniform *uniform = NULL; bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog)
GLint location = getUniformLocation(constant.name); {
ASSERT(IsSampler(uniform.type));
ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX);
if (location >= 0) // Previously defined, type and precision must match if (uniform.vsRegisterIndex != GL_INVALID_INDEX)
{
uniform = mUniforms[mUniformIndex[location].index];
}
else
{ {
uniform = new LinkedUniform(constant.type, constant.precision, constant.name, constant.arraySize, if (!assignSamplers(uniform.vsRegisterIndex, uniform.type, uniform.arraySize, mSamplersVS,
-1, sh::BlockMemberInfo::getDefaultBlockInfo()); &mUsedVertexSamplerRange, mRenderer->getMaxVertexTextureImageUnits()))
uniform->registerElement = constant.elementIndex; {
} infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).",
mRenderer->getMaxVertexTextureImageUnits());
return false;
}
if (!uniform) unsigned int maxVertexVectors = mRenderer->getReservedVertexUniformVectors() +
{ mRenderer->getMaxVertexUniformVectors();
return false; if (uniform.vsRegisterIndex + uniform.registerCount > maxVertexVectors)
{
infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)",
mRenderer->getMaxVertexUniformVectors());
return false;
}
} }
if (shader == GL_FRAGMENT_SHADER) if (uniform.psRegisterIndex != GL_INVALID_INDEX)
{ {
uniform->psRegisterIndex = constant.registerIndex; if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS,
} &mUsedPixelSamplerRange, MAX_TEXTURE_IMAGE_UNITS))
else if (shader == GL_VERTEX_SHADER) {
{ infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).",
uniform->vsRegisterIndex = constant.registerIndex; MAX_TEXTURE_IMAGE_UNITS);
} return false;
else UNREACHABLE(); }
if (location >= 0) unsigned int maxFragmentVectors = mRenderer->getReservedFragmentUniformVectors() +
{ mRenderer->getMaxFragmentUniformVectors();
return uniform->type == constant.type; if (uniform.psRegisterIndex + uniform.registerCount > maxFragmentVectors)
{
infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)",
mRenderer->getMaxFragmentUniformVectors());
return false;
}
} }
mUniforms.push_back(uniform); return true;
unsigned int uniformIndex = mUniforms.size() - 1; }
for (unsigned int arrayElementIndex = 0; arrayElementIndex < uniform->elementCount(); arrayElementIndex++) bool ProgramBinary::indexUniforms(InfoLog &infoLog)
{
for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
{ {
mUniformIndex.push_back(VariableLocation(uniform->name, arrayElementIndex, uniformIndex)); const LinkedUniform &uniform = *mUniforms[uniformIndex];
}
if (shader == GL_VERTEX_SHADER) if (IsSampler(uniform.type))
{
if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedVertexUniformVectors() + mRenderer->getMaxVertexUniformVectors())
{ {
infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", mRenderer->getMaxVertexUniformVectors()); if (!indexSamplerUniform(uniform, infoLog))
return false; {
return false;
}
}
for (unsigned int arrayElementIndex = 0; arrayElementIndex < uniform.elementCount(); arrayElementIndex++)
{
mUniformIndex.push_back(VariableLocation(uniform.name, arrayElementIndex, uniformIndex));
} }
} }
else if (shader == GL_FRAGMENT_SHADER)
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 (constant.registerIndex + uniform->registerCount > mRenderer->getReservedFragmentUniformVectors() + mRenderer->getMaxFragmentUniformVectors()) if (samplerIndex < limit)
{
outArray[samplerIndex].active = true;
outArray[samplerIndex].textureType = GetTextureType(samplerType);
outArray[samplerIndex].logicalTextureUnit = 0;
*usedRange = std::max(samplerIndex + 1, *usedRange);
}
else
{ {
infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", mRenderer->getMaxFragmentUniformVectors());
return false; return false;
} }
}
else UNREACHABLE(); samplerIndex++;
} while (samplerIndex < startSamplerIndex + samplerCount);
return true; return true;
} }
...@@ -2538,6 +2548,19 @@ LinkedUniform *ProgramBinary::getUniformByLocation(GLint location) const ...@@ -2538,6 +2548,19 @@ LinkedUniform *ProgramBinary::getUniformByLocation(GLint location) const
return mUniforms[mUniformIndex[location].index]; 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 void ProgramBinary::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const
{ {
ASSERT(uniformBlockIndex < mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount() ASSERT(uniformBlockIndex < mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount()
......
...@@ -146,6 +146,7 @@ class ProgramBinary : public RefCountObject ...@@ -146,6 +146,7 @@ class ProgramBinary : public RefCountObject
GLint getActiveUniformi(GLuint index, GLenum pname) const; GLint getActiveUniformi(GLuint index, GLenum pname) const;
bool isValidUniformLocation(GLint location) const; bool isValidUniformLocation(GLint location) const;
LinkedUniform *getUniformByLocation(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 getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const;
void getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const; void getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const;
...@@ -177,6 +178,15 @@ class ProgramBinary : public RefCountObject ...@@ -177,6 +178,15 @@ class ProgramBinary : public RefCountObject
private: private:
DISALLOW_COPY_AND_ASSIGN(ProgramBinary); DISALLOW_COPY_AND_ASSIGN(ProgramBinary);
struct Sampler
{
Sampler();
bool active;
GLint logicalTextureUnit;
TextureType textureType;
};
void reset(); void reset();
bool linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShader, VertexShader *vertexShader); bool linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShader, VertexShader *vertexShader);
...@@ -192,7 +202,11 @@ class ProgramBinary : public RefCountObject ...@@ -192,7 +202,11 @@ class ProgramBinary : public RefCountObject
bool linkValidateVariables(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying); 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 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 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 areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock);
bool linkUniformBlocks(InfoLog &infoLog, const VertexShader &vertexShader, const FragmentShader &fragmentShader); bool linkUniformBlocks(InfoLog &infoLog, const VertexShader &vertexShader, const FragmentShader &fragmentShader);
bool gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings, bool gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings,
...@@ -214,8 +228,6 @@ class ProgramBinary : public RefCountObject ...@@ -214,8 +228,6 @@ class ProgramBinary : public RefCountObject
template <typename T> template <typename T>
bool getUniformv(GLint location, GLsizei *bufSize, T *params, GLenum uniformType); bool getUniformv(GLint location, GLsizei *bufSize, T *params, GLenum uniformType);
static TextureType getTextureType(GLenum samplerType, InfoLog &infoLog);
class VertexExecutable class VertexExecutable
{ {
public: public:
...@@ -276,15 +288,6 @@ class ProgramBinary : public RefCountObject ...@@ -276,15 +288,6 @@ class ProgramBinary : public RefCountObject
GLenum mTransformFeedbackBufferMode; GLenum mTransformFeedbackBufferMode;
std::vector<LinkedVarying> mTransformFeedbackLinkedVaryings; std::vector<LinkedVarying> mTransformFeedbackLinkedVaryings;
struct Sampler
{
Sampler();
bool active;
GLint logicalTextureUnit;
TextureType textureType;
};
Sampler mSamplersPS[MAX_TEXTURE_IMAGE_UNITS]; Sampler mSamplersPS[MAX_TEXTURE_IMAGE_UNITS];
Sampler mSamplersVS[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; Sampler mSamplersVS[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS];
GLuint mUsedVertexSamplerRange; GLuint mUsedVertexSamplerRange;
......
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