Add support for OpenGL ES 3.2 features.
authorDaniel Andrade Groppe <daniel.andrade@mobica.com>
Wed, 27 Jan 2016 21:57:11 +0000 (15:57 -0600)
committerDaniel Andrade Groppe <daniel.andrade@mobica.com>
Wed, 27 Jan 2016 21:57:11 +0000 (15:57 -0600)
Generate version-appropriate shaders.
Add tests for functions introduced in 3.2:
- VertexAttribFormat
- VertexAttribIFormat
- DrawElementsBaseVertex
- DrawElementsInstancedBaseVertex
- DrawRangeElementsBaseVertex

Change-Id: Ibe32d0d7a5bd0e7692bb14271eb5af9599f21bad
Signed-off-by: Daniel Andrade Groppe <daniel.andrade@mobica.com>
modules/gles31/functional/es31fNegativeVertexArrayApiTests.cpp

index a7f50c2..8fa3fc6 100644 (file)
@@ -1,4 +1,4 @@
-/*-------------------------------------------------------------------------
+/*-------------------------------------------------------------------------
  * drawElements Quality Program OpenGL ES 3.1 Module
  * -------------------------------------------------
  *
  *//*--------------------------------------------------------------------*/
 
 #include "es31fNegativeVertexArrayApiTests.hpp"
-
 #include "gluCallLogWrapper.hpp"
 #include "gluContextInfo.hpp"
 #include "gluShaderProgram.hpp"
-
 #include "glwDefs.hpp"
 #include "glwEnums.hpp"
