Browse Source

GL: implement time queries for WebGL 2, and workarounds, and ...

There's a new firefox-fake-disjoint-timer-query-webgl2 workaround and a
half-page of text listing various caveats and issues you might run into.
Also exposing them in the OpenGLTester (although quite shitty at this
point).
pull/388/head
Vladimír Vondruš 7 years ago
parent
commit
60c18f93a1
  1. 6
      doc/changelog.dox
  2. 22
      doc/platforms-html5.dox
  3. 10
      src/Magnum/GL/AbstractQuery.cpp
  4. 9
      src/Magnum/GL/AbstractQuery.h
  5. 17
      src/Magnum/GL/CMakeLists.txt
  6. 3
      src/Magnum/GL/Context.cpp
  7. 9
      src/Magnum/GL/Extensions.h
  8. 2
      src/Magnum/GL/GL.h
  9. 4
      src/Magnum/GL/Implementation/QueryState.h
  10. 4
      src/Magnum/GL/Implementation/State.cpp
  11. 4
      src/Magnum/GL/Implementation/State.h
  12. 23
      src/Magnum/GL/Implementation/driverSpecific.cpp
  13. 2
      src/Magnum/GL/OpenGLTester.cpp
  14. 64
      src/Magnum/GL/OpenGLTester.h
  15. 11
      src/Magnum/GL/Test/CMakeLists.txt
  16. 14
      src/Magnum/GL/Test/TimeQueryGLTest.cpp
  17. 13
      src/Magnum/GL/TimeQuery.h
  18. 1
      src/MagnumExternal/OpenGL/GLES3/Emscripten/extensions.txt

6
doc/changelog.dox

@ -194,6 +194,12 @@ See also:
shell (as opposed to an APK) because using it causes the
@ref GL::Renderer::Error::OutOfMemory error. See @ref opengl-workarounds
for more information.
- Implemented @webgl_extension{EXT,disjoint_timer_query} and
@webgl_extension{EXT,disjoint_timer_query_webgl2} for WebGL, together with
a new @cpp "firefox-fake-disjoint-timer-query-webgl2" @ce workaround. See
@ref opengl-workarounds, @ref platforms-html5-webgl-timer-queries and
@ref platforms-html5-webgl-queries-zero for more information about various
caveats.
- New `--magnum-gpu-validation` @ref GL-Context-command-line "command-line option"
and a corresponding environment variable to conveniently enable
@gl_extension{KHR,debug} debug output. This flag also causes

22
doc/platforms-html5.dox

