Skip to content

Commit 61003cd

Browse files
csmartdalton86Skia Commit-Bot
authored andcommitted
Add support for WEBGL_multi_draw_instanced_base_vertex_base_instance
Bug: skia:10419 Change-Id: I82238c3115daa0c1879fe18a8f8af8199194be80 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/319936 Commit-Queue: Chris Dalton <csmartdalton@google.com> Reviewed-by: Kevin Lubick <kjlubick@google.com>
1 parent e4e0aad commit 61003cd

File tree

7 files changed

+99
-43
lines changed

7 files changed

+99
-43
lines changed

src/gpu/gl/GrGLAssembleWebGLInterfaceAutogen.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,11 +174,21 @@ sk_sp<const GrGLInterface> GrGLMakeAssembledWebGLInterface(void *ctx, GrGLGetPro
174174
GET_PROC(DrawElementsInstanced);
175175
}
176176

177+
if (extensions.has("GL_WEBGL_draw_instanced_base_vertex_base_instance")) {
178+
GET_PROC_SUFFIX(DrawArraysInstancedBaseInstance, WEBGL);
179+
GET_PROC_SUFFIX(DrawElementsInstancedBaseVertexBaseInstance, WEBGL);
180+
}
181+
177182
if (glVer >= GR_GL_VER(2,0)) {
178183
GET_PROC(DrawBuffers);
179184
GET_PROC(ReadBuffer);
180185
}
181186

187+
if (extensions.has("GL_WEBGL_multi_draw_instanced_base_vertex_base_instance")) {
188+
GET_PROC_SUFFIX(MultiDrawArraysInstancedBaseInstance, WEBGL);
189+
GET_PROC_SUFFIX(MultiDrawElementsInstancedBaseVertexBaseInstance, WEBGL);
190+
}
191+
182192
if (glVer >= GR_GL_VER(2,0)) {
183193
GET_PROC(DrawRangeElements);
184194
}

src/gpu/gl/GrGLCaps.cpp

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions,
3939
fDebugSupport = false;
4040
fES2CompatibilitySupport = false;
4141
fDrawRangeElementsSupport = false;
42-
fANGLEMultiDrawSupport = false;
43-
fMultiDrawIndirectSupport = false;
4442
fBaseVertexBaseInstanceSupport = false;
4543
fUseNonVBOVertexAndIndexDynamicData = false;
4644
fIsCoreProfile = false;
@@ -636,27 +634,38 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
636634
if (fBaseVertexBaseInstanceSupport) {
637635
fNativeDrawIndirectSupport = version >= GR_GL_VER(4,0) ||
638636
ctxInfo.hasExtension("GL_ARB_draw_indirect");
639-
fMultiDrawIndirectSupport = version >= GR_GL_VER(4,3) ||
640-
ctxInfo.hasExtension("GL_ARB_multi_draw_indirect");
637+
if (version >= GR_GL_VER(4,3) || ctxInfo.hasExtension("GL_ARB_multi_draw_indirect")) {
638+
fMultiDrawType = MultiDrawType::kMultiDrawIndirect;
639+
}
641640
}
642641
fDrawRangeElementsSupport = version >= GR_GL_VER(2,0);
643642
} else if (GR_IS_GR_GL_ES(standard)) {
644643
if (ctxInfo.hasExtension("GL_ANGLE_base_vertex_base_instance")) {
645644
fBaseVertexBaseInstanceSupport = true;
646645
fNativeDrawIndirectSupport = true;
647-
fANGLEMultiDrawSupport = true;
646+
fMultiDrawType = MultiDrawType::kANGLEOrWebGL;
648647
// The indirect structs need to reside in CPU memory for the ANGLE version.
649648
fUseClientSideIndirectBuffers = true;
650649
} else {
651650
fBaseVertexBaseInstanceSupport = ctxInfo.hasExtension("GL_EXT_base_instance");
652651
if (fBaseVertexBaseInstanceSupport) {
653652
fNativeDrawIndirectSupport = (version >= GR_GL_VER(3,1));
654-
fMultiDrawIndirectSupport = ctxInfo.hasExtension("GL_EXT_multi_draw_indirect");
653+
if (ctxInfo.hasExtension("GL_EXT_multi_draw_indirect")) {
654+
fMultiDrawType = MultiDrawType::kMultiDrawIndirect;
655+
}
655656
}
656657
}
657658
fDrawRangeElementsSupport = version >= GR_GL_VER(3,0);
658659
} else if (GR_IS_GR_WEBGL(standard)) {
659-
// WebGL lacks indirect support, but drawRange was added in WebGL 2.0
660+
fBaseVertexBaseInstanceSupport = ctxInfo.hasExtension(
661+
"WEBGL_draw_instanced_base_vertex_base_instance");
662+
if (fBaseVertexBaseInstanceSupport && ctxInfo.hasExtension(
663+
"GL_WEBGL_multi_draw_instanced_base_vertex_base_instance")) {
664+
fNativeDrawIndirectSupport = true;
665+
fMultiDrawType = MultiDrawType::kANGLEOrWebGL;
666+
}
667+
// The indirect structs need to reside in CPU memory for the WebGL version.
668+
fUseClientSideIndirectBuffers = true;
660669
fDrawRangeElementsSupport = version >= GR_GL_VER(2,0);
661670
}
662671

