Add ES 3.0 fallback for instanced rendering
Adds the ability for GLInstancedRendering to use
glDrawElementsInstanced when glDrawElementsIndirect is not supported.
The only remaining 3.1 dependency now is EXT_texture_buffer.
Also moves the cap for glDraw*Instanced out of GrCaps and into
GrGLCaps.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2193303002
Review-Url: https://codereview.chromium.org/2193303002
diff --git a/src/gpu/instanced/GLInstancedRendering.cpp b/src/gpu/instanced/GLInstancedRendering.cpp
index 440796e..3af1aa7 100644
--- a/src/gpu/instanced/GLInstancedRendering.cpp
+++ b/src/gpu/instanced/GLInstancedRendering.cpp
@@ -34,7 +34,8 @@
GrCaps::InstancedSupport GLInstancedRendering::CheckSupport(const GrGLCaps& glCaps) {
// This method is only intended to be used for initializing fInstancedSupport in the caps.
SkASSERT(GrCaps::InstancedSupport::kNone == glCaps.instancedSupport());
- if (!glCaps.vertexArrayObjectSupport() || !glCaps.drawIndirectSupport()) {
+ if (!glCaps.vertexArrayObjectSupport() ||
+ (!glCaps.drawIndirectSupport() && !glCaps.drawInstancedSupport())) {
return GrCaps::InstancedSupport::kNone;
}
return InstanceProcessor::CheckSupport(*glCaps.glslCaps(), glCaps);
@@ -118,23 +119,32 @@
}
SkASSERT(!fDrawIndirectBuffer);
- fDrawIndirectBuffer.reset(
- rp->createBuffer(sizeof(GrGLDrawElementsIndirectCommand) * numGLDrawCmds,
- kDrawIndirect_GrBufferType, kDynamic_GrAccessPattern,
- GrResourceProvider::kNoPendingIO_Flag |
- GrResourceProvider::kRequireGpuMemory_Flag));
- if (!fDrawIndirectBuffer) {
- return;
+ if (this->glGpu()->glCaps().drawIndirectSupport()) {
+ fDrawIndirectBuffer.reset(
+ rp->createBuffer(sizeof(GrGLDrawElementsIndirectCommand) * numGLDrawCmds,
+ kDrawIndirect_GrBufferType, kDynamic_GrAccessPattern,
+ GrResourceProvider::kNoPendingIO_Flag |
+ GrResourceProvider::kRequireGpuMemory_Flag));
+ if (!fDrawIndirectBuffer) {
+ return;
+ }
}
Instance* glMappedInstances = static_cast<Instance*>(fInstanceBuffer->map());
+ SkASSERT(glMappedInstances);
int glInstancesIdx = 0;
- auto* glMappedCmds = static_cast<GrGLDrawElementsIndirectCommand*>(fDrawIndirectBuffer->map());
+ GrGLDrawElementsIndirectCommand* glMappedCmds = nullptr;
int glDrawCmdsIdx = 0;
+ if (fDrawIndirectBuffer) {
+ glMappedCmds = static_cast<GrGLDrawElementsIndirectCommand*>(fDrawIndirectBuffer->map());
+ SkASSERT(glMappedCmds);
+ }
bool baseInstanceSupport = this->glGpu()->glCaps().baseInstanceSupport();
+ SkASSERT(!baseInstanceSupport || fDrawIndirectBuffer);
+ SkASSERT(!fGLDrawCmdsInfo);
if (GR_GL_LOG_INSTANCED_BATCHES || !baseInstanceSupport) {
fGLDrawCmdsInfo.reset(numGLDrawCmds);
}
@@ -160,18 +170,19 @@
draw = draw->fNext;
} while (draw && draw->fGeometry == geometry);
- GrGLDrawElementsIndirectCommand& glCmd = glMappedCmds[glDrawCmdsIdx];
- glCmd.fCount = geometry.fCount;
- glCmd.fInstanceCount = instanceCount;
- glCmd.fFirstIndex = geometry.fStart;
- glCmd.fBaseVertex = 0;
- glCmd.fBaseInstance = baseInstanceSupport ? glInstancesIdx : 0;
+ if (fDrawIndirectBuffer) {
+ GrGLDrawElementsIndirectCommand& glCmd = glMappedCmds[glDrawCmdsIdx];
+ glCmd.fCount = geometry.fCount;
+ glCmd.fInstanceCount = instanceCount;
+ glCmd.fFirstIndex = geometry.fStart;
+ glCmd.fBaseVertex = 0;
+ glCmd.fBaseInstance = baseInstanceSupport ? glInstancesIdx : 0;
+ }
if (GR_GL_LOG_INSTANCED_BATCHES || !baseInstanceSupport) {
- fGLDrawCmdsInfo[glDrawCmdsIdx].fInstanceCount = instanceCount;
-#if GR_GL_LOG_INSTANCED_BATCHES
- fGLDrawCmdsInfo[glDrawCmdsIdx].fGeometry = geometry;
-#endif
+ GLDrawCmdInfo& cmdInfo = fGLDrawCmdsInfo[glDrawCmdsIdx];
+ cmdInfo.fGeometry = geometry;
+ cmdInfo.fInstanceCount = instanceCount;
}
glInstancesIdx += instanceCount;
@@ -180,7 +191,9 @@
}
SkASSERT(glDrawCmdsIdx == numGLDrawCmds);
- fDrawIndirectBuffer->unmap();
+ if (fDrawIndirectBuffer) {
+ fDrawIndirectBuffer->unmap();
+ }
SkASSERT(glInstancesIdx == numGLInstances);
fInstanceBuffer->unmap();
@@ -188,14 +201,16 @@
void GLInstancedRendering::onDraw(const GrPipeline& pipeline, const InstanceProcessor& instProc,
const Batch* baseBatch) {
- if (!fDrawIndirectBuffer) {
+ if (!fDrawIndirectBuffer && !fGLDrawCmdsInfo) {
return; // beginFlush was not successful.
}
if (!this->glGpu()->flushGLState(pipeline, instProc)) {
return;
}
- this->glGpu()->bindBuffer(kDrawIndirect_GrBufferType, fDrawIndirectBuffer.get());
+ if (fDrawIndirectBuffer) {
+ this->glGpu()->bindBuffer(kDrawIndirect_GrBufferType, fDrawIndirectBuffer.get());
+ }
const GrGLCaps& glCaps = this->glGpu()->glCaps();
const GLBatch* batch = static_cast<const GLBatch*>(baseBatch);
@@ -214,23 +229,33 @@
SkASSERT(SkToBool(fGLDrawCmdsInfo) == !glCaps.baseInstanceSupport());
#endif
- if (1 == numCommands || !glCaps.baseInstanceSupport() || !glCaps.multiDrawIndirectSupport()) {
- int emulatedBaseInstance = batch->fEmulatedBaseInstance;
- for (int i = 0; i < numCommands; ++i) {
- int glCmdIdx = batch->fGLDrawCmdsIdx + i;
- this->flushInstanceAttribs(emulatedBaseInstance);
- GL_CALL(DrawElementsIndirect(GR_GL_TRIANGLES, GR_GL_UNSIGNED_BYTE,
- (GrGLDrawElementsIndirectCommand*) nullptr + glCmdIdx));
- if (!glCaps.baseInstanceSupport()) {
- emulatedBaseInstance += fGLDrawCmdsInfo[glCmdIdx].fInstanceCount;
- }
- }
- } else {
+ if (numCommands > 1 && glCaps.multiDrawIndirectSupport() && glCaps.baseInstanceSupport()) {
+ SkASSERT(fDrawIndirectBuffer);
int glCmdsIdx = batch->fGLDrawCmdsIdx;
this->flushInstanceAttribs(batch->fEmulatedBaseInstance);
GL_CALL(MultiDrawElementsIndirect(GR_GL_TRIANGLES, GR_GL_UNSIGNED_BYTE,
(GrGLDrawElementsIndirectCommand*) nullptr + glCmdsIdx,
numCommands, 0));
+ return;
+ }
+
+ int emulatedBaseInstance = batch->fEmulatedBaseInstance;
+ for (int i = 0; i < numCommands; ++i) {
+ int glCmdIdx = batch->fGLDrawCmdsIdx + i;
+ const GLDrawCmdInfo& cmdInfo = fGLDrawCmdsInfo[glCmdIdx];
+ this->flushInstanceAttribs(emulatedBaseInstance);
+ if (fDrawIndirectBuffer) {
+ GL_CALL(DrawElementsIndirect(GR_GL_TRIANGLES, GR_GL_UNSIGNED_BYTE,
+ (GrGLDrawElementsIndirectCommand*) nullptr + glCmdIdx));
+ } else {
+ GL_CALL(DrawElementsInstanced(GR_GL_TRIANGLES, cmdInfo.fGeometry.fCount,
+ GR_GL_UNSIGNED_BYTE,
+ (GrGLubyte*) nullptr + cmdInfo.fGeometry.fStart,
+ cmdInfo.fInstanceCount));
+ }
+ if (!glCaps.baseInstanceSupport()) {
+ emulatedBaseInstance += cmdInfo.fInstanceCount;
+ }
}
}