Implement the instanced draw calls in RendererGL.

BUG=angleproject:1136

Change-Id: I1167365618bdc3ca37ac0f4c60809de32c7a9d78
Reviewed-on: https://chromium-review.googlesource.com/295733
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/VertexAttribute.cpp b/src/libANGLE/VertexAttribute.cpp
index c164be5..13d78fd 100644
--- a/src/libANGLE/VertexAttribute.cpp
+++ b/src/libANGLE/VertexAttribute.cpp
@@ -52,4 +52,23 @@
     return attrib.stride ? attrib.stride : ComputeVertexAttributeTypeSize(attrib);
 }
 
+size_t ComputeVertexAttributeElementCount(const VertexAttribute &attrib,
+                                          size_t drawCount,
+                                          size_t instanceCount)
+{
+    // For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices.
+    //
+    // A vertex attribute with a positive divisor loads one instanced vertex for every set of
+    // non-instanced vertices, and the instanced vertex index advances once every "mDivisor"
+    // instances.
+    if (instanceCount > 0 && attrib.divisor > 0)
+    {
+        // When instanceDrawCount is not a multiple attrib.divisor, the division must round up.
+        // For instance, with 5 non-instanced vertices and a divisor equal to 3, we need 2 instanced
+        // vertices.
+        return (instanceCount + attrib.divisor - 1u) / attrib.divisor;
+    }
+
+    return drawCount;
+}
 }
diff --git a/src/libANGLE/VertexAttribute.h b/src/libANGLE/VertexAttribute.h
index d6a4afa..d1ee1b4 100644
--- a/src/libANGLE/VertexAttribute.h
+++ b/src/libANGLE/VertexAttribute.h
@@ -44,6 +44,9 @@
 
 size_t ComputeVertexAttributeTypeSize(const VertexAttribute& attrib);
 size_t ComputeVertexAttributeStride(const VertexAttribute& attrib);
+size_t ComputeVertexAttributeElementCount(const VertexAttribute &attrib,
+                                          size_t drawCount,
+                                          size_t instanceCount);
 
 struct VertexAttribCurrentValueData
 {
diff --git a/src/libANGLE/renderer/d3d/VertexDataManager.cpp b/src/libANGLE/renderer/d3d/VertexDataManager.cpp
index 4ae1e8d..254fc96 100644
--- a/src/libANGLE/renderer/d3d/VertexDataManager.cpp
+++ b/src/libANGLE/renderer/d3d/VertexDataManager.cpp
@@ -41,22 +41,6 @@
            stride;
 }
 
-static int StreamingBufferElementCount(const gl::VertexAttribute &attrib, int vertexDrawCount, int instanceDrawCount)
-{
-    // For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices.
-    //
-    // A vertex attribute with a positive divisor loads one instanced vertex for every set of
-    // non-instanced vertices, and the instanced vertex index advances once every "mDivisor" instances.
-    if (instanceDrawCount > 0 && attrib.divisor > 0)
-    {
-        // When instanceDrawCount is not a multiple attrib.divisor, the division must round up.
-        // For instance, with 5 non-instanced vertices and a divisor equal to 3, we need 2 instanced vertices.
-        return (instanceDrawCount + attrib.divisor - 1) / attrib.divisor;
-    }
-
-    return vertexDrawCount;
-}
-
 VertexDataManager::CurrentValueState::CurrentValueState()
     : buffer(nullptr),
       offset(0)
