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_shaders} extensions, no implementation done
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)
- @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)
- @gl_extension{EXT,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,multi_draw_instanced_base_vertex_base_instance}
- 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_dxt3,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) | |
@gl_extension{APPLE,texture_format_BGRA8888} | 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_astc} | 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,draw_instanced_base_vertex_base_instance} | missing support in Emscripten
@webgl_extension{WEBGL,multi_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} | |
@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
* @m_since{2020,06}
*
* In OpenGL ES, if @gl_extension{EXT,multi_draw_arrays} is not
* present, the functionality is emulated using a sequence of
* On OpenGL ES, if neither @gl_extension{EXT,multi_draw_arrays} nor
* @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.
*
* 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
#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
/* Multi draw implementation on ES */
if(context.isExtensionSupported<Extensions::EXT::multi_draw_arrays>()) {
extensions.push_back(Extensions::EXT::multi_draw_arrays::string());
if(context.isExtensionSupported<Extensions::EXT::multi_draw_arrays>() ||
context.isExtensionSupported<Extensions::ANGLE::multi_draw>())
#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;
} else multiDrawImplementation = &MeshView::multiDrawImplementationFallback;
#else
multiDrawImplementation = &MeshView::multiDrawImplementationFallback;
#endif
#endif
#ifdef MAGNUM_TARGET_GLES2

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

@ -60,6 +60,8 @@ struct MeshState {
#ifdef MAGNUM_TARGET_GLES
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
void(*bindVAOImplementation)(GLuint);

12
src/Magnum/GL/MeshView.cpp

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

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

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

Loading…
Cancel
Save