aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar csmartdalton <csmartdalton@google.com>2016-07-29 12:19:28 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-07-29 12:19:28 -0700
commit4c18b62a004599d5a36ab7d772302dff2be91a3b (patch)
tree4b97320146b07dc9ccfdaae3f42e2221dda77ded /src
parent848904e5b356ac427ccf68f8a39837e52fa61059 (diff)
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
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrCaps.cpp2
-rw-r--r--src/gpu/gl/GrGLCaps.cpp15
-rw-r--r--src/gpu/gl/GrGLCaps.h4
-rw-r--r--src/gpu/instanced/GLInstancedRendering.cpp93
-rw-r--r--src/gpu/instanced/GLInstancedRendering.h4
5 files changed, 74 insertions, 44 deletions
diff --git a/src/gpu/GrCaps.cpp b/src/gpu/GrCaps.cpp
index fa4230f9fc..33c22be9a0 100644
--- a/src/gpu/GrCaps.cpp
+++ b/src/gpu/GrCaps.cpp
@@ -99,7 +99,6 @@ GrCaps::GrCaps(const GrContextOptions& options) {
fMultisampleDisableSupport = false;
fUsesMixedSamples = false;
fPreferClientSideDynamicBuffers = false;
- fSupportsInstancedDraws = false;
fFullClearIsFree = false;
fMustClearUploadedBufferData = false;
fSampleShadingSupport = false;
@@ -181,7 +180,6 @@ SkString GrCaps::dump() const {
r.appendf("Multisample disable support : %s\n", gNY[fMultisampleDisableSupport]);
r.appendf("Uses Mixed Samples : %s\n", gNY[fUsesMixedSamples]);
r.appendf("Prefer client-side dynamic buffers : %s\n", gNY[fPreferClientSideDynamicBuffers]);
- r.appendf("Supports instanced draws : %s\n", gNY[fSupportsInstancedDraws]);
r.appendf("Full screen clear is free : %s\n", gNY[fFullClearIsFree]);
r.appendf("Must clear buffer memory : %s\n", gNY[fMustClearUploadedBufferData]);
r.appendf("Draw Instead of Clear [workaround] : %s\n", gNY[fUseDrawInsteadOfClear]);
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 653b5ca725..5a1a5b459b 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -38,6 +38,7 @@ GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions,
fDirectStateAccessSupport = false;
fDebugSupport = false;
fES2CompatibilitySupport = false;
+ fDrawInstancedSupport = false;
fDrawIndirectSupport = false;
fMultiDrawIndirectSupport = false;
fBaseInstanceSupport = false;
@@ -502,12 +503,12 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
if (kGL_GrGLStandard == standard) {
// 3.1 has draw_instanced but not instanced_arrays, for the time being we only care about
// instanced arrays, but we could make this more granular if we wanted
- fSupportsInstancedDraws =
+ fDrawInstancedSupport =
version >= GR_GL_VER(3, 2) ||
(ctxInfo.hasExtension("GL_ARB_draw_instanced") &&
ctxInfo.hasExtension("GL_ARB_instanced_arrays"));
} else {
- fSupportsInstancedDraws =
+ fDrawInstancedSupport =
version >= GR_GL_VER(3, 0) ||
(ctxInfo.hasExtension("GL_EXT_draw_instanced") &&
ctxInfo.hasExtension("GL_EXT_instanced_arrays"));
@@ -518,12 +519,15 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
ctxInfo.hasExtension("GL_ARB_draw_indirect");
fBaseInstanceSupport = version >= GR_GL_VER(4,2);
fMultiDrawIndirectSupport = version >= GR_GL_VER(4,3) ||
- (!fBaseInstanceSupport && // The ARB extension has no base inst.
+ (fDrawIndirectSupport &&
+ !fBaseInstanceSupport && // The ARB extension has no base inst.
ctxInfo.hasExtension("GL_ARB_multi_draw_indirect"));
} else {
fDrawIndirectSupport = version >= GR_GL_VER(3,1);
- fMultiDrawIndirectSupport = ctxInfo.hasExtension("GL_EXT_multi_draw_indirect");
- fBaseInstanceSupport = ctxInfo.hasExtension("GL_EXT_base_instance");
+ fMultiDrawIndirectSupport = fDrawIndirectSupport &&
+ ctxInfo.hasExtension("GL_EXT_multi_draw_indirect");
+ fBaseInstanceSupport = fDrawIndirectSupport &&
+ ctxInfo.hasExtension("GL_EXT_base_instance");
}
this->initShaderPrecisionTable(ctxInfo, gli, glslCaps);
@@ -1105,6 +1109,7 @@ SkString GrGLCaps::dump() const {
r.appendf("Vertex array object support: %s\n", (fVertexArrayObjectSupport ? "YES": "NO"));
r.appendf("Direct state access support: %s\n", (fDirectStateAccessSupport ? "YES": "NO"));
r.appendf("Debug support: %s\n", (fDebugSupport ? "YES": "NO"));
+ r.appendf("Draw instanced support: %s\n", (fDrawInstancedSupport ? "YES" : "NO"));
r.appendf("Draw indirect support: %s\n", (fDrawIndirectSupport ? "YES" : "NO"));
r.appendf("Multi draw indirect support: %s\n", (fMultiDrawIndirectSupport ? "YES" : "NO"));
r.appendf("Base instance support: %s\n", (fBaseInstanceSupport ? "YES" : "NO"));
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index 0cb353aa9f..3408ae0e8f 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -296,6 +296,9 @@ public:
/// Is there support for ES2 compatability?
bool ES2CompatibilitySupport() const { return fES2CompatibilitySupport; }
+ /// Is there support for glDraw*Instanced?
+ bool drawInstancedSupport() const { return fDrawInstancedSupport; }
+
/// Is there support for glDraw*Indirect? Note that the baseInstance fields of indirect draw
/// commands cannot be used unless we have base instance support.
bool drawIndirectSupport() const { return fDrawIndirectSupport; }
@@ -395,6 +398,7 @@ private:
bool fDirectStateAccessSupport : 1;
bool fDebugSupport : 1;
bool fES2CompatibilitySupport : 1;
+ bool fDrawInstancedSupport : 1;
bool fDrawIndirectSupport : 1;
bool fMultiDrawIndirectSupport : 1;
bool fBaseInstanceSupport : 1;
diff --git a/src/gpu/instanced/GLInstancedRendering.cpp b/src/gpu/instanced/GLInstancedRendering.cpp
index 440796e19a..3af1aa7ab3 100644
--- a/src/gpu/instanced/GLInstancedRendering.cpp
+++ b/src/gpu/instanced/GLInstancedRendering.cpp
@@ -34,7 +34,8 @@ private:
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 @@ void GLInstancedRendering::onBeginFlush(GrResourceProvider* rp) {
}
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 @@ void GLInstancedRendering::onBeginFlush(GrResourceProvider* rp) {
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 @@ void GLInstancedRendering::onBeginFlush(GrResourceProvider* rp) {
}
SkASSERT(glDrawCmdsIdx == numGLDrawCmds);
- fDrawIndirectBuffer->unmap();
+ if (fDrawIndirectBuffer) {
+ fDrawIndirectBuffer->unmap();
+ }
SkASSERT(glInstancesIdx == numGLInstances);
fInstanceBuffer->unmap();
@@ -188,14 +201,16 @@ void GLInstancedRendering::onBeginFlush(GrResourceProvider* rp) {
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 @@ void GLInstancedRendering::onDraw(const GrPipeline& pipeline, const InstanceProc
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;
+ }
}
}
diff --git a/src/gpu/instanced/GLInstancedRendering.h b/src/gpu/instanced/GLInstancedRendering.h
index 4e17cb4535..ce1638c7fc 100644
--- a/src/gpu/instanced/GLInstancedRendering.h
+++ b/src/gpu/instanced/GLInstancedRendering.h
@@ -43,10 +43,8 @@ private:
void flushInstanceAttribs(int baseInstance);
struct GLDrawCmdInfo {
- int fInstanceCount;
-#if GR_GL_LOG_INSTANCED_BATCHES
IndexRange fGeometry;
-#endif
+ int fInstanceCount;
};
GrGLuint fVertexArrayID;