Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GL/DebugTools: read buffer data on WebGL 2.0 #560

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions package/ci/circleci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ executors:
xcode-11_6:
macos:
xcode: 11.6.0
emscripten:
emscripten1:
docker:
# 1.39.0 is the oldest on Docker. Anything before 1.39.2 is useless as emar
# randomly asserts: https://github.com/emscripten-core/emscripten/pull/9742
Expand All @@ -28,6 +28,12 @@ executors:
# https://github.com/mosra/magnum/issues/413,
# https://github.com/emscripten-core/emscripten/pull/10161
- image: emscripten/emsdk:1.39.6-upstream
emscripten2:
docker:
# Used by the webgl2 job. First version that exposes glGetBufferSubData()
# so GLES3 tests can read buffer data without having to check the
# Emscripten version.
- image: emscripten/emsdk:2.0.17
android-29:
machine:
image: android:202102-01
Expand Down Expand Up @@ -512,7 +518,7 @@ jobs:
- lcov

emscripten-webgl1:
executor: emscripten
executor: emscripten1
environment:
# STUPID yml interprets unquoted ON as a boolean
TARGET_GLES2: "ON"
Expand All @@ -523,7 +529,7 @@ jobs:
script: emscripten.sh

emscripten-webgl2:
executor: emscripten
executor: emscripten2
environment:
# STUPID yml interprets unquoted OFF as a boolean
TARGET_GLES2: "OFF"
Expand Down
29 changes: 20 additions & 9 deletions src/Magnum/DebugTools/BufferData.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
DEALINGS IN THE SOFTWARE.
*/

#if defined(MAGNUM_TARGET_GL) && !defined(MAGNUM_TARGET_WEBGL)
#if defined(MAGNUM_TARGET_GL) && !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
/** @file
* @brief Function @ref Magnum::DebugTools::bufferData(), @ref Magnum::DebugTools::bufferSubData()
*/
Expand All @@ -36,7 +36,7 @@
#include "Magnum/GL/Buffer.h"
#include "Magnum/DebugTools/visibility.h"