@@ -278,12 +262,13 @@
         }
         else
         {
-            int totalCount = StreamingBufferElementCount(attrib, count, instances);
+            size_t totalCount = ComputeVertexAttributeElementCount(attrib, count, instances);
             ASSERT(!bufferImpl ||
                    ElementsInBuffer(attrib, static_cast<unsigned int>(bufferImpl->getSize())) >=
                        totalCount);
 
-            gl::Error error = mStreamingBuffer->reserveVertexSpace(attrib, totalCount, instances);
+            gl::Error error = mStreamingBuffer->reserveVertexSpace(
+                attrib, static_cast<GLsizei>(totalCount), instances);
             if (error.isError())
             {
                 return error;
@@ -388,20 +373,16 @@
     }
     else
     {
-        int totalCount = StreamingBufferElementCount(attrib, count, instances);
+        size_t totalCount = ComputeVertexAttributeElementCount(attrib, count, instances);
         gl::Error error = mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize);
         if (error.isError())
         {
             return error;
         }
 
-        error = mStreamingBuffer->storeVertexAttributes(attrib,
-                                                        translated->currentValueType,
-                                                        firstVertexIndex,
-                                                        totalCount,
-                                                        instances,
-                                                        &streamOffset,
-                                                        sourceData);
+        error = mStreamingBuffer->storeVertexAttributes(
+            attrib, translated->currentValueType, firstVertexIndex,
+            static_cast<GLsizei>(totalCount), instances, &streamOffset, sourceData);
         if (error.isError())
         {
             return error;
diff --git a/src/libANGLE/renderer/gl/FunctionsGL.cpp b/src/libANGLE/renderer/gl/FunctionsGL.cpp
index 9bc4603..d383d6f 100644
--- a/src/libANGLE/renderer/gl/FunctionsGL.cpp
+++ b/src/libANGLE/renderer/gl/FunctionsGL.cpp
@@ -71,7 +71,6 @@
     {
         if (std::find(extensions.begin(), extensions.end(), requiredExtension) == extensions.end())
         {
-            *outFunction = nullptr;
             return;
         }
     }
@@ -798,6 +797,8 @@
         profile = 0;
     }
 
+    // clang-format off
+
     // Load extensions
     // Even though extensions are written against specific versions of GL, many drivers expose the extensions
     // in even older versions.  Always try loading the extensions regardless of GL version.
@@ -880,6 +881,17 @@
     AssignGLExtensionEntryPoint(extensions, "GL_ARB_ES2_compatibility", loadProcAddress("glDepthRangef"), &depthRangef);
     AssignGLExtensionEntryPoint(extensions, "GL_ARB_ES2_compatibility", loadProcAddress("glClearDepthf"), &clearDepthf);
 
+    // GL_ARB_instanced_arrays
+    AssignGLExtensionEntryPoint(extensions, "GL_ARB_instanced_arrays", loadProcAddress("glVertexAttribDivisorARB"), &vertexAttribDivisor);
+
+    // GL_EXT_draw_instanced
+    AssignGLExtensionEntryPoint(extensions, "GL_EXT_draw_instanced", loadProcAddress("glDrawArraysInstancedEXT"), &drawArraysInstanced);
+    AssignGLExtensionEntryPoint(extensions, "GL_EXT_draw_instanced", loadProcAddress("glDrawElementsInstancedEXT"), &drawElementsInstanced);
+
+    // GL_ARB_draw_instanced
+    AssignGLExtensionEntryPoint(extensions, "GL_ARB_draw_instanced", loadProcAddress("glDrawArraysInstancedARB"), &drawArraysInstanced);
+    AssignGLExtensionEntryPoint(extensions, "GL_ARB_draw_instanced", loadProcAddress("glDrawElementsInstancedARB"), &drawElementsInstanced);
+
     // 1.0
     if (isAtLeastGL(gl::Version(1, 0)))
     {
@@ -1622,6 +1634,8 @@
         AssignGLEntryPoint(loadProcAddress("glVertexArrayVertexBuffer"), &vertexArrayVertexBuffer);
         AssignGLEntryPoint(loadProcAddress("glVertexArrayVertexBuffers"), &vertexArrayVertexBuffers);
     }
+
+    // clang-format on
 }
 
 bool FunctionsGL::isAtLeastGL(const gl::Version &glVersion) const
