Browse Source

GL: implement the base instance and base vertex ES and WebGL extensions.

AAAAAAAAAAAAAAAAAAAAAAAAAAAAA this was terrible! Why the hell it needs
to have so many variants, special cases and exceptions!!!
pull/495/head
Vladimír Vondruš 5 years ago
parent
commit
ffdebff048
  1. 12
      doc/changelog.dox
  2. 10
      doc/opengl-support.dox
  3. 8
      src/Magnum/GL/AbstractShaderProgram.cpp
  4. 10
      src/Magnum/GL/AbstractShaderProgram.h
  5. 134
      src/Magnum/GL/Implementation/MeshState.cpp
  6. 22
      src/Magnum/GL/Implementation/MeshState.h
  7. 12
      src/Magnum/GL/Implementation/driverSpecific.cpp
  8. 122
      src/Magnum/GL/Mesh.cpp
  9. 54
      src/Magnum/GL/Mesh.h
  10. 54
      src/Magnum/GL/MeshView.cpp
  11. 25
      src/Magnum/GL/MeshView.h
  12. 462
      src/Magnum/GL/Test/MeshGLTest.cpp

12
doc/changelog.dox

@ -62,14 +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 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)
- Recognizing ANGLE GLES and WebGL base vertex, base instance and multi-draw
extensions and using them in @ref GL::AbstractShaderProgram::draw(Mesh&)
and @ref GL::AbstractShaderProgram::draw(Containers::ArrayView<const Containers::Reference<MeshView>>):
- @gl_extension{EXT,draw_elements_base_vertex}
- @gl_extension{OES,draw_elements_base_vertex}
- @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_base_vertex_base_instance](https://chromium.googlesource.com/angle/angle/+/master/extensions/ANGLE_base_vertex_base_instance.txt)
- @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

10
doc/opengl-support.dox

@ -450,7 +450,7 @@ Extension | Status
@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) | 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) | done except instanced multi-draw
@gl_extension{APPLE,texture_format_BGRA8888} | done
@gl_extension{APPLE,clip_distance} | done
@gl_extension{ARM,shader_framebuffer_fetch} | missing renderer setup and limit query
@ -472,7 +472,7 @@ Extension | Status
@gl_extension{EXT,texture_compression_s3tc} | done
@gl_extension{EXT,pvrtc_sRGB} | done
@gl_extension{EXT,shader_integer_mix} | done (shading language only)
@gl_extension{EXT,draw_elements_base_vertex} | |
@gl_extension{EXT,draw_elements_base_vertex} | done
@gl_extension{EXT,texture_norm16} | done
@gl_extension{EXT,texture_sRGB_R8} | done
@gl_extension{EXT,texture_sRGB_RG8} | done
@ -500,7 +500,7 @@ Extension | Status
@gl_extension{OES,stencil1} | done
@gl_extension{OES,stencil4} | done
@gl_extension{OES,texture_float_linear} | done
@gl_extension{OES,draw_elements_base_vertex} | |
@gl_extension{OES,draw_elements_base_vertex} | done
@gl_extension{OVR,multiview} | |
@gl_extension{OVR,multiview2} | |
@ -573,8 +573,8 @@ Extension | Status
@webgl_extension{WEBGL,compressed_texture_s3tc_srgb} | done
@webgl_extension{WEBGL,multi_draw} | done
@webgl_extension{WEBGL,blend_equation_advanced_coherent} | done
@webgl_extension{WEBGL,draw_instanced_base_vertex_base_instance} | |
@webgl_extension{WEBGL,multi_draw_instanced_base_vertex_base_instance} | |
@webgl_extension{WEBGL,draw_instanced_base_vertex_base_instance} | done
@webgl_extension{WEBGL,multi_draw_instanced_base_vertex_base_instance} | done except instanced multi-draw
@section opengl-unsupported Unsupported OpenGL features

8
src/Magnum/GL/AbstractShaderProgram.cpp