@ -438,6 +438,28 @@ WebGL specification provide even more detail:
- [Differences Between WebGL and OpenGL ES 2.0](http://www.khronos.org/registry/webgl/specs/latest/1.0/#6)
- [Differences Between WebGL and OpenGL ES 3.0](https://www.khronos.org/registry/webgl/specs/latest/2.0/#5)
@subsection platforms-html5-webgl-timer-queries Timer queries not available in the browser
Similarly to [Rowhammer](https://en.wikipedia.org/wiki/Row_hammer), GPU timer
queries could be abused to do a bit-flip attack, which is the reason why
@webgl_extension{EXT,disjoint_timer_query} / @webgl_extension{EXT,disjoint_timer_query_webgl2} might not be available in
your browser. Recent versions of Chrome [expose it again](https://bugs.chromium.org/p/chromium/issues/detail?id=823863),
and Firefox exposes it if you enable `webgl.enable-privileged-extensions` in
`about:config` ([source](https://www.khronos.org/webgl/public-mailing-list/public_webgl/1803/msg00017.php)).
[More details about the GLitch vulnerability.](https://www.vusec.net/wp-content/uploads/2018/05/glitch.pdf)
@subsection platforms-html5-webgl-queries-zero Queries always report zero results
Compared to OpenGL ES, WebGL [has an additional restriction](https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.12)
where it's not guaranteed for a @ref GL::PrimitiveQuery, @ref GL::SampleQuery
or @ref GL::TimeQuery to return a result in the same frame, which in practice
means that the queries will return zero. This is particularly problematic in
headless tests / benchmarks and currently there's no builtin way in Magnum to
circumvent this limitation.
If you're on Firefox, you can enable the `webgl.allow-immediate-queries` option
in `about:flags`, which will make these working.
@section platforms-html5-code-size Compilation time / code size tradeoffs
By default, the toolchain configures the compiler and linker to use `-O3` in

10
src/Magnum/GL/AbstractQuery.cpp

@ -46,10 +46,8 @@ AbstractQuery::~AbstractQuery() {
#ifndef MAGNUM_TARGET_GLES2
glDeleteQueries(1, &_id);
#elif !defined(CORRADE_TARGET_EMSCRIPTEN)
glDeleteQueriesEXT(1, &_id);
#else
CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
glDeleteQueriesEXT(1, &_id);
#endif
_flags |= ObjectFlag::Created;
}
@ -57,10 +55,8 @@ AbstractQuery::~AbstractQuery() {
void AbstractQuery::createImplementationDefault() {
#ifndef MAGNUM_TARGET_GLES2
glGenQueries(1, &_id);
#elif !defined(CORRADE_TARGET_EMSCRIPTEN)
glGenQueriesEXT(1, &_id);
#else
CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
glGenQueriesEXT(1, &_id);
#endif
}
@ -112,7 +108,6 @@ template<> UnsignedInt AbstractQuery::result<UnsignedInt>() {
template<> bool AbstractQuery::result<bool>() { return result<UnsignedInt>() != 0; }
#ifndef MAGNUM_TARGET_WEBGL
template<> Int AbstractQuery::result<Int>() {
Int result;
#ifndef MAGNUM_TARGET_GLES
@ -143,7 +138,6 @@ template<> Long AbstractQuery::result<Long>() {
return result;
}
#endif
#endif
void AbstractQuery::begin() {
#ifndef MAGNUM_TARGET_GLES2

9
src/Magnum/GL/AbstractQuery.h

@ -25,11 +25,9 @@
DEALINGS IN THE SOFTWARE.
*/
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
/** @file
* @brief Class @ref Magnum::GL::AbstractQuery
*/
#endif
#include <Corrade/Containers/ArrayView.h>
#include <Corrade/Utility/Assert.h>
@ -39,7 +37,6 @@
#include "Magnum/configure.h"
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
namespace Magnum { namespace GL {
namespace Implementation { struct QueryState; }
@ -49,7 +46,6 @@ namespace Implementation { struct QueryState; }
See @ref PrimitiveQuery, @ref SampleQuery and @ref TimeQuery documentation for
more information.
@requires_webgl20 Queries are not available in WebGL 1.0.
@todo `QUERY_COUNTER_BITS` (not sure since when this is supported)
*/
class MAGNUM_GL_EXPORT AbstractQuery: public AbstractObject {
@ -203,11 +199,9 @@ class MAGNUM_GL_EXPORT AbstractQuery: public AbstractObject {
template<> bool MAGNUM_GL_EXPORT AbstractQuery::result<bool>();
template<> UnsignedInt MAGNUM_GL_EXPORT AbstractQuery::result<UnsignedInt>();
template<> Int MAGNUM_GL_EXPORT AbstractQuery::result<Int>();
#ifndef MAGNUM_TARGET_WEBGL
template<> UnsignedLong MAGNUM_GL_EXPORT AbstractQuery::result<UnsignedLong>();
template<> Long MAGNUM_GL_EXPORT AbstractQuery::result<Long>();
#endif
#endif
inline AbstractQuery::AbstractQuery(AbstractQuery&& other) noexcept: _id(other._id), _target(other._target) {
other._id = 0;
@ -227,8 +221,5 @@ inline GLuint AbstractQuery::release() {
}
}}
#else
#error this header is not available in WebGL 1.0 build
#endif
#endif

17
src/Magnum/GL/CMakeLists.txt

@ -25,6 +25,7 @@
set(MagnumGL_SRCS
AbstractObject.cpp
AbstractQuery.cpp
AbstractShaderProgram.cpp
Attribute.cpp
Buffer.cpp
@ -43,6 +44,7 @@ set(MagnumGL_SRCS
Implementation/ContextState.cpp
Implementation/FramebufferState.cpp
Implementation/MeshState.cpp
Implementation/QueryState.cpp
Implementation/RendererState.cpp
Implementation/ShaderProgramState.cpp
Implementation/ShaderState.cpp
@ -63,6 +65,7 @@ set(MagnumGL_GracefulAssert_SRCS
set(MagnumGL_HEADERS
AbstractFramebuffer.h
AbstractObject.h
AbstractQuery.h
AbstractShaderProgram.h
AbstractTexture.h
Attribute.h
@ -84,6 +87,7 @@ set(MagnumGL_HEADERS
Shader.h
Texture.h
TextureFormat.h
TimeQuery.h
Version.h
visibility.h)
@ -95,6 +99,7 @@ set(MagnumGL_PRIVATE_HEADERS
Implementation/FramebufferState.h
Implementation/maxTextureSize.h
Implementation/MeshState.h
Implementation/QueryState.h
Implementation/RendererState.h
Implementation/ShaderProgramState.h
Implementation/ShaderState.h
@ -137,8 +142,7 @@ if(NOT TARGET_WEBGL)
Implementation/DebugState.cpp)
list(APPEND MagnumGL_HEADERS
DebugOutput.h
TimeQuery.h)
DebugOutput.h)
list(APPEND MagnumGL_PRIVATE_HEADERS
Implementation/DebugState.h)
@ -160,17 +164,8 @@ endif()
# Desktop, OpenGL ES and WebGL 2.0 stuff that is not available in WebGL 1.0
if(NOT (TARGET_WEBGL AND TARGET_GLES2))
list(APPEND MagnumGL_SRCS
AbstractQuery.cpp
Implementation/QueryState.cpp)
list(APPEND MagnumGL_HEADERS
AbstractQuery.h
SampleQuery.h)
list(APPEND MagnumGL_PRIVATE_HEADERS
Implementation/QueryState.h)
endif()
# Objects shared between main and test library

3
src/Magnum/GL/Context.cpp

@ -247,9 +247,12 @@ constexpr Extension ExtensionList460[]{
#elif defined(MAGNUM_TARGET_WEBGL)
constexpr Extension ExtensionList[]{
_extension(EXT,texture_filter_anisotropic),
#ifdef MAGNUM_TARGET_GLES2
_extension(EXT,disjoint_timer_query),
#endif
#ifndef MAGNUM_TARGET_GLES2
_extension(EXT,color_buffer_float),
_extension(EXT,disjoint_timer_query_webgl2),
#endif
_extension(EXT,texture_compression_rgtc),
_extension(EXT,texture_compression_bptc),

9
src/Magnum/GL/Extensions.h

@ -274,16 +274,21 @@ namespace ANGLE {
_extension( 4,EXT,sRGB, GLES200, GLES300) // #17
_extension( 5,EXT,blend_minmax, GLES200, GLES300) // #25
#endif
#ifdef MAGNUM_TARGET_GLES2
/* Replaced by EXT_disjoint_timer_query_webgl2 in WebGL 2 */
_extension( 6,EXT,disjoint_timer_query, GLES200, None) // #26
#endif
#ifdef MAGNUM_TARGET_GLES2
_extension( 7,EXT,shader_texture_lod, GLES200, GLES300) // #27
#endif
#ifndef MAGNUM_TARGET_GLES2
/* Replaces WEBGL_color_buffer_float from WebGL 1 */
_extension( 8,EXT,color_buffer_float, GLES300, None) // #31
/* Replaces WEBGL_disjoint_timer_query from WebGL 1 */
_extension( 9,EXT,disjoint_timer_query_webgl2, GLES300, None) // #33
#endif
_extension( 9,EXT,texture_compression_rgtc, GLES200, None) // #38
_extension(10,EXT,texture_compression_bptc, GLES200, None) // #39
_extension(10,EXT,texture_compression_rgtc, GLES200, None) // #38
_extension(11,EXT,texture_compression_bptc, GLES200, None) // #39
} namespace OES {
#ifdef MAGNUM_TARGET_GLES2
_extension(15,OES,texture_float, GLES200, GLES300) // #1

2
src/Magnum/GL/GL.h

@ -44,9 +44,7 @@ namespace Magnum { namespace GL {
FramebufferTarget enums used only directly with framebuffer instance */
class AbstractFramebuffer;
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
class AbstractQuery;
#endif
class AbstractShaderProgram;
class AbstractTexture;

4
src/Magnum/GL/Implementation/QueryState.h

@ -37,10 +37,6 @@
#include "Magnum/GL/AbstractQuery.h"
#endif
#if defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2)
#error this header is not available in WebGL 1.0 build
#endif
namespace Magnum { namespace GL { namespace Implementation {
struct QueryState {

4
src/Magnum/GL/Implementation/State.cpp

@ -37,9 +37,7 @@
#endif
#include "Magnum/GL/Implementation/FramebufferState.h"
#include "Magnum/GL/Implementation/MeshState.h"
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
#include "Magnum/GL/Implementation/QueryState.h"
#endif
#include "Magnum/GL/Implementation/RendererState.h"
#include "Magnum/GL/Implementation/ShaderState.h"
#include "Magnum/GL/Implementation/ShaderProgramState.h"
@ -67,9 +65,7 @@ State::State(Context& context, std::ostream* const out) {
#endif
framebuffer.reset(new FramebufferState{context, extensions});
mesh.reset(new MeshState{context, *this->context, extensions});
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
query.reset(new QueryState{context, extensions});
#endif
renderer.reset(new RendererState{context, extensions});
shader.reset(new ShaderState(context, extensions));
shaderProgram.reset(new ShaderProgramState{context, extensions});

4
src/Magnum/GL/Implementation/State.h

@ -39,9 +39,7 @@ struct DebugState;
#endif
struct FramebufferState;
struct MeshState;
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
struct QueryState;
#endif
struct RendererState;
struct ShaderState;
struct ShaderProgramState;
@ -65,9 +63,7 @@ struct State {
#endif
Containers::Pointer<FramebufferState> framebuffer;
Containers::Pointer<MeshState> mesh;
#if !(defined(MAGNUM_TARGET_WEBGL) && defined(MAGNUM_TARGET_GLES2))
Containers::Pointer<QueryState> query;
#endif
Containers::Pointer<RendererState> renderer;
Containers::Pointer<ShaderState> shader;
Containers::Pointer<ShaderProgramState> shaderProgram;

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

@ -280,6 +280,19 @@ namespace {
framebuffer size, otherwise it assumes it's zero-sized. */
"apitrace-zero-initial-viewport",
#endif
#if defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2)
/* While the EXT_disjoint_timer_query extension should be only on WebGL 1 and
EXT_disjoint_timer_query_webgl2 only on WebGL 2, Firefox reports
EXT_disjoint_timer_query on both. The entry points work correctly however,
so this workaround makes Magnum pretend EXT_disjoint_timer_query_webgl2 is
available when it detects EXT_disjoint_timer_query on WebGL 2 builds on
Firefox. See also https://bugzilla.mozilla.org/show_bug.cgi?id=1328882,
https://www.khronos.org/webgl/public-mailing-list/public_webgl/1705/msg00015.php
and https://github.com/emscripten-core/emscripten/pull/9652 for the
Emscripten-side part of this workaround. */
"firefox-fake-disjoint-timer-query-webgl2",
#endif
/* [workarounds] */
};
}
@ -470,6 +483,16 @@ void Context::setupDriverWorkarounds() {
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
}
#endif
#if defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2)
if(rendererString() == "Mozilla") {
for(const auto& extension: extensionStrings()) {
if(extension == "GL_EXT_disjoint_timer_query" && !isDriverWorkaroundDisabled("firefox-fake-disjoint-timer-query-webgl2")) {
_extensionStatus.set(Extensions::EXT::disjoint_timer_query_webgl2::Index, true);
}
}
}
#endif
}
}}

2
src/Magnum/GL/OpenGLTester.cpp

@ -39,7 +39,6 @@ OpenGLTester::OpenGLTester(): TestSuite::Tester{TestSuite::Tester::TesterConfigu
OpenGLTester::~OpenGLTester() = default;
#ifndef MAGNUM_TARGET_WEBGL
void OpenGLTester::gpuTimeBenchmarkBegin() {
setBenchmarkName("GPU time");
@ -53,6 +52,5 @@ std::uint64_t OpenGLTester::gpuTimeBenchmarkEnd() {
_gpuTimeQuery.end();
return _gpuTimeQuery.result<UnsignedLong>();
}
#endif
}}

64
src/Magnum/GL/OpenGLTester.h

@ -35,6 +35,7 @@
#include <Corrade/TestSuite/Tester.h>
#include "Magnum/GL/Renderer.h"
#include "Magnum/GL/TimeQuery.h"
#if defined(MAGNUM_TARGET_HEADLESS) || defined(CORRADE_TARGET_EMSCRIPTEN) || defined(CORRADE_TARGET_ANDROID)
#include "Magnum/Platform/WindowlessEglApplication.h"
@ -58,10 +59,6 @@
#error cannot run OpenGL tests on this platform
#endif
#ifndef MAGNUM_TARGET_WEBGL
#include "Magnum/GL/TimeQuery.h"
#endif
namespace Magnum { namespace GL {
/**
@ -134,7 +131,12 @@ which is supported here as well as in all other application implementations.
This class adds @ref BenchmarkType::GpuTime to the benchmark type enum,
allowing you to measure time spent on GPU as opposed to CPU or wall clock time.
@requires_gles GPU time benchmarking is not available on WebGL.
If @gl_extension{ARB,timer_query} desktop extension (part of OpenGL 3.3),
@gl_extension{EXT,disjoint_timer_query} OpenGL ES extension,
@webgl_extension{EXT,disjoint_timer_query} WebGL 1 extension or
@gl_extension{EXT,disjoint_timer_query_webgl2} WebGL 2 extension is not
available, GPU time benchmarks will get automatically skipped, producing a
@cb{.ansi} SKIP @ce message on the output.
@note This class is available only if Magnum is compiled with
@ref MAGNUM_TARGET_GL enabled (done by default). See @ref building-features
@ -142,7 +144,6 @@ allowing you to measure time spent on GPU as opposed to CPU or wall clock time.
*/
class OpenGLTester: public TestSuite::Tester {
public:
#ifndef MAGNUM_TARGET_WEBGL
/**
* @brief Benchmark type
*
@ -178,14 +179,19 @@ class OpenGLTester: public TestSuite::Tester {
/**
* GPU time, measured using @ref TimeQuery::Target::TimeElapsed.
* Note that the result of the query is retrieved synchronously and
* thus may cause pipeline bubble. Increase number of iterations
* thus may cause a pipeline bubble. Increase number of iterations
* passed to @ref CORRADE_BENCHMARK() to amortize the measurement
* error.
* @requires_gles GPU time benchmarking is not available on WebGL.
*
* If @gl_extension{ARB,timer_query} desktop extension (part of
* OpenGL 3.3), @gl_extension{EXT,disjoint_timer_query} OpenGL ES
* extension, @webgl_extension{EXT,disjoint_timer_query} WebGL 1
* extension or @gl_extension{EXT,disjoint_timer_query_webgl2}
* WebGL 2 extension is not available, GPU time benchmarks will get
* automatically skipped.
*/
GpuTime = 32
};
#endif
/**
* @brief Constructor
@ -196,13 +202,18 @@ class OpenGLTester: public TestSuite::Tester {
~OpenGLTester();
#ifndef MAGNUM_TARGET_WEBGL
/**
* @brief Add benchmarks
*
* Extends @ref Corrade::TestSuite::Tester::addBenchmarks(std::initializer_list<void(Derived::*)()>, std::size_t, BenchmarkType) with support
* for GPU benchmark types.
* @requires_gles GPU time benchmarking is not available on WebGL.
*
* If @gl_extension{ARB,timer_query} desktop extension (part of OpenGL
* 3.3), @gl_extension{EXT,disjoint_timer_query} OpenGL ES extension,
* @webgl_extension{EXT,disjoint_timer_query} WebGL 1 extension or
* @gl_extension{EXT,disjoint_timer_query_webgl2} WebGL 2 extension is
* not available, @ref BenchmarkType::GpuTime benchmarks will get
* automatically skipped.
*/
template<class Derived> void addBenchmarks(std::initializer_list<void(Derived::*)()> benchmarks, std::size_t batchCount, BenchmarkType benchmarkType = BenchmarkType::Default) {
if(benchmarkType == BenchmarkType::GpuTime)
@ -216,7 +227,13 @@ class OpenGLTester: public TestSuite::Tester {
*
* Extends @ref Corrade::TestSuite::Tester::addBenchmarks(std::initializer_list<void(Derived::*)()>, std::size_t, void(Derived::*)(), void(Derived::*)(), BenchmarkType) with support
* for GPU benchmark types.
* @requires_gles GPU time benchmarking is not available on WebGL.
*
* If @gl_extension{ARB,timer_query} desktop extension (part of OpenGL
* 3.3), @gl_extension{EXT,disjoint_timer_query} OpenGL ES extension,
* @webgl_extension{EXT,disjoint_timer_query} WebGL 1 extension or
* @gl_extension{EXT,disjoint_timer_query_webgl2} WebGL 2 extension is
* not available, @ref BenchmarkType::GpuTime benchmarks will get
* automatically skipped.
*/
template<class Derived> void addBenchmarks(std::initializer_list<void(Derived::*)()> benchmarks, std::size_t batchCount, void(Derived::*setup)(), void(Derived::*teardown)(), BenchmarkType benchmarkType = BenchmarkType::Default) {
if(benchmarkType == BenchmarkType::GpuTime)
@ -230,7 +247,13 @@ class OpenGLTester: public TestSuite::Tester {
*
* Extends @ref Corrade::TestSuite::Tester::addInstancedBenchmarks(std::initializer_list<void(Derived::*)()>, std::size_t, std::size_t, BenchmarkType) with support for GPU
* benchmark types.
* @requires_gles GPU time benchmarking is not available on WebGL.
*
* If @gl_extension{ARB,timer_query} desktop extension (part of OpenGL
* 3.3), @gl_extension{EXT,disjoint_timer_query} OpenGL ES extension,
* @webgl_extension{EXT,disjoint_timer_query} WebGL 1 extension or
* @gl_extension{EXT,disjoint_timer_query_webgl2} WebGL 2 extension is
* not available, @ref BenchmarkType::GpuTime benchmarks will get
* automatically skipped.
*/
template<class Derived> void addInstancedBenchmarks(std::initializer_list<void(Derived::*)()> benchmarks, std::size_t batchCount, std::size_t instanceCount, BenchmarkType benchmarkType = BenchmarkType::Default) {
if(benchmarkType == BenchmarkType::GpuTime)
@ -244,30 +267,31 @@ class OpenGLTester: public TestSuite::Tester {
*
* Extends @ref Corrade::TestSuite::Tester::addInstancedBenchmarks(std::initializer_list<void(Derived::*)()>, std::size_t, std::size_t, void(Derived::*)(), void(Derived::*)(), BenchmarkType)
* with support for GPU benchmark types.
* @requires_gles GPU time benchmarking is not available on WebGL.
*
* If @gl_extension{ARB,timer_query} desktop extension (part of OpenGL
* 3.3), @gl_extension{EXT,disjoint_timer_query} OpenGL ES extension,
* @webgl_extension{EXT,disjoint_timer_query} WebGL 1 extension or
* @gl_extension{EXT,disjoint_timer_query_webgl2} WebGL 2 extension is
* not available, @ref BenchmarkType::GpuTime benchmarks will get
* automatically skipped.
*/
template<class Derived> void addInstancedBenchmarks(std::initializer_list<void(Derived::*)()> benchmarks, std::size_t batchCount, std::size_t instanceCount, void(Derived::*setup)(), void(Derived::*teardown)(), BenchmarkType benchmarkType = BenchmarkType::Default) {
if(benchmarkType == BenchmarkType::GpuTime)
addCustomInstancedBenchmarks<Derived>(benchmarks, batchCount, instanceCount, &OpenGLTester::gpuTimeBenchmarkBegin, &OpenGLTester::gpuTimeBenchmarkEnd, setup, teardown, BenchmarkUnits::Nanoseconds);
addCustomInstancedBenchmarks<Derived>(benchmarks, batchCount, instanceCount, setup, teardown, &OpenGLTester::gpuTimeBenchmarkBegin, &OpenGLTester::gpuTimeBenchmarkEnd, BenchmarkUnits::Nanoseconds);
else
Tester::addInstancedBenchmarks(benchmarks, batchCount, instanceCount, setup, teardown, Tester::BenchmarkType(Int(benchmarkType)));
}
#endif
private:
#ifndef MAGNUM_TARGET_WEBGL
void gpuTimeBenchmarkBegin();
std::uint64_t gpuTimeBenchmarkEnd();
#endif
struct WindowlessApplication: Platform::WindowlessApplication {
explicit WindowlessApplication(const Arguments& arguments): Platform::WindowlessApplication{arguments} {}
int exec() override final { return 0; }
} _windowlessApplication;
#ifndef MAGNUM_TARGET_WEBGL
TimeQuery _gpuTimeQuery{NoCreate};
#endif
};
/** @hideinitializer

11
src/Magnum/GL/Test/CMakeLists.txt

@ -37,6 +37,7 @@ corrade_add_test(GLRenderbufferTest RenderbufferTest.cpp LIBRARIES MagnumGL)
corrade_add_test(GLSamplerTest SamplerTest.cpp LIBRARIES MagnumGLTestLib)
corrade_add_test(GLShaderTest ShaderTest.cpp LIBRARIES MagnumGL)
corrade_add_test(GLTextureTest TextureTest.cpp LIBRARIES MagnumGL)
corrade_add_test(GLTimeQueryTest TimeQueryTest.cpp LIBRARIES MagnumGL)
corrade_add_test(GLVersionTest VersionTest.cpp LIBRARIES MagnumGL)
set_target_properties(
@ -54,6 +55,7 @@ set_target_properties(
GLSamplerTest
GLShaderTest
GLTextureTest
GLTimeQueryTest
GLVersionTest
PROPERTIES FOLDER "Magnum/GL/Test")
@ -93,11 +95,6 @@ if(NOT (MAGNUM_TARGET_WEBGL AND MAGNUM_TARGET_GLES2))
set_target_properties(GLSampleQueryTest PROPERTIES FOLDER "Magnum/GL/Test")
endif()
if(NOT MAGNUM_TARGET_WEBGL)
corrade_add_test(GLTimeQueryTest TimeQueryTest.cpp LIBRARIES MagnumGL)
set_target_properties(GLTimeQueryTest PROPERTIES FOLDER "Magnum/GL/Test")
endif()
if(NOT MAGNUM_TARGET_GLES)
corrade_add_test(GLRectangleTextureTest RectangleTextureTest.cpp LIBRARIES MagnumGL)
set_target_properties(GLRectangleTextureTest PROPERTIES FOLDER "Magnum/GL/Test")
@ -112,6 +109,7 @@ if(BUILD_GL_TESTS)
corrade_add_test(GLRendererGLTest RendererGLTest.cpp LIBRARIES MagnumOpenGLTester)
corrade_add_test(GLRenderbufferGLTest RenderbufferGLTest.cpp LIBRARIES MagnumOpenGLTester)
corrade_add_test(GLTextureGLTest TextureGLTest.cpp LIBRARIES MagnumOpenGLTesterTestLib)
corrade_add_test(GLTimeQueryGLTest TimeQueryGLTest.cpp LIBRARIES MagnumOpenGLTester)
corrade_add_resource(GLAbstractShaderProgramGLTest_RES AbstractShaderProgramGLTestFiles/resources.conf)
corrade_add_test(GLAbstractShaderProgramGLTest
@ -147,6 +145,7 @@ if(BUILD_GL_TESTS)
GLMeshGLTest
GLRenderbufferGLTest
GLTextureGLTest
GLTimeQueryGLTest
GLAbstractShaderProgramGLTest
GLAbstractShaderProgramGLTest_RES-dependencies
@ -157,12 +156,10 @@ if(BUILD_GL_TESTS)
if(NOT MAGNUM_TARGET_WEBGL)
corrade_add_test(GLAbstractObjectGLTest AbstractObjectGLTest.cpp LIBRARIES MagnumOpenGLTester)
corrade_add_test(GLDebugOutputGLTest DebugOutputGLTest.cpp LIBRARIES MagnumOpenGLTester)
corrade_add_test(GLTimeQueryGLTest TimeQueryGLTest.cpp LIBRARIES MagnumOpenGLTester)
set_target_properties(
GLAbstractObjectGLTest
GLDebugOutputGLTest
GLTimeQueryGLTest
PROPERTIES FOLDER "Magnum/GL/Test")
endif()

14
src/Magnum/GL/Test/TimeQueryGLTest.cpp

@ -52,6 +52,9 @@ void TimeQueryGLTest::wrap() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::ARB::timer_query>())
CORRADE_SKIP(Extensions::ARB::timer_query::string() + std::string(" is not available"));
#elif defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2)
if(!Context::current().isExtensionSupported<Extensions::EXT::disjoint_timer_query_webgl2>())
CORRADE_SKIP(Extensions::EXT::disjoint_timer_query_webgl2::string() + std::string(" is not available"));
#else
if(!Context::current().isExtensionSupported<Extensions::EXT::disjoint_timer_query>())
CORRADE_SKIP(Extensions::EXT::disjoint_timer_query::string() + std::string(" is not available"));
@ -83,6 +86,9 @@ void TimeQueryGLTest::queryTime() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::ARB::timer_query>())
CORRADE_SKIP(Extensions::ARB::timer_query::string() + std::string(" is not available"));
#elif defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2)
if(!Context::current().isExtensionSupported<Extensions::EXT::disjoint_timer_query_webgl2>())
CORRADE_SKIP(Extensions::EXT::disjoint_timer_query_webgl2::string() + std::string(" is not available"));
#else
if(!Context::current().isExtensionSupported<Extensions::EXT::disjoint_timer_query>())
CORRADE_SKIP(Extensions::EXT::disjoint_timer_query::string() + std::string(" is not available"));
@ -107,7 +113,13 @@ void TimeQueryGLTest::queryTime() {
}
void TimeQueryGLTest::queryTimestamp() {
#ifdef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES
if(!Context::current().isExtensionSupported<Extensions::ARB::timer_query>())
CORRADE_SKIP(Extensions::ARB::timer_query::string() + std::string(" is not available"));
#elif defined(MAGNUM_TARGET_WEBGL) && !defined(MAGNUM_TARGET_GLES2)
if(!Context::current().isExtensionSupported<Extensions::EXT::disjoint_timer_query_webgl2>())
CORRADE_SKIP(Extensions::EXT::disjoint_timer_query_webgl2::string() + std::string(" is not available"));
#else
if(!Context::current().isExtensionSupported<Extensions::EXT::disjoint_timer_query>())
CORRADE_SKIP(Extensions::EXT::disjoint_timer_query::string() + std::string(" is not available"));
#endif

13
src/Magnum/GL/TimeQuery.h

@ -25,15 +25,12 @@
DEALINGS IN THE SOFTWARE.
*/
#ifndef MAGNUM_TARGET_WEBGL
/** @file
* @brief Class @ref Magnum::GL::TimeQuery
*/
#endif
#include "Magnum/GL/AbstractQuery.h"
#ifndef MAGNUM_TARGET_WEBGL
namespace Magnum { namespace GL {
/**
@ -52,7 +49,8 @@ times are reported in nanoseconds.
@requires_gl33 Extension @gl_extension{ARB,timer_query}
@requires_es_extension Extension @gl_extension{EXT,disjoint_timer_query}
@requires_gles Time query is not available in WebGL.
@requires_webgl_extension Extension @webgl_extension{EXT,disjoint_timer_query}
on WebGL 1, @gl_extension{EXT,disjoint_timer_query_webgl2} on WebGL 2
@see @ref PrimitiveQuery, @ref SampleQuery
@todo timestamp with glGet + example usage
@ -163,10 +161,8 @@ class TimeQuery: public AbstractQuery {
void timestamp() {
#ifndef MAGNUM_TARGET_GLES
glQueryCounter(id(), GL_TIMESTAMP);
#elif !defined(CORRADE_TARGET_EMSCRIPTEN)
glQueryCounterEXT(id(), GL_TIMESTAMP_EXT);
#else
CORRADE_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
glQueryCounterEXT(id(), GL_TIMESTAMP_EXT);
#endif
}
@ -175,8 +171,5 @@ class TimeQuery: public AbstractQuery {
};
}}
#else
#error this header is not available in WebGL build
#endif
#endif

1
src/MagnumExternal/OpenGL/GLES3/Emscripten/extensions.txt vendored

@ -5,6 +5,7 @@
version 3.0 es
extension EXT_texture_filter_anisotropic optional
# It's actually EXT_disjoint_timer_query_webgl2, but that's not known to gl.xml
extension EXT_disjoint_timer_query optional
extension EXT_color_buffer_float optional
extension EXT_texture_compression_rgtc optional

Loading…
Cancel
Save