Add GL indirect drawing APIs
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1666803002
Review URL: https://codereview.chromium.org/1666803002
diff --git a/include/gpu/gl/GrGLFunctions.h b/include/gpu/gl/GrGLFunctions.h
index 1086186..ad59ec0 100644
--- a/include/gpu/gl/GrGLFunctions.h
+++ b/include/gpu/gl/GrGLFunctions.h
@@ -13,14 +13,6 @@
extern "C" {
-typedef void (GR_GL_FUNCTION_TYPE* GRGLDEBUGPROC)(GrGLenum source,
- GrGLenum type,
- GrGLuint id,
- GrGLenum severity,
- GrGLsizei length,
- const GrGLchar* message,
- const void* userParam);
-
///////////////////////////////////////////////////////////////////////////////
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLActiveTextureProc)(GrGLenum texture);
@@ -66,9 +58,13 @@
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDisableProc)(GrGLenum cap);
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDisableVertexAttribArrayProc)(GrGLuint index);
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawArraysProc)(GrGLenum mode, GrGLint first, GrGLsizei count);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawArraysInstancedProc)(GrGLenum mode, GrGLint first, GrGLsizei count, GrGLsizei primcount);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawArraysIndirectProc)(GrGLenum mode, GrGLvoid* indirect);
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawBufferProc)(GrGLenum mode);
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawBuffersProc)(GrGLsizei n, const GrGLenum* bufs);
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawElementsProc)(GrGLenum mode, GrGLsizei count, GrGLenum type, const GrGLvoid* indices);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawElementsInstancedProc)(GrGLenum mode, GrGLsizei count, GrGLenum type, const GrGLvoid *indices, GrGLsizei primcount);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawElementsIndirectProc)(GrGLenum mode, GrGLenum type, GrGLvoid* indirect);
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLEGLImageTargetTexture2DProc)(GrGLenum target, GrGLeglImage image);
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLEnableProc)(GrGLenum cap);
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLEnableVertexAttribArrayProc)(GrGLuint index);
@@ -179,6 +175,7 @@
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLVertexAttrib2fvProc)(GrGLuint indx, const GrGLfloat* values);
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLVertexAttrib3fvProc)(GrGLuint indx, const GrGLfloat* values);
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLVertexAttrib4fvProc)(GrGLuint indx, const GrGLfloat* values);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLVertexAttribDivisorProc)(GrGLuint index, GrGLuint divisor);
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLVertexAttribPointerProc)(GrGLuint indx, GrGLint size, GrGLenum type, GrGLboolean normalized, GrGLsizei stride, const GrGLvoid* ptr);
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLViewportProc)(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height);
@@ -216,12 +213,9 @@
/* GL_NV_framebuffer_mixed_samples */
typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCoverageModulationProc)(GrGLenum components);
-/* ARB_draw_instanced */
-typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawArraysInstancedProc)(GrGLenum mode, GrGLint first, GrGLsizei count, GrGLsizei primcount);
-typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLDrawElementsInstancedProc)(GrGLenum mode, GrGLsizei count, GrGLenum type, const GrGLvoid *indices, GrGLsizei primcount);
-
-/* ARB_instanced_arrays */
-typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLVertexAttribDivisorProc)(GrGLuint index, GrGLuint divisor);
+/* EXT_multi_draw_indirect */
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLMultiDrawArraysIndirectProc)(GrGLenum mode, const GrGLvoid *indirect, GrGLsizei drawcount, GrGLsizei stride);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLMultiDrawElementsIndirectProc)(GrGLenum mode, GrGLenum type, const GrGLvoid *indirect, GrGLsizei drawcount, GrGLsizei stride);
/* NV_bindless_texture */
typedef GrGLuint64 (GR_GL_FUNCTION_TYPE* GrGLGetTextureHandleProc)(GrGLuint texture);
diff --git a/include/gpu/gl/GrGLInterface.h b/include/gpu/gl/GrGLInterface.h
index 5fa31ed..dd9a9fb 100644
--- a/include/gpu/gl/GrGLInterface.h
+++ b/include/gpu/gl/GrGLInterface.h
@@ -196,9 +196,13 @@
GLPtr<GrGLDisableProc> fDisable;
GLPtr<GrGLDisableVertexAttribArrayProc> fDisableVertexAttribArray;
GLPtr<GrGLDrawArraysProc> fDrawArrays;
+ GLPtr<GrGLDrawArraysIndirectProc> fDrawArraysIndirect;
+ GLPtr<GrGLDrawArraysInstancedProc> fDrawArraysInstanced;
GLPtr<GrGLDrawBufferProc> fDrawBuffer;
GLPtr<GrGLDrawBuffersProc> fDrawBuffers;
GLPtr<GrGLDrawElementsProc> fDrawElements;
+ GLPtr<GrGLDrawElementsIndirectProc> fDrawElementsIndirect;
+ GLPtr<GrGLDrawElementsInstancedProc> fDrawElementsInstanced;
GLPtr<GrGLEnableProc> fEnable;
GLPtr<GrGLEnableVertexAttribArrayProc> fEnableVertexAttribArray;
GLPtr<GrGLEndQueryProc> fEndQuery;
@@ -327,6 +331,7 @@
GLPtr<GrGLVertexAttrib2fvProc> fVertexAttrib2fv;
GLPtr<GrGLVertexAttrib3fvProc> fVertexAttrib3fv;
GLPtr<GrGLVertexAttrib4fvProc> fVertexAttrib4fv;
+ GLPtr<GrGLVertexAttribDivisorProc> fVertexAttribDivisor;
GLPtr<GrGLVertexAttribPointerProc> fVertexAttribPointer;
GLPtr<GrGLViewportProc> fViewport;
@@ -362,12 +367,9 @@
/* NV_framebuffer_mixed_samples */
GLPtr<GrGLCoverageModulationProc> fCoverageModulation;
- /* ARB_draw_instanced */
- GLPtr<GrGLDrawArraysInstancedProc> fDrawArraysInstanced;
- GLPtr<GrGLDrawElementsInstancedProc> fDrawElementsInstanced;
-
- /* ARB_instanced_arrays */
- GLPtr<GrGLVertexAttribDivisorProc> fVertexAttribDivisor;
+ /* EXT_multi_draw_indirect */
+ GLPtr<GrGLMultiDrawArraysIndirectProc> fMultiDrawArraysIndirect;
+ GLPtr<GrGLMultiDrawElementsIndirectProc> fMultiDrawElementsIndirect;
/* NV_bindless_texture */
// We use the NVIDIA verson for now because it does not require dynamically uniform handles.
diff --git a/include/gpu/gl/GrGLTypes.h b/include/gpu/gl/GrGLTypes.h
index 248ce88..d0edcf1 100644
--- a/include/gpu/gl/GrGLTypes.h
+++ b/include/gpu/gl/GrGLTypes.h
@@ -58,10 +58,40 @@
typedef signed long int GrGLsizeiptr;
#endif
typedef void* GrGLeglImage;
+
+struct GrGLDrawArraysIndirectCommand {
+ GrGLuint fCount;
+ GrGLuint fInstanceCount;
+ GrGLuint fFirst;
+ GrGLuint fBaseInstance; // Requires EXT_base_instance on ES.
+};
+
+GR_STATIC_ASSERT(16 == sizeof(GrGLDrawArraysIndirectCommand));
+
+struct GrGLDrawElementsIndirectCommand {
+ GrGLuint fCount;
+ GrGLuint fInstanceCount;
+ GrGLuint fFirstIndex;
+ GrGLuint fBaseVertex;
+ GrGLuint fBaseInstance; // Requires EXT_base_instance on ES.
+};
+
+GR_STATIC_ASSERT(20 == sizeof(GrGLDrawElementsIndirectCommand));
+
+/**
+ * KHR_debug
+ */
+typedef void (GR_GL_FUNCTION_TYPE* GRGLDEBUGPROC)(GrGLenum source,
+ GrGLenum type,
+ GrGLuint id,
+ GrGLenum severity,
+ GrGLsizei length,
+ const GrGLchar* message,
+ const void* userParam);
+
/**
* EGL types.
*/
-
typedef void* GrEGLImage;
typedef void* GrEGLDisplay;
typedef void* GrEGLContext;
diff --git a/src/gpu/gl/GrGLAssembleInterface.cpp b/src/gpu/gl/GrGLAssembleInterface.cpp
index 6b578f3..30eed62 100644
--- a/src/gpu/gl/GrGLAssembleInterface.cpp
+++ b/src/gpu/gl/GrGLAssembleInterface.cpp
@@ -138,6 +138,19 @@
GET_PROC(DrawBuffer);
GET_PROC(DrawBuffers);
GET_PROC(DrawElements);
+
+ if (glVer >= GR_GL_VER(3,1) || extensions.has("GL_ARB_draw_instanced") ||
+ extensions.has("GL_EXT_draw_instanced")) {
+ GET_PROC(DrawArraysInstanced);
+ GET_PROC(DrawElementsInstanced);
+ }
+
+ if (glVer >= GR_GL_VER(4,0)) {
+ // We don't use ARB_draw_indirect because it does not support a base instance.
+ GET_PROC(DrawArraysIndirect);
+ GET_PROC(DrawElementsIndirect);
+ }
+
GET_PROC(Enable);
GET_PROC(EnableVertexAttribArray);
GET_PROC(EndQuery);
@@ -228,6 +241,11 @@
GET_PROC(VertexAttrib2fv);
GET_PROC(VertexAttrib3fv);
GET_PROC(VertexAttrib4fv);
+
+ if (glVer >= GR_GL_VER(3,2) || extensions.has("GL_ARB_instanced_arrays")) {
+ GET_PROC(VertexAttribDivisor);
+ }
+
GET_PROC(VertexAttribPointer);
GET_PROC(Viewport);
GET_PROC(BindFragDataLocationIndexed);
@@ -338,14 +356,10 @@
GET_PROC(GetProgramResourceLocation);
}
- if (glVer >= GR_GL_VER(3,1) || extensions.has("GL_ARB_draw_instanced") ||
- extensions.has("GL_EXT_draw_instanced")) {
- GET_PROC(DrawArraysInstanced);
- GET_PROC(DrawElementsInstanced);
- }
-
- if (glVer >= GR_GL_VER(3,2) || extensions.has("GL_ARB_instanced_arrays")) {
- GET_PROC(VertexAttribDivisor);
+ if (glVer >= GR_GL_VER(4,3)) {
+ // We don't use ARB_multi_draw_indirect because it does not support GL_DRAW_INDIRECT_BUFFER.
+ GET_PROC(MultiDrawArraysIndirect);
+ GET_PROC(MultiDrawElementsIndirect);
}
if (extensions.has("GL_NV_bindless_texture")) {
@@ -564,6 +578,20 @@
GET_PROC(Disable);
GET_PROC(DisableVertexAttribArray);
GET_PROC(DrawArrays);
+
+ if (version >= GR_GL_VER(3,0)) {
+ GET_PROC(DrawArraysInstanced);
+ GET_PROC(DrawElementsInstanced);
+ } else if (extensions.has("GL_EXT_draw_instanced")) {
+ GET_PROC_SUFFIX(DrawArraysInstanced, EXT);
+ GET_PROC_SUFFIX(DrawElementsInstanced, EXT);
+ }
+
+ if (version >= GR_GL_VER(3,1)) {
+ GET_PROC(DrawArraysIndirect);
+ GET_PROC(DrawElementsIndirect);
+ }
+
GET_PROC(DrawElements);
GET_PROC(Enable);
GET_PROC(EnableVertexAttribArray);
@@ -643,6 +671,13 @@
GET_PROC(VertexAttrib2fv);
GET_PROC(VertexAttrib3fv);
GET_PROC(VertexAttrib4fv);
+
+ if (version >= GR_GL_VER(3,0)) {
+ GET_PROC(VertexAttribDivisor);
+ } else if (extensions.has("GL_EXT_instanced_arrays")) {
+ GET_PROC_SUFFIX(VertexAttribDivisor, EXT);
+ }
+
GET_PROC(VertexAttribPointer);
GET_PROC(Viewport);
GET_PROC(BindFramebuffer);
@@ -779,18 +814,9 @@
GET_PROC_SUFFIX(CoverageModulation, CHROMIUM);
}
- if (version >= GR_GL_VER(3,0)) {
- GET_PROC(DrawArraysInstanced);
- GET_PROC(DrawElementsInstanced);
- } else if (extensions.has("GL_EXT_draw_instanced")) {
- GET_PROC_SUFFIX(DrawArraysInstanced, EXT);
- GET_PROC_SUFFIX(DrawElementsInstanced, EXT);
- }
-
- if (version >= GR_GL_VER(3,0)) {
- GET_PROC(VertexAttribDivisor);
- } else if (extensions.has("GL_EXT_instanced_arrays")) {
- GET_PROC_SUFFIX(VertexAttribDivisor, EXT);
+ if (extensions.has("GL_EXT_multi_draw_indirect")) {
+ GET_PROC_SUFFIX(MultiDrawArraysIndirect, EXT);
+ GET_PROC_SUFFIX(MultiDrawElementsIndirect, EXT);
}
if (extensions.has("GL_NV_bindless_texture")) {
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 1a87274..a913fbe 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -41,6 +41,9 @@
fDebugSupport = false;
fES2CompatibilitySupport = false;
fMultisampleDisableSupport = false;
+ fDrawIndirectSupport = false;
+ fMultiDrawIndirectSupport = false;
+ fBaseInstanceSupport = false;
fUseNonVBOVertexAndIndexDynamicData = false;
fIsCoreProfile = false;
fBindFragDataLocationSupport = false;
@@ -482,6 +485,17 @@
ctxInfo.hasExtension("GL_EXT_instanced_arrays"));
}
+ if (kGL_GrGLStandard == standard) {
+ // We don't use ARB_draw_indirect because it does not support a base instance.
+ // We don't use ARB_multi_draw_indirect because it does not support GL_DRAW_INDIRECT_BUFFER.
+ fDrawIndirectSupport =
+ fMultiDrawIndirectSupport = fBaseInstanceSupport = version >= GR_GL_VER(4,3);
+ } else {
+ fDrawIndirectSupport = version >= GR_GL_VER(3,1);
+ fMultiDrawIndirectSupport = ctxInfo.hasExtension("GL_EXT_multi_draw_indirect");
+ fBaseInstanceSupport = ctxInfo.hasExtension("GL_EXT_base_instance");
+ }
+
this->initShaderPrecisionTable(ctxInfo, gli, glslCaps);
if (contextOptions.fUseShaderSwizzling) {
@@ -936,6 +950,9 @@
r.appendf("Direct state access support: %s\n", (fDirectStateAccessSupport ? "YES": "NO"));
r.appendf("Debug support: %s\n", (fDebugSupport ? "YES": "NO"));
r.appendf("Multisample disable support: %s\n", (fMultisampleDisableSupport ? "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"));
r.appendf("Use non-VBO for dynamic data: %s\n",
(fUseNonVBOVertexAndIndexDynamicData ? "YES" : "NO"));
r.appendf("SRGB write contol: %s\n", (fSRGBWriteControl ? "YES" : "NO"));
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index 044ecce..abfcc28 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -283,6 +283,17 @@
/// Can we call glDisable(GL_MULTISAMPLE)?
bool multisampleDisableSupport() const { return fMultisampleDisableSupport; }
+ /// 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; }
+
+ /// Is there support for glMultiDraw*Indirect? Note that the baseInstance fields of indirect
+ /// draw commands cannot be used unless we have base instance support.
+ bool multiDrawIndirectSupport() const { return fMultiDrawIndirectSupport; }
+
+ /// Are the baseInstance fields supported in indirect draw commands?
+ bool baseInstanceSupport() const { return fBaseInstanceSupport; }
+
/// Use indices or vertices in CPU arrays rather than VBOs for dynamic content.
bool useNonVBOVertexAndIndexDynamicData() const { return fUseNonVBOVertexAndIndexDynamicData; }
@@ -378,6 +389,9 @@
bool fDebugSupport : 1;
bool fES2CompatibilitySupport : 1;
bool fMultisampleDisableSupport : 1;
+ bool fDrawIndirectSupport : 1;
+ bool fMultiDrawIndirectSupport : 1;
+ bool fBaseInstanceSupport : 1;
bool fUseNonVBOVertexAndIndexDynamicData : 1;
bool fIsCoreProfile : 1;
bool fBindFragDataLocationSupport : 1;
diff --git a/src/gpu/gl/GrGLDefines.h b/src/gpu/gl/GrGLDefines.h
index a759413..9be769f 100644
--- a/src/gpu/gl/GrGLDefines.h
+++ b/src/gpu/gl/GrGLDefines.h
@@ -108,8 +108,10 @@
/* Buffer Objects */
#define GR_GL_ARRAY_BUFFER 0x8892
#define GR_GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GR_GL_DRAW_INDIRECT_BUFFER 0x8F3F
#define GR_GL_ARRAY_BUFFER_BINDING 0x8894
#define GR_GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GR_GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43
#define GR_GL_PIXEL_PACK_BUFFER 0x88EB
#define GR_GL_PIXEL_UNPACK_BUFFER 0x88EC
diff --git a/src/gpu/gl/GrGLInterface.cpp b/src/gpu/gl/GrGLInterface.cpp
index b8d7db6..925f081 100644
--- a/src/gpu/gl/GrGLInterface.cpp
+++ b/src/gpu/gl/GrGLInterface.cpp
@@ -579,6 +579,22 @@
}
}
+ if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,3)) ||
+ (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,1))) {
+ if (NULL == fFunctions.fDrawArraysIndirect ||
+ NULL == fFunctions.fDrawElementsIndirect) {
+ RETURN_FALSE_INTERFACE
+ }
+ }
+
+ if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,3)) ||
+ (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_EXT_multi_draw_indirect"))) {
+ if (NULL == fFunctions.fMultiDrawArraysIndirect ||
+ NULL == fFunctions.fMultiDrawElementsIndirect) {
+ RETURN_FALSE_INTERFACE
+ }
+ }
+
if (fExtensions.has("GL_NV_bindless_texture")) {
if (nullptr == fFunctions.fGetTextureHandle ||
nullptr == fFunctions.fGetTextureSamplerHandle ||