OSDN Git Service

Uniform Blocks API
authorAlexis Hetu <sugoi@google.com>
Thu, 30 Apr 2015 19:48:23 +0000 (15:48 -0400)
committerAlexis Hétu <sugoi@google.com>
Tue, 9 Jun 2015 13:56:25 +0000 (13:56 +0000)
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/3015
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
src/Main/Config.hpp
src/OpenGL/libGLESv2/Program.cpp
src/OpenGL/libGLESv2/Program.h
src/OpenGL/libGLESv2/Shader.cpp
src/OpenGL/libGLESv2/Shader.h
src/OpenGL/libGLESv2/Texture.h
src/OpenGL/libGLESv2/libGLESv2.cpp
src/OpenGL/libGLESv2/libGLESv3.cpp
src/OpenGL/libGLESv2/utilities.cpp
src/OpenGL/libGLESv2/utilities.h

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