Browse Source

GL: implement ANGLE_multi_draw and WEBGL_multi_draw support.

pull/495/head
Vladimír Vondruš 5 years ago
parent
commit
63f55a37b1
  1. 6
      doc/changelog.dox
  2. 8
      doc/opengl-support.dox
  3. 6
      src/Magnum/GL/AbstractShaderProgram.h
  4. 39
      src/Magnum/GL/Implementation/MeshState.cpp
  5. 2
      src/Magnum/GL/Implementation/MeshState.h
  6. 12
      src/Magnum/GL/MeshView.cpp
  7. 2
      src/Magnum/GL/MeshView.h
  8. 24
      src/Magnum/GL/Test/MeshGLTest.cpp

6
doc/changelog.dox

@ -62,12 +62,14 @@ See also:
@webgl_extension{WEBGL,debug_renderer_info} and @webgl_extension{WEBGL,debug_renderer_info} and
@webgl_extension{WEBGL,debug_shaders} extensions, no implementation done @webgl_extension{WEBGL,debug_shaders} extensions, no implementation done
yet yet
- Recognizing ANGLE GLES and WebGL multi-draw extensions: - Recognizing ANGLE GLES and WebGL multi-draw extensions and using them in
@ref GL::AbstractShaderProgram::draw(Containers::ArrayView<const Containers::Reference<MeshView>>):
- @m_class{m-doc-external} [ANGLE_multi_draw](https://chromium.googlesource.com/angle/angle/+/master/extensions/ANGLE_multi_draw.txt) - @m_class{m-doc-external} [ANGLE_multi_draw](https://chromium.googlesource.com/angle/angle/+/master/extensions/ANGLE_multi_draw.txt)
- @webgl_extension{WEBGL,multi_draw}
- The following extensions are recognized but not used yet:
- @m_class{m-doc-external} [ANGLE_base_vertex_base_instance](https://chromium.googlesource.com/angle/angle/+/master/extensions/ANGLE_base_vertex_base_instance.txt) - @m_class{m-doc-external} [ANGLE_base_vertex_base_instance](https://chromium.googlesource.com/angle/angle/+/master/extensions/ANGLE_base_vertex_base_instance.txt)
- @gl_extension{EXT,draw_elements_base_vertex} - @gl_extension{EXT,draw_elements_base_vertex}
- @gl_extension{OES,draw_elements_base_vertex} - @gl_extension{OES,draw_elements_base_vertex}
- @webgl_extension{WEBGL,multi_draw}
- @webgl_extension{WEBGL,draw_instanced_base_vertex_base_instance} - @webgl_extension{WEBGL,draw_instanced_base_vertex_base_instance}
- @webgl_extension{WEBGL,multi_draw_instanced_base_vertex_base_instance} - @webgl_extension{WEBGL,multi_draw_instanced_base_vertex_base_instance}
- Added a @ref GL::AbstractTexture::target() getter to simplify interaction - Added a @ref GL::AbstractTexture::target() getter to simplify interaction

8
doc/opengl-support.dox

@ -449,7 +449,7 @@ Extension | Status
@gl_extension2{ANGLE,texture_compression_dxt1,ANGLE_texture_compression_dxt} | done @gl_extension2{ANGLE,texture_compression_dxt1,ANGLE_texture_compression_dxt} | done
@gl_extension2{ANGLE,texture_compression_dxt3,ANGLE_texture_compression_dxt} | done @gl_extension2{ANGLE,texture_compression_dxt3,ANGLE_texture_compression_dxt} | done
@gl_extension2{ANGLE,texture_compression_dxt5,ANGLE_texture_compression_dxt} | done @gl_extension2{ANGLE,texture_compression_dxt5,ANGLE_texture_compression_dxt} | done
@m_class{m-doc-external} [ANGLE_multi_draw](https://chromium.googlesource.com/angle/angle/+/master/extensions/ANGLE_multi_draw.txt) (unlisted) | | @m_class{m-doc-external} [ANGLE_multi_draw](https://chromium.googlesource.com/angle/angle/+/master/extensions/ANGLE_multi_draw.txt) (unlisted) | done
@m_class{m-doc-external} [ANGLE_base_vertex_base_instance](https://chromium.googlesource.com/angle/angle/+/master/extensions/ANGLE_base_vertex_base_instance.txt) (unlisted) | | @m_class{m-doc-external} [ANGLE_base_vertex_base_instance](https://chromium.googlesource.com/angle/angle/+/master/extensions/ANGLE_base_vertex_base_instance.txt) (unlisted) | |
@gl_extension{APPLE,texture_format_BGRA8888} | done @gl_extension{APPLE,texture_format_BGRA8888} | done
@gl_extension{APPLE,clip_distance} | done @gl_extension{APPLE,clip_distance} | done
@ -571,10 +571,10 @@ Extension | Status
@webgl_extension{WEBGL,compressed_texture_pvrtc} | done @webgl_extension{WEBGL,compressed_texture_pvrtc} | done
@webgl_extension{WEBGL,compressed_texture_astc} | done @webgl_extension{WEBGL,compressed_texture_astc} | done
@webgl_extension{WEBGL,compressed_texture_s3tc_srgb} | done @webgl_extension{WEBGL,compressed_texture_s3tc_srgb} | done
@webgl_extension{WEBGL,multi_draw} | missing support in Emscripten @webgl_extension{WEBGL,multi_draw} | done
@webgl_extension{WEBGL,blend_equation_advanced_coherent} | done @webgl_extension{WEBGL,blend_equation_advanced_coherent} | done
@webgl_extension{WEBGL,draw_instanced_base_vertex_base_instance} | missing support in Emscripten @webgl_extension{WEBGL,draw_instanced_base_vertex_base_instance} | |
@webgl_extension{WEBGL,multi_draw_instanced_base_vertex_base_instance} | missing support in Emscripten @webgl_extension{WEBGL,multi_draw_instanced_base_vertex_base_instance} | |
@section opengl-unsupported Unsupported OpenGL features @section opengl-unsupported Unsupported OpenGL features

6
src/Magnum/GL/AbstractShaderProgram.h

@ -840,8 +840,10 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject {
* @brief Draw multiple meshes at once * @brief Draw multiple meshes at once
* @m_since{2020,06} * @m_since{2020,06}
* *
* In OpenGL ES, if @gl_extension{EXT,multi_draw_arrays} is not * On OpenGL ES, if neither @gl_extension{EXT,multi_draw_arrays} nor
* present, the functionality is emulated using a sequence of * @m_class{m-doc-external} [ANGLE_multi_draw](https://chromium.googlesource.com/angle/angle/+/master/extensions/ANGLE_multi_draw.txt)
* is present, and on WebGL if @webgl_extension{WEBGL,multi_draw} is
* not present, the functionality is emulated using a sequence of
* @ref draw(MeshView&) calls. * @ref draw(MeshView&) calls.
* *
* If @gl_extension{ARB,vertex_array_object} (part of OpenGL 3.0), * If @gl_extension{ARB,vertex_array_object} (part of OpenGL 3.0),

39
src/Magnum/GL/Implementation/MeshState.cpp

@ -108,16 +108,43 @@ MeshState::MeshState(Context& context, ContextState& contextState, std::vector<s
#endif #endif
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
/* Multi draw implementation on ES. Because there's a lot of dispatch logic
involved, the multiDrawImplementationDefault then has internal
extension-specific codepaths based on whether EXT, OES, ANGLE or
whichever entrypoints are supported. */
#ifndef MAGNUM_TARGET_WEBGL #ifndef MAGNUM_TARGET_WEBGL
/* Multi draw implementation on ES */ if(context.isExtensionSupported<Extensions::EXT::multi_draw_arrays>() ||
if(context.isExtensionSupported<Extensions::EXT::multi_draw_arrays>()) { context.isExtensionSupported<Extensions::ANGLE::multi_draw>())
extensions.push_back(Extensions::EXT::multi_draw_arrays::string()); #else
if(context.isExtensionSupported<Extensions::WEBGL::multi_draw>())
#endif
{
#ifndef MAGNUM_TARGET_WEBGL
if(context.isExtensionSupported<Extensions::EXT::multi_draw_arrays>()) {
extensions.push_back(Extensions::EXT::multi_draw_arrays::string());
multiDrawArraysImplementation = glMultiDrawArraysEXT;
multiDrawElementsImplementation = glMultiDrawElementsEXT;
} else if(context.isExtensionSupported<Extensions::ANGLE::multi_draw>()) {
extensions.push_back(Extensions::ANGLE::multi_draw::string());
multiDrawArraysImplementation = glMultiDrawArraysANGLE;
multiDrawElementsImplementation = glMultiDrawElementsANGLE;
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE();
#else
{
extensions.push_back(Extensions::WEBGL::multi_draw::string());
/* The WEBGL extension uses the same entrypoints as the ANGLE
extension it was based on */
multiDrawArraysImplementation = glMultiDrawArraysANGLE;
multiDrawElementsImplementation = glMultiDrawElementsANGLE;
}
#endif
multiDrawImplementation = &MeshView::multiDrawImplementationDefault; multiDrawImplementation = &MeshView::multiDrawImplementationDefault;
} else multiDrawImplementation = &MeshView::multiDrawImplementationFallback; } else multiDrawImplementation = &MeshView::multiDrawImplementationFallback;
#else
multiDrawImplementation = &MeshView::multiDrawImplementationFallback;
#endif
#endif #endif
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2

2
src/Magnum/GL/Implementation/MeshState.h

@ -60,6 +60,8 @@ struct MeshState {
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
void(*multiDrawImplementation)(Containers::ArrayView<const Containers::Reference<MeshView>>); void(*multiDrawImplementation)(Containers::ArrayView<const Containers::Reference<MeshView>>);
void(APIENTRY *multiDrawArraysImplementation)(GLenum, const GLint*, const GLsizei*, GLsizei);
void(APIENTRY *multiDrawElementsImplementation)(GLenum, const GLsizei*, GLenum, const void* const*, GLsizei);
#endif #endif
void(*bindVAOImplementation)(GLuint); void(*bindVAOImplementation)(GLuint);

12
src/Magnum/GL/MeshView.cpp

@ -84,7 +84,6 @@ MeshView& MeshView::draw(AbstractShaderProgram&& shader, TransformFeedback& xfb,
#endif #endif
#endif #endif
#ifndef MAGNUM_TARGET_WEBGL
void MeshView::multiDrawImplementationDefault(Containers::ArrayView<const Containers::Reference<MeshView>> meshes) { void MeshView::multiDrawImplementationDefault(Containers::ArrayView<const Containers::Reference<MeshView>> meshes) {
CORRADE_INTERNAL_ASSERT(meshes.size()); CORRADE_INTERNAL_ASSERT(meshes.size());
@ -123,10 +122,11 @@ void MeshView::multiDrawImplementationDefault(Containers::ArrayView<const Contai
/* Non-indexed meshes */ /* Non-indexed meshes */
if(!original._indexBuffer.id()) { if(!original._indexBuffer.id()) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
glMultiDrawArrays(GLenum(original._primitive), baseVertex, count, meshes.size()); glMultiDrawArrays
#else #else
glMultiDrawArraysEXT(GLenum(original._primitive), baseVertex, count, meshes.size()); state.multiDrawArraysImplementation
#endif #endif
(GLenum(original._primitive), baseVertex, count, meshes.size());
/* Indexed meshes */ /* Indexed meshes */
} else { } else {
@ -140,16 +140,16 @@ void MeshView::multiDrawImplementationDefault(Containers::ArrayView<const Contai
#endif #endif
{ {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
glMultiDrawElements(GLenum(original._primitive), count, GLenum(original._indexType), indices, meshes.size()); glMultiDrawElements
#else #else
glMultiDrawElementsEXT(GLenum(original._primitive), count, GLenum(original._indexType), indices, meshes.size()); state.multiDrawElementsImplementation
#endif #endif
(GLenum(original._primitive), count, GLenum(original._indexType), indices, meshes.size());
} }
} }
(original.*state.unbindImplementation)(); (original.*state.unbindImplementation)();
} }
#endif
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
void MeshView::multiDrawImplementationFallback(Containers::ArrayView<const Containers::Reference<MeshView>> meshes) { void MeshView::multiDrawImplementationFallback(Containers::ArrayView<const Containers::Reference<MeshView>> meshes) {

2
src/Magnum/GL/MeshView.h

@ -257,9 +257,7 @@ class MAGNUM_GL_EXPORT MeshView {
friend AbstractShaderProgram; friend AbstractShaderProgram;
friend Implementation::MeshState; friend Implementation::MeshState;
#ifndef MAGNUM_TARGET_WEBGL
static MAGNUM_GL_LOCAL void multiDrawImplementationDefault(Containers::ArrayView<const Containers::Reference<MeshView>> meshes); static MAGNUM_GL_LOCAL void multiDrawImplementationDefault(Containers::ArrayView<const Containers::Reference<MeshView>> meshes);
#endif
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
static MAGNUM_GL_LOCAL void multiDrawImplementationFallback(Containers::ArrayView<const Containers::Reference<MeshView>> meshes); static MAGNUM_GL_LOCAL void multiDrawImplementationFallback(Containers::ArrayView<const Containers::Reference<MeshView>> meshes);
#endif #endif

24
src/Magnum/GL/Test/MeshGLTest.cpp

@ -3005,9 +3005,15 @@ template<class T> T MultiChecker::get(PixelFormat format, PixelType type) {
#endif #endif
void MeshGLTest::multiDraw() { void MeshGLTest::multiDraw() {
#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) #ifdef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::EXT::multi_draw_arrays>()) #ifndef MAGNUM_TARGET_WEBGL
Debug() << Extensions::EXT::multi_draw_arrays::string() << "not supported, using fallback implementation"; if(!Context::current().isExtensionSupported<Extensions::EXT::multi_draw_arrays>() &&
!Context::current().isExtensionSupported<Extensions::ANGLE::multi_draw>())
Debug{} << "Neither" << Extensions::EXT::multi_draw_arrays::string() << "nor" << Extensions::ANGLE::multi_draw::string() << "is supported, using fallback implementation";
#else
if(!Context::current().isExtensionSupported<Extensions::WEBGL::multi_draw>())
Debug{} << Extensions::WEBGL::multi_draw::string() << "is not supported, using fallback implementation";
#endif
#endif #endif
typedef Attribute<0, Float> Attribute; typedef Attribute<0, Float> Attribute;
@ -3042,9 +3048,15 @@ void MeshGLTest::multiDraw() {
} }
void MeshGLTest::multiDrawIndexed() { void MeshGLTest::multiDrawIndexed() {
#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_WEBGL) #ifdef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::EXT::multi_draw_arrays>()) #ifndef MAGNUM_TARGET_WEBGL
Debug() << Extensions::EXT::multi_draw_arrays::string() << "not supported, using fallback implementation"; if(!Context::current().isExtensionSupported<Extensions::EXT::multi_draw_arrays>() &&
!Context::current().isExtensionSupported<Extensions::ANGLE::multi_draw>())
Debug{} << "Neither" << Extensions::EXT::multi_draw_arrays::string() << "nor" << Extensions::ANGLE::multi_draw::string() << "is supported, using fallback implementation";
#else
if(!Context::current().isExtensionSupported<Extensions::WEBGL::multi_draw>())
Debug{} << Extensions::WEBGL::multi_draw::string() << "is not supported, using fallback implementation";
#endif
#endif #endif
Buffer vertices; Buffer vertices;

Loading…
Cancel
Save