diff --git a/src/libANGLE/renderer/gl/RendererGL.cpp b/src/libANGLE/renderer/gl/RendererGL.cpp
index cb4110d..f4db4d7 100644
--- a/src/libANGLE/renderer/gl/RendererGL.cpp
+++ b/src/libANGLE/renderer/gl/RendererGL.cpp
@@ -131,7 +131,7 @@
 
 gl::Error RendererGL::drawArrays(const gl::Data &data, GLenum mode, GLint first, GLsizei count)
 {
-    gl::Error error = mStateManager->setDrawArraysState(data, first, count);
+    gl::Error error = mStateManager->setDrawArraysState(data, first, count, 0);
     if (error.isError())
     {
         return error;
@@ -151,7 +151,17 @@
                                           GLsizei count,
                                           GLsizei instanceCount)
 {
-    UNIMPLEMENTED();
+    gl::Error error = mStateManager->setDrawArraysState(data, first, count, instanceCount);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    if (!mSkipDrawCalls)
+    {
+        mFunctions->drawArraysInstanced(mode, first, count, instanceCount);
+    }
+
     return gl::Error(GL_NO_ERROR);
 }
 
@@ -163,7 +173,8 @@
                                    const gl::RangeUI &indexRange)
 {
     const GLvoid *drawIndexPointer = nullptr;
-    gl::Error error = mStateManager->setDrawElementsState(data, count, type, indices, &drawIndexPointer);
+    gl::Error error =
+        mStateManager->setDrawElementsState(data, count, type, indices, 0, &drawIndexPointer);
     if (error.isError())
     {
         return error;
@@ -185,7 +196,19 @@
                                             GLsizei instances,
                                             const gl::RangeUI &indexRange)
 {
-    UNIMPLEMENTED();
+    const GLvoid *drawIndexPointer = nullptr;
+    gl::Error error = mStateManager->setDrawElementsState(data, count, type, indices, instances,
+                                                          &drawIndexPointer);
+    if (error.isError())
+    {
+        return error;
+    }
+
+    if (!mSkipDrawCalls)
+    {
+        mFunctions->drawElementsInstanced(mode, count, type, drawIndexPointer, instances);
+    }
+
     return gl::Error(GL_NO_ERROR);
 }
 
diff --git a/src/libANGLE/renderer/gl/StateManagerGL.cpp b/src/libANGLE/renderer/gl/StateManagerGL.cpp
index 6514b25..adf25da 100644
--- a/src/libANGLE/renderer/gl/StateManagerGL.cpp
+++ b/src/libANGLE/renderer/gl/StateManagerGL.cpp
@@ -401,7 +401,10 @@
     }
 }
 
