LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu/instanced - GLInstancedRendering.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 179 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 16 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2016 Google Inc.
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #include "GLInstancedRendering.h"
       9             : 
      10             : #include "GrResourceProvider.h"
      11             : #include "gl/GrGLGpu.h"
      12             : #include "instanced/InstanceProcessor.h"
      13             : 
      14             : #define GL_CALL(X) GR_GL_CALL(this->glGpu()->glInterface(), X)
      15             : 
      16             : namespace gr_instanced {
      17             : 
      18           0 : class GLInstancedRendering::GLOp final : public InstancedRendering::Op {
      19             : public:
      20           0 :     DEFINE_OP_CLASS_ID
      21             : 
      22           0 :     GLOp(GLInstancedRendering* instRendering, GrPaint&& paint)
      23           0 :             : INHERITED(ClassID(), std::move(paint), instRendering) {}
      24           0 :     int numGLCommands() const { return 1 + fNumChangesInGeometry; }
      25             : 
      26             : private:
      27             :     int fEmulatedBaseInstance;
      28             :     int fGLDrawCmdsIdx;
      29             : 
      30             :     friend class GLInstancedRendering;
      31             : 
      32             :     typedef Op INHERITED;
      33             : };
      34             : 
      35           0 : GrCaps::InstancedSupport GLInstancedRendering::CheckSupport(const GrGLCaps& glCaps) {
      36             :     // This method is only intended to be used for initializing fInstancedSupport in the caps.
      37           0 :     SkASSERT(GrCaps::InstancedSupport::kNone == glCaps.instancedSupport());
      38           0 :     if (!glCaps.vertexArrayObjectSupport() ||
      39           0 :         (!glCaps.drawIndirectSupport() && !glCaps.drawInstancedSupport())) {
      40           0 :         return GrCaps::InstancedSupport::kNone;
      41             :     }
      42           0 :     return InstanceProcessor::CheckSupport(*glCaps.shaderCaps(), glCaps);
      43             : }
      44             : 
      45           0 : GLInstancedRendering::GLInstancedRendering(GrGLGpu* gpu)
      46             :     : INHERITED(gpu),
      47             :       fVertexArrayID(0),
      48             :       fGLDrawCmdsInfo(0),
      49           0 :       fInstanceAttribsBufferUniqueId(SK_InvalidUniqueID) {
      50           0 :     SkASSERT(GrCaps::InstancedSupport::kNone != this->gpu()->caps()->instancedSupport());
      51           0 : }
      52             : 
      53           0 : GLInstancedRendering::~GLInstancedRendering() {
      54           0 :     if (fVertexArrayID) {
      55           0 :         GL_CALL(DeleteVertexArrays(1, &fVertexArrayID));
      56           0 :         this->glGpu()->notifyVertexArrayDelete(fVertexArrayID);
      57             :     }
      58           0 : }
      59             : 
      60           0 : inline GrGLGpu* GLInstancedRendering::glGpu() const {
      61           0 :     return static_cast<GrGLGpu*>(this->gpu());
      62             : }
      63             : 
      64           0 : std::unique_ptr<InstancedRendering::Op> GLInstancedRendering::makeOp(GrPaint&& paint) {
      65           0 :     return std::unique_ptr<Op>(new GLOp(this, std::move(paint)));
      66             : }
      67             : 
      68           0 : void GLInstancedRendering::onBeginFlush(GrResourceProvider* rp) {
      69             :     // Count what there is to draw.
      70           0 :     OpList::Iter iter;
      71           0 :     iter.init(this->trackedOps(), OpList::Iter::kHead_IterStart);
      72           0 :     int numGLInstances = 0;
      73           0 :     int numGLDrawCmds = 0;
      74           0 :     while (Op* o = iter.get()) {
      75           0 :         GLOp* op = static_cast<GLOp*>(o);
      76           0 :         iter.next();
      77             : 
      78           0 :         numGLInstances += op->fNumDraws;
      79           0 :         numGLDrawCmds += op->numGLCommands();
      80           0 :     }
      81           0 :     if (!numGLDrawCmds) {
      82           0 :         return;
      83             :     }
      84           0 :     SkASSERT(numGLInstances);
      85             : 
      86             :     // Lazily create a vertex array object.
      87           0 :     if (!fVertexArrayID) {
      88           0 :         GL_CALL(GenVertexArrays(1, &fVertexArrayID));
      89           0 :         if (!fVertexArrayID) {
      90           0 :             return;
      91             :         }
      92           0 :         this->glGpu()->bindVertexArray(fVertexArrayID);
      93             : 
      94             :         // Attach our index buffer to the vertex array.
      95           0 :         SkASSERT(!this->indexBuffer()->isCPUBacked());
      96           0 :         GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER,
      97             :                            static_cast<const GrGLBuffer*>(this->indexBuffer())->bufferID()));
      98             : 
      99             :         // Set up the non-instanced attribs.
     100           0 :         this->glGpu()->bindBuffer(kVertex_GrBufferType, this->vertexBuffer());
     101           0 :         GL_CALL(EnableVertexAttribArray((int)Attrib::kShapeCoords));
     102           0 :         GL_CALL(VertexAttribPointer((int)Attrib::kShapeCoords, 2, GR_GL_FLOAT, GR_GL_FALSE,
     103             :                                     sizeof(ShapeVertex), (void*) offsetof(ShapeVertex, fX)));
     104           0 :         GL_CALL(EnableVertexAttribArray((int)Attrib::kVertexAttrs));
     105           0 :         GL_CALL(VertexAttribIPointer((int)Attrib::kVertexAttrs, 1, GR_GL_INT, sizeof(ShapeVertex),
     106             :                                      (void*) offsetof(ShapeVertex, fAttrs)));
     107             : 
     108           0 :         SkASSERT(fInstanceAttribsBufferUniqueId.isInvalid());
     109             :     }
     110             : 
     111             :     // Create and map instance and draw-indirect buffers.
     112           0 :     SkASSERT(!fInstanceBuffer);
     113           0 :     fInstanceBuffer.reset(
     114             :         rp->createBuffer(sizeof(Instance) * numGLInstances, kVertex_GrBufferType,
     115             :                          kDynamic_GrAccessPattern,
     116             :                          GrResourceProvider::kNoPendingIO_Flag |
     117           0 :                          GrResourceProvider::kRequireGpuMemory_Flag));
     118           0 :     if (!fInstanceBuffer) {
     119           0 :         return;
     120             :     }
     121             : 
     122           0 :     SkASSERT(!fDrawIndirectBuffer);
     123           0 :     if (this->glGpu()->glCaps().drawIndirectSupport()) {
     124           0 :         fDrawIndirectBuffer.reset(
     125             :             rp->createBuffer(sizeof(GrGLDrawElementsIndirectCommand) * numGLDrawCmds,
     126             :                              kDrawIndirect_GrBufferType, kDynamic_GrAccessPattern,
     127             :                              GrResourceProvider::kNoPendingIO_Flag |
     128           0 :                              GrResourceProvider::kRequireGpuMemory_Flag));
     129           0 :         if (!fDrawIndirectBuffer) {
     130           0 :             return;
     131             :         }
     132             :     }
     133             : 
     134           0 :     Instance* glMappedInstances = static_cast<Instance*>(fInstanceBuffer->map());
     135           0 :     SkASSERT(glMappedInstances);
     136           0 :     int glInstancesIdx = 0;
     137             : 
     138           0 :     GrGLDrawElementsIndirectCommand* glMappedCmds = nullptr;
     139           0 :     int glDrawCmdsIdx = 0;
     140           0 :     if (fDrawIndirectBuffer) {
     141           0 :         glMappedCmds = static_cast<GrGLDrawElementsIndirectCommand*>(fDrawIndirectBuffer->map());
     142           0 :         SkASSERT(glMappedCmds);
     143             :     }
     144             : 
     145           0 :     bool baseInstanceSupport = this->glGpu()->glCaps().baseInstanceSupport();
     146           0 :     SkASSERT(!baseInstanceSupport || fDrawIndirectBuffer);
     147             : 
     148           0 :     SkASSERT(!fGLDrawCmdsInfo);
     149           0 :     if (GR_GL_LOG_INSTANCED_OPS || !baseInstanceSupport) {
     150           0 :         fGLDrawCmdsInfo.reset(numGLDrawCmds);
     151             :     }
     152             : 
     153             :     // Generate the instance and draw-indirect buffer contents based on the tracked ops.
     154           0 :     iter.init(this->trackedOps(), OpList::Iter::kHead_IterStart);
     155           0 :     while (Op* o = iter.get()) {
     156           0 :         GLOp* op = static_cast<GLOp*>(o);
     157           0 :         iter.next();
     158             : 
     159           0 :         op->fEmulatedBaseInstance = baseInstanceSupport ? 0 : glInstancesIdx;
     160           0 :         op->fGLDrawCmdsIdx = glDrawCmdsIdx;
     161             : 
     162           0 :         const Op::Draw* draw = op->fHeadDraw;
     163           0 :         SkASSERT(draw);
     164           0 :         do {
     165           0 :             int instanceCount = 0;
     166           0 :             IndexRange geometry = draw->fGeometry;
     167           0 :             SkASSERT(!geometry.isEmpty());
     168             : 
     169           0 :             do {
     170           0 :                 glMappedInstances[glInstancesIdx + instanceCount++] = draw->fInstance;
     171           0 :                 draw = draw->fNext;
     172           0 :             } while (draw && draw->fGeometry == geometry);
     173             : 
     174           0 :             if (fDrawIndirectBuffer) {
     175           0 :                 GrGLDrawElementsIndirectCommand& glCmd = glMappedCmds[glDrawCmdsIdx];
     176           0 :                 glCmd.fCount = geometry.fCount;
     177           0 :                 glCmd.fInstanceCount = instanceCount;
     178           0 :                 glCmd.fFirstIndex = geometry.fStart;
     179           0 :                 glCmd.fBaseVertex = 0;
     180           0 :                 glCmd.fBaseInstance = baseInstanceSupport ? glInstancesIdx : 0;
     181             :             }
     182             : 
     183           0 :             if (GR_GL_LOG_INSTANCED_OPS || !baseInstanceSupport) {
     184           0 :                 GLDrawCmdInfo& cmdInfo = fGLDrawCmdsInfo[glDrawCmdsIdx];
     185           0 :                 cmdInfo.fGeometry = geometry;
     186           0 :                 cmdInfo.fInstanceCount = instanceCount;
     187             :             }
     188             : 
     189           0 :             glInstancesIdx += instanceCount;
     190           0 :             ++glDrawCmdsIdx;
     191           0 :         } while (draw);
     192           0 :     }
     193             : 
     194           0 :     SkASSERT(glDrawCmdsIdx == numGLDrawCmds);
     195           0 :     if (fDrawIndirectBuffer) {
     196           0 :         fDrawIndirectBuffer->unmap();
     197             :     }
     198             : 
     199           0 :     SkASSERT(glInstancesIdx == numGLInstances);
     200           0 :     fInstanceBuffer->unmap();
     201             : }
     202             : 
     203           0 : void GLInstancedRendering::onDraw(const GrPipeline& pipeline, const InstanceProcessor& instProc,
     204             :                                   const Op* baseOp) {
     205           0 :     if (!fDrawIndirectBuffer && !fGLDrawCmdsInfo) {
     206           0 :         return; // beginFlush was not successful.
     207             :     }
     208           0 :     if (!this->glGpu()->flushGLState(pipeline, instProc, false)) {
     209           0 :         return;
     210             :     }
     211             : 
     212           0 :     if (fDrawIndirectBuffer) {
     213           0 :         this->glGpu()->bindBuffer(kDrawIndirect_GrBufferType, fDrawIndirectBuffer.get());
     214             :     }
     215             : 
     216           0 :     const GrGLCaps& glCaps = this->glGpu()->glCaps();
     217           0 :     const GLOp* op = static_cast<const GLOp*>(baseOp);
     218           0 :     int numCommands = op->numGLCommands();
     219             : 
     220             : #if GR_GL_LOG_INSTANCED_OPS
     221             :     SkASSERT(fGLDrawCmdsInfo);
     222             :     SkDebugf("Instanced op: [");
     223             :     for (int i = 0; i < numCommands; ++i) {
     224             :         int glCmdIdx = op->fGLDrawCmdsIdx + i;
     225             :         SkDebugf("%s%i * %s", (i ? ",  " : ""), fGLDrawCmdsInfo[glCmdIdx].fInstanceCount,
     226             :                  InstanceProcessor::GetNameOfIndexRange(fGLDrawCmdsInfo[glCmdIdx].fGeometry));
     227             :     }
     228             :     SkDebugf("]\n");
     229             : #else
     230           0 :     SkASSERT(SkToBool(fGLDrawCmdsInfo) == !glCaps.baseInstanceSupport());
     231             : #endif
     232             : 
     233           0 :     if (numCommands > 1 && glCaps.multiDrawIndirectSupport() && glCaps.baseInstanceSupport()) {
     234           0 :         SkASSERT(fDrawIndirectBuffer);
     235           0 :         int glCmdsIdx = op->fGLDrawCmdsIdx;
     236           0 :         this->flushInstanceAttribs(op->fEmulatedBaseInstance);
     237           0 :         GL_CALL(MultiDrawElementsIndirect(GR_GL_TRIANGLES, GR_GL_UNSIGNED_BYTE,
     238             :                                           (GrGLDrawElementsIndirectCommand*) nullptr + glCmdsIdx,
     239             :                                           numCommands, 0));
     240           0 :         return;
     241             :     }
     242             : 
     243           0 :     int emulatedBaseInstance = op->fEmulatedBaseInstance;
     244           0 :     for (int i = 0; i < numCommands; ++i) {
     245           0 :         int glCmdIdx = op->fGLDrawCmdsIdx + i;
     246           0 :         this->flushInstanceAttribs(emulatedBaseInstance);
     247           0 :         if (fDrawIndirectBuffer) {
     248           0 :             GL_CALL(DrawElementsIndirect(GR_GL_TRIANGLES, GR_GL_UNSIGNED_BYTE,
     249             :                                          (GrGLDrawElementsIndirectCommand*) nullptr + glCmdIdx));
     250             :         } else {
     251           0 :             const GLDrawCmdInfo& cmdInfo = fGLDrawCmdsInfo[glCmdIdx];
     252           0 :             GL_CALL(DrawElementsInstanced(GR_GL_TRIANGLES, cmdInfo.fGeometry.fCount,
     253             :                                           GR_GL_UNSIGNED_BYTE,
     254             :                                           (GrGLubyte*) nullptr + cmdInfo.fGeometry.fStart,
     255             :                                           cmdInfo.fInstanceCount));
     256             :         }
     257           0 :         if (!glCaps.baseInstanceSupport()) {
     258           0 :             const GLDrawCmdInfo& cmdInfo = fGLDrawCmdsInfo[glCmdIdx];
     259           0 :             emulatedBaseInstance += cmdInfo.fInstanceCount;
     260             :         }
     261             :     }
     262             : }
     263             : 
     264           0 : void GLInstancedRendering::flushInstanceAttribs(int baseInstance) {
     265           0 :     SkASSERT(fVertexArrayID);
     266           0 :     this->glGpu()->bindVertexArray(fVertexArrayID);
     267             : 
     268           0 :     SkASSERT(fInstanceBuffer);
     269           0 :     if (fInstanceAttribsBufferUniqueId != fInstanceBuffer->uniqueID() ||
     270           0 :         fInstanceAttribsBaseInstance != baseInstance) {
     271           0 :         Instance* offsetInBuffer = (Instance*) nullptr + baseInstance;
     272             : 
     273           0 :         this->glGpu()->bindBuffer(kVertex_GrBufferType, fInstanceBuffer.get());
     274             : 
     275             :         // Info attrib.
     276           0 :         GL_CALL(EnableVertexAttribArray((int)Attrib::kInstanceInfo));
     277           0 :         GL_CALL(VertexAttribIPointer((int)Attrib::kInstanceInfo, 1, GR_GL_UNSIGNED_INT,
     278             :                                      sizeof(Instance), &offsetInBuffer->fInfo));
     279           0 :         GL_CALL(VertexAttribDivisor((int)Attrib::kInstanceInfo, 1));
     280             : 
     281             :         // Shape matrix attrib.
     282           0 :         GL_CALL(EnableVertexAttribArray((int)Attrib::kShapeMatrixX));
     283           0 :         GL_CALL(EnableVertexAttribArray((int)Attrib::kShapeMatrixY));
     284           0 :         GL_CALL(VertexAttribPointer((int)Attrib::kShapeMatrixX, 3, GR_GL_FLOAT, GR_GL_FALSE,
     285             :                                     sizeof(Instance), &offsetInBuffer->fShapeMatrix2x3[0]));
     286           0 :         GL_CALL(VertexAttribPointer((int)Attrib::kShapeMatrixY, 3, GR_GL_FLOAT, GR_GL_FALSE,
     287             :                                     sizeof(Instance), &offsetInBuffer->fShapeMatrix2x3[3]));
     288           0 :         GL_CALL(VertexAttribDivisor((int)Attrib::kShapeMatrixX, 1));
     289           0 :         GL_CALL(VertexAttribDivisor((int)Attrib::kShapeMatrixY, 1));
     290             : 
     291             :         // Color attrib.
     292           0 :         GL_CALL(EnableVertexAttribArray((int)Attrib::kColor));
     293           0 :         GL_CALL(VertexAttribPointer((int)Attrib::kColor, 4, GR_GL_UNSIGNED_BYTE, GR_GL_TRUE,
     294             :                                     sizeof(Instance), &offsetInBuffer->fColor));
     295           0 :         GL_CALL(VertexAttribDivisor((int)Attrib::kColor, 1));
     296             : 
     297             :         // Local rect attrib.
     298           0 :         GL_CALL(EnableVertexAttribArray((int)Attrib::kLocalRect));
     299           0 :         GL_CALL(VertexAttribPointer((int)Attrib::kLocalRect, 4, GR_GL_FLOAT, GR_GL_FALSE,
     300             :                                     sizeof(Instance), &offsetInBuffer->fLocalRect));
     301           0 :         GL_CALL(VertexAttribDivisor((int)Attrib::kLocalRect, 1));
     302             : 
     303           0 :         fInstanceAttribsBufferUniqueId = fInstanceBuffer->uniqueID();
     304           0 :         fInstanceAttribsBaseInstance = baseInstance;
     305             :     }
     306           0 : }
     307             : 
     308           0 : void GLInstancedRendering::onEndFlush() {
     309           0 :     fInstanceBuffer.reset();
     310           0 :     fDrawIndirectBuffer.reset();
     311           0 :     fGLDrawCmdsInfo.reset(0);
     312           0 : }
     313             : 
     314           0 : void GLInstancedRendering::onResetGpuResources(ResetType resetType) {
     315           0 :     if (fVertexArrayID && ResetType::kDestroy == resetType) {
     316           0 :         GL_CALL(DeleteVertexArrays(1, &fVertexArrayID));
     317           0 :         this->glGpu()->notifyVertexArrayDelete(fVertexArrayID);
     318             :     }
     319           0 :     fVertexArrayID = 0;
     320           0 :     fInstanceBuffer.reset();
     321           0 :     fDrawIndirectBuffer.reset();
     322           0 :     fInstanceAttribsBufferUniqueId.makeInvalid();
     323           0 : }
     324             : 
     325             : }

Generated by: LCOV version 1.13