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
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 @@ GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerInd
switch (type)
{
case SAMPLER_PIXEL:
ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
ASSERT(samplerIndex < ArraySize(mSamplersPS));
if (mSamplersPS[samplerIndex].active)
{
......@@ -361,7 +391,7 @@ GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerInd
}
break;
case SAMPLER_VERTEX:
ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
ASSERT(samplerIndex < ArraySize(mSamplersVS));
if (mSamplersVS[samplerIndex].active)
{
......@@ -386,11 +416,11 @@ TextureType ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int
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,56 +1929,25 @@ bool ProgramBinary::linkUniforms(InfoLog &infoLog, const std::vector<sh::Uniform
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]);
}
initializeUniformStorage();
return true;
}
TextureType ProgramBinary::getTextureType(GLenum samplerType, InfoLog &infoLog)
{
switch(samplerType)
if (!indexUniforms(infoLog))
{
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 false;
}
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())
{
......@@ -1970,10 +1969,8 @@ bool ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant, In
fieldRegisterIndex, field.elementIndex);
fieldUniform.fields = field.fields;
if (!defineUniform(shader, fieldUniform, infoLog))
{
return false;
}
defineUniform(shader, fieldUniform);
}
}
}
......@@ -1989,118 +1986,131 @@ bool ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant, In
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();
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);
}
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;
GLint location = getUniformLocation(constant.name);
bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog)
{
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
{
uniform = mUniforms[mUniformIndex[location].index];
}
else
if (uniform.vsRegisterIndex != GL_INVALID_INDEX)
{
uniform = new LinkedUniform(constant.type, constant.precision, constant.name, constant.arraySize,
-1, sh::BlockMemberInfo::getDefaultBlockInfo());
uniform->registerElement = constant.elementIndex;
}
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;
}
if (!uniform)
{
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;
}
}
if (shader == GL_FRAGMENT_SHADER)
if (uniform.psRegisterIndex != GL_INVALID_INDEX)
{
uniform->psRegisterIndex = constant.registerIndex;
}
else if (shader == GL_VERTEX_SHADER)
{
uniform->vsRegisterIndex = constant.registerIndex;
}
else UNREACHABLE();
if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS,
&mUsedPixelSamplerRange, MAX_TEXTURE_IMAGE_UNITS))
{
infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).",
MAX_TEXTURE_IMAGE_UNITS);
return false;
}
if (location >= 0)
{
return uniform->type == constant.type;
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;
}
}
mUniforms.push_back(uniform);
unsigned int uniformIndex = mUniforms.size() - 1;
return true;
}
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 (constant.registerIndex + uniform->registerCount > mRenderer->getReservedVertexUniformVectors() + mRenderer->getMaxVertexUniformVectors())
if (IsSampler(uniform.type))
{
infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", mRenderer->getMaxVertexUniformVectors());
return false;
if (!indexSamplerUniform(uniform, infoLog))
{
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;
}
}
else UNREACHABLE();
samplerIndex++;
} while (samplerIndex < startSamplerIndex + samplerCount);
return true;
}
......@@ -2538,6 +2548,19 @@ LinkedUniform *ProgramBinary::getUniformByLocation(GLint location) const
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()
......
......@@ -146,6 +146,7 @@ class ProgramBinary : public RefCountObject
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 @@ class ProgramBinary : public RefCountObject
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 @@ 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 &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 @@ class ProgramBinary : public RefCountObject
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 @@ class ProgramBinary : public RefCountObject
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;
......
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