-gl::Error StateManagerGL::setDrawArraysState(const gl::Data &data, GLint first, GLsizei count)
+gl::Error StateManagerGL::setDrawArraysState(const gl::Data &data,
+                                             GLint first,
+                                             GLsizei count,
+                                             GLsizei instanceCount)
 {
     const gl::State &state = *data.state;
 
@@ -410,8 +413,8 @@
     const gl::VertexArray *vao = state.getVertexArray();
     const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
 
-    gl::Error error =
-        vaoGL->syncDrawArraysState(program->getActiveAttribLocationsMask(), first, count);
+    gl::Error error = vaoGL->syncDrawArraysState(program->getActiveAttribLocationsMask(), first,
+                                                 count, instanceCount);
     if (error.isError())
     {
         return error;
@@ -422,7 +425,11 @@
     return setGenericDrawState(data);
 }
 
-gl::Error StateManagerGL::setDrawElementsState(const gl::Data &data, GLsizei count, GLenum type, const GLvoid *indices,
+gl::Error StateManagerGL::setDrawElementsState(const gl::Data &data,
+                                               GLsizei count,
+                                               GLenum type,
+                                               const GLvoid *indices,
+                                               GLsizei instanceCount,
                                                const GLvoid **outIndices)
 {
     const gl::State &state = *data.state;
@@ -433,7 +440,7 @@
     const VertexArrayGL *vaoGL = GetImplAs<VertexArrayGL>(vao);
 
     gl::Error error = vaoGL->syncDrawElementsState(program->getActiveAttribLocationsMask(), count,
-                                                   type, indices, outIndices);
+                                                   type, indices, instanceCount, outIndices);
     if (error.isError())
     {
         return error;
diff --git a/src/libANGLE/renderer/gl/StateManagerGL.h b/src/libANGLE/renderer/gl/StateManagerGL.h
index 1502fd8..97c8666 100644
--- a/src/libANGLE/renderer/gl/StateManagerGL.h
+++ b/src/libANGLE/renderer/gl/StateManagerGL.h
@@ -105,8 +105,15 @@
     void setPixelPackState(const gl::PixelPackState &pack);
     void setPixelPackState(GLint alignment, GLint rowLength, GLint skipRows, GLint skipPixels);
 
-    gl::Error setDrawArraysState(const gl::Data &data, GLint first, GLsizei count);
-    gl::Error setDrawElementsState(const gl::Data &data, GLsizei count, GLenum type, const GLvoid *indices,
+    gl::Error setDrawArraysState(const gl::Data &data,
+                                 GLint first,
+                                 GLsizei count,
+                                 GLsizei instanceCount);
+    gl::Error setDrawElementsState(const gl::Data &data,
+                                   GLsizei count,
+                                   GLenum type,
+                                   const GLvoid *indices,
+                                   GLsizei instanceCount,
                                    const GLvoid **outIndices);
 
     void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits);
diff --git a/src/libANGLE/renderer/gl/VertexArrayGL.cpp b/src/libANGLE/renderer/gl/VertexArrayGL.cpp
index 4fc9a65..1166ae2 100644
--- a/src/libANGLE/renderer/gl/VertexArrayGL.cpp
+++ b/src/libANGLE/renderer/gl/VertexArrayGL.cpp
@@ -77,18 +77,21 @@
 
 gl::Error VertexArrayGL::syncDrawArraysState(const gl::AttributesMask &activeAttributesMask,
                                              GLint first,
-                                             GLsizei count) const
+                                             GLsizei count,
+                                             GLsizei instanceCount) const
 {
-    return syncDrawState(activeAttributesMask, first, count, GL_NONE, nullptr, nullptr);
+    return syncDrawState(activeAttributesMask, first, count, GL_NONE, nullptr, instanceCount,
+                         nullptr);
 }
 
 gl::Error VertexArrayGL::syncDrawElementsState(const gl::AttributesMask &activeAttributesMask,
                                                GLsizei count,
                                                GLenum type,
                                                const GLvoid *indices,
+                                               GLsizei instanceCount,
                                                const GLvoid **outIndices) const
 {
-    return syncDrawState(activeAttributesMask, 0, count, type, indices, outIndices);
+    return syncDrawState(activeAttributesMask, 0, count, type, indices, instanceCount, outIndices);
 }
 
 gl::Error VertexArrayGL::syncDrawState(const gl::AttributesMask &activeAttributesMask,
@@ -96,6 +99,7 @@
                                        GLsizei count,
                                        GLenum type,
                                        const GLvoid *indices,
+                                       GLsizei instanceCount,
                                        const GLvoid **outIndices) const
 {
     mStateManager->bindVertexArray(mVertexArrayID, getAppliedElementArrayBufferID());
@@ -123,7 +127,7 @@
 
     if (attributesNeedStreaming)
     {
-        Error error = streamAttributes(activeAttributesMask, indexRange);
+        Error error = streamAttributes(activeAttributesMask, instanceCount, indexRange);
         if (error.isError())
         {
             return error;
@@ -213,6 +217,7 @@
 }
 
 void VertexArrayGL::computeStreamingAttributeSizes(const gl::AttributesMask &activeAttributesMask,
+                                                   GLsizei instanceCount,
                                                    const gl::RangeUI &indexRange,
                                                    size_t *outStreamingDataSize,
                                                    size_t *outMaxAttributeDataSize) const
@@ -228,26 +233,28 @@
         const auto &attrib = attribs[idx];
         ASSERT(AttributeNeedsStreaming(attrib));
 
-        const size_t streamedVertexCount = indexRange.end - indexRange.start + 1;
+        const size_t vertexCount = indexRange.end - indexRange.start + 1;
 
         // If streaming is going to be required, compute the size of the required buffer
         // and how much slack space at the beginning of the buffer will be required by determining
         // the attribute with the largest data size.
         size_t typeSize = ComputeVertexAttributeTypeSize(attrib);
-        *outStreamingDataSize += typeSize * streamedVertexCount;
+        *outStreamingDataSize +=
+            typeSize * ComputeVertexAttributeElementCount(attrib, vertexCount, instanceCount);
         *outMaxAttributeDataSize = std::max(*outMaxAttributeDataSize, typeSize);
     }
 }
 
 gl::Error VertexArrayGL::streamAttributes(const gl::AttributesMask &activeAttributesMask,
+                                          GLsizei instanceCount,
                                           const gl::RangeUI &indexRange) const
 {
     // Sync the vertex attribute state and track what data needs to be streamed
     size_t streamingDataSize    = 0;
     size_t maxAttributeDataSize = 0;
 
-    computeStreamingAttributeSizes(activeAttributesMask, indexRange, &streamingDataSize,
-                                   &maxAttributeDataSize);
+    computeStreamingAttributeSizes(activeAttributesMask, instanceCount, indexRange,
+                                   &streamingDataSize, &maxAttributeDataSize);
 
     if (streamingDataSize == 0)
     {
@@ -282,7 +289,7 @@
         uint8_t *bufferPointer = reinterpret_cast<uint8_t*>(mFunctions->mapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
         size_t curBufferOffset = bufferEmptySpace;
 
-        const size_t streamedVertexCount = indexRange.end - indexRange.start + 1;
+        const size_t vertexCount = indexRange.end - indexRange.start + 1;
 
         const auto &attribs = mData.getVertexAttributes();
         for (unsigned int idx :
@@ -291,6 +298,9 @@
             const auto &attrib = attribs[idx];
             ASSERT(AttributeNeedsStreaming(attrib));
 
+            const size_t streamedVertexCount =
+                ComputeVertexAttributeElementCount(attrib, vertexCount, instanceCount);
+
             const size_t sourceStride = ComputeVertexAttributeStride(attrib);
             const size_t destStride   = ComputeVertexAttributeTypeSize(attrib);
 
diff --git a/src/libANGLE/renderer/gl/VertexArrayGL.h b/src/libANGLE/renderer/gl/VertexArrayGL.h
index 52c8f4e..343fd31 100644
--- a/src/libANGLE/renderer/gl/VertexArrayGL.h
+++ b/src/libANGLE/renderer/gl/VertexArrayGL.h
@@ -25,11 +25,13 @@
 
     gl::Error syncDrawArraysState(const gl::AttributesMask &activeAttributesMask,
                                   GLint first,
-                                  GLsizei count) const;
+                                  GLsizei count,
+                                  GLsizei instanceCount) const;
     gl::Error syncDrawElementsState(const gl::AttributesMask &activeAttributesMask,
                                     GLsizei count,
                                     GLenum type,
                                     const GLvoid *indices,
+                                    GLsizei instanceCount,
                                     const GLvoid **outIndices) const;
 
     GLuint getVertexArrayID() const;
@@ -43,6 +45,7 @@
                             GLsizei count,
                             GLenum type,
                             const GLvoid *indices,
+                            GLsizei instanceCount,
                             const GLvoid **outIndices) const;
 
     // Apply index data, only sets outIndexRange if attributesNeedStreaming is true
@@ -52,12 +55,14 @@
     // Returns the amount of space needed to stream all attributes that need streaming
     // and the data size of the largest attribute
     void computeStreamingAttributeSizes(const gl::AttributesMask &activeAttributesMask,
+                                        GLsizei instanceCount,
                                         const gl::RangeUI &indexRange,
                                         size_t *outStreamingDataSize,
                                         size_t *outMaxAttributeDataSize) const;
 
     // Stream attributes that have client data
     gl::Error streamAttributes(const gl::AttributesMask &activeAttributesMask,
+                               GLsizei instanceCount,
                                const gl::RangeUI &indexRange) const;
 
     void updateNeedsStreaming(size_t attribIndex);
diff --git a/src/libANGLE/renderer/gl/renderergl_utils.cpp b/src/libANGLE/renderer/gl/renderergl_utils.cpp
index 527f25a..47b2797 100644
--- a/src/libANGLE/renderer/gl/renderergl_utils.cpp
+++ b/src/libANGLE/renderer/gl/renderergl_utils.cpp
@@ -532,6 +532,12 @@
                             functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_EXT_frag_depth");
     extensions->fboRenderMipmap = functions->isAtLeastGL(gl::Version(3, 0)) || functions->hasGLExtension("GL_EXT_framebuffer_object") ||
                                   functions->isAtLeastGLES(gl::Version(3, 0)) || functions->hasGLESExtension("GL_OES_fbo_render_mipmap");
+    extensions->instancedArrays = functions->isAtLeastGL(gl::Version(3, 1)) ||
+                                  (functions->hasGLExtension("GL_ARB_instanced_arrays") &&
+                                   (functions->hasGLExtension("GL_ARB_draw_instanced") ||
+                                    functions->hasGLExtension("GL_EXT_draw_instanced"))) ||
+                                  functions->isAtLeastGLES(gl::Version(3, 0)) ||
+                                  functions->hasGLESExtension("GL_EXT_instanced_arrays");
 }
 
 void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workarounds)