@ -358,10 +358,8 @@ void AbstractShaderProgram::draw(Mesh& mesh) {
use();
#ifndef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
mesh.drawInternal(mesh._count, mesh._baseVertex, mesh._instanceCount, mesh._baseInstance, mesh._indexOffset, mesh._indexStart, mesh._indexEnd);
#elif !defined(MAGNUM_TARGET_GLES2)
mesh.drawInternal(mesh._count, mesh._baseVertex, mesh._instanceCount, mesh._indexOffset, mesh._indexStart, mesh._indexEnd);
#else
mesh.drawInternal(mesh._count, mesh._baseVertex, mesh._instanceCount, mesh._indexOffset);
#endif
@ -375,10 +373,8 @@ void AbstractShaderProgram::draw(MeshView& mesh) {
use();
#ifndef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
mesh._original->drawInternal(mesh._count, mesh._baseVertex, mesh._instanceCount, mesh._baseInstance, mesh._indexOffset, mesh._indexStart, mesh._indexEnd);
#elif !defined(MAGNUM_TARGET_GLES2)
mesh._original->drawInternal(mesh._count, mesh._baseVertex, mesh._instanceCount, mesh._indexOffset, mesh._indexStart, mesh._indexEnd);
#else
mesh._original->drawInternal(mesh._count, mesh._baseVertex, mesh._instanceCount, mesh._indexOffset);
#endif

10
src/Magnum/GL/AbstractShaderProgram.h

@ -863,8 +863,14 @@ class MAGNUM_GL_EXPORT AbstractShaderProgram: public AbstractObject {
* @requires_gl32 Extension @gl_extension{ARB,draw_elements_base_vertex}
* if the mesh is indexed and @ref MeshView::baseVertex() is not
* `0`
* @requires_gl Specifying base vertex for indexed meshes is not
* available in OpenGL ES or WebGL.
* @requires_es_extension OpenGL ES 3.0 and extension
* @gl_extension{OES,draw_elements_base_vertex} or
* @gl_extension{EXT,draw_elements_base_vertex} if the mesh is
* indexed and @ref MeshView::baseVertex() is not `0`
* @requires_webgl_extension WebGL 2.0 and extension
* @webgl_extension{WEBGL,multi_draw_instanced_base_vertex_base_instance}
* if the mesh is indexed and @ref MeshView::baseVertex() is not
* `0`
*/
void draw(Containers::ArrayView<const Containers::Reference<MeshView>> meshes);

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

@ -107,6 +107,102 @@ MeshState::MeshState(Context& context, ContextState& contextState, std::vector<s
}
#endif
/* Base vertex draws on ES 2/3 and WebGL 2 */
#if defined(MAGNUM_TARGET_GLES) && !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
#ifndef MAGNUM_TARGET_WEBGL
#ifndef MAGNUM_TARGET_GLES2
if(context.isVersionSupported(Version::GLES320)) {
drawElementsBaseVertexImplementation = glDrawElementsBaseVertex;
drawRangeElementsBaseVertexImplementation = glDrawRangeElementsBaseVertex;
drawElementsInstancedBaseVertexImplementation = glDrawElementsInstancedBaseVertex;
} else
#endif
if(context.isExtensionSupported<Extensions::EXT::draw_elements_base_vertex>()) {
extensions.push_back(Extensions::EXT::draw_elements_base_vertex::string());
drawElementsBaseVertexImplementation = glDrawElementsBaseVertexEXT;
#ifndef MAGNUM_TARGET_GLES2
drawRangeElementsBaseVertexImplementation = glDrawRangeElementsBaseVertexEXT;
drawElementsInstancedBaseVertexImplementation = glDrawElementsInstancedBaseVertexEXT;
#endif
} else if(context.isExtensionSupported<Extensions::OES::draw_elements_base_vertex>()) {
extensions.push_back(Extensions::OES::draw_elements_base_vertex::string());
drawElementsBaseVertexImplementation = glDrawElementsBaseVertexOES;
#ifndef MAGNUM_TARGET_GLES2
drawRangeElementsBaseVertexImplementation = glDrawRangeElementsBaseVertexOES;
drawElementsInstancedBaseVertexImplementation = glDrawElementsInstancedBaseVertexOES;
#endif
} else
#else
if(context.isExtensionSupported<Extensions::WEBGL::draw_instanced_base_vertex_base_instance>()) {
extensions.push_back(Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string());
/* The WEBGL extension uses the same entrypoints as the ANGLE extension
it was based on, however we wrap it to supply trivial instance count
because there's no non-instanced variant. Only available since
1.39.15: https://github.com/emscripten-core/emscripten/pull/11054 */
#if __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 13915
drawElementsBaseVertexImplementation = Mesh::drawElementsBaseVertexImplementationANGLE;
drawRangeElementsBaseVertexImplementation = Mesh::drawRangeElementsBaseVertexImplementationANGLE;
drawElementsInstancedBaseVertexImplementation = Mesh::drawElementsInstancedBaseVertexImplementationANGLE;
#else
/* In Context::setupDriverWorkarounds() we make sure the extension is
not even advertised, so this shouldn't be reached. */
CORRADE_INTERNAL_ASSERT_UNREACHABLE();
#endif
} else
#endif
{
drawElementsBaseVertexImplementation = Mesh::drawElementsBaseVertexImplementationAssert;
#ifndef MAGNUM_TARGET_GLES2
drawRangeElementsBaseVertexImplementation = Mesh::drawRangeElementsBaseVertexImplementationAssert;
drawElementsInstancedBaseVertexImplementation = Mesh::drawElementsInstancedBaseVertexImplementationAssert;
#endif
}
#endif
/* Base instance draws on ES3 and WebGL2 */
#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_GLES2)
#ifndef MAGNUM_TARGET_WEBGL
#ifndef MAGNUM_TARGET_GLES2
if(context.isExtensionSupported<Extensions::ANGLE::base_vertex_base_instance>()) {
extensions.push_back(Extensions::ANGLE::base_vertex_base_instance::string());
drawArraysInstancedBaseInstanceImplementation = glDrawArraysInstancedBaseInstanceANGLE;
/* This variant isn't in the ext, emulated using
glDrawElementsInstancedBaseVertexBaseInstanceANGLE */
drawElementsInstancedBaseInstanceImplementation = Mesh::drawElementsInstancedBaseInstanceImplementationANGLE;
drawElementsInstancedBaseVertexBaseInstanceImplementation = glDrawElementsInstancedBaseVertexBaseInstanceANGLE;
} else
#endif
#else
if(context.isExtensionSupported<Extensions::WEBGL::draw_instanced_base_vertex_base_instance>()) {
extensions.push_back(Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string());
/* The WEBGL extension uses the same entrypoints as the ANGLE extension
it was based on. Only available since 1.39.15:
https://github.com/emscripten-core/emscripten/pull/11054 */
#if __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 13915
drawArraysInstancedBaseInstanceImplementation = glDrawArraysInstancedBaseInstanceANGLE;
/* This variant isn't in the ext, emulated using
glDrawElementsInstancedBaseVertexBaseInstanceANGLE */
drawElementsInstancedBaseInstanceImplementation = Mesh::drawElementsInstancedBaseInstanceImplementationANGLE;
drawElementsInstancedBaseVertexBaseInstanceImplementation = glDrawElementsInstancedBaseVertexBaseInstanceANGLE;
#else
/* In Context::setupDriverWorkarounds() we make sure the extension is
not even advertised, so this shouldn't be reached. */
CORRADE_INTERNAL_ASSERT_UNREACHABLE();
#endif
} else
#endif
{
drawArraysInstancedBaseInstanceImplementation = Mesh::drawArraysInstancedBaseInstanceImplementationAssert;
drawElementsInstancedBaseInstanceImplementation = Mesh::drawElementsInstancedBaseInstanceImplementationAssert;
drawElementsInstancedBaseVertexBaseInstanceImplementation = Mesh::drawElementsInstancedBaseVertexBaseInstanceImplementationAssert;
}
#endif
#ifdef MAGNUM_TARGET_GLES
/* Multi draw implementation on ES. Because there's a lot of dispatch logic
involved, the multiDrawImplementationDefault then has internal
@ -149,6 +245,44 @@ MeshState::MeshState(Context& context, ContextState& contextState, std::vector<s
}
#endif
/* These function pointers make sense only if the general multi-draw
extension is supported. Also, not on WebGL 1 at all. */
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
#ifndef MAGNUM_TARGET_WEBGL
if(context.isExtensionSupported<Extensions::EXT::draw_elements_base_vertex>()) {
extensions.push_back(Extensions::EXT::draw_elements_base_vertex::string());
multiDrawElementsBaseVertexImplementation = glMultiDrawElementsBaseVertexEXT;
} else if(context.isExtensionSupported<Extensions::OES::draw_elements_base_vertex>()) {
extensions.push_back(Extensions::OES::draw_elements_base_vertex::string());
/* Yes, it's really EXT, the same as with
EXT_draw_elements_base_vertex. I have no idea why the two
extensions exist and why it isn't just one. */
multiDrawElementsBaseVertexImplementation = glMultiDrawElementsBaseVertexEXT;
} else
#else
if(context.isExtensionSupported<Extensions::WEBGL::multi_draw_instanced_base_vertex_base_instance>()) {
extensions.push_back(Extensions::WEBGL::multi_draw_instanced_base_vertex_base_instance::string());
/* The WEBGL extension uses the same entrypoints as the ANGLE
extension it was based on, however we wrap it and supply trivial
instance counts because there's no non-instanced variant. Only
available since 2.0.5: https://github.com/emscripten-core/emscripten/pull/12282 */
#if __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 20005
multiDrawElementsBaseVertexImplementation = MeshView::multiDrawElementsBaseVertexImplementationANGLE;
#else
/* In Context::setupDriverWorkarounds() we make sure the extension
is not even advertised, so this shouldn't be reached. */
CORRADE_INTERNAL_ASSERT_UNREACHABLE();
#endif
} else
#endif
{
multiDrawElementsBaseVertexImplementation = MeshView::multiDrawElementsBaseVertexImplementationAssert;
}
#endif
multiDrawImplementation = &MeshView::multiDrawImplementationDefault;
} else multiDrawImplementation = &MeshView::multiDrawImplementationFallback;

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

@ -53,15 +53,37 @@ struct MeshState {
void(Mesh::*bindImplementation)();
void(Mesh::*unbindImplementation)();
#ifdef MAGNUM_TARGET_GLES
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void(APIENTRY *drawElementsBaseVertexImplementation)(GLenum, GLsizei, GLenum, const void*, GLint);
#endif
#ifndef MAGNUM_TARGET_GLES2
void(APIENTRY *drawRangeElementsBaseVertexImplementation)(GLenum, GLuint, GLuint, GLsizei, GLenum, const void*, GLint);
#endif
#endif
#ifdef MAGNUM_TARGET_GLES2
void(APIENTRY *drawArraysInstancedImplementation)(GLenum, GLint, GLsizei, GLsizei);
#endif
#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_GLES2)
void(APIENTRY *drawArraysInstancedBaseInstanceImplementation)(GLenum, GLint, GLsizei, GLsizei, GLuint);
#endif
#ifdef MAGNUM_TARGET_GLES2
void(APIENTRY *drawElementsInstancedImplementation)(GLenum, GLsizei, GLenum, const void*, GLsizei);
#endif
#if defined(MAGNUM_TARGET_GLES) && !defined(MAGNUM_TARGET_GLES2)
void(APIENTRY *drawElementsInstancedBaseVertexImplementation)(GLenum, GLsizei, GLenum, const void*, GLsizei, GLint);
void(APIENTRY *drawElementsInstancedBaseInstanceImplementation)(GLenum, GLsizei, GLenum, const void*, GLsizei, GLuint);
void(APIENTRY *drawElementsInstancedBaseVertexBaseInstanceImplementation)(GLenum, GLsizei, GLenum, const void*, GLsizei, GLint, GLuint);
#endif
#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);
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void(APIENTRY *multiDrawElementsBaseVertexImplementation)(GLenum, const GLsizei*, GLenum, const void* const*, GLsizei, const GLint*);
#endif
#endif
void(*bindVAOImplementation)(GLuint);

12
src/Magnum/GL/Implementation/driverSpecific.cpp

@ -547,6 +547,18 @@ void Context::setupDriverWorkarounds() {
#if __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ < 20000
_setRequiredVersion(WEBGL::multi_draw, None);
#endif
#ifndef MAGNUM_TARGET_GLES2
/* WEBGL_multi_draw_instanced_base_vertex_base_instance only since
Emscripten 2.0.5: https://github.com/emscripten-core/emscripten/pull/12282 */
#if __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ < 20005
_setRequiredVersion(WEBGL::multi_draw_instanced_base_vertex_base_instance, None);
#endif
/* WEBGL_draw_instanced_base_vertex_base_instance only since Emscripten
1.39.15: https://github.com/emscripten-core/emscripten/pull/11054 */
#if __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ < 13915
_setRequiredVersion(WEBGL::draw_instanced_base_vertex_base_instance, None);
#endif
#endif
#endif
#undef _setRequiredVersion

122
src/Magnum/GL/Mesh.cpp

@ -401,10 +401,8 @@ Mesh& Mesh::setIndexBuffer(Buffer& buffer, const GLintptr offset, const MeshInde
return *this;
}
#ifndef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, UnsignedInt baseInstance, GLintptr indexOffset, Int indexStart, Int indexEnd)
#elif !defined(MAGNUM_TARGET_GLES2)
void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr indexOffset, Int indexStart, Int indexEnd)
#else
void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr indexOffset)
#endif
@ -421,15 +419,30 @@ void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr i
/* Indexed mesh with base vertex */
} else if(baseVertex) {
#ifndef MAGNUM_TARGET_GLES
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
#ifndef MAGNUM_TARGET_GLES2
/* Indexed mesh with specified range */
if(indexEnd) {
glDrawRangeElementsBaseVertex(GLenum(_primitive), indexStart, indexEnd, count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), baseVertex);
#ifndef MAGNUM_TARGET_GLES
glDrawRangeElementsBaseVertex
#else
state.drawRangeElementsBaseVertexImplementation
#endif
(GLenum(_primitive), indexStart, indexEnd, count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), baseVertex);
/* Indexed mesh */
} else glDrawElementsBaseVertex(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), baseVertex);
} else
#endif
{
#ifndef MAGNUM_TARGET_GLES
glDrawElementsBaseVertex
#else
state.drawElementsBaseVertexImplementation
#endif
(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), baseVertex);
}
#else
CORRADE_ASSERT_UNREACHABLE("GL::Mesh::draw(): desktop OpenGL is required for base vertex specification in indexed meshes", );
CORRADE_ASSERT_UNREACHABLE("GL::AbstractShaderProgram::draw(): indexed mesh draw with base vertex specification possible only since WebGL 2.0", );
#endif
/* Indexed mesh */
@ -457,10 +470,15 @@ void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr i
} else {
/* Non-indexed mesh */
if(!_indexBuffer.id()) {
#ifndef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
/* Non-indexed mesh with base instance */
if(baseInstance) {
glDrawArraysInstancedBaseInstance(GLenum(_primitive), baseVertex, count, instanceCount, baseInstance);
#ifndef MAGNUM_TARGET_GLES
glDrawArraysInstancedBaseInstance
#else
state.drawArraysInstancedBaseInstanceImplementation
#endif
(GLenum(_primitive), baseVertex, count, instanceCount, baseInstance);
/* Non-indexed mesh */
} else
@ -476,28 +494,40 @@ void Mesh::drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr i
/* Indexed mesh with base vertex */
} else if(baseVertex) {
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
#ifndef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
/* Indexed mesh with base vertex and base instance */
if(baseInstance) {
glDrawElementsInstancedBaseVertexBaseInstance(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), instanceCount, baseVertex, baseInstance);
#ifndef MAGNUM_TARGET_GLES
glDrawElementsInstancedBaseVertexBaseInstance
#else
state.drawElementsInstancedBaseVertexBaseInstanceImplementation
#endif
(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), instanceCount, baseVertex, baseInstance);
/* Indexed mesh with base vertex */
} else
#endif
{
glDrawElementsInstancedBaseVertex(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), instanceCount, baseVertex);
} else {
#ifndef MAGNUM_TARGET_GLES
glDrawElementsInstancedBaseVertex
#else
state.drawElementsInstancedBaseVertexImplementation
#endif
(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), instanceCount, baseVertex);
}
#else
CORRADE_ASSERT_UNREACHABLE("GL::Mesh::draw(): OpenGL ES 3.2 or desktop GL is required for base vertex specification in indexed meshes", );
CORRADE_ASSERT_UNREACHABLE("GL::AbstractShaderProgram::draw(): instanced indexed mesh draw with base vertex specification possible only since OpenGL ES 3.0", );
#endif
/* Indexed mesh */
} else {
#ifndef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
/* Indexed mesh with base instance */
if(baseInstance) {
glDrawElementsInstancedBaseInstance(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), instanceCount, baseInstance);
#ifndef MAGNUM_TARGET_GLES
glDrawElementsInstancedBaseInstance
#else
state.drawElementsInstancedBaseInstanceImplementation
#endif
(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), instanceCount, baseInstance);
/* Instanced mesh */
} else
@ -873,4 +903,58 @@ void Mesh::unbindImplementationDefault() {
void Mesh::unbindImplementationVAO() {}
#ifdef MAGNUM_TARGET_GLES
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
#if defined(MAGNUM_TARGET_WEBGL) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_patch__ >= 13915
void Mesh::drawElementsBaseVertexImplementationANGLE(GLenum mode, GLsizei count, GLenum type, const void* indices, GLint baseVertex) {
glDrawElementsInstancedBaseVertexBaseInstanceANGLE(mode, count, type, indices, 1, baseVertex, 0);
}
#endif
void Mesh::drawElementsBaseVertexImplementationAssert(GLenum, GLsizei, GLenum, const void*, GLint) {
CORRADE_ASSERT_UNREACHABLE("GL::AbstractShaderProgram::draw(): no extension available for indexed mesh draw with base vertex specification", );
}
#endif
#ifndef MAGNUM_TARGET_GLES2
#if defined(MAGNUM_TARGET_WEBGL) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_patch__ >= 13915
void Mesh::drawRangeElementsBaseVertexImplementationANGLE(const GLenum mode, GLuint, GLuint, GLsizei count, GLenum type, const void* indices, GLint baseVertex) {
glDrawElementsInstancedBaseVertexBaseInstanceANGLE(mode, count, type, indices, 1, baseVertex, 0);
}
#endif
void Mesh::drawRangeElementsBaseVertexImplementationAssert(GLenum, GLuint, GLuint, GLsizei, GLenum, const void*, GLint) {
CORRADE_ASSERT_UNREACHABLE("GL::AbstractShaderProgram::draw(): no extension available for indexed mesh draw with base vertex specification", );
}
void Mesh::drawArraysInstancedBaseInstanceImplementationAssert(GLenum, GLint, GLsizei, GLsizei, GLuint) {
CORRADE_ASSERT_UNREACHABLE("GL::AbstractShaderProgram::draw(): no extension available for instanced mesh draw with base instance specification", );
}
#if !defined(MAGNUM_TARGET_WEBGL) || __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_patch__ >= 13915
void Mesh::drawElementsInstancedBaseInstanceImplementationANGLE(const GLenum mode, const GLsizei count, const GLenum type, const void* const indices, const GLsizei instanceCount, const GLuint baseInstance) {
glDrawElementsInstancedBaseVertexBaseInstanceANGLE(mode, count, type, indices, instanceCount, 0, baseInstance);
}
#endif
void Mesh::drawElementsInstancedBaseInstanceImplementationAssert(GLenum, GLsizei, GLenum, const void*, GLsizei, GLuint) {
CORRADE_ASSERT_UNREACHABLE("GL::AbstractShaderProgram::draw(): no extension available for instanced indexed mesh draw with base instance specification", );
}
void Mesh::drawElementsInstancedBaseVertexBaseInstanceImplementationAssert(GLenum, GLsizei, GLenum, const void*, GLsizei, GLint, GLuint) {
CORRADE_ASSERT_UNREACHABLE("GL::AbstractShaderProgram::draw(): no extension available for instanced indexed mesh draw with base vertex and base instance specification", );
}
#if defined(MAGNUM_TARGET_WEBGL) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_patch__ >= 13915
void Mesh::drawElementsInstancedBaseVertexImplementationANGLE(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instanceCount, GLint baseVertex) {
glDrawElementsInstancedBaseVertexBaseInstanceANGLE(mode, count, type, indices, instanceCount, baseVertex, 0);
}
#endif
void Mesh::drawElementsInstancedBaseVertexImplementationAssert(GLenum, GLsizei, GLenum, const void*, GLsizei, GLint) {
CORRADE_ASSERT_UNREACHABLE("GL::AbstractShaderProgram::draw(): no extension available for instanced indexed mesh draw with base vertex specification", );
}
#endif
#endif
}}