#if defined(MAGNUM_TARGET_GL) && !defined(MAGNUM_TARGET_WEBGL)
#if defined(MAGNUM_TARGET_GL) && !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
namespace Magnum { namespace DebugTools {

namespace Implementation {
Expand All @@ -47,35 +47,46 @@ namespace Implementation {
@brief Buffer subdata

Emulates @ref GL::Buffer::subData() call on platforms that don't support it
(such as OpenGL ES) by using @ref GL::Buffer::map().
(such as OpenGL ES) by using @ref GL::Buffer::mapRead(). On desktop GL and
WebGL 2.0 it's just an alias to @ref GL::Buffer::subData().

@note This function is available only if Magnum is compiled with
@ref MAGNUM_TARGET_GL "TARGET_GL" enabled (done by default). See
@ref building-features for more information.

@requires_gles30 Extension @gl_extension{EXT,map_buffer_range} in OpenGL ES
2.0.
@requires_gles Buffer mapping is not available in WebGL.
@requires_webgl20 Buffer data queries or buffer mapping are not available in
WebGL 1.0.
*/
template<class T> Containers::Array<T> inline bufferSubData(GL::Buffer& buffer, GLintptr offset, GLsizeiptr size) {
template<class T = char> Containers::Array<T> inline bufferSubData(GL::Buffer& buffer, GLintptr offset, GLsizeiptr size) {
pezcode marked this conversation as resolved.
Show resolved Hide resolved
if(!size) return {};
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_WEBGL)
Containers::Array<char> data = buffer.subData(offset, size*sizeof(T));
CORRADE_INTERNAL_ASSERT(!data.deleter());
return Containers::Array<T>{reinterpret_cast<T*>(data.release()), std::size_t(size)};
#else
Containers::Array<T> data{std::size_t(size)};
if(size) Implementation::bufferSubData(buffer, offset, size*sizeof(T), data);
Implementation::bufferSubData(buffer, offset, size*sizeof(T), data);
return data;
#endif
}

/**
@brief Buffer data

Emulates @ref GL::Buffer::data() call on platforms that don't support it (such
as OpenGL ES) by using @ref GL::Buffer::map().
as OpenGL ES) by using @ref GL::Buffer::mapRead(). On desktop GL and WebGL 2.0
it's just an alias to @ref GL::Buffer::data().

@note This function is available only if Magnum is compiled with
@ref MAGNUM_TARGET_GL "TARGET_GL" enabled (done by default). See
@ref building-features for more information.

@requires_gles30 Extension @gl_extension{EXT,map_buffer_range} in OpenGL ES
2.0.
@requires_gles Buffer mapping is not available in WebGL.
@requires_webgl20 Buffer data queries or buffer mapping are not available in
WebGL 1.0.
*/
template<class T = char> Containers::Array<T> inline bufferData(GL::Buffer& buffer) {
const Int bufferSize = buffer.size();
Expand All @@ -85,7 +96,7 @@ template<class T = char> Containers::Array<T> inline bufferData(GL::Buffer& buff

}}
#else
#error this header is available only in the OpenGL (ES) build and not available in the WebGL build
#error this header is not available in the WebGL 1.0 build
#endif

#endif
2 changes: 1 addition & 1 deletion src/Magnum/DebugTools/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ if(TARGET_GL)
endif()
endif()

if(NOT MAGNUM_TARGET_WEBGL)
if(NOT (MAGNUM_TARGET_WEBGL AND MAGNUM_TARGET_GLES2))
list(APPEND MagnumDebugTools_SRCS
BufferData.cpp)

Expand Down
38 changes: 26 additions & 12 deletions src/Magnum/DebugTools/Test/BufferDataGLTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,37 +47,51 @@ BufferDataGLTest::BufferDataGLTest() {
constexpr Int Data[] = {2, 7, 5, 13, 25};

void BufferDataGLTest::data() {
#ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::map_buffer_range>())
CORRADE_SKIP(GL::Extensions::ARB::map_buffer_range::string() << "is not supported.");
#elif defined(MAGNUM_TARGET_GLES2)
#ifdef MAGNUM_TARGET_GLES2
if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::map_buffer_range>())
CORRADE_SKIP(GL::Extensions::EXT::map_buffer_range::string() << "is not supported.");
#endif

GL::Buffer buffer;

const Containers::Array<Int> emptyContents = bufferData<Int>(buffer);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_VERIFY(emptyContents.isEmpty());

buffer.setData(Data, GL::BufferUsage::StaticDraw);
const Containers::Array<Int> contents = bufferData<Int>(buffer);

const Containers::Array<char> contents = bufferData(buffer);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE_AS(contents,
Containers::arrayCast<const char>(Containers::arrayView(Data)),
TestSuite::Compare::Container);
const Containers::Array<Int> intContents = bufferData<Int>(buffer);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE_AS(contents, Containers::arrayView(Data),
CORRADE_COMPARE_AS(intContents, Containers::arrayView(Data),
TestSuite::Compare::Container);
}

void BufferDataGLTest::subData() {
#ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::map_buffer_range>())
CORRADE_SKIP(GL::Extensions::ARB::map_buffer_range::string() << "is not supported.");
#elif defined(MAGNUM_TARGET_GLES2)
#ifdef MAGNUM_TARGET_GLES2
if(!GL::Context::current().isExtensionSupported<GL::Extensions::EXT::map_buffer_range>())
CORRADE_SKIP(GL::Extensions::EXT::map_buffer_range::string() << "is not supported.");
#endif

GL::Buffer buffer;
buffer.setData(Data, GL::BufferUsage::StaticDraw);
const Containers::Array<Int> contents = bufferSubData<Int>(buffer, 4, 3);

const Containers::Array<char> contents = bufferSubData(buffer, 4, 3*4);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE_AS(contents, Containers::arrayView(Data).slice(1, 4),
CORRADE_COMPARE_AS(contents,
Containers::arrayCast<const char>(Containers::arrayView(Data).slice(1, 4)),
TestSuite::Compare::Container);
const Containers::Array<Int> intContents = bufferSubData<Int>(buffer, 4, 3);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_COMPARE_AS(intContents, Containers::arrayView(Data).slice(1, 4),
TestSuite::Compare::Container);
const Containers::Array<Int> emptyContents = bufferSubData<Int>(buffer, 4, 0);
MAGNUM_VERIFY_NO_GL_ERROR();
CORRADE_VERIFY(emptyContents.isEmpty());
}

}}}}
Expand Down
2 changes: 1 addition & 1 deletion src/Magnum/DebugTools/Test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ if(TARGET_GL)
corrade_add_test(DebugToolsTextureImageGLTest TextureImageGLTest.cpp
LIBRARIES MagnumDebugTools MagnumOpenGLTester)

if(NOT MAGNUM_TARGET_WEBGL)
if(NOT (MAGNUM_TARGET_WEBGL AND MAGNUM_TARGET_GLES2))
corrade_add_test(DebugToolsBufferDataGLTest BufferDataGLTest.cpp
LIBRARIES MagnumDebugTools MagnumOpenGLTester)
endif()
Expand Down
8 changes: 5 additions & 3 deletions src/Magnum/GL/Buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ Int Buffer::size() {
return size;
}

#ifndef MAGNUM_TARGET_GLES
#if !defined(MAGNUM_TARGET_GLES) || (defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 20017)
Containers::Array<char> Buffer::data() {
return subData(0, size());
}
Expand Down Expand Up @@ -372,7 +372,7 @@ Buffer& Buffer::flushMappedRange(const GLintptr offset, const GLsizeiptr length)
bool Buffer::unmap() { return (this->*Context::current().state().buffer.unmapImplementation)(); }
#endif

#ifndef MAGNUM_TARGET_GLES
#if !defined(MAGNUM_TARGET_GLES) || (defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 20017)
Containers::Array<char> Buffer::subData(const GLintptr offset, const GLsizeiptr size) {
Containers::Array<char> data(size);
if(size) (this->*Context::current().state().buffer.getSubDataImplementation)(offset, size, data);
Expand Down Expand Up @@ -468,11 +468,13 @@ void Buffer::getParameterImplementationDSA(const GLenum value, GLint* const data
}
#endif

#ifndef MAGNUM_TARGET_GLES
#if !defined(MAGNUM_TARGET_GLES) || (defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 20017)
void Buffer::getSubDataImplementationDefault(const GLintptr offset, const GLsizeiptr size, GLvoid* const data) {
glGetBufferSubData(GLenum(bindSomewhereInternal(_targetHint)), offset, size, data);
}
#endif

#ifndef MAGNUM_TARGET_GLES
void Buffer::getSubDataImplementationDSA(const GLintptr offset, const GLsizeiptr size, GLvoid* const data) {
glGetNamedBufferSubData(_id, offset, size, data);
}
Expand Down
22 changes: 14 additions & 8 deletions src/Magnum/GL/Buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -1089,7 +1089,7 @@ class MAGNUM_GL_EXPORT Buffer: public AbstractObject {
*/
Int size();

#ifndef MAGNUM_TARGET_GLES
#if !defined(MAGNUM_TARGET_GLES) || (defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 20017)
/**
* @brief Buffer data
*
Expand All @@ -1101,9 +1101,11 @@ class MAGNUM_GL_EXPORT Buffer: public AbstractObject {
* eventually @fn_gl{BindBuffer} and @fn_gl{GetBufferParameter}
* with @def_gl{BUFFER_SIZE}, then @fn_gl2_keyword{GetNamedBufferSubData,GetBufferSubData},
* eventually @fn_gl_keyword{GetBufferSubData}
* @requires_gl Buffer data queries are not available in OpenGL ES and
* WebGL. Use @ref map(), @ref mapRead() or @ref DebugTools::bufferData()
* in OpenGL ES instead.
* @requires_gl Buffer data queries are not available in OpenGL ES. Use
* @ref map(), @ref mapRead() or @ref DebugTools::bufferData()
* instead.
* @requires_webgl20 Buffer data queries are not available in
* WebGL 1.0. Emscripten 2.0.17 or higher is required in WebGL2.
*/
Containers::Array<char> data();

Expand All @@ -1119,9 +1121,11 @@ class MAGNUM_GL_EXPORT Buffer: public AbstractObject {
* @see @ref size(), @ref data(), @ref setSubData(), @ref setTargetHint(),
* @fn_gl2_keyword{GetNamedBufferSubData,GetBufferSubData},
* eventually @fn_gl{BindBuffer} and @fn_gl_keyword{GetBufferSubData}
* @requires_gl Buffer data queries are not available in OpenGL ES and
* WebGL. Use @ref map(), @ref mapRead() or @ref DebugTools::bufferData()
* in OpenGL ES instead.
* @requires_gl Buffer data queries are not available in OpenGL ES. Use
* @ref map(), @ref mapRead() or @ref DebugTools::bufferData() in
* OpenGL ES instead.
* @requires_webgl20 Buffer data queries are not available in
* WebGL 1.0. Emscripten 2.0.17 or higher is required in WebGL2.
*/
Containers::Array<char> subData(GLintptr offset, GLsizeiptr size);
#endif
Expand Down Expand Up @@ -1357,8 +1361,10 @@ class MAGNUM_GL_EXPORT Buffer: public AbstractObject {
void MAGNUM_GL_LOCAL getParameterImplementationDSA(GLenum value, GLint* data);
#endif

#ifndef MAGNUM_TARGET_GLES
#if !defined(MAGNUM_TARGET_GLES) || (defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 20017)
void MAGNUM_GL_LOCAL getSubDataImplementationDefault(GLintptr offset, GLsizeiptr size, GLvoid* data);
#endif
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_GL_LOCAL getSubDataImplementationDSA(GLintptr offset, GLsizeiptr size, GLvoid* data);
#endif

Expand Down
2 changes: 1 addition & 1 deletion src/Magnum/GL/Implementation/BufferState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ BufferState::BufferState(Context& context, Containers::StaticArrayView<Implement
storageImplementation = &Buffer::storageImplementationDefault;
#endif
getParameterImplementation = &Buffer::getParameterImplementationDefault;
#ifndef MAGNUM_TARGET_GLES
#if !defined(MAGNUM_TARGET_GLES) || (defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 20017)
getSubDataImplementation = &Buffer::getSubDataImplementationDefault;
#endif
dataImplementation = &Buffer::dataImplementationDefault;
Expand Down
2 changes: 1 addition & 1 deletion src/Magnum/GL/Implementation/BufferState.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ struct BufferState {
void(Buffer::*storageImplementation)(Containers::ArrayView<const void>, Buffer::StorageFlags);
#endif
void(Buffer::*getParameterImplementation)(GLenum, GLint*);
#ifndef MAGNUM_TARGET_GLES2
#if !defined(MAGNUM_TARGET_GLES) || (defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2) && __EMSCRIPTEN_major__*10000 + __EMSCRIPTEN_minor__*100 + __EMSCRIPTEN_tiny__ >= 20017)
void(Buffer::*getSubDataImplementation)(GLintptr, GLsizeiptr, GLvoid*);
#endif
void(Buffer::*dataImplementation)(GLsizeiptr, const GLvoid*, BufferUsage);
Expand Down
Loading