Commit d1746741 by Alexis Hetu Committed by Alexis Hétu

Uniform Blocks API

Implemented API level functionality for Uniform Blocks all the way down to the Program, without actually linking the uniforms, which will require more work in shaders to interpret these properly. Change-Id: I503a9bca63adb5160be7ff7597d3996d356fc1e3 Reviewed-on: https://swiftshader-review.googlesource.com/3015Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent 8f1b0ee5
...@@ -78,6 +78,7 @@ enum ...@@ -78,6 +78,7 @@ enum
MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS = MAX_UNIFORM_BLOCKS_COMPONENTS + 4 * FRAGMENT_UNIFORM_VECTORS, MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS = MAX_UNIFORM_BLOCKS_COMPONENTS + 4 * FRAGMENT_UNIFORM_VECTORS,
MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS = MAX_UNIFORM_BLOCKS_COMPONENTS + 4 * VERTEX_UNIFORM_VECTORS, MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS = MAX_UNIFORM_BLOCKS_COMPONENTS + 4 * VERTEX_UNIFORM_VECTORS,
MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS = 4, MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS = 4,
MAX_UNIFORM_BUFFER_BINDINGS = 36,
}; };
#endif // sw_Config_hpp #endif // sw_Config_hpp
...@@ -66,6 +66,26 @@ namespace es2 ...@@ -66,6 +66,26 @@ namespace es2
return size() * VariableRowCount(type); return size() * VariableRowCount(type);
} }
UniformBlock::UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize) :
name(name), elementIndex(elementIndex), dataSize(dataSize), psRegisterIndex(GL_INVALID_INDEX), vsRegisterIndex(GL_INVALID_INDEX)
{
}
bool UniformBlock::isArrayElement() const
{
return elementIndex != GL_INVALID_INDEX;
}
bool UniformBlock::isReferencedByVertexShader() const
{
return vsRegisterIndex != GL_INVALID_INDEX;
}
bool UniformBlock::isReferencedByFragmentShader() const
{
return psRegisterIndex != GL_INVALID_INDEX;
}
UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index) : name(name), element(element), index(index) UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index) : name(name), element(element), index(index)
{ {
} }
...@@ -82,6 +102,7 @@ namespace es2 ...@@ -82,6 +102,7 @@ namespace es2
infoLog = 0; infoLog = 0;
validated = false; validated = false;
resetUniformBlockBindings();
unlink(); unlink();
orphaned = false; orphaned = false;
...@@ -261,24 +282,20 @@ namespace es2 ...@@ -261,24 +282,20 @@ namespace es2
return TEXTURE_2D; return TEXTURE_2D;
} }
GLint Program::getUniformLocation(std::string name) GLint Program::getUniformLocation(const std::string &name) const
{ {
int subscript = 0; size_t subscript = GL_INVALID_INDEX;
std::string baseName = es2::ParseUniformName(name, &subscript);
// Strip any trailing array operator and retrieve the subscript
size_t open = name.find_last_of('[');
size_t close = name.find_last_of(']');
if(open != std::string::npos && close == name.length() - 1)
{
subscript = atoi(name.substr(open + 1).c_str());
name.erase(open);
}
unsigned int numUniforms = uniformIndex.size(); unsigned int numUniforms = uniformIndex.size();
for(unsigned int location = 0; location < numUniforms; location++) for(unsigned int location = 0; location < numUniforms; location++)
{ {
if(uniformIndex[location].name == name && const int index = uniformIndex[location].index;
uniformIndex[location].element == subscript) const bool isArray = uniforms[index]->isArray();
if(uniformIndex[location].name == baseName &&
((isArray && uniformIndex[location].element == subscript) ||
(subscript == GL_INVALID_INDEX)))
{ {
return location; return location;
} }
...@@ -287,6 +304,107 @@ namespace es2 ...@@ -287,6 +304,107 @@ namespace es2
return -1; return -1;
} }
GLuint Program::getUniformIndex(const std::string &name) const
{
size_t subscript = GL_INVALID_INDEX;
std::string baseName = es2::ParseUniformName(name, &subscript);
// The app is not allowed to specify array indices other than 0 for arrays of basic types
if(subscript != 0 && subscript != GL_INVALID_INDEX)
{
return GL_INVALID_INDEX;
}
unsigned int numUniforms = uniforms.size();
for(unsigned int index = 0; index < numUniforms; index++)
{
if(uniforms[index]->name == baseName)
{
if(uniforms[index]->isArray() || subscript == GL_INVALID_INDEX)
{
return index;
}
}
}
return GL_INVALID_INDEX;
}
void Program::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const
{
ASSERT(uniformBlockIndex < getActiveUniformBlockCount());
const UniformBlock &uniformBlock = *uniformBlocks[uniformBlockIndex];
switch(pname)
{
case GL_UNIFORM_BLOCK_DATA_SIZE:
*params = static_cast<GLint>(uniformBlock.dataSize);
break;
case GL_UNIFORM_BLOCK_NAME_LENGTH:
*params = static_cast<GLint>(uniformBlock.name.size() + 1 + (uniformBlock.isArrayElement() ? 3 : 0));
break;
case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
*params = static_cast<GLint>(uniformBlock.memberUniformIndexes.size());
break;
case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
{
for(unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
{
params[blockMemberIndex] = static_cast<GLint>(uniformBlock.memberUniformIndexes[blockMemberIndex]);
}
}
break;
case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
*params = static_cast<GLint>(uniformBlock.isReferencedByVertexShader());
break;
case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
*params = static_cast<GLint>(uniformBlock.isReferencedByFragmentShader());
break;
default: UNREACHABLE();
}
}
GLuint Program::getUniformBlockIndex(const std::string &name) const
{
size_t subscript = GL_INVALID_INDEX;
std::string baseName = es2::ParseUniformName(name, &subscript);
unsigned int numUniformBlocks = getActiveUniformBlockCount();
for(unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++)
{
const UniformBlock &uniformBlock = *uniformBlocks[blockIndex];
if(uniformBlock.name == baseName)
{
const bool arrayElementZero = (subscript == GL_INVALID_INDEX && uniformBlock.elementIndex == 0);
if(subscript == uniformBlock.elementIndex || arrayElementZero)
{
return blockIndex;
}
}
}
return GL_INVALID_INDEX;
}
void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
{
uniformBlockBindings[uniformBlockIndex] = uniformBlockBinding;
}
GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
{
return uniformBlockBindings[uniformBlockIndex];
}
void Program::resetUniformBlockBindings()
{
for(unsigned int blockId = 0; blockId < MAX_UNIFORM_BUFFER_BINDINGS; blockId++)
{
uniformBlockBindings[blockId] = 0;
}
}
bool Program::setUniformfv(GLint location, GLsizei count, const GLfloat *v, int numElements) bool Program::setUniformfv(GLint location, GLsizei count, const GLfloat *v, int numElements)
{ {
ASSERT(numElements >= 1 && numElements <= 4); ASSERT(numElements >= 1 && numElements <= 4);
...@@ -1046,6 +1164,8 @@ namespace es2 ...@@ -1046,6 +1164,8 @@ namespace es2
{ {
unlink(); unlink();
resetUniformBlockBindings();
if(!fragmentShader || !fragmentShader->isCompiled()) if(!fragmentShader || !fragmentShader->isCompiled())
{ {
return; return;
...@@ -1163,7 +1283,7 @@ namespace es2 ...@@ -1163,7 +1283,7 @@ namespace es2
return -1; return -1;
} }
bool Program::linkUniforms(Shader *shader) bool Program::linkUniforms(const Shader *shader)
{ {
const glsl::ActiveUniforms &activeUniforms = shader->activeUniforms; const glsl::ActiveUniforms &activeUniforms = shader->activeUniforms;
...@@ -2158,7 +2278,7 @@ namespace es2 ...@@ -2158,7 +2278,7 @@ namespace es2
linked = false; linked = false;
} }
bool Program::isLinked() bool Program::isLinked() const
{ {
return linked; return linked;
} }
...@@ -2380,6 +2500,63 @@ namespace es2 ...@@ -2380,6 +2500,63 @@ namespace es2
return maxLength; return maxLength;
} }
void Program::getActiveUniformBlockName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const
{
ASSERT(index < getActiveUniformBlockCount());
const UniformBlock &uniformBlock = *uniformBlocks[index];
if(bufSize > 0)
{
std::string string = uniformBlock.name;
if(uniformBlock.isArrayElement())
{
string += "[";
string += std::to_string(uniformBlock.elementIndex);
string += "]";
}
strncpy(name, string.c_str(), bufSize);
name[bufSize - 1] = '\0';
if(length)
{
*length = strlen(name);
}
}
}
GLint Program::getActiveUniformBlockCount() const
{
return uniformBlocks.size();
}
GLint Program::getActiveUniformBlockMaxLength() const
{
int maxLength = 0;
if(isLinked())
{
unsigned int numUniformBlocks = getActiveUniformBlockCount();
for(unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++)
{
const UniformBlock &uniformBlock = *uniformBlocks[uniformBlockIndex];
if(!uniformBlock.name.empty())
{
const int length = uniformBlock.name.length() + 1;
// Counting in "[0]".
const int arrayLength = (uniformBlock.isArrayElement() ? 3 : 0);
maxLength = std::max(length + arrayLength, maxLength);
}
}
}
return maxLength;
}
void Program::flagForDeletion() void Program::flagForDeletion()
{ {
orphaned = true; orphaned = true;
......
...@@ -54,6 +54,26 @@ namespace es2 ...@@ -54,6 +54,26 @@ namespace es2
short vsRegisterIndex; short vsRegisterIndex;
}; };
// Helper struct representing a single shader uniform block
struct UniformBlock
{
// use GL_INVALID_INDEX for non-array elements
UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize);
bool isArrayElement() const;
bool isReferencedByVertexShader() const;
bool isReferencedByFragmentShader() const;
const std::string name;
const unsigned int elementIndex;
const unsigned int dataSize;
std::vector<unsigned int> memberUniformIndexes;
unsigned int psRegisterIndex;
unsigned int vsRegisterIndex;
};
// Struct used for correlating uniforms/elements of uniform arrays to handles // Struct used for correlating uniforms/elements of uniform arrays to handles
struct UniformLocation struct UniformLocation
{ {
...@@ -85,7 +105,13 @@ namespace es2 ...@@ -85,7 +105,13 @@ namespace es2
GLint getSamplerMapping(sw::SamplerType type, unsigned int samplerIndex); GLint getSamplerMapping(sw::SamplerType type, unsigned int samplerIndex);
TextureType getSamplerTextureType(sw::SamplerType type, unsigned int samplerIndex); TextureType getSamplerTextureType(sw::SamplerType type, unsigned int samplerIndex);
GLint getUniformLocation(std::string name); GLuint getUniformIndex(const std::string &name) const;
GLuint getUniformBlockIndex(const std::string &name) const;
void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding);
GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const;
void getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const;
GLint getUniformLocation(const std::string &name) const;
bool setUniform1fv(GLint location, GLsizei count, const GLfloat *v); bool setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
bool setUniform2fv(GLint location, GLsizei count, const GLfloat *v); bool setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
bool setUniform3fv(GLint location, GLsizei count, const GLfloat *v); bool setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
...@@ -116,7 +142,7 @@ namespace es2 ...@@ -116,7 +142,7 @@ namespace es2
void applyUniforms(); void applyUniforms();
void link(); void link();
bool isLinked(); bool isLinked() const;
int getInfoLogLength() const; int getInfoLogLength() const;
void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog); void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog);
void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders); void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);
...@@ -129,6 +155,10 @@ namespace es2 ...@@ -129,6 +155,10 @@ namespace es2
GLint getActiveUniformCount() const; GLint getActiveUniformCount() const;
GLint getActiveUniformMaxLength() const; GLint getActiveUniformMaxLength() const;
void getActiveUniformBlockName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
GLint getActiveUniformBlockCount() const;
GLint getActiveUniformBlockMaxLength() const;
void addRef(); void addRef();
void release(); void release();
unsigned int getRefCount() const; unsigned int getRefCount() const;
...@@ -143,13 +173,14 @@ namespace es2 ...@@ -143,13 +173,14 @@ namespace es2
private: private:
void unlink(); void unlink();
void resetUniformBlockBindings();
bool linkVaryings(); bool linkVaryings();
bool linkAttributes(); bool linkAttributes();
int getAttributeBinding(const std::string &name); int getAttributeBinding(const std::string &name);
bool linkUniforms(Shader *shader); bool linkUniforms(const Shader *shader);
bool defineUniform(GLenum shader, GLenum type, GLenum precision, const std::string &_name, unsigned int arraySize, int registerIndex); bool defineUniform(GLenum shader, GLenum type, GLenum precision, const std::string &_name, unsigned int arraySize, int registerIndex);
bool applyUniform1bv(GLint location, GLsizei count, const GLboolean *v); bool applyUniform1bv(GLint location, GLsizei count, const GLboolean *v);
bool applyUniform2bv(GLint location, GLsizei count, const GLboolean *v); bool applyUniform2bv(GLint location, GLsizei count, const GLboolean *v);
...@@ -199,6 +230,8 @@ namespace es2 ...@@ -199,6 +230,8 @@ namespace es2
glsl::Attribute linkedAttribute[MAX_VERTEX_ATTRIBS]; glsl::Attribute linkedAttribute[MAX_VERTEX_ATTRIBS];
int attributeStream[MAX_VERTEX_ATTRIBS]; int attributeStream[MAX_VERTEX_ATTRIBS];
GLuint uniformBlockBindings[MAX_UNIFORM_BUFFER_BINDINGS];
struct Sampler struct Sampler
{ {
bool active; bool active;
...@@ -213,6 +246,8 @@ namespace es2 ...@@ -213,6 +246,8 @@ namespace es2
UniformArray uniforms; UniformArray uniforms;
typedef std::vector<UniformLocation> UniformIndex; typedef std::vector<UniformLocation> UniformIndex;
UniformIndex uniformIndex; UniformIndex uniformIndex;
typedef std::vector<UniformBlock*> UniformBlockArray;
UniformBlockArray uniformBlocks;
bool linked; bool linked;
bool orphaned; // Flag to indicate that the program can be deleted when no longer in use bool orphaned; // Flag to indicate that the program can be deleted when no longer in use
......
...@@ -408,7 +408,7 @@ VertexShader::~VertexShader() ...@@ -408,7 +408,7 @@ VertexShader::~VertexShader()
delete vertexShader; delete vertexShader;
} }
GLenum VertexShader::getType() GLenum VertexShader::getType() const
{ {
return GL_VERTEX_SHADER; return GL_VERTEX_SHADER;
} }
...@@ -461,7 +461,7 @@ FragmentShader::~FragmentShader() ...@@ -461,7 +461,7 @@ FragmentShader::~FragmentShader()
delete pixelShader; delete pixelShader;
} }
GLenum FragmentShader::getType() GLenum FragmentShader::getType() const
{ {
return GL_FRAGMENT_SHADER; return GL_FRAGMENT_SHADER;
} }
......
...@@ -44,7 +44,7 @@ public: ...@@ -44,7 +44,7 @@ public:
virtual ~Shader(); virtual ~Shader();
virtual GLenum getType() = 0; virtual GLenum getType() const = 0;
GLuint getName() const; GLuint getName() const;
void deleteSource(); void deleteSource();
...@@ -96,7 +96,7 @@ public: ...@@ -96,7 +96,7 @@ public:
~VertexShader(); ~VertexShader();
virtual GLenum getType(); virtual GLenum getType() const;
int getSemanticIndex(const std::string &attributeName); int getSemanticIndex(const std::string &attributeName);
virtual sw::Shader *getShader() const; virtual sw::Shader *getShader() const;
...@@ -116,7 +116,7 @@ public: ...@@ -116,7 +116,7 @@ public:
~FragmentShader(); ~FragmentShader();
virtual GLenum getType(); virtual GLenum getType() const;
virtual sw::Shader *getShader() const; virtual sw::Shader *getShader() const;
virtual sw::PixelShader *getPixelShader() const; virtual sw::PixelShader *getPixelShader() const;
......
...@@ -46,7 +46,7 @@ enum ...@@ -46,7 +46,7 @@ enum
IMPLEMENTATION_MAX_COLOR_ATTACHMENTS = MAX_COLOR_ATTACHMENTS, IMPLEMENTATION_MAX_COLOR_ATTACHMENTS = MAX_COLOR_ATTACHMENTS,
IMPLEMENTATION_MAX_DRAW_BUFFERS = 8, IMPLEMENTATION_MAX_DRAW_BUFFERS = 8,
IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS = MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS = MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS = 36, IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS = MAX_UNIFORM_BUFFER_BINDINGS,
IMPLEMENTATION_UNIFORM_BUFFER_OFFSET_ALIGNMENT = 1, IMPLEMENTATION_UNIFORM_BUFFER_OFFSET_ALIGNMENT = 1,
}; };
......
...@@ -3151,6 +3151,8 @@ void GetProgramiv(GLuint program, GLenum pname, GLint* params) ...@@ -3151,6 +3151,8 @@ void GetProgramiv(GLuint program, GLenum pname, GLint* params)
return error(GL_INVALID_VALUE); return error(GL_INVALID_VALUE);
} }
egl::GLint clientVersion = egl::getClientVersion();
switch(pname) switch(pname)
{ {
case GL_DELETE_STATUS: case GL_DELETE_STATUS:
...@@ -3180,6 +3182,20 @@ void GetProgramiv(GLuint program, GLenum pname, GLint* params) ...@@ -3180,6 +3182,20 @@ void GetProgramiv(GLuint program, GLenum pname, GLint* params)
case GL_ACTIVE_UNIFORM_MAX_LENGTH: case GL_ACTIVE_UNIFORM_MAX_LENGTH:
*params = programObject->getActiveUniformMaxLength(); *params = programObject->getActiveUniformMaxLength();
return; return;
case GL_ACTIVE_UNIFORM_BLOCKS:
if(clientVersion >= 3)
{
*params = programObject->getActiveUniformBlockCount();
return;
}
else return error(GL_INVALID_ENUM);
case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
if(clientVersion >= 3)
{
*params = programObject->getActiveUniformBlockMaxLength();
return;
}
else return error(GL_INVALID_ENUM);
default: default:
return error(GL_INVALID_ENUM); return error(GL_INVALID_ENUM);
} }
......
...@@ -2672,6 +2672,11 @@ GL_APICALL void GL_APIENTRY glGetUniformIndices(GLuint program, GLsizei uniformC ...@@ -2672,6 +2672,11 @@ GL_APICALL void GL_APIENTRY glGetUniformIndices(GLuint program, GLsizei uniformC
TRACE("(GLuint program = %d, GLsizei uniformCount = %d, const GLchar *const*uniformNames = %p, GLuint *uniformIndices = %p)", TRACE("(GLuint program = %d, GLsizei uniformCount = %d, const GLchar *const*uniformNames = %p, GLuint *uniformIndices = %p)",
program, uniformCount, uniformNames, uniformIndices); program, uniformCount, uniformNames, uniformIndices);
if (uniformCount < 0)
{
return error(GL_INVALID_VALUE);
}
es2::Context *context = es2::getContext(); es2::Context *context = es2::getContext();
if(context) if(context)
...@@ -2682,9 +2687,22 @@ GL_APICALL void GL_APIENTRY glGetUniformIndices(GLuint program, GLsizei uniformC ...@@ -2682,9 +2687,22 @@ GL_APICALL void GL_APIENTRY glGetUniformIndices(GLuint program, GLsizei uniformC
{ {
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
}
UNIMPLEMENTED(); if(!programObject->isLinked())
{
for(int uniformId = 0; uniformId < uniformCount; uniformId++)
{
uniformIndices[uniformId] = GL_INVALID_INDEX;
}
}
else
{
for(int uniformId = 0; uniformId < uniformCount; uniformId++)
{
uniformIndices[uniformId] = programObject->getUniformIndex(uniformNames[uniformId]);
}
}
}
} }
GL_APICALL void GL_APIENTRY glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params) GL_APICALL void GL_APIENTRY glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params)
...@@ -2737,10 +2755,9 @@ GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex(GLuint program, const GLcha ...@@ -2737,10 +2755,9 @@ GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex(GLuint program, const GLcha
{ {
return error(GL_INVALID_OPERATION, GL_INVALID_INDEX); return error(GL_INVALID_OPERATION, GL_INVALID_INDEX);
} }
}
UNIMPLEMENTED(); return programObject->getUniformBlockIndex(uniformBlockName);
return GL_INVALID_INDEX; }
} }
GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params) GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params)
...@@ -2748,20 +2765,6 @@ GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uni ...@@ -2748,20 +2765,6 @@ GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uni
TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLenum pname = 0x%X, GLint *params = %p)", TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLenum pname = 0x%X, GLint *params = %p)",
program, uniformBlockIndex, pname, params); program, uniformBlockIndex, pname, params);
switch(pname)
{
case GL_UNIFORM_BLOCK_BINDING:
case GL_UNIFORM_BLOCK_DATA_SIZE:
case GL_UNIFORM_BLOCK_NAME_LENGTH:
case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
break;
default:
return error(GL_INVALID_ENUM);
}
es2::Context *context = es2::getContext(); es2::Context *context = es2::getContext();
if(context) if(context)
...@@ -2772,9 +2775,24 @@ GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uni ...@@ -2772,9 +2775,24 @@ GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uni
{ {
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
}
UNIMPLEMENTED(); switch(pname)
{
case GL_UNIFORM_BLOCK_BINDING:
*params = static_cast<GLint>(program->getUniformBlockBinding(uniformBlockIndex));
break;
case GL_UNIFORM_BLOCK_DATA_SIZE:
case GL_UNIFORM_BLOCK_NAME_LENGTH:
case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
program->getActiveUniformBlockiv(uniformBlockIndex, pname, params);
break;
default:
return error(GL_INVALID_ENUM);
}
}
} }
GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName)
...@@ -2792,9 +2810,9 @@ GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName(GLuint program, GLuint u ...@@ -2792,9 +2810,9 @@ GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName(GLuint program, GLuint u
{ {
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
}
UNIMPLEMENTED(); programObject->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName);
}
} }
GL_APICALL void GL_APIENTRY glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) GL_APICALL void GL_APIENTRY glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
...@@ -2802,6 +2820,11 @@ GL_APICALL void GL_APIENTRY glUniformBlockBinding(GLuint program, GLuint uniform ...@@ -2802,6 +2820,11 @@ GL_APICALL void GL_APIENTRY glUniformBlockBinding(GLuint program, GLuint uniform
TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLuint uniformBlockBinding = %d)", TRACE("(GLuint program = %d, GLuint uniformBlockIndex = %d, GLuint uniformBlockBinding = %d)",
program, uniformBlockIndex, uniformBlockBinding); program, uniformBlockIndex, uniformBlockBinding);
if(uniformBlockBinding >= es2::IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS)
{
return error(GL_INVALID_VALUE);
}
es2::Context *context = es2::getContext(); es2::Context *context = es2::getContext();
if(context) if(context)
...@@ -2812,9 +2835,9 @@ GL_APICALL void GL_APIENTRY glUniformBlockBinding(GLuint program, GLuint uniform ...@@ -2812,9 +2835,9 @@ GL_APICALL void GL_APIENTRY glUniformBlockBinding(GLuint program, GLuint uniform
{ {
return error(GL_INVALID_VALUE); return error(GL_INVALID_VALUE);
} }
}
UNIMPLEMENTED(); programObject->bindUniformBlock(uniformBlockIndex, uniformBlockIndex);
}
} }
GL_APICALL void GL_APIENTRY glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount) GL_APICALL void GL_APIENTRY glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
......
...@@ -487,6 +487,37 @@ namespace es2 ...@@ -487,6 +487,37 @@ namespace es2
return false; return false;
} }
std::string ParseUniformName(const std::string &name, size_t *outSubscript)
{
// Strip any trailing array operator and retrieve the subscript
size_t open = name.find_last_of('[');
size_t close = name.find_last_of(']');
bool hasIndex = (open != std::string::npos) && (close == name.length() - 1);
if(!hasIndex)
{
if(outSubscript)
{
*outSubscript = GL_INVALID_INDEX;
}
return name;
}
if(outSubscript)
{
int index = atoi(name.substr(open + 1).c_str());
if(index >= 0)
{
*outSubscript = index;
}
else
{
*outSubscript = GL_INVALID_INDEX;
}
}
return name.substr(0, open);
}
} }
namespace es2sw namespace es2sw
......
...@@ -48,6 +48,10 @@ namespace es2 ...@@ -48,6 +48,10 @@ namespace es2
bool IsColorRenderable(GLenum internalformat); bool IsColorRenderable(GLenum internalformat);
bool IsDepthRenderable(GLenum internalformat); bool IsDepthRenderable(GLenum internalformat);
bool IsStencilRenderable(GLenum internalformat); bool IsStencilRenderable(GLenum internalformat);
// Parse the base uniform name and array index. Returns the base name of the uniform. outSubscript is
// set to GL_INVALID_INDEX if the provided name is not an array or the array index is invalid.
std::string ParseUniformName(const std::string &name, size_t *outSubscript);
} }
namespace es2sw namespace es2sw
......
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