54
src/Magnum/GL/Mesh.h

@ -608,8 +608,12 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject {
* @see @ref setCount(), @ref setBaseInstance()
* @requires_gl32 Extension @gl_extension{ARB,draw_elements_base_vertex}
* for indexed meshes
* @requires_gles32 Base vertex cannot be specified for indexed meshes
* in OpenGL ES 3.1 or WebGL.
* @requires_gles32 Extension @gl_extension{OES,draw_elements_base_vertex}
* or @gl_extension{EXT,draw_elements_base_vertex} for indexed
* meshes on OpenGL ES 3.1 and older
* @requires_webgl_extension WebGL 2.0 and extension
* @webgl_extension{WEBGL,draw_instanced_base_vertex_base_instance}
* for indexed meshes
*/
Mesh& setBaseVertex(Int baseVertex) {
_baseVertex = baseVertex;
@ -647,7 +651,7 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject {
return *this;
}
#ifndef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
/** @brief Base instance */
UnsignedInt baseInstance() const { return _baseInstance; }
@ -659,8 +663,10 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject {
* Default is @cpp 0 @ce.
* @see @ref setInstanceCount(), @ref setBaseVertex()
* @requires_gl42 Extension @gl_extension{ARB,base_instance}
* @requires_gl Base instance cannot be specified in OpenGL ES or
* WebGL.
* @requires_es_extension OpenGL ES 3.1 and extension
* @m_class{m-doc-external} [ANGLE_base_vertex_base_instance](https://chromium.googlesource.com/angle/angle/+/master/extensions/ANGLE_base_vertex_base_instance.txt)
* @requires_webgl_extension WebGL 2.0 and extension
* @webgl_extension{WEBGL,draw_instanced_base_vertex_base_instance}
*/
Mesh& setBaseInstance(UnsignedInt baseInstance) {
_baseInstance = baseInstance;
@ -1068,10 +1074,8 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject {
void MAGNUM_GL_LOCAL bindVAO();
#ifndef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
void drawInternal(Int count, Int baseVertex, Int instanceCount, UnsignedInt baseInstance, GLintptr indexOffset, Int indexStart, Int indexEnd);
#elif !defined(MAGNUM_TARGET_GLES2)
void drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr indexOffset, Int indexStart, Int indexEnd);
#else
void drawInternal(Int count, Int baseVertex, Int instanceCount, GLintptr indexOffset);
#endif
@ -1133,6 +1137,36 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject {
void MAGNUM_GL_LOCAL unbindImplementationDefault();
void MAGNUM_GL_LOCAL unbindImplementationVAO();
#ifdef MAGNUM_TARGET_GLES
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
#if defined(MAGNUM_TARGET_WEBGL) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 13915
static void MAGNUM_GL_LOCAL drawElementsBaseVertexImplementationANGLE(GLenum mode, GLsizei count, GLenum type, const void* indices, GLint baseVertex);
#endif
static void MAGNUM_GL_LOCAL drawElementsBaseVertexImplementationAssert(GLenum, GLsizei, GLenum, const void*, GLint);
#endif
#ifndef MAGNUM_TARGET_GLES2
#if defined(MAGNUM_TARGET_WEBGL) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 13915
static void MAGNUM_GL_LOCAL drawRangeElementsBaseVertexImplementationANGLE(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices, GLint baseVertex);
#endif
static void MAGNUM_GL_LOCAL drawRangeElementsBaseVertexImplementationAssert(GLenum, GLuint, GLuint, GLsizei, GLenum, const void*, GLint);
static void MAGNUM_GL_LOCAL drawArraysInstancedBaseInstanceImplementationAssert(GLenum, GLint, GLsizei, GLsizei, GLuint);
#if !defined(MAGNUM_TARGET_WEBGL) || __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 13915
static void MAGNUM_GL_LOCAL drawElementsInstancedBaseInstanceImplementationANGLE(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instanceCount, GLuint baseInstance);
#endif
static void MAGNUM_GL_LOCAL drawElementsInstancedBaseInstanceImplementationAssert(GLenum, GLsizei, GLenum, const void*, GLsizei, GLuint);
static void MAGNUM_GL_LOCAL drawElementsInstancedBaseVertexBaseInstanceImplementationAssert(GLenum, GLsizei, GLenum, const void*, GLsizei, GLint, GLuint);
#if defined(MAGNUM_TARGET_WEBGL) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 13915
static void MAGNUM_GL_LOCAL drawElementsInstancedBaseVertexImplementationANGLE(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instanceCount, GLint baseVertex);
#endif
static void MAGNUM_GL_LOCAL drawElementsInstancedBaseVertexImplementationAssert(GLenum, GLsizei, GLenum, const void*, GLsizei, GLint);
#endif
#endif
/* _id, _primitive, _flags set from constructors */
GLuint _id;
MeshPrimitive _primitive;
@ -1144,10 +1178,8 @@ class MAGNUM_GL_EXPORT Mesh: public AbstractObject {
object is constructed using NoCreate). Also fits in the gap. */
bool _constructed{};
Int _count{}, _baseVertex{}, _instanceCount{1};
#ifndef MAGNUM_TARGET_GLES
UnsignedInt _baseInstance{};
#endif
#ifndef MAGNUM_TARGET_GLES2
UnsignedInt _baseInstance{};
UnsignedInt _indexStart{}, _indexEnd{};
#endif
GLintptr _indexOffset{};

54
src/Magnum/GL/MeshView.cpp

@ -26,6 +26,7 @@
#include "MeshView.h"
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/ArrayTuple.h>
#include <Corrade/Utility/Assert.h>
#include "Magnum/GL/AbstractShaderProgram.h"
@ -95,24 +96,16 @@ void MeshView::multiDrawImplementationDefault(Containers::ArrayView<const Contai
Containers::Array<GLint> baseVertex{meshes.size()};
/* Gather the parameters */
#ifndef MAGNUM_TARGET_GLES
bool hasBaseVertex = false;
#endif
std::size_t i = 0;
for(MeshView& mesh: meshes) {
CORRADE_ASSERT(mesh._instanceCount == 1, "GL::MeshView::draw(): cannot draw multiple instanced meshes", );
CORRADE_ASSERT(mesh._instanceCount == 1, "GL::AbstractShaderProgram::draw(): cannot draw multiple instanced meshes", );
count[i] = mesh._count;
indices[i] = reinterpret_cast<GLvoid*>(mesh._indexOffset);
baseVertex[i] = mesh._baseVertex;
if(mesh._baseVertex) {
#ifndef MAGNUM_TARGET_GLES
hasBaseVertex = true;
#else
CORRADE_ASSERT(!original._indexBuffer.id(), "GL::MeshView::draw(): desktop OpenGL is required for base vertex specification in indexed meshes", );
#endif
}
if(mesh._baseVertex) hasBaseVertex = true;
++i;
}
@ -131,14 +124,20 @@ void MeshView::multiDrawImplementationDefault(Containers::ArrayView<const Contai
/* Indexed meshes */
} else {
/* Indexed meshes with base vertex */
#ifndef MAGNUM_TARGET_GLES
if(hasBaseVertex) {
glMultiDrawElementsBaseVertex(GLenum(original._primitive), count, GLenum(original._indexType), indices, meshes.size(), baseVertex);
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
#ifndef MAGNUM_TARGET_GLES
glMultiDrawElementsBaseVertex
#else
state.multiDrawElementsBaseVertexImplementation
#endif
(GLenum(original._primitive), count, GLenum(original._indexType), indices, meshes.size(), baseVertex);
#else
CORRADE_ASSERT_UNREACHABLE("GL::AbstractShaderProgram::draw(): indexed mesh multi-draw with base vertex specification possible only since WebGL 2.0", );
#endif
/* Indexed meshes */
} else
#endif
{
} else {
#ifndef MAGNUM_TARGET_GLES
glMultiDrawElements
#else
@ -157,10 +156,10 @@ void MeshView::multiDrawImplementationFallback(Containers::ArrayView<const Conta
/* Nothing to draw in this mesh */
if(!mesh._count) continue;
CORRADE_ASSERT(mesh._instanceCount == 1, "GL::MeshView::draw(): cannot draw multiple instanced meshes", );
CORRADE_ASSERT(mesh._instanceCount == 1, "GL::AbstractShaderProgram::draw(): cannot draw multiple instanced meshes", );
#ifndef MAGNUM_TARGET_GLES2
mesh._original.get().drawInternal(mesh._count, mesh._baseVertex, 1, mesh._indexOffset, mesh._indexStart, mesh._indexEnd);
mesh._original.get().drawInternal(mesh._count, mesh._baseVertex, 1, mesh._baseInstance, mesh._indexOffset, mesh._indexStart, mesh._indexEnd);
#else
mesh._original.get().drawInternal(mesh._count, mesh._baseVertex, 1, mesh._indexOffset);
#endif
@ -168,4 +167,25 @@ void MeshView::multiDrawImplementationFallback(Containers::ArrayView<const Conta
}
#endif
#ifdef MAGNUM_TARGET_GLES
#if defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 20005
void MeshView::multiDrawElementsBaseVertexImplementationANGLE(const GLenum mode, const GLsizei* const count, const GLenum type, const void* const* const indices, const GLsizei drawCount, const GLint* const baseVertex) {
/** @todo merge with the allocation in multiDrawImplementationDefault */
Containers::ArrayView<GLsizei> instanceCount;
Containers::ArrayView<GLuint> baseInstance;
Containers::ArrayTuple data{
{Containers::NoInit, std::size_t(drawCount), instanceCount},
{Containers::ValueInit, std::size_t(drawCount), baseInstance},
};
for(GLsizei& i: instanceCount) i = 1;
glMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(mode, count, type, indices, instanceCount, baseVertex, baseInstance, drawCount);
}
#endif
void MeshView::multiDrawElementsBaseVertexImplementationAssert(GLenum, const GLsizei*, GLenum, const void* const*, GLsizei, const GLint*) {
CORRADE_ASSERT_UNREACHABLE("GL::AbstractShaderProgram::draw(): no extension available for indexed mesh multi-draw with base vertex specification", );
}
#endif
}}

25
src/Magnum/GL/MeshView.h

@ -134,8 +134,12 @@ class MAGNUM_GL_EXPORT MeshView {
* @cpp 0 @ce.
* @requires_gl32 Extension @gl_extension{ARB,draw_elements_base_vertex}
* for indexed meshes
* @requires_gles32 Base vertex cannot be specified for indexed meshes
* in OpenGL ES 3.1 or WebGL.
* @requires_es_extension Extension @gl_extension{OES,draw_elements_base_vertex}
* or @gl_extension{EXT,draw_elements_base_vertex} for indexed
* meshes on OpenGL ES 3.1 and older
* @requires_webgl_extension WebGL 2.0 and extension
* @webgl_extension{WEBGL,draw_instanced_base_vertex_base_instance}
* for indexed meshes
*/
MeshView& setBaseVertex(Int baseVertex) {
_baseVertex = baseVertex;
@ -201,7 +205,7 @@ class MAGNUM_GL_EXPORT MeshView {
return *this;
}
#ifndef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
/** @brief Base instance */
UnsignedInt baseInstance() const { return _baseInstance; }
@ -212,8 +216,10 @@ class MAGNUM_GL_EXPORT MeshView {
* Ignored when calling @ref AbstractShaderProgram::drawTransformFeedback().
* Default is @cpp 0 @ce.
* @requires_gl42 Extension @gl_extension{ARB,base_instance}
* @requires_gl Base instance cannot be specified in OpenGL ES or
* WebGL.
* @requires_es_extension OpenGL ES 3.1 and extension
* @m_class{m-doc-external} [ANGLE_base_vertex_base_instance](https://chromium.googlesource.com/angle/angle/+/master/extensions/ANGLE_base_vertex_base_instance.txt)
* @requires_webgl_extension WebGL 2.0 and extension
* @webgl_extension{WEBGL,draw_instanced_base_vertex_base_instance}
*/
MeshView& setBaseInstance(UnsignedInt baseInstance) {
_baseInstance = baseInstance;
@ -262,11 +268,18 @@ class MAGNUM_GL_EXPORT MeshView {
static MAGNUM_GL_LOCAL void multiDrawImplementationFallback(Containers::ArrayView<const Containers::Reference<MeshView>> meshes);
#endif
#ifdef MAGNUM_TARGET_GLES
#if defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 20005
static MAGNUM_GL_LOCAL void multiDrawElementsBaseVertexImplementationANGLE(GLenum mode, const GLsizei* count, GLenum type, const void* const* indices, GLsizei drawCount, const GLint* baseVertex);
#endif
static MAGNUM_GL_LOCAL void multiDrawElementsBaseVertexImplementationAssert(GLenum, const GLsizei*, GLenum, const void* const*, GLsizei, const GLint*);
#endif
Containers::Reference<Mesh> _original;
bool _countSet{};
Int _count{}, _baseVertex{}, _instanceCount{1};
#ifndef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
UnsignedInt _baseInstance{};
#endif
GLintptr _indexOffset{};

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

@ -137,16 +137,38 @@ struct MeshGLTest: OpenGLTester {
void unbindVAOBeforeEnteringExternalSection();
void bindScratchVaoWhenEnteringExternalSection();
#ifndef MAGNUM_TARGET_GLES
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void setBaseVertex();
#endif
#ifdef MAGNUM_TARGET_GLES
void setBaseVertexNoExtensionAvailable();
void setBaseVertexRangeNoExtensionAvailable();
#endif
void setInstanceCount();
void setInstanceCountIndexed();
#ifndef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
void setInstanceCountBaseInstance();
void setInstanceCountBaseInstanceIndexed();
void setInstanceCountBaseVertex();
void setInstanceCountBaseVertexBaseInstance();
#ifdef MAGNUM_TARGET_GLES
void setInstanceCountBaseInstanceNoExtensionAvailable();
#endif
#endif
void setInstanceCountIndexed();
#ifndef MAGNUM_TARGET_GLES2
void setInstanceCountIndexedBaseInstance();
#ifdef MAGNUM_TARGET_GLES
void setInstanceCountIndexedBaseInstanceNoExtensionAvailable();
#endif
#endif
#ifndef MAGNUM_TARGET_GLES2
void setInstanceCountIndexedBaseVertex();
#endif
#ifdef MAGNUM_TARGET_GLES
void setInstanceCountIndexedBaseVertexNoExtensionAvailable();
#endif
#ifndef MAGNUM_TARGET_GLES2
void setInstanceCountIndexedBaseVertexBaseInstance();
#ifdef MAGNUM_TARGET_GLES
void setInstanceCountIndexedBaseVertexBaseInstanceNoExtensionAvailable();
#endif
#endif
void addVertexBufferInstancedFloat();
@ -160,9 +182,13 @@ struct MeshGLTest: OpenGLTester {
void multiDraw();
void multiDrawIndexed();
#ifndef MAGNUM_TARGET_GLES
void multiDrawInstanced();
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void multiDrawBaseVertex();
#endif
#ifdef MAGNUM_TARGET_GLES
void multiDrawBaseVertexNoExtensionAvailable();
#endif
};
MeshGLTest::MeshGLTest() {
@ -259,16 +285,38 @@ MeshGLTest::MeshGLTest() {
&MeshGLTest::unbindVAOBeforeEnteringExternalSection,
&MeshGLTest::bindScratchVaoWhenEnteringExternalSection,
#ifndef MAGNUM_TARGET_GLES
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
&MeshGLTest::setBaseVertex,
#endif
#ifdef MAGNUM_TARGET_GLES
&MeshGLTest::setBaseVertexNoExtensionAvailable,
&MeshGLTest::setBaseVertexRangeNoExtensionAvailable,
#endif
&MeshGLTest::setInstanceCount,
&MeshGLTest::setInstanceCountIndexed,
#ifndef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
&MeshGLTest::setInstanceCountBaseInstance,
&MeshGLTest::setInstanceCountBaseInstanceIndexed,
&MeshGLTest::setInstanceCountBaseVertex,
&MeshGLTest::setInstanceCountBaseVertexBaseInstance,
#ifdef MAGNUM_TARGET_GLES
&MeshGLTest::setInstanceCountBaseInstanceNoExtensionAvailable,
#endif
#endif
&MeshGLTest::setInstanceCountIndexed,
#ifndef MAGNUM_TARGET_GLES2
&MeshGLTest::setInstanceCountIndexedBaseInstance,
#ifdef MAGNUM_TARGET_GLES
&MeshGLTest::setInstanceCountIndexedBaseInstanceNoExtensionAvailable,
#endif
#endif
#ifndef MAGNUM_TARGET_GLES2
&MeshGLTest::setInstanceCountIndexedBaseVertex,
#endif
#ifdef MAGNUM_TARGET_GLES
&MeshGLTest::setInstanceCountIndexedBaseVertexNoExtensionAvailable,
#endif
#ifndef MAGNUM_TARGET_GLES2
&MeshGLTest::setInstanceCountIndexedBaseVertexBaseInstance,
#ifdef MAGNUM_TARGET_GLES
&MeshGLTest::setInstanceCountIndexedBaseVertexBaseInstanceNoExtensionAvailable,
#endif
#endif
&MeshGLTest::addVertexBufferInstancedFloat,
@ -282,8 +330,12 @@ MeshGLTest::MeshGLTest() {
&MeshGLTest::multiDraw,
&MeshGLTest::multiDrawIndexed,
#ifndef MAGNUM_TARGET_GLES
&MeshGLTest::multiDrawBaseVertex
&MeshGLTest::multiDrawInstanced,
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
&MeshGLTest::multiDrawBaseVertex,
#endif
#ifdef MAGNUM_TARGET_GLES
&MeshGLTest::multiDrawBaseVertexNoExtensionAvailable
#endif
});
}
@ -1966,7 +2018,6 @@ const Float indexedVertexData[] = {
1.0f, -0.5f
};
#ifndef MAGNUM_TARGET_GLES
const Float indexedVertexDataBaseVertex[] = {
0.0f, 0.0f, /* Offset */
@ -1995,7 +2046,6 @@ const Float indexedVertexDataBaseVertex[] = {
0.4f, 0.0f, -0.9f,
1.0f, -0.5f
};
#endif
#ifndef MAGNUM_TARGET_GLES2
constexpr Color4ub indexedResult{64 + 15 + 97, 17 + 164 + 28, 56 + 17, 255};
@ -2485,10 +2535,19 @@ void MeshGLTest::bindScratchVaoWhenEnteringExternalSection() {
#endif
}
#ifndef MAGNUM_TARGET_GLES
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void MeshGLTest::setBaseVertex() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::ARB::draw_elements_base_vertex>())
CORRADE_SKIP(Extensions::ARB::draw_elements_base_vertex::string() + std::string(" is not available."));
#elif !defined(MAGNUM_TARGET_WEBGL)
if(!Context::current().isExtensionSupported<Extensions::OES::draw_elements_base_vertex>() &&
!Context::current().isExtensionSupported<Extensions::EXT::draw_elements_base_vertex>())
CORRADE_SKIP(std::string{"Neither "} + Extensions::OES::draw_elements_base_vertex::string() + " nor " + Extensions::EXT::draw_elements_base_vertex::string() + " is available.");
#else
if(!Context::current().isExtensionSupported<Extensions::WEBGL::draw_instanced_base_vertex_base_instance>())
CORRADE_SKIP(Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string() + std::string{" is not available."});
#endif
Buffer vertices;
vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw);
@ -2513,6 +2572,72 @@ void MeshGLTest::setBaseVertex() {
}
#endif
#ifdef MAGNUM_TARGET_GLES
void MeshGLTest::setBaseVertexNoExtensionAvailable() {
#ifndef MAGNUM_TARGET_WEBGL
if(Context::current().isVersionSupported(Version::GLES320))
CORRADE_SKIP("OpenGL ES 3.2 is available.");
if(Context::current().isExtensionSupported<Extensions::EXT::draw_elements_base_vertex>())
CORRADE_SKIP(Extensions::EXT::draw_elements_base_vertex::string() + std::string{" is available."});
if(Context::current().isExtensionSupported<Extensions::OES::draw_elements_base_vertex>())
CORRADE_SKIP(Extensions::OES::draw_elements_base_vertex::string() + std::string{" is available."});
#elif !defined(MAGNUM_TARGET_GLES2)
if(Context::current().isExtensionSupported<Extensions::WEBGL::draw_instanced_base_vertex_base_instance>())
CORRADE_SKIP(Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string() + std::string{" is available."});
#endif
constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setCount(3)
.setBaseVertex(1)
.setIndexBuffer(indices, 0, MeshIndexType::UnsignedShort);
std::ostringstream out;
Error redirectError{&out};
MultipleShader{}.draw(mesh);
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
CORRADE_COMPARE(out.str(), "GL::AbstractShaderProgram::draw(): no extension available for indexed mesh draw with base vertex specification\n");
#else
CORRADE_COMPARE(out.str(), "GL::AbstractShaderProgram::draw(): indexed mesh draw with base vertex specification possible only since WebGL 2.0\n");
#endif
}
void MeshGLTest::setBaseVertexRangeNoExtensionAvailable() {
#ifndef MAGNUM_TARGET_WEBGL
if(Context::current().isVersionSupported(Version::GLES320))
CORRADE_SKIP("OpenGL ES 3.2 is available.");
if(Context::current().isExtensionSupported<Extensions::EXT::draw_elements_base_vertex>())
CORRADE_SKIP(Extensions::EXT::draw_elements_base_vertex::string() + std::string{" is available."});
if(Context::current().isExtensionSupported<Extensions::OES::draw_elements_base_vertex>())
CORRADE_SKIP(Extensions::OES::draw_elements_base_vertex::string() + std::string{" is available."});
#elif !defined(MAGNUM_TARGET_GLES2)
if(Context::current().isExtensionSupported<Extensions::WEBGL::draw_instanced_base_vertex_base_instance>())
CORRADE_SKIP(Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string() + std::string{" is available."});
#endif
constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setCount(3)
.setBaseVertex(1)
.setIndexBuffer(indices, 0, MeshIndexType::UnsignedShort, 0, 2);
std::ostringstream out;
Error redirectError{&out};
MultipleShader{}.draw(mesh);
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
CORRADE_COMPARE(out.str(), "GL::AbstractShaderProgram::draw(): no extension available for indexed mesh draw with base vertex specification\n");
#else
CORRADE_COMPARE(out.str(), "GL::AbstractShaderProgram::draw(): indexed mesh draw with base vertex specification possible only since WebGL 2.0\n");
#endif
}
#endif
void MeshGLTest::setInstanceCount() {
/* Verbatim copy of addVertexBufferFloat() with added extension check and
setInstanceCount() call. It would just render three times the same
@ -2561,6 +2686,71 @@ void MeshGLTest::setInstanceCount() {
CORRADE_COMPARE(value, 96);
}
#ifndef MAGNUM_TARGET_GLES2
void MeshGLTest::setInstanceCountBaseInstance() {
/* Verbatim copy of setInstanceCount() with additional extension check and
setBaseInstance() call. It would just render three times the same
value. I'm too lazy to invent proper test case, so I'll just check that
it didn't generate any error and rendered something */
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::ARB::draw_instanced>())
CORRADE_SKIP(Extensions::ARB::draw_instanced::string() + std::string(" is not available."));
if(!Context::current().isExtensionSupported<Extensions::ARB::base_instance>())
CORRADE_SKIP(Extensions::ARB::base_instance::string() + std::string(" is not available."));
#elif !defined(MAGNUM_TARGET_WEBGL)
if(!Context::current().isExtensionSupported<Extensions::ANGLE::base_vertex_base_instance>())
CORRADE_SKIP(Extensions::ANGLE::base_vertex_base_instance::string() + std::string{" is not available."});
#else
if(!Context::current().isExtensionSupported<Extensions::WEBGL::draw_instanced_base_vertex_base_instance>())
CORRADE_SKIP(Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string() + std::string{" is not available."});
#endif
typedef Attribute<0, Float> Attribute;
const Float data[] = { 0.0f, -0.7f, Math::unpack<Float, UnsignedByte>(96) };
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.setInstanceCount(3)
.setBaseInstance(72)
.addVertexBuffer(buffer, 4, Attribute());
MAGNUM_VERIFY_NO_GL_ERROR();
const auto value = Checker(FloatShader("float", "vec4(valueInterpolated, 0.0, 0.0, 0.0)"),
RenderbufferFormat::RGBA8,
mesh).get<UnsignedByte>(PixelFormat::RGBA, PixelType::UnsignedByte);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(value, 96);
}
#ifdef MAGNUM_TARGET_GLES
void MeshGLTest::setInstanceCountBaseInstanceNoExtensionAvailable() {
#ifndef MAGNUM_TARGET_WEBGL
if(Context::current().isExtensionSupported<Extensions::ANGLE::base_vertex_base_instance>())
CORRADE_SKIP(Extensions::ANGLE::base_vertex_base_instance::string() + std::string{" is available."});
#else
if(Context::current().isExtensionSupported<Extensions::WEBGL::draw_instanced_base_vertex_base_instance>())
CORRADE_SKIP(Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string() + std::string{" is available."});
#endif
Mesh mesh;
mesh.setCount(3)
.setInstanceCount(2)
.setBaseInstance(1);
std::ostringstream out;
Error redirectError{&out};
MultipleShader{}.draw(mesh);
CORRADE_COMPARE(out.str(), "GL::AbstractShaderProgram::draw(): no extension available for instanced mesh draw with base instance specification\n");
}
#endif
#endif
void MeshGLTest::setInstanceCountIndexed() {
/* Verbatim copy of setIndexBuffer() with added extension check and
setInstanceCount() call. It would just render three times the same
@ -2611,50 +2801,25 @@ void MeshGLTest::setInstanceCountIndexed() {
CORRADE_COMPARE(value, indexedResult);
}
#ifndef MAGNUM_TARGET_GLES
void MeshGLTest::setInstanceCountBaseInstance() {
/* Verbatim copy of setInstanceCount() with additional extension check and
setBaseInstance() call. It would just render three times the same
value. I'm too lazy to invent proper test case, so I'll just check that
it didn't generate any error and rendered something */
if(!Context::current().isExtensionSupported<Extensions::ARB::draw_instanced>())
CORRADE_SKIP(Extensions::ARB::draw_instanced::string() + std::string(" is not available."));
if(!Context::current().isExtensionSupported<Extensions::ARB::base_instance>())
CORRADE_SKIP(Extensions::ARB::base_instance::string() + std::string(" is not available."));
typedef Attribute<0, Float> Attribute;
const Float data[] = { 0.0f, -0.7f, Math::unpack<Float, UnsignedByte>(96) };
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setBaseVertex(1)
.setInstanceCount(3)
.setBaseInstance(72)
.addVertexBuffer(buffer, 4, Attribute());
MAGNUM_VERIFY_NO_GL_ERROR();
const auto value = Checker(FloatShader("float", "vec4(valueInterpolated, 0.0, 0.0, 0.0)"),
RenderbufferFormat::RGBA8,
mesh).get<UnsignedByte>(PixelFormat::RGBA, PixelType::UnsignedByte);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(value, 96);
}
void MeshGLTest::setInstanceCountBaseInstanceIndexed() {
#ifndef MAGNUM_TARGET_GLES2
void MeshGLTest::setInstanceCountIndexedBaseInstance() {
/* Verbatim copy of setInstanceCountIndexed() with additional extension
check and setBaseInstance() call. It would just render three times the
same value. I'm too lazy to invent proper test case, so I'll just check
that it didn't generate any error and rendered something */
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::ARB::draw_instanced>())
CORRADE_SKIP(Extensions::ARB::draw_instanced::string() + std::string(" is not available."));
if(!Context::current().isExtensionSupported<Extensions::ARB::base_instance>())
CORRADE_SKIP(Extensions::ARB::base_instance::string() + std::string(" is not available."));
#elif !defined(MAGNUM_TARGET_WEBGL)
if(!Context::current().isExtensionSupported<Extensions::ANGLE::base_vertex_base_instance>())
CORRADE_SKIP(Extensions::ANGLE::base_vertex_base_instance::string() + std::string{" is not available."});
#else
if(!Context::current().isExtensionSupported<Extensions::WEBGL::draw_instanced_base_vertex_base_instance>())
CORRADE_SKIP(Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string() + std::string{" is not available."});
#endif
Buffer vertices;
vertices.setData(indexedVertexData, BufferUsage::StaticDraw);
@ -2679,16 +2844,54 @@ void MeshGLTest::setInstanceCountBaseInstanceIndexed() {
CORRADE_COMPARE(value, indexedResult);
}
void MeshGLTest::setInstanceCountBaseVertex() {
#ifdef MAGNUM_TARGET_GLES
void MeshGLTest::setInstanceCountIndexedBaseInstanceNoExtensionAvailable() {
#ifndef MAGNUM_TARGET_WEBGL
if(Context::current().isExtensionSupported<Extensions::ANGLE::base_vertex_base_instance>())
CORRADE_SKIP(Extensions::ANGLE::base_vertex_base_instance::string() + std::string{" is available."});
#else
if(Context::current().isExtensionSupported<Extensions::WEBGL::draw_instanced_base_vertex_base_instance>())
CORRADE_SKIP(Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string() + std::string{" is available."});
#endif
constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setCount(3)
.setInstanceCount(2)
.setBaseInstance(1)
.setIndexBuffer(indices, 0, MeshIndexType::UnsignedShort);
std::ostringstream out;
Error redirectError{&out};
MultipleShader{}.draw(mesh);
CORRADE_COMPARE(out.str(), "GL::AbstractShaderProgram::draw(): no extension available for instanced indexed mesh draw with base instance specification\n");
}
#endif
#endif
#ifndef MAGNUM_TARGET_GLES2
void MeshGLTest::setInstanceCountIndexedBaseVertex() {
/* Verbatim copy of setBaseVertex() with additional extension check and
setInstanceCount() call. It would just render three times the same
value. I'm too lazy to invent proper test case, so I'll just check
that it didn't generate any error and rendered something */
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::ARB::draw_instanced>())
CORRADE_SKIP(Extensions::ARB::draw_instanced::string() + std::string(" is not available."));
if(!Context::current().isExtensionSupported<Extensions::ARB::draw_elements_base_vertex>())
CORRADE_SKIP(Extensions::ARB::draw_elements_base_vertex::string() + std::string(" is not available."));
#elif !defined(MAGNUM_TARGET_WEBGL)
if(!Context::current().isExtensionSupported<Extensions::OES::draw_elements_base_vertex>() &&
!Context::current().isExtensionSupported<Extensions::EXT::draw_elements_base_vertex>())
CORRADE_SKIP(std::string{"Neither "} + Extensions::OES::draw_elements_base_vertex::string() + " nor " + Extensions::EXT::draw_elements_base_vertex::string() + " is available.");
#else
if(!Context::current().isExtensionSupported<Extensions::WEBGL::draw_instanced_base_vertex_base_instance>())
CORRADE_SKIP(Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string() + std::string{" is not available."});
#endif
Buffer vertices;
vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw);
@ -2712,19 +2915,66 @@ void MeshGLTest::setInstanceCountBaseVertex() {
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(value, indexedResult);
}
#endif
#ifdef MAGNUM_TARGET_GLES
void MeshGLTest::setInstanceCountIndexedBaseVertexNoExtensionAvailable() {
#ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_WEBGL
if(Context::current().isVersionSupported(Version::GLES320))
CORRADE_SKIP("OpenGL ES 3.2 is available.");
if(Context::current().isExtensionSupported<Extensions::EXT::draw_elements_base_vertex>())
CORRADE_SKIP(Extensions::EXT::draw_elements_base_vertex::string() + std::string{" is available."});
if(Context::current().isExtensionSupported<Extensions::OES::draw_elements_base_vertex>())
CORRADE_SKIP(Extensions::OES::draw_elements_base_vertex::string() + std::string{" is available."});
#else
if(Context::current().isExtensionSupported<Extensions::WEBGL::draw_instanced_base_vertex_base_instance>())
CORRADE_SKIP(Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string() + std::string{" is available."});
#endif
#endif
void MeshGLTest::setInstanceCountBaseVertexBaseInstance() {
constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setCount(3)
.setInstanceCount(2)
.setBaseVertex(1)
.setIndexBuffer(indices, 0, MeshIndexType::UnsignedShort);
std::ostringstream out;
Error redirectError{&out};
MultipleShader{}.draw(mesh);
#ifndef MAGNUM_TARGET_GLES2
CORRADE_COMPARE(out.str(), "GL::AbstractShaderProgram::draw(): no extension available for instanced indexed mesh draw with base vertex specification\n");
#else
CORRADE_COMPARE(out.str(), "GL::AbstractShaderProgram::draw(): instanced indexed mesh draw with base vertex specification possible only since OpenGL ES 3.0\n");
#endif
}
#endif
#ifndef MAGNUM_TARGET_GLES2
void MeshGLTest::setInstanceCountIndexedBaseVertexBaseInstance() {
/* Verbatim copy of setInstanceCountBaseVertex() with added extension check
and setBaseInstance() call. It would just render three times the same
value. I'm too lazy to invent proper test case, so I'll just check
that it didn't generate any error and rendered something */
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::ARB::draw_instanced>())
CORRADE_SKIP(Extensions::ARB::draw_instanced::string() + std::string(" is not available."));
if(!Context::current().isExtensionSupported<Extensions::ARB::draw_elements_base_vertex>())
CORRADE_SKIP(Extensions::ARB::draw_elements_base_vertex::string() + std::string(" is not available."));
if(!Context::current().isExtensionSupported<Extensions::ARB::base_instance>())
CORRADE_SKIP(Extensions::ARB::base_instance::string() + std::string(" is not available."));
#elif !defined(MAGNUM_TARGET_WEBGL)
if(!Context::current().isExtensionSupported<Extensions::ANGLE::base_vertex_base_instance>())
CORRADE_SKIP(Extensions::ANGLE::base_vertex_base_instance::string() + std::string{" is not available."});
#else
if(!Context::current().isExtensionSupported<Extensions::WEBGL::draw_instanced_base_vertex_base_instance>())
CORRADE_SKIP(Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string() + std::string{" is not available."});
#endif
Buffer vertices;
vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw);
@ -2749,6 +2999,38 @@ void MeshGLTest::setInstanceCountBaseVertexBaseInstance() {
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE(value, indexedResult);
}
#ifdef MAGNUM_TARGET_GLES
void MeshGLTest::setInstanceCountIndexedBaseVertexBaseInstanceNoExtensionAvailable() {
#ifndef MAGNUM_TARGET_WEBGL
if(Context::current().isExtensionSupported<Extensions::ANGLE::base_vertex_base_instance>())
CORRADE_SKIP(Extensions::ANGLE::base_vertex_base_instance::string() + std::string{" is available."});
#else
if(Context::current().isExtensionSupported<Extensions::WEBGL::draw_instanced_base_vertex_base_instance>())
CORRADE_SKIP(Extensions::WEBGL::draw_instanced_base_vertex_base_instance::string() + std::string{" is available."});
#endif
constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setCount(3)
.setInstanceCount(2)
.setBaseVertex(1)
.setBaseInstance(1)
.setIndexBuffer(indices, 0, MeshIndexType::UnsignedShort);
std::ostringstream out;
Error redirectError{&out};
MultipleShader{}.draw(mesh);
#ifndef MAGNUM_TARGET_GLES2
CORRADE_COMPARE(out.str(), "GL::AbstractShaderProgram::draw(): no extension available for instanced indexed mesh draw with base vertex and base instance specification\n");
#else
CORRADE_COMPARE(out.str(), "GL::AbstractShaderProgram::draw(): instanced indexed mesh draw with base vertex specification possible only since OpenGL 3.0\n");
#endif
}
#endif
#endif
void MeshGLTest::addVertexBufferInstancedFloat() {
@ -3079,10 +3361,31 @@ void MeshGLTest::multiDrawIndexed() {
CORRADE_COMPARE(value, indexedResult);
}
#ifndef MAGNUM_TARGET_GLES
void MeshGLTest::multiDrawInstanced() {
Mesh mesh;
MeshView view{mesh};
view.setCount(3)
.setInstanceCount(2);
std::ostringstream out;
Error redirectError{&out};
MultipleShader{}.draw({view, view});
CORRADE_COMPARE(out.str(), "GL::AbstractShaderProgram::draw(): cannot draw multiple instanced meshes\n");
}
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
void MeshGLTest::multiDrawBaseVertex() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::ARB::draw_elements_base_vertex>())
CORRADE_SKIP(Extensions::ARB::draw_elements_base_vertex::string() + std::string(" is not available."));
#elif !defined(MAGNUM_TARGET_WEBGL)
if(!Context::current().isExtensionSupported<Extensions::OES::draw_elements_base_vertex>() &&
!Context::current().isExtensionSupported<Extensions::EXT::draw_elements_base_vertex>())
CORRADE_SKIP(std::string{"Neither "} + Extensions::OES::draw_elements_base_vertex::string() + " nor " + Extensions::EXT::draw_elements_base_vertex::string() + " is available.");
#else
if(!Context::current().isExtensionSupported<Extensions::WEBGL::multi_draw_instanced_base_vertex_base_instance>())
CORRADE_SKIP(Extensions::WEBGL::multi_draw_instanced_base_vertex_base_instance::string() + std::string{" is not available."});
#endif
Buffer vertices;
vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw);
@ -3106,6 +3409,53 @@ void MeshGLTest::multiDrawBaseVertex() {
}
#endif
#ifdef MAGNUM_TARGET_GLES
void MeshGLTest::multiDrawBaseVertexNoExtensionAvailable() {
#ifdef MAGNUM_TARGET_GLES
/* If the multidraw extensions aren't available, we can't test this assert,
only the assert in the fallback path, which is already tested above. */
#ifndef MAGNUM_TARGET_WEBGL
if(!Context::current().isExtensionSupported<Extensions::EXT::multi_draw_arrays>() &&
!Context::current().isExtensionSupported<Extensions::ANGLE::multi_draw>())
CORRADE_SKIP(std::string{"Neither "} + Extensions::EXT::multi_draw_arrays::string() + " nor " + Extensions::ANGLE::multi_draw::string() + " is available.");
#else
if(!Context::current().isExtensionSupported<Extensions::WEBGL::multi_draw>())
CORRADE_SKIP(Extensions::WEBGL::multi_draw::string() + std::string{" is not available."});
#endif
#endif
#ifndef MAGNUM_TARGET_WEBGL
if(Context::current().isExtensionSupported<Extensions::EXT::draw_elements_base_vertex>())
CORRADE_SKIP(Extensions::EXT::draw_elements_base_vertex::string() + std::string{" is available."});
if(Context::current().isExtensionSupported<Extensions::OES::draw_elements_base_vertex>())
CORRADE_SKIP(Extensions::OES::draw_elements_base_vertex::string() + std::string{" is available."});
#elif !defined(MAGNUM_TARGET_GLES2)
if(Context::current().isExtensionSupported<Extensions::WEBGL::multi_draw_instanced_base_vertex_base_instance>())
CORRADE_SKIP(Extensions::WEBGL::multi_draw_instanced_base_vertex_base_instance::string() + std::string{" is available."});
#endif
constexpr UnsignedShort indexData[] = { 2, 1, 0 };
Buffer indices{Buffer::TargetHint::ElementArray};
indices.setData(indexData, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setIndexBuffer(indices, 0, MeshIndexType::UnsignedShort);
MeshView view{mesh};
view.setCount(3)
.setBaseVertex(1);
std::ostringstream out;
Error redirectError{&out};
MultipleShader{}.draw({view, view});
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
CORRADE_COMPARE(out.str(), "GL::AbstractShaderProgram::draw(): no extension available for indexed mesh multi-draw with base vertex specification\n");
#else
CORRADE_COMPARE(out.str(), "GL::AbstractShaderProgram::draw(): indexed mesh multi-draw with base vertex specification possible only since WebGL 2.0\n");
#endif
}
#endif
}}}}
CORRADE_TEST_MAIN(Magnum::GL::Test::MeshGLTest)

Loading…
Cancel
Save