+#include "tcuStringTemplate.hpp"
 
 namespace deqp
 {
+
+using std::string;
+using std::map;
+
 namespace gles31
 {
 namespace Functional
@@ -43,13 +46,13 @@ using tcu::TestLog;
 using glu::CallLogWrapper;
 using namespace glw;
 
-static const char* vertexShaderSource          =       "#version 300 es\n"
+static const char* vertexShaderSource          =       "${GLSL_VERSION_STRING}\n"
                                                                                                "void main (void)\n"
                                                                                                "{\n"
                                                                                                "       gl_Position = vec4(0.0);\n"
                                                                                                "}\n\0";
 
-static const char* fragmentShaderSource                =       "#version 300 es\n"
+static const char* fragmentShaderSource                =       "${GLSL_VERSION_STRING}\n"
                                                                                                "layout(location = 0) out mediump vec4 fragColor;"
                                                                                                "void main (void)\n"
                                                                                                "{\n"
@@ -210,10 +213,121 @@ void vertex_attrib_i_pointer (NegativeTestContext& ctx)
        ctx.endSection();
 }
 
+void vertex_attrib_format (NegativeTestContext& ctx)
+{
+       int             maxVertexAttribs                                = ctx.getInteger(GL_MAX_VERTEX_ATTRIBS);
+       int             maxVertexAttribRelativeOffset   = ctx.getInteger(GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET);
+       GLuint  vao                                                             = 0;
+
+       ctx.beginSection("GL_INVALID_VALUE is generated if attribindex is greater than or equal to the value of MAX_VERTEX_ATTRIBS.");
+       ctx.glGenVertexArrays(1, &vao);
+       ctx.glBindVertexArray(vao);
+       ctx.glBindBuffer(GL_ARRAY_BUFFER, 0);
+       ctx.glVertexAttribFormat(maxVertexAttribs, 4, GL_FLOAT, GL_FALSE, maxVertexAttribRelativeOffset);
+       ctx.expectError(GL_INVALID_VALUE);
+       ctx.endSection();
+
+       ctx.beginSection("GL_INVALID_VALUE is generated if size is not one of 1, 2, 3, 4.");
+       ctx.glGenVertexArrays(1, &vao);
+       ctx.glBindVertexArray(vao);
+       ctx.glBindBuffer(GL_ARRAY_BUFFER, 0);
+       ctx.glVertexAttribFormat(1, 0, GL_FLOAT, GL_FALSE, maxVertexAttribRelativeOffset);
+       ctx.expectError(GL_INVALID_VALUE);
+       ctx.endSection();
+
+       ctx.beginSection("GL_INVALID_ENUM is generated if type is not one of the parameter token names allowed.");
+       ctx.glGenVertexArrays(1, &vao);
+       ctx.glBindVertexArray(vao);
+       ctx.glBindBuffer(GL_ARRAY_BUFFER, 0);
+       ctx.glVertexAttribFormat(1, 4, 1, GL_FALSE, 0);
+       ctx.expectError(GL_INVALID_ENUM);
+       ctx.endSection();
+
+       ctx.beginSection("GL_INVALID_OPERATION is generated if type is not a token name allowed.");
+       ctx.glGenVertexArrays(1, &vao);
+       ctx.glBindVertexArray(0);
+       ctx.glBindBuffer(GL_ARRAY_BUFFER, 0);
+       ctx.glVertexAttribFormat(1, 4, GL_FLOAT, GL_FALSE, 0);
+       ctx.expectError(GL_INVALID_OPERATION);
+       ctx.endSection();
+
+       ctx.beginSection("GL_INVALID_OPERATION is generated if type is GL_INT_2_10_10_10_REV and size is not 4.");
+       ctx.glGenVertexArrays(1, &vao);
+       ctx.glBindVertexArray(vao);
+       ctx.glBindBuffer(GL_ARRAY_BUFFER, 0);
+       ctx.glVertexAttribFormat(1, 3, GL_INT_2_10_10_10_REV, GL_FALSE, 0);
+       ctx.expectError(GL_INVALID_OPERATION);
+       ctx.endSection();
+
+       ctx.beginSection("GL_INVALID_OPERATION is generated if type is GL_UNSIGNED_INT_2_10_10_10_REV and size is not 4.");
+       ctx.glGenVertexArrays(1, &vao);
+       ctx.glBindVertexArray(vao);
+       ctx.glBindBuffer(GL_ARRAY_BUFFER, 0);
+       ctx.glVertexAttribFormat(1, 3, GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 0);
+       ctx.expectError(GL_INVALID_OPERATION);
+       ctx.endSection();
+
+       ctx.beginSection("GL_INVALID_VALUE is generated if relativeoffset is larger than the value of GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET.");
+       ctx.glGenVertexArrays(1, &vao);
+       ctx.glBindVertexArray(vao);
+       ctx.glBindBuffer(GL_ARRAY_BUFFER, 0);
+       ctx.glVertexAttribFormat(1, 4, GL_FLOAT, GL_FALSE, maxVertexAttribRelativeOffset + 1);
+       ctx.expectError(GL_INVALID_VALUE);
+       ctx.endSection();
+}
+
+void vertex_attrib_i_format (NegativeTestContext& ctx)
+{
+       int             maxVertexAttribs                                = ctx.getInteger(GL_MAX_VERTEX_ATTRIBS);
+       int             maxVertexAttribRelativeOffset   = ctx.getInteger(GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET);
+       GLuint  vao                                                             = 0;
+
+       ctx.beginSection("GL_INVALID_VALUE is generated if attribindex is greater than or equal to the value of GL_MAX_VERTEX_ATTRIBS.");
+       ctx.glGenVertexArrays(1, &vao);
+       ctx.glBindVertexArray(vao);
+       ctx.glBindBuffer(GL_ARRAY_BUFFER, 0);
+       ctx.glVertexAttribIFormat(maxVertexAttribs, 4, GL_INT, 0);
+       ctx.expectError(GL_INVALID_VALUE);
+       ctx.endSection();
+
+       ctx.beginSection("GL_INVALID_VALUE is generated if size is not one the values 1, 2, 3, 4.");
+       ctx.glGenVertexArrays(1, &vao);
+       ctx.glBindVertexArray(vao);
+       ctx.glBindBuffer(GL_ARRAY_BUFFER, 0);
+       ctx.glVertexAttribIFormat(1, 0, GL_INT, 0);
+       ctx.expectError(GL_INVALID_VALUE);
+       ctx.endSection();
+
+       ctx.beginSection("GL_INVALID_ENUM is generated if type is not one of the parameter token names allowed.");
+       ctx.glGenVertexArrays(1, &vao);
+       ctx.glBindVertexArray(vao);
+       ctx.glBindBuffer(GL_ARRAY_BUFFER, 0);
+       ctx.glVertexAttribIFormat(1, 4, GL_FLOAT, 0);
+       ctx.expectError(GL_INVALID_ENUM);
+       ctx.endSection();
+
+       ctx.beginSection("GL_INVALID_OPERATION is generated if type is not a token name allowed.");
+       ctx.glGenVertexArrays(1, &vao);
+       ctx.glBindVertexArray(0);
+       ctx.glBindBuffer(GL_ARRAY_BUFFER, 0);
+       ctx.glVertexAttribIFormat(1, 4, GL_INT, 0);
+       ctx.expectError(GL_INVALID_OPERATION);
+       ctx.endSection();
+
+       ctx.beginSection("GL_INVALID_VALUE is generated if relativeoffset is larger than the value of GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET.");
+       ctx.glGenVertexArrays(1, &vao);
+       ctx.glBindVertexArray(vao);
+       ctx.glBindBuffer(GL_ARRAY_BUFFER, 0);
+       ctx.glVertexAttribIFormat(1, 4, GL_INT, maxVertexAttribRelativeOffset + 1);
+       ctx.expectError(GL_INVALID_VALUE);
+       ctx.endSection();
+}
+
 void enable_vertex_attrib_array (NegativeTestContext& ctx)
 {
-       ctx.beginSection("GL_INVALID_VALUE is generated if index is greater than or equal to GL_MAX_VERTEX_ATTRIBS.");
        int maxVertexAttribs = ctx.getInteger(GL_MAX_VERTEX_ATTRIBS);
+
+       ctx.beginSection("GL_INVALID_VALUE is generated if index is greater than or equal to GL_MAX_VERTEX_ATTRIBS.");
        ctx.glEnableVertexAttribArray(maxVertexAttribs);
        ctx.expectError(GL_INVALID_VALUE);
        ctx.endSection();
@@ -221,8 +335,9 @@ void enable_vertex_attrib_array (NegativeTestContext& ctx)
 
 void disable_vertex_attrib_array (NegativeTestContext& ctx)
 {
-       ctx.beginSection("GL_INVALID_VALUE is generated if index is greater than or equal to GL_MAX_VERTEX_ATTRIBS.");
        int maxVertexAttribs = ctx.getInteger(GL_MAX_VERTEX_ATTRIBS);
+
+       ctx.beginSection("GL_INVALID_VALUE is generated if index is greater than or equal to GL_MAX_VERTEX_ATTRIBS.");
        ctx.glDisableVertexAttribArray(maxVertexAttribs);
        ctx.expectError(GL_INVALID_VALUE);
        ctx.endSection();
@@ -230,8 +345,9 @@ void disable_vertex_attrib_array (NegativeTestContext& ctx)
 
 void gen_vertex_arrays (NegativeTestContext& ctx)
 {
-       ctx.beginSection("GL_INVALID_VALUE is generated if n is negative.");
        GLuint arrays = 0;
+
+       ctx.beginSection("GL_INVALID_VALUE is generated if n is negative.");
        ctx.glGenVertexArrays(-1, &arrays);
        ctx.expectError(GL_INVALID_VALUE);
        ctx.endSection();
@@ -255,8 +371,9 @@ void delete_vertex_arrays (NegativeTestContext& ctx)
 
 void vertex_attrib_divisor (NegativeTestContext& ctx)
 {
-       ctx.beginSection("GL_INVALID_VALUE is generated if index is greater than or equal to GL_MAX_VERTEX_ATTRIBS.");
        int maxVertexAttribs = ctx.getInteger(GL_MAX_VERTEX_ATTRIBS);
+
+       ctx.beginSection("GL_INVALID_VALUE is generated if index is greater than or equal to GL_MAX_VERTEX_ATTRIBS.");
        ctx.glVertexAttribDivisor(maxVertexAttribs, 0);
        ctx.expectError(GL_INVALID_VALUE);
        ctx.endSection();
@@ -264,9 +381,14 @@ void vertex_attrib_divisor (NegativeTestContext& ctx)
 
 void draw_arrays (NegativeTestContext& ctx)
 {
-       glu::ShaderProgram program(ctx.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+       const bool                                      isES32  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       GLuint                                          fbo             = 0;
+       map<string, string>             args;
+       args["GLSL_VERSION_STRING"]                     = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+       glu::ShaderProgram                      program (ctx.getRenderContext(), glu::makeVtxFragSources(tcu::StringTemplate(vertexShaderSource).specialize(args), tcu::StringTemplate(fragmentShaderSource).specialize(args)));
+
        ctx.glUseProgram(program.getProgram());
-       GLuint fbo = 0;
+       ctx.expectError(GL_NO_ERROR);
 
        ctx.beginSection("GL_INVALID_ENUM is generated if mode is not an accepted value.");
        ctx.glDrawArrays(-1, 0, 1);
@@ -293,8 +415,8 @@ void draw_arrays (NegativeTestContext& ctx)
 
 void draw_arrays_invalid_program (NegativeTestContext& ctx)
 {
-       ctx.glUseProgram(0);
        GLuint fbo = 0;
+       ctx.glUseProgram(0);
 
        ctx.beginSection("GL_INVALID_ENUM is generated if mode is not an accepted value.");
        ctx.glDrawArrays(-1, 0, 1);
@@ -319,9 +441,14 @@ void draw_arrays_invalid_program (NegativeTestContext& ctx)
 
 void draw_arrays_incomplete_primitive (NegativeTestContext& ctx)
 {
-       glu::ShaderProgram program(ctx.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+       const bool                                      isES32  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       GLuint                                          fbo             = 0;
+       map<string, string>             args;
+       args["GLSL_VERSION_STRING"]                     = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+       glu::ShaderProgram                      program (ctx.getRenderContext(), glu::makeVtxFragSources(tcu::StringTemplate(vertexShaderSource).specialize(args), tcu::StringTemplate(fragmentShaderSource).specialize(args)));
+
        ctx.glUseProgram(program.getProgram());
-       GLuint fbo = 0;
+       ctx.expectError(GL_NO_ERROR);
 
        ctx.beginSection("GL_INVALID_ENUM is generated if mode is not an accepted value.");
        ctx.glDrawArrays(-1, 0, 1);
@@ -348,12 +475,17 @@ void draw_arrays_incomplete_primitive (NegativeTestContext& ctx)
 
 void draw_elements (NegativeTestContext& ctx)
 {
-       glu::ShaderProgram program(ctx.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+       const bool                                      isES32  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       GLuint                                          fbo             = 0;
+       GLuint                                          buf             = 0;
+       GLuint                                          tfID    = 0;
+       GLfloat                                         vertices[1];
+       map<string, string>             args;
+       args["GLSL_VERSION_STRING"]                     = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+       glu::ShaderProgram                      program (ctx.getRenderContext(), glu::makeVtxFragSources(tcu::StringTemplate(vertexShaderSource).specialize(args), tcu::StringTemplate(fragmentShaderSource).specialize(args)));
+
        ctx.glUseProgram(program.getProgram());
-       GLuint fbo = 0;
-       GLuint buf = 0;
-       GLuint tfID = 0;
-       GLfloat vertices[1];
+       ctx.expectError(GL_NO_ERROR);
 
        ctx.beginSection("GL_INVALID_ENUM is generated if mode is not an accepted value.");
        ctx.glDrawElements(-1, 1, GL_UNSIGNED_BYTE, vertices);
@@ -385,32 +517,32 @@ void draw_elements (NegativeTestContext& ctx)
        if (!ctx.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) // GL_EXT_geometry_shader removes error
        {
                ctx.beginSection("GL_INVALID_OPERATION is generated if transform feedback is active and not paused.");
-               const char* tfVarying           = "gl_Position";
+               const char* tfVarying = "gl_Position";
 
-               ctx.glGenBuffers                                (1, &buf);
-               ctx.glGenTransformFeedbacks             (1, &tfID);
+               ctx.glGenBuffers(1, &buf);
+               ctx.glGenTransformFeedbacks(1, &tfID);
 
-               ctx.glUseProgram                                (program.getProgram());
-               ctx.glTransformFeedbackVaryings (program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS);
-               ctx.glLinkProgram                               (program.getProgram());
-               ctx.glBindTransformFeedback             (GL_TRANSFORM_FEEDBACK, tfID);
-               ctx.glBindBuffer                                (GL_TRANSFORM_FEEDBACK_BUFFER, buf);
-               ctx.glBufferData                                (GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW);
-               ctx.glBindBufferBase                    (GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
-               ctx.glBeginTransformFeedback    (GL_POINTS);
-               ctx.expectError                         (GL_NO_ERROR);
+               ctx.glUseProgram(program.getProgram());
+               ctx.glTransformFeedbackVaryings(program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS);
+               ctx.glLinkProgram(program.getProgram());
+               ctx.glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfID);
+               ctx.glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buf);
+               ctx.glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW);
+               ctx.glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+               ctx.glBeginTransformFeedback(GL_POINTS);
+               ctx.expectError(GL_NO_ERROR);
 
-               ctx.glDrawElements                              (GL_POINTS, 1, GL_UNSIGNED_BYTE, vertices);
-               ctx.expectError                         (GL_INVALID_OPERATION);
+               ctx.glDrawElements(GL_POINTS, 1, GL_UNSIGNED_BYTE, vertices);
+               ctx.expectError(GL_INVALID_OPERATION);
 
                ctx.glPauseTransformFeedback();
-               ctx.glDrawElements                              (GL_POINTS, 1, GL_UNSIGNED_BYTE, vertices);
-               ctx.expectError                         (GL_NO_ERROR);
+               ctx.glDrawElements(GL_POINTS, 1, GL_UNSIGNED_BYTE, vertices);
+               ctx.expectError(GL_NO_ERROR);
 
-               ctx.glEndTransformFeedback              ();
-               ctx.glDeleteBuffers                             (1, &buf);
-               ctx.glDeleteTransformFeedbacks  (1, &tfID);
-               ctx.expectError                         (GL_NO_ERROR);
+               ctx.glEndTransformFeedback();
+               ctx.glDeleteBuffers(1, &buf);
+               ctx.glDeleteTransformFeedbacks(1, &tfID);
+               ctx.expectError(GL_NO_ERROR);
                ctx.endSection();
        }
 
@@ -420,8 +552,8 @@ void draw_elements (NegativeTestContext& ctx)
 void draw_elements_invalid_program (NegativeTestContext& ctx)
 {
        ctx.glUseProgram(0);
-       GLuint fbo = 0;
-       GLfloat vertices[1];
+       GLuint  fbo = 0;
+       GLfloat vertices[1];
 
        ctx.beginSection("GL_INVALID_ENUM is generated if mode is not an accepted value.");
        ctx.glDrawElements(-1, 1, GL_UNSIGNED_BYTE, vertices);
@@ -453,12 +585,17 @@ void draw_elements_invalid_program (NegativeTestContext& ctx)
 
 void draw_elements_incomplete_primitive (NegativeTestContext& ctx)
 {
-       glu::ShaderProgram program(ctx.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+       const bool                                      isES32  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       GLuint                                          fbo             = 0;
+       GLuint                                          buf             = 0;
+       GLuint                                          tfID    = 0;
+       GLfloat                                         vertices[1];
+       map<string, string>             args;
+       args["GLSL_VERSION_STRING"]                     = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+       glu::ShaderProgram                      program (ctx.getRenderContext(), glu::makeVtxFragSources(tcu::StringTemplate(vertexShaderSource).specialize(args), tcu::StringTemplate(fragmentShaderSource).specialize(args)));
+
        ctx.glUseProgram(program.getProgram());
-       GLuint fbo = 0;
-       GLuint buf = 0;
-       GLuint tfID = 0;
-       GLfloat vertices[1];
+       ctx.expectError(GL_NO_ERROR);
 
        ctx.beginSection("GL_INVALID_ENUM is generated if mode is not an accepted value.");
        ctx.glDrawElements(-1, 1, GL_UNSIGNED_BYTE, vertices);
@@ -490,43 +627,83 @@ void draw_elements_incomplete_primitive (NegativeTestContext& ctx)
        if (!ctx.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) // GL_EXT_geometry_shader removes error
        {
                ctx.beginSection("GL_INVALID_OPERATION is generated if transform feedback is active and not paused.");
-               const char* tfVarying           = "gl_Position";
-
-               ctx.glGenBuffers                                (1, &buf);
-               ctx.glGenTransformFeedbacks             (1, &tfID);
-
-               ctx.glUseProgram                                (program.getProgram());
-               ctx.glTransformFeedbackVaryings (program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS);
-               ctx.glLinkProgram                               (program.getProgram());
-               ctx.glBindTransformFeedback             (GL_TRANSFORM_FEEDBACK, tfID);
-               ctx.glBindBuffer                                (GL_TRANSFORM_FEEDBACK_BUFFER, buf);
-               ctx.glBufferData                                (GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW);
-               ctx.glBindBufferBase                    (GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
-               ctx.glBeginTransformFeedback    (GL_TRIANGLES);
-               ctx.expectError                                 (GL_NO_ERROR);
-
-               ctx.glDrawElements                              (GL_TRIANGLES, 1, GL_UNSIGNED_BYTE, vertices);
-               ctx.expectError                                 (GL_INVALID_OPERATION);
-
-               ctx.glPauseTransformFeedback    ();
-               ctx.glDrawElements                              (GL_TRIANGLES, 1, GL_UNSIGNED_BYTE, vertices);
-               ctx.expectError                                 (GL_NO_ERROR);
-
-               ctx.glEndTransformFeedback              ();
-               ctx.glDeleteBuffers                             (1, &buf);
-               ctx.glDeleteTransformFeedbacks  (1, &tfID);
-               ctx.expectError                                 (GL_NO_ERROR);
-               ctx.endSection                                  ();
+               const char* tfVarying= "gl_Position";
+
+               ctx.glGenBuffers(1, &buf);
+               ctx.glGenTransformFeedbacks(1, &tfID);
+
+               ctx.glUseProgram(program.getProgram());
+               ctx.glTransformFeedbackVaryings(program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS);
+               ctx.glLinkProgram(program.getProgram());
+               ctx.glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfID);
+               ctx.glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buf);
+               ctx.glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW);
+               ctx.glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+               ctx.glBeginTransformFeedback(GL_TRIANGLES);
+               ctx.expectError(GL_NO_ERROR);
+
+               ctx.glDrawElements(GL_TRIANGLES, 1, GL_UNSIGNED_BYTE, vertices);
+               ctx.expectError(GL_INVALID_OPERATION);
+
+               ctx.glPauseTransformFeedback();
+               ctx.glDrawElements(GL_TRIANGLES, 1, GL_UNSIGNED_BYTE, vertices);
+               ctx.expectError(GL_NO_ERROR);
+
+               ctx.glEndTransformFeedback();
+               ctx.glDeleteBuffers(1, &buf);
+               ctx.glDeleteTransformFeedbacks(1, &tfID);
+               ctx.expectError(GL_NO_ERROR);
+               ctx.endSection();
        }
 
        ctx.glUseProgram(0);
 }
 
+void draw_elements_base_vertex (NegativeTestContext& ctx)
+{
+       TCU_CHECK_AND_THROW(NotSupportedError, contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)), "This test requires a 3.2 context or higher context version.");
+
+       GLuint  fbo = 0;
+       GLfloat vertices[1];
+
+       ctx.beginSection("GL_INVALID_ENUM is generated if mode is not an accepted value.");
+       ctx.glDrawElementsBaseVertex(-1, 1, GL_UNSIGNED_INT, vertices, 1);
+       ctx.expectError(GL_INVALID_ENUM);
+       ctx.endSection();
+
+       ctx.beginSection("GL_INVALID_ENUM is generated if type is not one of the accepted values.");
+       ctx.glDrawElementsBaseVertex(GL_POINTS, 1, -1, vertices, 1);
+       ctx.expectError(GL_INVALID_ENUM);
+       ctx.glDrawElementsBaseVertex(GL_POINTS, 1, GL_FLOAT, vertices, 1);
+       ctx.expectError(GL_INVALID_ENUM);
+       ctx.endSection();
+
+       ctx.beginSection("GL_INVALID_VALUE is generated if count is negative.");
+       ctx.glDrawElementsBaseVertex(GL_POINTS, -1, GL_UNSIGNED_INT, vertices, 1);
+       ctx.expectError(GL_INVALID_VALUE);
+       ctx.endSection();
+
+       ctx.beginSection("GL_INVALID_FRAMEBUFFER_OPERATION is generated if the currently bound framebuffer is not framebuffer complete.");
+       ctx.glGenFramebuffers(1, &fbo);
+       ctx.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+       ctx.glCheckFramebufferStatus(GL_FRAMEBUFFER);
+       ctx.glDrawElementsBaseVertex(GL_POINTS, -1, GL_UNSIGNED_INT, vertices, 1);
+       ctx.expectError(GL_INVALID_FRAMEBUFFER_OPERATION);
+       ctx.glBindFramebuffer(GL_FRAMEBUFFER, 0);
+       ctx.glDeleteFramebuffers(1, &fbo);
+       ctx.endSection();
+}
+
 void draw_arrays_instanced (NegativeTestContext& ctx)
 {
-       glu::ShaderProgram program(ctx.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+       const bool                                      isES32  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       GLuint                                          fbo             = 0;
+       map<string, string>             args;
+       args["GLSL_VERSION_STRING"]                     = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+       glu::ShaderProgram                      program (ctx.getRenderContext(), glu::makeVtxFragSources(tcu::StringTemplate(vertexShaderSource).specialize(args), tcu::StringTemplate(fragmentShaderSource).specialize(args)));
+
        ctx.glUseProgram(program.getProgram());
-       GLuint fbo = 0;
+       ctx.expectError(GL_NO_ERROR);
        ctx.glVertexAttribDivisor(0, 1);
        ctx.expectError(GL_NO_ERROR);
 
@@ -587,9 +764,12 @@ void draw_arrays_instanced_invalid_program (NegativeTestContext& ctx)
 
 void draw_arrays_instanced_incomplete_primitive (NegativeTestContext& ctx)
 {
-       glu::ShaderProgram program(ctx.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
-       ctx.glUseProgram(program.getProgram());
-       GLuint fbo = 0;
+       const bool                                      isES32  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       GLuint                                          fbo             = 0;
+       map<string, string>             args;
+       args["GLSL_VERSION_STRING"]                     = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+       glu::ShaderProgram                      program (ctx.getRenderContext(), glu::makeVtxFragSources(tcu::StringTemplate(vertexShaderSource).specialize(args), tcu::StringTemplate(fragmentShaderSource).specialize(args)));
+
        ctx.glVertexAttribDivisor(0, 1);
        ctx.expectError(GL_NO_ERROR);
 
@@ -620,12 +800,16 @@ void draw_arrays_instanced_incomplete_primitive (NegativeTestContext& ctx)
 
 void draw_elements_instanced (NegativeTestContext& ctx)
 {
-       glu::ShaderProgram program(ctx.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+       const bool                                      isES32  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       GLuint                                          fbo             = 0;
+       GLuint                                          buf             = 0;
+       GLuint                                          tfID    = 0;
+       GLfloat                                         vertices[1];
+       map<string, string>             args;
+       args["GLSL_VERSION_STRING"]                     = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+       glu::ShaderProgram                      program (ctx.getRenderContext(), glu::makeVtxFragSources(tcu::StringTemplate(vertexShaderSource).specialize(args), tcu::StringTemplate(fragmentShaderSource).specialize(args)));
+
        ctx.glUseProgram(program.getProgram());
-       GLuint fbo = 0;
-       GLuint buf = 0;
-       GLuint tfID = 0;
-       GLfloat vertices[1];
        ctx.glVertexAttribDivisor(0, 1);
        ctx.expectError(GL_NO_ERROR);
 
@@ -661,32 +845,32 @@ void draw_elements_instanced (NegativeTestContext& ctx)
        if (!ctx.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) // GL_EXT_geometry_shader removes error
        {
                ctx.beginSection("GL_INVALID_OPERATION is generated if transform feedback is active and not paused.");
-               const char* tfVarying           = "gl_Position";
+               const char* tfVarying = "gl_Position";
 
-               ctx.glGenBuffers                                (1, &buf);
-               ctx.glGenTransformFeedbacks             (1, &tfID);
+               ctx.glGenBuffers(1, &buf);
+               ctx.glGenTransformFeedbacks(1, &tfID);
 
-               ctx.glUseProgram                                (program.getProgram());
-               ctx.glTransformFeedbackVaryings (program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS);
-               ctx.glLinkProgram                               (program.getProgram());
-               ctx.glBindTransformFeedback             (GL_TRANSFORM_FEEDBACK, tfID);
-               ctx.glBindBuffer                                (GL_TRANSFORM_FEEDBACK_BUFFER, buf);
-               ctx.glBufferData                                (GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW);
-               ctx.glBindBufferBase                    (GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
-               ctx.glBeginTransformFeedback    (GL_POINTS);
-               ctx.expectError                         (GL_NO_ERROR);
+               ctx.glUseProgram(program.getProgram());
+               ctx.glTransformFeedbackVaryings(program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS);
+               ctx.glLinkProgram(program.getProgram());
+               ctx.glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfID);
+               ctx.glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buf);
+               ctx.glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW);
+               ctx.glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+               ctx.glBeginTransformFeedback(GL_POINTS);
+               ctx.expectError(GL_NO_ERROR);
 
-               ctx.glDrawElementsInstanced             (GL_POINTS, 1, GL_UNSIGNED_BYTE, vertices, 1);
-               ctx.expectError                         (GL_INVALID_OPERATION);
+               ctx.glDrawElementsInstanced(GL_POINTS, 1, GL_UNSIGNED_BYTE, vertices, 1);
+               ctx.expectError(GL_INVALID_OPERATION);
 
                ctx.glPauseTransformFeedback();
-               ctx.glDrawElementsInstanced             (GL_POINTS, 1, GL_UNSIGNED_BYTE, vertices, 1);
-               ctx.expectError                         (GL_NO_ERROR);
+               ctx.glDrawElementsInstanced(GL_POINTS, 1, GL_UNSIGNED_BYTE, vertices, 1);
+               ctx.expectError(GL_NO_ERROR);
 
-               ctx.glEndTransformFeedback              ();
-               ctx.glDeleteBuffers                             (1, &buf);
-               ctx.glDeleteTransformFeedbacks  (1, &tfID);
-               ctx.expectError                         (GL_NO_ERROR);
+               ctx.glEndTransformFeedback();
+               ctx.glDeleteBuffers(1, &buf);
+               ctx.glDeleteTransformFeedbacks(1, &tfID);
+               ctx.expectError(GL_NO_ERROR);
                ctx.endSection();
        }
 
@@ -733,12 +917,16 @@ void draw_elements_instanced_invalid_program (NegativeTestContext& ctx)
 
 void draw_elements_instanced_incomplete_primitive (NegativeTestContext& ctx)
 {
-       glu::ShaderProgram program(ctx.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+       const bool                                      isES32  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       GLuint                                          fbo             = 0;
+       GLuint                                          buf             = 0;
+       GLuint                                          tfID    = 0;
+       GLfloat                                         vertices[1];
+       map<string, string>             args;
+       args["GLSL_VERSION_STRING"]                     = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+       glu::ShaderProgram                      program (ctx.getRenderContext(), glu::makeVtxFragSources(tcu::StringTemplate(vertexShaderSource).specialize(args), tcu::StringTemplate(fragmentShaderSource).specialize(args)));
+
        ctx.glUseProgram(program.getProgram());
-       GLuint fbo = 0;
-       GLuint buf = 0;
-       GLuint tfID = 0;
-       GLfloat vertices[1];
        ctx.glVertexAttribDivisor(0, 1);
        ctx.expectError(GL_NO_ERROR);
 
@@ -774,46 +962,98 @@ void draw_elements_instanced_incomplete_primitive (NegativeTestContext& ctx)
        if (!ctx.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) // GL_EXT_geometry_shader removes error
        {
                ctx.beginSection("GL_INVALID_OPERATION is generated if transform feedback is active and not paused.");
-               const char* tfVarying           = "gl_Position";
+               const char* tfVarying= "gl_Position";
 
-               ctx.glGenBuffers                                (1, &buf);
-               ctx.glGenTransformFeedbacks             (1, &tfID);
+               ctx.glGenBuffers(1, &buf);
+               ctx.glGenTransformFeedbacks(1, &tfID);
 
-               ctx.glUseProgram                                (program.getProgram());
-               ctx.glTransformFeedbackVaryings (program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS);
-               ctx.glLinkProgram                               (program.getProgram());
-               ctx.glBindTransformFeedback             (GL_TRANSFORM_FEEDBACK, tfID);
-               ctx.glBindBuffer                                (GL_TRANSFORM_FEEDBACK_BUFFER, buf);
-               ctx.glBufferData                                (GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW);
-               ctx.glBindBufferBase                    (GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
-               ctx.glBeginTransformFeedback    (GL_TRIANGLES);
-               ctx.expectError                                 (GL_NO_ERROR);
+               ctx.glUseProgram(program.getProgram());
+               ctx.glTransformFeedbackVaryings(program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS);
+               ctx.glLinkProgram(program.getProgram());
+               ctx.glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfID);
+               ctx.glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buf);
+               ctx.glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW);
+               ctx.glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+               ctx.glBeginTransformFeedback(GL_TRIANGLES);
+               ctx.expectError(GL_NO_ERROR);
 
-               ctx.glDrawElementsInstanced             (GL_TRIANGLES, 1, GL_UNSIGNED_BYTE, vertices, 1);
-               ctx.expectError                                 (GL_INVALID_OPERATION);
+               ctx.glDrawElementsInstanced(GL_TRIANGLES, 1, GL_UNSIGNED_BYTE, vertices, 1);
+               ctx.expectError(GL_INVALID_OPERATION);
 
                ctx.glPauseTransformFeedback();
-               ctx.glDrawElementsInstanced             (GL_TRIANGLES, 1, GL_UNSIGNED_BYTE, vertices, 1);
-               ctx.expectError                                 (GL_NO_ERROR);
+               ctx.glDrawElementsInstanced     (GL_TRIANGLES, 1, GL_UNSIGNED_BYTE, vertices, 1);
+               ctx.expectError(GL_NO_ERROR);
 
-               ctx.glEndTransformFeedback              ();
-               ctx.glDeleteBuffers                             (1, &buf);
-               ctx.glDeleteTransformFeedbacks  (1, &tfID);
-               ctx.expectError                                 (GL_NO_ERROR);
+               ctx.glEndTransformFeedback();
+               ctx.glDeleteBuffers(1, &buf);
+               ctx.glDeleteTransformFeedbacks(1, &tfID);
+               ctx.expectError(GL_NO_ERROR);
                ctx.endSection();
        }
 
        ctx.glUseProgram(0);
 }
 
+void draw_elements_instanced_base_vertex (NegativeTestContext& ctx)
+{
+       TCU_CHECK_AND_THROW(NotSupportedError, contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)), "This test requires a 3.2 context or higher context version.");
+
+       const bool                                      isES32  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       GLuint                                          fbo             = 0;
+       GLfloat                                         vertices[1];
+       map<string, string>             args;
+       args["GLSL_VERSION_STRING"]                     = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+       glu::ShaderProgram                      program (ctx.getRenderContext(), glu::makeVtxFragSources(tcu::StringTemplate(vertexShaderSource).specialize(args), tcu::StringTemplate(fragmentShaderSource).specialize(args)));
+
+       ctx.glUseProgram(program.getProgram());
+       ctx.glVertexAttribDivisor(0, 1);
+       ctx.expectError(GL_NO_ERROR);
+
+       ctx.beginSection("GL_INVALID_ENUM is generated if mode is not an accepted value.");
+       ctx.glDrawElementsInstancedBaseVertex(-1, 1, GL_UNSIGNED_BYTE, vertices, 1, 1);
+       ctx.expectError(GL_INVALID_ENUM);
+       ctx.endSection();
+
+       ctx.beginSection("GL_INVALID_ENUM is generated if type is not one of the accepted values.");
+       ctx.glDrawElementsInstancedBaseVertex(GL_POINTS, 1, -1, vertices, 1, 1);
+       ctx.expectError(GL_INVALID_ENUM);
+       ctx.glDrawElementsInstancedBaseVertex(GL_POINTS, 1, GL_FLOAT, vertices, 1, 1);
+       ctx.expectError(GL_INVALID_ENUM);
+       ctx.endSection();
+
+       ctx.beginSection("GL_INVALID_VALUE is generated if count or primcount are negative.");
+       ctx.glDrawElementsInstancedBaseVertex(GL_POINTS, -1, GL_UNSIGNED_BYTE, vertices, 1, 1);
+       ctx.expectError(GL_INVALID_VALUE);
+       ctx.glDrawElementsInstancedBaseVertex(GL_POINTS, 11, GL_UNSIGNED_BYTE, vertices, -1, 1);
+       ctx.expectError(GL_INVALID_VALUE);
+       ctx.endSection();
+
+       ctx.beginSection("GL_INVALID_FRAMEBUFFER_OPERATION is generated if the currently bound framebuffer is not framebuffer complete.");
+       ctx.glGenFramebuffers(1, &fbo);
+       ctx.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+       ctx.glCheckFramebufferStatus(GL_FRAMEBUFFER);
+       ctx.glDrawElementsInstancedBaseVertex(GL_POINTS, 1, GL_UNSIGNED_BYTE, vertices, 1, 1);
+       ctx.expectError(GL_INVALID_FRAMEBUFFER_OPERATION);
+       ctx.glBindFramebuffer(GL_FRAMEBUFFER, 0);
+       ctx.glDeleteFramebuffers(1, &fbo);
+       ctx.endSection();
+
+       ctx.glUseProgram(0);
+}
+
 void draw_range_elements (NegativeTestContext& ctx)
 {
-       glu::ShaderProgram program(ctx.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+       const bool                                      isES32  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       GLuint                                          fbo             = 0;
+       GLuint                                          buf             = 0;
+       GLuint                                          tfID    = 0;
+       GLfloat                                         vertices[1];
+       map<string, string>             args;
+       args["GLSL_VERSION_STRING"]                     = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+       glu::ShaderProgram                      program (ctx.getRenderContext(), glu::makeVtxFragSources(tcu::StringTemplate(vertexShaderSource).specialize(args), tcu::StringTemplate(fragmentShaderSource).specialize(args)));
+
        ctx.glUseProgram(program.getProgram());
-       GLuint fbo = 0;
-       GLuint buf = 0;
-       GLuint tfID = 0;
-       GLfloat vertices[1];
+       ctx.expectError(GL_NO_ERROR);
 
        ctx.beginSection("GL_INVALID_ENUM is generated if mode is not an accepted value.");
        ctx.glDrawRangeElements(-1, 0, 1, 1, GL_UNSIGNED_BYTE, vertices);
@@ -850,32 +1090,32 @@ void draw_range_elements (NegativeTestContext& ctx)
        if (!ctx.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) // GL_EXT_geometry_shader removes error
        {
                ctx.beginSection("GL_INVALID_OPERATION is generated if transform feedback is active and not paused.");
-               const char* tfVarying           = "gl_Position";
+               const char* tfVarying= "gl_Position";
 
-               ctx.glGenBuffers                                (1, &buf);
-               ctx.glGenTransformFeedbacks             (1, &tfID);
+               ctx.glGenBuffers(1, &buf);
+               ctx.glGenTransformFeedbacks(1, &tfID);
 
-               ctx.glUseProgram                                (program.getProgram());
-               ctx.glTransformFeedbackVaryings (program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS);
-               ctx.glLinkProgram                               (program.getProgram());
-               ctx.glBindTransformFeedback             (GL_TRANSFORM_FEEDBACK, tfID);
-               ctx.glBindBuffer                                (GL_TRANSFORM_FEEDBACK_BUFFER, buf);
-               ctx.glBufferData                                (GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW);
-               ctx.glBindBufferBase                    (GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
-               ctx.glBeginTransformFeedback    (GL_POINTS);
-               ctx.expectError                                 (GL_NO_ERROR);
+               ctx.glUseProgram(program.getProgram());
+               ctx.glTransformFeedbackVaryings(program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS);
+               ctx.glLinkProgram(program.getProgram());
+               ctx.glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfID);
+               ctx.glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buf);
+               ctx.glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW);
+               ctx.glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+               ctx.glBeginTransformFeedback(GL_POINTS);
+               ctx.expectError(GL_NO_ERROR);
 
-               ctx.glDrawRangeElements                 (GL_POINTS, 0, 1, 1, GL_UNSIGNED_BYTE, vertices);
-               ctx.expectError                                 (GL_INVALID_OPERATION);
+               ctx.glDrawRangeElements(GL_POINTS, 0, 1, 1, GL_UNSIGNED_BYTE, vertices);
+               ctx.expectError(GL_INVALID_OPERATION);
 
                ctx.glPauseTransformFeedback();
-               ctx.glDrawRangeElements                 (GL_POINTS, 0, 1, 1, GL_UNSIGNED_BYTE, vertices);
-               ctx.expectError                                 (GL_NO_ERROR);
+               ctx.glDrawRangeElements(GL_POINTS, 0, 1, 1, GL_UNSIGNED_BYTE, vertices);
+               ctx.expectError(GL_NO_ERROR);
 
-               ctx.glEndTransformFeedback              ();
-               ctx.glDeleteBuffers                             (1, &buf);
-               ctx.glDeleteTransformFeedbacks  (1, &tfID);
-               ctx.expectError                                 (GL_NO_ERROR);
+               ctx.glEndTransformFeedback();
+               ctx.glDeleteBuffers(1, &buf);
+               ctx.glDeleteTransformFeedbacks(1, &tfID);
+               ctx.expectError(GL_NO_ERROR);
                ctx.endSection();
        }
 
@@ -923,12 +1163,17 @@ void draw_range_elements_invalid_program (NegativeTestContext& ctx)
 
 void draw_range_elements_incomplete_primitive (NegativeTestContext& ctx)
 {
-       glu::ShaderProgram program(ctx.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
+       const bool                                      isES32  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       GLuint                                          fbo             = 0;
+       GLuint                                          buf             = 0;
+       GLuint                                          tfID    = 0;
+       GLfloat                                         vertices[1];
+       map<string, string>             args;
+       args["GLSL_VERSION_STRING"]                     = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+       glu::ShaderProgram                      program (ctx.getRenderContext(), glu::makeVtxFragSources(tcu::StringTemplate(vertexShaderSource).specialize(args), tcu::StringTemplate(fragmentShaderSource).specialize(args)));
+
        ctx.glUseProgram(program.getProgram());
-       GLuint fbo = 0;
-       GLuint buf = 0;
-       GLuint tfID = 0;
-       GLfloat vertices[1];
+       ctx.expectError(GL_NO_ERROR);
 
        ctx.beginSection("GL_INVALID_ENUM is generated if mode is not an accepted value.");
        ctx.glDrawRangeElements(-1, 0, 1, 1, GL_UNSIGNED_BYTE, vertices);
@@ -965,69 +1210,123 @@ void draw_range_elements_incomplete_primitive (NegativeTestContext& ctx)
        if (!ctx.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader")) // GL_EXT_geometry_shader removes error
        {
                ctx.beginSection("GL_INVALID_OPERATION is generated if transform feedback is active and not paused.");
-               const char* tfVarying           = "gl_Position";
+               const char* tfVarying = "gl_Position";
 
-               ctx.glGenBuffers                                (1, &buf);
-               ctx.glGenTransformFeedbacks             (1, &tfID);
+               ctx.glGenBuffers(1, &buf);
+               ctx.glGenTransformFeedbacks(1, &tfID);
 
-               ctx.glUseProgram                                (program.getProgram());
-               ctx.glTransformFeedbackVaryings (program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS);
-               ctx.glLinkProgram                               (program.getProgram());
-               ctx.glBindTransformFeedback             (GL_TRANSFORM_FEEDBACK, tfID);
-               ctx.glBindBuffer                                (GL_TRANSFORM_FEEDBACK_BUFFER, buf);
-               ctx.glBufferData                                (GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW);
-               ctx.glBindBufferBase                    (GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
-               ctx.glBeginTransformFeedback    (GL_TRIANGLES);
-               ctx.expectError                         (GL_NO_ERROR);
+               ctx.glUseProgram(program.getProgram());
+               ctx.glTransformFeedbackVaryings(program.getProgram(), 1, &tfVarying, GL_INTERLEAVED_ATTRIBS);
+               ctx.glLinkProgram(program.getProgram());
+               ctx.glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfID);
+               ctx.glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buf);
+               ctx.glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 32, DE_NULL, GL_DYNAMIC_DRAW);
+               ctx.glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buf);
+               ctx.glBeginTransformFeedback(GL_TRIANGLES);
+               ctx.expectError(GL_NO_ERROR);
 
-               ctx.glDrawRangeElements                 (GL_TRIANGLES, 0, 1, 1, GL_UNSIGNED_BYTE, vertices);
-               ctx.expectError                         (GL_INVALID_OPERATION);
+               ctx.glDrawRangeElements(GL_TRIANGLES, 0, 1, 1, GL_UNSIGNED_BYTE, vertices);
+               ctx.expectError(GL_INVALID_OPERATION);
 
                ctx.glPauseTransformFeedback();
-               ctx.glDrawRangeElements                 (GL_TRIANGLES, 0, 1, 1, GL_UNSIGNED_BYTE, vertices);
-               ctx.expectError                         (GL_NO_ERROR);
+               ctx.glDrawRangeElements(GL_TRIANGLES, 0, 1, 1, GL_UNSIGNED_BYTE, vertices);
+               ctx.expectError(GL_NO_ERROR);
 
-               ctx.glEndTransformFeedback              ();
-               ctx.glDeleteBuffers                             (1, &buf);
-               ctx.glDeleteTransformFeedbacks  (1, &tfID);
-               ctx.expectError                         (GL_NO_ERROR);
+               ctx.glEndTransformFeedback();
+               ctx.glDeleteBuffers(1, &buf);
+               ctx.glDeleteTransformFeedbacks(1, &tfID);
+               ctx.expectError(GL_NO_ERROR);
                ctx.endSection();
        }
 
        ctx.glUseProgram(0);
 }
 
+void draw_range_elements_base_vertex (NegativeTestContext& ctx)
+{
+       TCU_CHECK_AND_THROW(NotSupportedError, contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)), "This test requires a 3.2 context or higher context version.");
+
+       const bool                                      isES32  = glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+       GLuint                                          fbo             = 0;
+       GLfloat                                         vertices[1];
+       map<string, string>             args;
+       args["GLSL_VERSION_STRING"]                     = isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+       glu::ShaderProgram                      program (ctx.getRenderContext(), glu::makeVtxFragSources(tcu::StringTemplate(vertexShaderSource).specialize(args), tcu::StringTemplate(fragmentShaderSource).specialize(args)));
+
+       ctx.glUseProgram(program.getProgram());
+       ctx.expectError(GL_NO_ERROR);
+
+       ctx.beginSection("GL_INVALID_ENUM is generated if mode is not an accepted value.");
+       ctx.glDrawRangeElementsBaseVertex(-1, 0, 1, 1, GL_UNSIGNED_BYTE, vertices, 1);
+       ctx.expectError(GL_INVALID_ENUM);
+       ctx.endSection();
+
+       ctx.beginSection("GL_INVALID_ENUM is generated if type is not one of the accepted values.");
+       ctx.glDrawRangeElementsBaseVertex(GL_POINTS, 0, 1, 1, -1, vertices, 1);
+       ctx.expectError(GL_INVALID_ENUM);
+       ctx.glDrawRangeElementsBaseVertex(GL_POINTS, 0, 1, 1, GL_FLOAT, vertices, 1);
+       ctx.expectError(GL_INVALID_ENUM);
+       ctx.endSection();
+
+       ctx.beginSection("GL_INVALID_VALUE is generated if count is negative.");
+       ctx.glDrawRangeElementsBaseVertex(GL_POINTS, 0, 1, -1, GL_UNSIGNED_BYTE, vertices, 1);
+       ctx.expectError(GL_INVALID_VALUE);
+       ctx.endSection();
+
+       ctx.beginSection("GL_INVALID_VALUE is generated if end < start.");
+       ctx.glDrawRangeElementsBaseVertex(GL_POINTS, 1, 0, 1, GL_UNSIGNED_BYTE, vertices, 1);
+       ctx.expectError(GL_INVALID_VALUE);
+       ctx.endSection();
+
+       ctx.beginSection("GL_INVALID_FRAMEBUFFER_OPERATION is generated if the currently bound framebuffer is not framebuffer complete.");
+       ctx.glGenFramebuffers(1, &fbo);
+       ctx.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+       ctx.glCheckFramebufferStatus(GL_FRAMEBUFFER);
+       ctx.glDrawRangeElementsBaseVertex(GL_POINTS, 0, 1, 1, GL_UNSIGNED_BYTE, vertices, 1);
+       ctx.expectError(GL_INVALID_FRAMEBUFFER_OPERATION);
+       ctx.glBindFramebuffer(GL_FRAMEBUFFER, 0);
+       ctx.glDeleteFramebuffers(1, &fbo);
+       ctx.endSection();
+
+       ctx.glUseProgram(0);
+}
+
 std::vector<FunctionContainer> getNegativeVertexArrayApiTestFunctions ()
 {
        FunctionContainer funcs[] =
        {
-               {vertex_attribf,                                                                "vertex_attribf",                                                               "Invalid glVertexAttrib{1234}f() usage"         },
-               {vertex_attribfv,                                                               "vertex_attribfv",                                                              "Invalid glVertexAttrib{1234}fv() usage"        },
-               {vertex_attribi4,                                                               "vertex_attribi4",                                                              "Invalid glVertexAttribI4{i|ui}f() usage"       },
-               {vertex_attribi4v,                                                              "vertex_attribi4v",                                                             "Invalid glVertexAttribI4{i|ui}fv() usage"      },
-               {vertex_attrib_pointer,                                                 "vertex_attrib_pointer",                                                "Invalid glVertexAttribPointer() usage"         },
-               {vertex_attrib_i_pointer,                                               "vertex_attrib_i_pointer",                                              "Invalid glVertexAttribPointer() usage"         },
-               {enable_vertex_attrib_array,                                    "enable_vertex_attrib_array",                                   "Invalid glEnableVertexAttribArray() usage"     },
-               {disable_vertex_attrib_array,                                   "disable_vertex_attrib_array",                                  "Invalid glDisableVertexAttribArray() usage"},
-               {gen_vertex_arrays,                                                             "gen_vertex_arrays",                                                    "Invalid glGenVertexArrays() usage"                     },
-               {bind_vertex_array,                                                             "bind_vertex_array",                                                    "Invalid glBindVertexArray() usage"                     },
-               {delete_vertex_arrays,                                                  "delete_vertex_arrays",                                                 "Invalid glDeleteVertexArrays() usage"          },
-               {vertex_attrib_divisor,                                                 "vertex_attrib_divisor",                                                "Invalid glVertexAttribDivisor() usage"         },
-               {draw_arrays,                                                                   "draw_arrays",                                                                  "Invalid glDrawArrays() usage"                          },
-               {draw_arrays_invalid_program,                                   "draw_arrays_invalid_program",                                  "Invalid glDrawArrays() usage"                          },
-               {draw_arrays_incomplete_primitive,                              "draw_arrays_incomplete_primitive",                             "Invalid glDrawArrays() usage"                          },
-               {draw_elements,                                                                 "draw_elements",                                                                "Invalid glDrawElements() usage"                        },
-               {draw_elements_invalid_program,                                 "draw_elements_invalid_program",                                "Invalid glDrawElements() usage"                        },
-               {draw_elements_incomplete_primitive,                    "draw_elements_incomplete_primitive",                   "Invalid glDrawElements() usage"                        },
-               {draw_arrays_instanced,                                                 "draw_arrays_instanced",                                                "Invalid glDrawArraysInstanced() usage"         },
-               {draw_arrays_instanced_invalid_program,                 "draw_arrays_instanced_invalid_program",                "Invalid glDrawArraysInstanced() usage"         },
-               {draw_arrays_instanced_incomplete_primitive,    "draw_arrays_instanced_incomplete_primitive",   "Invalid glDrawArraysInstanced() usage"         },
-               {draw_elements_instanced,                                               "draw_elements_instanced",                                              "Invalid glDrawElementsInstanced() usage"       },
-               {draw_elements_instanced_invalid_program,               "draw_elements_instanced_invalid_program",              "Invalid glDrawElementsInstanced() usage"       },
-               {draw_elements_instanced_incomplete_primitive,  "draw_elements_instanced_incomplete_primitive", "Invalid glDrawElementsInstanced() usage"       },
-               {draw_range_elements,                                                   "draw_range_elements",                                                  "Invalid glDrawRangeElements() usage"           },
-               {draw_range_elements_invalid_program,                   "draw_range_elements_invalid_program",                  "Invalid glDrawRangeElements() usage"           },
-               {draw_range_elements_incomplete_primitive,              "draw_range_elements_incomplete_primitive",             "Invalid glDrawRangeElements() usage"           },
+               {vertex_attribf,                                                                "vertex_attribf",                                                               "Invalid glVertexAttrib{1234}f() usage"                         },
+               {vertex_attribfv,                                                               "vertex_attribfv",                                                              "Invalid glVertexAttrib{1234}fv() usage"                        },
+               {vertex_attribi4,                                                               "vertex_attribi4",                                                              "Invalid glVertexAttribI4{i|ui}f() usage"                       },
+               {vertex_attribi4v,                                                              "vertex_attribi4v",                                                             "Invalid glVertexAttribI4{i|ui}fv() usage"                      },
+               {vertex_attrib_pointer,                                                 "vertex_attrib_pointer",                                                "Invalid glVertexAttribPointer() usage"                         },
+               {vertex_attrib_i_pointer,                                               "vertex_attrib_i_pointer",                                              "Invalid glVertexAttribPointer() usage"                         },
+               {vertex_attrib_format,                                                  "vertex_attrib_format",                                                 "Invalid glVertexAttribFormat() usage"                          },
+               {vertex_attrib_i_format,                                                "vertex_attrib_i_format",                                               "Invalid glVertexAttribIFormat() usage"                         },
+               {enable_vertex_attrib_array,                                    "enable_vertex_attrib_array",                                   "Invalid glEnableVertexAttribArray() usage"                     },
+               {disable_vertex_attrib_array,                                   "disable_vertex_attrib_array",                                  "Invalid glDisableVertexAttribArray() usage"            },
+               {gen_vertex_arrays,                                                             "gen_vertex_arrays",                                                    "Invalid glGenVertexArrays() usage"                                     },
+               {bind_vertex_array,                                                             "bind_vertex_array",                                                    "Invalid glBindVertexArray() usage"                                     },
+               {delete_vertex_arrays,                                                  "delete_vertex_arrays",                                                 "Invalid glDeleteVertexArrays() usage"                          },
+               {vertex_attrib_divisor,                                                 "vertex_attrib_divisor",                                                "Invalid glVertexAttribDivisor() usage"                         },
+               {draw_arrays,                                                                   "draw_arrays",                                                                  "Invalid glDrawArrays() usage"                                          },
+               {draw_arrays_invalid_program,                                   "draw_arrays_invalid_program",                                  "Invalid glDrawArrays() usage"                                          },
+               {draw_arrays_incomplete_primitive,                              "draw_arrays_incomplete_primitive",                             "Invalid glDrawArrays() usage"                                          },
+               {draw_elements,                                                                 "draw_elements",                                                                "Invalid glDrawElements() usage"                                        },
+               {draw_elements_base_vertex,                                             "draw_elements_base_vertex",                                    "Invalid glDrawElementsBaseVertex() usage"                      },
+               {draw_elements_invalid_program,                                 "draw_elements_invalid_program",                                "Invalid glDrawElements() usage"                                        },
+               {draw_elements_incomplete_primitive,                    "draw_elements_incomplete_primitive",                   "Invalid glDrawElements() usage"                                        },
+               {draw_arrays_instanced,                                                 "draw_arrays_instanced",                                                "Invalid glDrawArraysInstanced() usage"                         },
+               {draw_arrays_instanced_invalid_program,                 "draw_arrays_instanced_invalid_program",                "Invalid glDrawArraysInstanced() usage"                         },
+               {draw_arrays_instanced_incomplete_primitive,    "draw_arrays_instanced_incomplete_primitive",   "Invalid glDrawArraysInstanced() usage"                         },
+               {draw_elements_instanced,                                               "draw_elements_instanced",                                              "Invalid glDrawElementsInstanced() usage"                       },
+               {draw_elements_instanced_invalid_program,               "draw_elements_instanced_invalid_program",              "Invalid glDrawElementsInstanced() usage"                       },
+               {draw_elements_instanced_incomplete_primitive,  "draw_elements_instanced_incomplete_primitive", "Invalid glDrawElementsInstanced() usage"                       },
+               {draw_elements_instanced_base_vertex,                   "draw_elements_instanced_base_vertex",                  "Invalid glDrawElementsInstancedBaseVertex() usage"     },
+               {draw_range_elements,                                                   "draw_range_elements",                                                  "Invalid glDrawRangeElements() usage"                           },
+               {draw_range_elements_invalid_program,                   "draw_range_elements_invalid_program",                  "Invalid glDrawRangeElements() usage"                           },
+               {draw_range_elements_incomplete_primitive,              "draw_range_elements_incomplete_primitive",             "Invalid glDrawRangeElements() usage"                           },
+               {draw_range_elements_base_vertex,                               "draw_range_elements_base_vertex",                              "Invalid glDrawRangeElementsBaseVertex() usage"         },
        };
 
        return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));