@@ -1135,6 +1144,15 @@ void GrGLCaps::initStencilSupport(const GrGLContextInfo& ctxInfo) {
11351144
}
11361145

11371146
#ifdef SK_ENABLE_DUMP_GPU
1147+
static const char* multi_draw_type_name(GrGLCaps::MultiDrawType multiDrawType) {
1148+
switch (multiDrawType) {
1149+
case GrGLCaps::MultiDrawType::kNone : return "kNone";
1150+
case GrGLCaps::MultiDrawType::kMultiDrawIndirect : return "kMultiDrawIndirect";
1151+
case GrGLCaps::MultiDrawType::kANGLEOrWebGL : return "kMultiDrawIndirect";
1152+
}
1153+
SkUNREACHABLE;
1154+
}
1155+
11381156
void GrGLCaps::onDumpJSON(SkJSONWriter* writer) const {
11391157

11401158
// We are called by the base class, which has already called beginObject(). We choose to nest
@@ -1192,14 +1210,14 @@ void GrGLCaps::onDumpJSON(SkJSONWriter* writer) const {
11921210
writer->appendString("MSAA Type", kMSFBOExtStr[fMSFBOType]);
11931211
writer->appendString("Invalidate FB Type", kInvalidateFBTypeStr[fInvalidateFBType]);
11941212
writer->appendString("Map Buffer Type", kMapBufferTypeStr[fMapBufferType]);
1213+
writer->appendString("Multi Draw Type", multi_draw_type_name(fMultiDrawType));
11951214
writer->appendS32("Max FS Uniform Vectors", fMaxFragmentUniformVectors);
11961215
writer->appendBool("Pack Flip Y support", fPackFlipYSupport);
11971216

11981217
writer->appendBool("Texture Usage support", fTextureUsageSupport);
11991218
writer->appendBool("GL_ARB_imaging support", fImagingSupport);
12001219
writer->appendBool("Vertex array object support", fVertexArrayObjectSupport);
12011220
writer->appendBool("Debug support", fDebugSupport);
1202-
writer->appendBool("Multi draw indirect support", fMultiDrawIndirectSupport);
12031221
writer->appendBool("Base (vertex base) instance support", fBaseVertexBaseInstanceSupport);
12041222
writer->appendBool("RGBA 8888 pixel ops are slow", fRGBA8888PixelsOpsAreSlow);
12051223
writer->appendBool("Partial FBO read is slow", fPartialFBOReadIsSlow);
@@ -3616,14 +3634,14 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
36163634
ctxInfo.angleBackend() != GrGLANGLEBackend::kOpenGL) {
36173635
fBaseVertexBaseInstanceSupport = false;
36183636
fNativeDrawIndirectSupport = false;
3619-
fMultiDrawIndirectSupport = false;
3637+
fMultiDrawType = MultiDrawType::kNone;
36203638
}
36213639

36223640
// http://anglebug.com/4538
36233641
if (fBaseVertexBaseInstanceSupport && !fDrawInstancedSupport) {
36243642
fBaseVertexBaseInstanceSupport = false;
36253643
fNativeDrawIndirectSupport = false;
3626-
fMultiDrawIndirectSupport = false;
3644+
fMultiDrawType = MultiDrawType::kNone;
36273645
}
36283646

36293647
// Currently the extension is advertised but fb fetch is broken on 500 series Adrenos like the

src/gpu/gl/GrGLCaps.h

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,13 @@ class GrGLCaps : public GrCaps {
104104
kNVFence
105105
};
106106

107+
enum class MultiDrawType {
108+
kNone,
109+
kMultiDrawIndirect, // ARB_multi_draw_indirect, EXT_multi_draw_indirect, or GL 4.3 core.
110+
kANGLEOrWebGL // ANGLE_base_vertex_base_instance or
111+
// WEBGL_draw_instanced_base_vertex_base_instance
112+
};
113+
107114
/**
108115
* Initializes the GrGLCaps to the set of features supported in the current
109116
* OpenGL context accessible via ctxInfo.
@@ -283,6 +290,9 @@ class GrGLCaps : public GrCaps {
283290
/// How are GrFences implemented?
284291
FenceType fenceType() const { return fFenceType; }
285292

293+
/// How are multi draws implemented (if at all)?
294+
MultiDrawType multiDrawType() const { return fMultiDrawType; }
295+
286296
/// The maximum number of fragment uniform vectors (GLES has min. 16).
287297
int maxFragmentUniformVectors() const { return fMaxFragmentUniformVectors; }
288298

@@ -304,13 +314,6 @@ class GrGLCaps : public GrCaps {
304314
/// Is there support for ES2 compatability?
305315
bool ES2CompatibilitySupport() const { return fES2CompatibilitySupport; }
306316

307-
/// Is there support for GL_ANGLE_base_vertex_base_instance?
308-
bool ANGLEMultiDrawSupport() const { return fANGLEMultiDrawSupport; }
309-
310-
/// Is there support for glMultiDraw*Indirect? Note that the baseInstance fields of indirect
311-
/// draw commands cannot be used unless we have base instance support.
312-
bool multiDrawIndirectSupport() const { return fMultiDrawIndirectSupport; }
313-
314317
/// Is there support for glDrawRangeElements?
315318
bool drawRangeElementsSupport() const { return fDrawRangeElementsSupport; }
316319

@@ -526,6 +529,7 @@ class GrGLCaps : public GrCaps {
526529
MapBufferType fMapBufferType = kNone_MapBufferType;
527530
TransferBufferType fTransferBufferType = TransferBufferType::kNone;
528531
FenceType fFenceType = FenceType::kNone;
532+
MultiDrawType fMultiDrawType = MultiDrawType::kNone;
529533

530534
bool fPackFlipYSupport : 1;
531535
bool fTextureUsageSupport : 1;
@@ -534,8 +538,6 @@ class GrGLCaps : public GrCaps {
534538
bool fDebugSupport : 1;
535539
bool fES2CompatibilitySupport : 1;
536540
bool fDrawRangeElementsSupport : 1;
537-
bool fANGLEMultiDrawSupport : 1;
538-
bool fMultiDrawIndirectSupport : 1;
539541
bool fBaseVertexBaseInstanceSupport : 1;
540542
bool fUseNonVBOVertexAndIndexDynamicData : 1;
541543
bool fIsCoreProfile : 1;

src/gpu/gl/GrGLInterfaceAutogen.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,9 @@ bool GrGLInterface::validate() const {
289289
fExtensions.has("GL_ARB_base_instance"))) ||
290290
(GR_IS_GR_GL_ES(fStandard) && (
291291
fExtensions.has("GL_EXT_base_instance") ||
292-
fExtensions.has("GL_ANGLE_base_vertex_base_instance")))) {
292+
fExtensions.has("GL_ANGLE_base_vertex_base_instance"))) ||
293+
(GR_IS_GR_WEBGL(fStandard) && (
294+
fExtensions.has("GL_WEBGL_draw_instanced_base_vertex_base_instance")))) {
293295
if (!fFunctions.fDrawArraysInstancedBaseInstance ||
294296
!fFunctions.fDrawElementsInstancedBaseVertexBaseInstance) {
295297
RETURN_FALSE_INTERFACE;
@@ -319,7 +321,9 @@ bool GrGLInterface::validate() const {
319321
}
320322

321323
if ((GR_IS_GR_GL_ES(fStandard) && (
322-
fExtensions.has("GL_ANGLE_base_vertex_base_instance")))) {
324+
fExtensions.has("GL_ANGLE_base_vertex_base_instance"))) ||
325+
(GR_IS_GR_WEBGL(fStandard) && (
326+
fExtensions.has("GL_WEBGL_multi_draw_instanced_base_vertex_base_instance")))) {
323327
if (!fFunctions.fMultiDrawArraysInstancedBaseInstance ||
324328
!fFunctions.fMultiDrawElementsInstancedBaseVertexBaseInstance) {
325329
RETURN_FALSE_INTERFACE;

src/gpu/gl/GrGLOpsRenderPass.cpp

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,8 @@ static const void* buffer_offset_to_gl_address(const GrBuffer* drawIndirectBuffe
232232

233233
void GrGLOpsRenderPass::onDrawIndirect(const GrBuffer* drawIndirectBuffer, size_t offset,
234234
int drawCount) {
235+
using MultiDrawType = GrGLCaps::MultiDrawType;
236+
235237
SkASSERT(fGpu->caps()->nativeDrawIndirectSupport());
236238
SkASSERT(fGpu->glCaps().baseVertexBaseInstanceSupport());
237239
SkASSERT(fDidBindVertexBuffer || fGpu->glCaps().drawArraysBaseVertexIsBroken());
@@ -242,14 +244,15 @@ void GrGLOpsRenderPass::onDrawIndirect(const GrBuffer* drawIndirectBuffer, size_
242244
this->bindVertexBuffer(fActiveVertexBuffer.get(), 0);
243245
}
244246

245-
if (fGpu->glCaps().ANGLEMultiDrawSupport()) {
246-
this->multiDrawArraysANGLE(drawIndirectBuffer, offset, drawCount);
247+
if (fGpu->glCaps().multiDrawType() == MultiDrawType::kANGLEOrWebGL) {
248+
// ANGLE and WebGL don't support glDrawElementsIndirect. We draw everything as a multi draw.
249+
this->multiDrawArraysANGLEOrWebGL(drawIndirectBuffer, offset, drawCount);
247250
return;
248251
}
249252

250253
fGpu->bindBuffer(GrGpuBufferType::kDrawIndirect, drawIndirectBuffer);
251254

252-
if (fGpu->glCaps().multiDrawIndirectSupport() && drawCount > 1) {
255+
if (drawCount > 1 && fGpu->glCaps().multiDrawType() == MultiDrawType::kMultiDrawIndirect) {
253256
GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
254257
GL_CALL(MultiDrawArraysIndirect(glPrimType,
255258
buffer_offset_to_gl_address(drawIndirectBuffer, offset),
@@ -265,9 +268,9 @@ void GrGLOpsRenderPass::onDrawIndirect(const GrBuffer* drawIndirectBuffer, size_
265268
}
266269
}
267270

268-
void GrGLOpsRenderPass::multiDrawArraysANGLE(const GrBuffer* drawIndirectBuffer, size_t offset,
269-
int drawCount) {
270-
SkASSERT(fGpu->glCaps().ANGLEMultiDrawSupport());
271+
void GrGLOpsRenderPass::multiDrawArraysANGLEOrWebGL(const GrBuffer* drawIndirectBuffer,
272+
size_t offset, int drawCount) {
273+
SkASSERT(fGpu->glCaps().multiDrawType() == GrGLCaps::MultiDrawType::kANGLEOrWebGL);
271274
SkASSERT(drawIndirectBuffer->isCpuBuffer());
272275

273276
constexpr static int kMaxDrawCountPerBatch = 128;
@@ -289,30 +292,39 @@ void GrGLOpsRenderPass::multiDrawArraysANGLE(const GrBuffer* drawIndirectBuffer,
289292
fInstanceCounts[i] = cmd.fInstanceCount;
290293
fBaseInstances[i] = cmd.fBaseInstance;
291294
}
292-
GL_CALL(MultiDrawArraysInstancedBaseInstance(glPrimType, fFirsts, fCounts, fInstanceCounts,
293-
fBaseInstances, countInBatch));
295+
if (countInBatch == 1) {
296+
GL_CALL(DrawArraysInstancedBaseInstance(glPrimType, fFirsts[0], fCounts[0],
297+
fInstanceCounts[0], fBaseInstances[0]));
298+
} else {
299+
GL_CALL(MultiDrawArraysInstancedBaseInstance(glPrimType, fFirsts, fCounts,
300+
fInstanceCounts, fBaseInstances,
301+
countInBatch));
302+
}
294303
drawCount -= countInBatch;
295304
cmds += countInBatch;
296305
}
297306
}
298307

299308
void GrGLOpsRenderPass::onDrawIndexedIndirect(const GrBuffer* drawIndirectBuffer, size_t offset,
300309
int drawCount) {
310+
using MultiDrawType = GrGLCaps::MultiDrawType;
311+
301312
SkASSERT(fGpu->caps()->nativeDrawIndirectSupport());
302313
SkASSERT(!fGpu->caps()->nativeDrawIndexedIndirectIsBroken());
303314
SkASSERT(fGpu->glCaps().baseVertexBaseInstanceSupport());
304315
// The vertex buffer should have already gotten bound (as opposed us stashing it away during
305316
// onBindBuffers and not expecting to bind it until this point).
306317
SkASSERT(fDidBindVertexBuffer);
307318

308-
if (fGpu->glCaps().ANGLEMultiDrawSupport()) {
309-
this->multiDrawElementsANGLE(drawIndirectBuffer, offset, drawCount);
319+
if (fGpu->glCaps().multiDrawType() == MultiDrawType::kANGLEOrWebGL) {
320+
// ANGLE and WebGL don't support glDrawElementsIndirect. We draw everything as a multi draw.
321+
this->multiDrawElementsANGLEOrWebGL(drawIndirectBuffer, offset, drawCount);
310322
return;
311323
}
312324

313325
fGpu->bindBuffer(GrGpuBufferType::kDrawIndirect, drawIndirectBuffer);
314326

315-
if (fGpu->glCaps().multiDrawIndirectSupport() && drawCount > 1) {
327+
if (drawCount > 1 && fGpu->glCaps().multiDrawType() == MultiDrawType::kMultiDrawIndirect) {
316328
GrGLenum glPrimType = fGpu->prepareToDraw(fPrimitiveType);
317329
GL_CALL(MultiDrawElementsIndirect(glPrimType, GR_GL_UNSIGNED_SHORT,
318330
buffer_offset_to_gl_address(drawIndirectBuffer, offset),
@@ -328,9 +340,9 @@ void GrGLOpsRenderPass::onDrawIndexedIndirect(const GrBuffer* drawIndirectBuffer
328340
}
329341
}
330342

331-
void GrGLOpsRenderPass::multiDrawElementsANGLE(const GrBuffer* drawIndirectBuffer, size_t offset,
332-
int drawCount) {
333-
SkASSERT(fGpu->glCaps().ANGLEMultiDrawSupport());
343+
void GrGLOpsRenderPass::multiDrawElementsANGLEOrWebGL(const GrBuffer* drawIndirectBuffer,
344+
size_t offset, int drawCount) {
345+
SkASSERT(fGpu->glCaps().multiDrawType() == GrGLCaps::MultiDrawType::kANGLEOrWebGL);
334346
SkASSERT(drawIndirectBuffer->isCpuBuffer());
335347

336348
constexpr static int kMaxDrawCountPerBatch = 128;
@@ -354,10 +366,18 @@ void GrGLOpsRenderPass::multiDrawElementsANGLE(const GrBuffer* drawIndirectBuffe
354366
fBaseVertices[i] = cmd.fBaseVertex;
355367
fBaseInstances[i] = cmd.fBaseInstance;
356368
}
357-
GL_CALL(MultiDrawElementsInstancedBaseVertexBaseInstance(glPrimType, fCounts,
358-
GR_GL_UNSIGNED_SHORT, fIndices,
359-
fInstanceCounts, fBaseVertices,
360-
fBaseInstances, countInBatch));
369+
if (countInBatch == 1) {
370+
GL_CALL(DrawElementsInstancedBaseVertexBaseInstance(glPrimType, fCounts[0],
371+
GR_GL_UNSIGNED_SHORT, fIndices[0],
372+
fInstanceCounts[0],
373+
fBaseVertices[0],
374+
fBaseInstances[0]));
375+
} else {
376+
GL_CALL(MultiDrawElementsInstancedBaseVertexBaseInstance(glPrimType, fCounts,
377+
GR_GL_UNSIGNED_SHORT, fIndices,
378+
fInstanceCounts, fBaseVertices,
379+
fBaseInstances, countInBatch));
380+
}
361381
drawCount -= countInBatch;
362382
cmds += countInBatch;
363383
}

src/gpu/gl/GrGLOpsRenderPass.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,12 @@ class GrGLOpsRenderPass : public GrOpsRenderPass {
6767
void onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount, int baseInstance,
6868
int baseVertex) override;
6969
void onDrawIndirect(const GrBuffer* drawIndirectBuffer, size_t offset, int drawCount) override;
70-
void multiDrawArraysANGLE(const GrBuffer* drawIndirectBuffer, size_t offset, int drawCount);
70+
void multiDrawArraysANGLEOrWebGL(const GrBuffer* drawIndirectBuffer, size_t offset,
71+
int drawCount);
7172
void onDrawIndexedIndirect(const GrBuffer* drawIndirectBuffer, size_t offset,
7273
int drawCount) override;
73-
void multiDrawElementsANGLE(const GrBuffer* drawIndirectBuffer, size_t offset, int drawCount);
74+
void multiDrawElementsANGLEOrWebGL(const GrBuffer* drawIndirectBuffer, size_t offset,
75+
int drawCount);
7476
void onClear(const GrScissorState& scissor, const SkPMColor4f& color) override;
7577
void onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) override;
7678

tools/gpu/gl/interface/interface.json5

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@
170170
{/* else if */ "ext": "GL_ARB_base_instance"}],
171171
"GLES": [{"ext": "GL_EXT_base_instance"},
172172
{/* else if */ "ext": "GL_ANGLE_base_vertex_base_instance"}],
173-
"WebGL": null,
173+
"WebGL": [{"ext": "GL_WEBGL_draw_instanced_base_vertex_base_instance"}],
174174

175175
"functions": [
176176
"DrawArraysInstancedBaseInstance", "DrawElementsInstancedBaseVertexBaseInstance"
@@ -201,7 +201,7 @@
201201
{
202202
"GL": null,
203203
"GLES": [{"ext": "GL_ANGLE_base_vertex_base_instance"}],
204-
"WebGL": null,
204+
"WebGL": [{"ext": "GL_WEBGL_multi_draw_instanced_base_vertex_base_instance"}],
205205

206206
"functions": [
207207
"MultiDrawArraysInstancedBaseInstance", "MultiDrawElementsInstancedBaseVertexBaseInstance",

0 commit comments

Comments
 (0)