From d2e28e5f9981854f1a7435b734a2e6e146b4e643 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 17 Aug 2014 12:58:07 +0200 Subject: [PATCH] Split Query.h into per-class header. The old Query.h header is still working, but marked as deprecated and will be removed in some future release. --- src/Magnum/{Query.cpp => AbstractQuery.cpp} | 2 +- src/Magnum/AbstractQuery.h | 182 ++++++++ src/Magnum/CMakeLists.txt | 10 +- src/Magnum/PrimitiveQuery.h | 110 +++++ src/Magnum/Query.h | 460 +------------------- src/Magnum/SampleQuery.h | 191 ++++++++ src/Magnum/Test/AbstractQueryGLTest.cpp | 2 +- src/Magnum/Test/PrimitiveQueryGLTest.cpp | 2 +- src/Magnum/Test/SampleQueryGLTest.cpp | 2 +- src/Magnum/Test/TimeQueryGLTest.cpp | 2 +- src/Magnum/TimeQuery.h | 121 +++++ 11 files changed, 623 insertions(+), 461 deletions(-) rename src/Magnum/{Query.cpp => AbstractQuery.cpp} (99%) create mode 100644 src/Magnum/AbstractQuery.h create mode 100644 src/Magnum/PrimitiveQuery.h create mode 100644 src/Magnum/SampleQuery.h create mode 100644 src/Magnum/TimeQuery.h diff --git a/src/Magnum/Query.cpp b/src/Magnum/AbstractQuery.cpp similarity index 99% rename from src/Magnum/Query.cpp rename to src/Magnum/AbstractQuery.cpp index 1a74b584e..2de393661 100644 --- a/src/Magnum/Query.cpp +++ b/src/Magnum/AbstractQuery.cpp @@ -23,7 +23,7 @@ DEALINGS IN THE SOFTWARE. */ -#include "Query.h" +#include "AbstractQuery.h" #include diff --git a/src/Magnum/AbstractQuery.h b/src/Magnum/AbstractQuery.h new file mode 100644 index 000000000..0dcd628d4 --- /dev/null +++ b/src/Magnum/AbstractQuery.h @@ -0,0 +1,182 @@ +#ifndef Magnum_AbstractQuery_h +#define Magnum_AbstractQuery_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::AbstractQuery + */ + +#include +#include + +#include "Magnum/AbstractObject.h" +#include "Magnum/configure.h" + +namespace Magnum { + +/** +@brief Base class for queries + +See @ref PrimitiveQuery, @ref SampleQuery and @ref TimeQuery documentation for +more information. +@todo `QUERY_COUNTER_BITS` (not sure since when this is supported) +*/ +class MAGNUM_EXPORT AbstractQuery: public AbstractObject { + public: + /** @brief Copying is not allowed */ + AbstractQuery(const AbstractQuery&) = delete; + + /** @brief Move constructor */ + AbstractQuery(AbstractQuery&& other) noexcept; + + /** @brief Copying is not allowed */ + AbstractQuery& operator=(const AbstractQuery&) = delete; + + /** @brief Move assignment */ + AbstractQuery& operator=(AbstractQuery&& other) noexcept; + + /** @brief OpenGL query ID */ + GLuint id() const { return _id; } + + /** + * @brief %Query label + * + * The result is *not* cached, repeated queries will result in repeated + * OpenGL calls. If OpenGL 4.3 is not supported and neither + * @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES + * extension is available, this function returns empty string. + * @see @fn_gl{GetObjectLabel} with @def_gl{QUERY} or + * @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with + * @def_gl{QUERY_OBJECT_EXT} + */ + std::string label() const; + + /** + * @brief Set query label + * @return Reference to self (for method chaining) + * + * Default is empty string. If OpenGL 4.3 is not supported and neither + * @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES + * extension is available, this function does nothing. + * @see @ref maxLabelLength(), @fn_gl{ObjectLabel} with + * @def_gl{QUERY} or @fn_gl_extension2{LabelObject,EXT,debug_label} + * with @def_gl{QUERY_OBJECT_EXT} + */ + AbstractQuery& setLabel(const std::string& label) { + return setLabelInternal({label.data(), label.size()}); + } + + /** @overload */ + template AbstractQuery& setLabel(const char(&label)[size]) { + return setLabelInternal(label); + } + + /** + * @brief Whether the result is available + * + * @see @fn_gl{GetQueryObject} with @def_gl{QUERY_RESULT_AVAILABLE} + */ + bool resultAvailable(); + + /** + * @brief Result + * @tparam T Result type. Can be either `bool`, @ref UnsignedInt, + * @ref Int, @ref UnsignedLong or @ref Long. + * + * Note that this function is blocking until the result is available. + * See resultAvailable(). + * @attention @ref Magnum::UnsignedLong "UnsignedLong" and @ref Magnum::Long "Long" + * result type is not available in @ref MAGNUM_TARGET_WEBGL "WebGL". + * @see @fn_gl{GetQueryObject} with @def_gl{QUERY_RESULT} + * @requires_gl33 %Extension @extension{ARB,timer_query} for result + * type @ref Magnum::UnsignedInt "UnsignedInt" and @ref Magnum::Long + * "Long" + * @requires_es_extension %Extension @es_extension{EXT,disjoint_timer_query} + * for result types @ref Magnum::Int "Int", @ref Magnum::UnsignedLong "UnsignedLong" + * @ref Magnum::Long "Long". + */ + template T result(); + + /** + * @brief End query + * + * The result can be then retrieved by calling @ref result(). + * @see @fn_gl{EndQuery} + */ + void end(); + + protected: + /** + * @brief Constructor + * + * Generates one OpenGL query. + * @see @fn_gl{GenQueries} + */ + explicit AbstractQuery(); + + /** + * @brief Destructor + * + * Deletes assigned OpenGL query. + * @see @fn_gl{DeleteQueries} + */ + ~AbstractQuery(); + + #ifdef DOXYGEN_GENERATING_OUTPUT + private: + #endif + void begin(GLenum target); + + private: + AbstractQuery& setLabelInternal(Containers::ArrayReference label); + + GLuint _id; + GLenum _target; +}; + +#ifndef DOXYGEN_GENERATING_OUTPUT +template<> bool MAGNUM_EXPORT AbstractQuery::result(); +template<> UnsignedInt MAGNUM_EXPORT AbstractQuery::result(); +template<> Int MAGNUM_EXPORT AbstractQuery::result(); +#ifndef MAGNUM_TARGET_WEBGL +template<> UnsignedLong MAGNUM_EXPORT AbstractQuery::result(); +template<> Long MAGNUM_EXPORT AbstractQuery::result(); +#endif +#endif + +inline AbstractQuery::AbstractQuery(AbstractQuery&& other) noexcept: _id(other._id), _target(other._target) { + other._id = 0; +} + +inline AbstractQuery& AbstractQuery::operator=(AbstractQuery&& other) noexcept { + std::swap(_id, other._id); + std::swap(_target, other._target); + return *this; +} + +} + +#endif diff --git a/src/Magnum/CMakeLists.txt b/src/Magnum/CMakeLists.txt index d6db799e4..b560ce451 100644 --- a/src/Magnum/CMakeLists.txt +++ b/src/Magnum/CMakeLists.txt @@ -31,6 +31,7 @@ set(Magnum_SRCS AbstractFramebuffer.cpp AbstractImage.cpp AbstractObject.cpp + AbstractQuery.cpp AbstractTexture.cpp AbstractShaderProgram.cpp Buffer.cpp @@ -44,7 +45,6 @@ set(Magnum_SRCS Mesh.cpp MeshView.cpp OpenGL.cpp - Query.cpp Renderbuffer.cpp Renderer.cpp Resource.cpp @@ -83,6 +83,7 @@ set(Magnum_HEADERS AbstractFramebuffer.h AbstractImage.h AbstractObject.h + AbstractQuery.h AbstractResourceLoader.h AbstractShaderProgram.h AbstractTexture.h @@ -103,17 +104,18 @@ set(Magnum_HEADERS Mesh.h MeshView.h OpenGL.h - Query.h Renderbuffer.h RenderbufferFormat.h Renderer.h Resource.h ResourceManager.h + SampleQuery.h Sampler.h Shader.h Texture.h TextureFormat.h Timeline.h + TimeQuery.h Types.h Version.h @@ -135,7 +137,8 @@ set(Magnum_PRIVATE_HEADERS # Deprecated headers if(BUILD_DEPRECATED) set(Magnum_HEADERS ${Magnum_HEADERS} - DebugMarker.h) + DebugMarker.h + Query.h) endif() # Desktop-only stuff @@ -155,6 +158,7 @@ if(NOT TARGET_GLES2) set(Magnum_HEADERS ${Magnum_HEADERS} BufferImage.h MultisampleTexture.h + PrimitiveQuery.h TextureArray.h) set(Magnum_SRCS ${Magnum_SRCS} BufferImage.cpp diff --git a/src/Magnum/PrimitiveQuery.h b/src/Magnum/PrimitiveQuery.h new file mode 100644 index 000000000..d196e95ca --- /dev/null +++ b/src/Magnum/PrimitiveQuery.h @@ -0,0 +1,110 @@ +#ifndef Magnum_PrimitiveQuery_h +#define Magnum_PrimitiveQuery_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#ifndef MAGNUM_TARGET_GLES2 +/** @file + * @brief Class @ref Magnum::PrimitiveQuery + */ +#endif + +#include "Magnum/AbstractQuery.h" + +#ifndef MAGNUM_TARGET_GLES2 +namespace Magnum { + +/** +@brief Query for primitives + +Queries count of generated primitives from vertex shader, geometry shader or +transform feedback. Example usage: +@code +PrimitiveQuery q; + +q.begin(PrimitiveQuery::Target::PrimitivesGenerated); +// rendering... +q.end(); + +if(!q.resultAvailable()) { + // do some work until to give OpenGL some time... +} + +// ...or block until the result is available +UnsignedInt primitiveCount = q.result(); +@endcode +@requires_gl30 %Extension @extension{EXT,transform_feedback} +@requires_gles30 Only sample queries are available on OpenGL ES 2.0. + +@see @ref SampleQuery, @ref TimeQuery +@todo glBeginQueryIndexed +*/ +class PrimitiveQuery: public AbstractQuery { + public: + /** @brief Query target */ + enum class Target: GLenum { + #ifndef MAGNUM_TARGET_GLES + /** + * Count of primitives generated from vertex shader or geometry + * shader. + * @requires_gl Only transform feedback query is available in + * OpenGL ES. + */ + PrimitivesGenerated = GL_PRIMITIVES_GENERATED, + #endif + + /** Count of primitives written to transform feedback buffer. */ + TransformFeedbackPrimitivesWritten = GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN + }; + + explicit PrimitiveQuery() {} + + /** + * @brief Begin query + * + * Begins counting of given @p target until @ref end() is called. + * @see @fn_gl{BeginQuery} + */ + void begin(Target target) { + AbstractQuery::begin(GLenum(target)); + } + + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + PrimitiveQuery& setLabel(const std::string& label) { + AbstractQuery::setLabel(label); + return *this; + } + template PrimitiveQuery& setLabel(const char(&label)[size]) { + AbstractQuery::setLabel(label); + return *this; + } + #endif +}; + +} +#endif + +#endif diff --git a/src/Magnum/Query.h b/src/Magnum/Query.h index 2e2f265fb..5bde8162e 100644 --- a/src/Magnum/Query.h +++ b/src/Magnum/Query.h @@ -27,463 +27,17 @@ /** @file * @brief Class @ref Magnum::AbstractQuery, @ref Magnum::PrimitiveQuery, @ref Magnum::SampleQuery, @ref Magnum::TimeQuery + * @deprecated Use @ref Magnum/PrimitiveQuery.h, @ref Magnum/SampleQuery.h or @ref Magnum/TimeQuery.h instead. */ -#include -#include - -#include "Magnum/AbstractObject.h" #include "Magnum/configure.h" -namespace Magnum { - -/** -@brief Base class for queries - -See @ref PrimitiveQuery, @ref SampleQuery and @ref TimeQuery documentation for -more information. -@todo `QUERY_COUNTER_BITS` (not sure since when this is supported) -*/ -class MAGNUM_EXPORT AbstractQuery: public AbstractObject { - public: - /** @brief Copying is not allowed */ - AbstractQuery(const AbstractQuery&) = delete; - - /** @brief Move constructor */ - AbstractQuery(AbstractQuery&& other) noexcept; - - /** @brief Copying is not allowed */ - AbstractQuery& operator=(const AbstractQuery&) = delete; - - /** @brief Move assignment */ - AbstractQuery& operator=(AbstractQuery&& other) noexcept; - - /** @brief OpenGL query ID */ - GLuint id() const { return _id; } - - /** - * @brief %Query label - * - * The result is *not* cached, repeated queries will result in repeated - * OpenGL calls. If OpenGL 4.3 is not supported and neither - * @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES - * extension is available, this function returns empty string. - * @see @fn_gl{GetObjectLabel} with @def_gl{QUERY} or - * @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with - * @def_gl{QUERY_OBJECT_EXT} - */ - std::string label() const; - - /** - * @brief Set query label - * @return Reference to self (for method chaining) - * - * Default is empty string. If OpenGL 4.3 is not supported and neither - * @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES - * extension is available, this function does nothing. - * @see @ref maxLabelLength(), @fn_gl{ObjectLabel} with - * @def_gl{QUERY} or @fn_gl_extension2{LabelObject,EXT,debug_label} - * with @def_gl{QUERY_OBJECT_EXT} - */ - AbstractQuery& setLabel(const std::string& label) { - return setLabelInternal({label.data(), label.size()}); - } - - /** @overload */ - template AbstractQuery& setLabel(const char(&label)[size]) { - return setLabelInternal(label); - } - - /** - * @brief Whether the result is available - * - * @see @fn_gl{GetQueryObject} with @def_gl{QUERY_RESULT_AVAILABLE} - */ - bool resultAvailable(); - - /** - * @brief Result - * @tparam T Result type. Can be either `bool`, @ref UnsignedInt, - * @ref Int, @ref UnsignedLong or @ref Long. - * - * Note that this function is blocking until the result is available. - * See resultAvailable(). - * @attention @ref Magnum::UnsignedLong "UnsignedLong" and @ref Magnum::Long "Long" - * result type is not available in @ref MAGNUM_TARGET_WEBGL "WebGL". - * @see @fn_gl{GetQueryObject} with @def_gl{QUERY_RESULT} - * @requires_gl33 %Extension @extension{ARB,timer_query} for result - * type @ref Magnum::UnsignedInt "UnsignedInt" and @ref Magnum::Long - * "Long" - * @requires_es_extension %Extension @es_extension{EXT,disjoint_timer_query} - * for result types @ref Magnum::Int "Int", @ref Magnum::UnsignedLong "UnsignedLong" - * @ref Magnum::Long "Long". - */ - template T result(); - - /** - * @brief End query - * - * The result can be then retrieved by calling @ref result(). - * @see @fn_gl{EndQuery} - */ - void end(); - - protected: - /** - * @brief Constructor - * - * Generates one OpenGL query. - * @see @fn_gl{GenQueries} - */ - explicit AbstractQuery(); - - /** - * @brief Destructor - * - * Deletes assigned OpenGL query. - * @see @fn_gl{DeleteQueries} - */ - ~AbstractQuery(); - - #ifdef DOXYGEN_GENERATING_OUTPUT - private: - #endif - void begin(GLenum target); - - private: - AbstractQuery& setLabelInternal(Containers::ArrayReference label); - - GLuint _id; - GLenum _target; -}; - - -#ifndef DOXYGEN_GENERATING_OUTPUT -template<> bool MAGNUM_EXPORT AbstractQuery::result(); -template<> UnsignedInt MAGNUM_EXPORT AbstractQuery::result(); -template<> Int MAGNUM_EXPORT AbstractQuery::result(); -#ifndef MAGNUM_TARGET_WEBGL -template<> UnsignedLong MAGNUM_EXPORT AbstractQuery::result(); -template<> Long MAGNUM_EXPORT AbstractQuery::result(); -#endif -#endif - -#ifndef MAGNUM_TARGET_GLES2 -/** -@brief Query for primitives - -Queries count of generated primitives from vertex shader, geometry shader or -transform feedback. Example usage: -@code -PrimitiveQuery q; - -q.begin(PrimitiveQuery::Target::PrimitivesGenerated); -// rendering... -q.end(); - -if(!q.resultAvailable()) { - // do some work until to give OpenGL some time... -} - -// ...or block until the result is available -UnsignedInt primitiveCount = q.result(); -@endcode -@requires_gl30 %Extension @extension{EXT,transform_feedback} -@requires_gles30 Only sample queries are available on OpenGL ES 2.0. - -@see @ref SampleQuery, @ref TimeQuery -@todo glBeginQueryIndexed -*/ -class PrimitiveQuery: public AbstractQuery { - public: - /** @brief Query target */ - enum class Target: GLenum { - #ifndef MAGNUM_TARGET_GLES - /** - * Count of primitives generated from vertex shader or geometry - * shader. - * @requires_gl Only transform feedback query is available in - * OpenGL ES. - */ - PrimitivesGenerated = GL_PRIMITIVES_GENERATED, - #endif - - /** Count of primitives written to transform feedback buffer. */ - TransformFeedbackPrimitivesWritten = GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN - }; - - explicit PrimitiveQuery() {} - - /** - * @brief Begin query - * - * Begins counting of given @p target until @ref end() is called. - * @see @fn_gl{BeginQuery} - */ - void begin(Target target) { - AbstractQuery::begin(GLenum(target)); - } - - /* Overloads to remove WTF-factor from method chaining order */ - #ifndef DOXYGEN_GENERATING_OUTPUT - PrimitiveQuery& setLabel(const std::string& label) { - AbstractQuery::setLabel(label); - return *this; - } - template PrimitiveQuery& setLabel(const char(&label)[size]) { - AbstractQuery::setLabel(label); - return *this; - } - #endif -}; +#ifdef MAGNUM_BUILD_DEPRECATED +#include "Magnum/PrimitiveQuery.h" +#include "Magnum/SampleQuery.h" +#include "Magnum/TimeQuery.h" +#else +#error use Magnum/PrimitiveQuery.h, Magnum/SampleQuery.h or Magnum/TimeQuery.h instead. #endif -/** -@brief Query for samples - -Queries count of samples passed from fragment shader or boolean value -indicating whether any samples passed. Can be used for example for conditional -rendering: -@code -SampleQuery q; - -q.begin(SampleQuery::Target::AnySamplesPassed); -// render simplified object to test whether it is visible at all... -q.end(); - -// render full version of the object only if it is visible -if(q.result()) { - // ... -} -@endcode -This approach has some drawbacks, as the rendering is blocked until result is -available for the CPU to decide. This can be improved by using conditional -rendering on GPU itself. The drawing commands will be sent to the GPU and -processed or discarded later, so CPU can continue executing the code without -waiting for the result. -@code -SampleQuery q; - -q.begin(SampleQuery::Target::AnySamplesPassed); -// render simplified object to test whether it is visible at all... -q.end(); - -q.beginConditionalRender(SampleQuery::ConditionalRenderMode::Wait); -// render full version of the object only if the query returns nonzero result -q.endConditionalRender(); -@endcode - -@see @ref PrimitiveQuery, @ref TimeQuery -@requires_gles30 %Extension @es_extension{EXT,occlusion_query_boolean} in - OpenGL ES 2.0 -*/ -class SampleQuery: public AbstractQuery { - public: - /** @brief Query target */ - enum class Target: GLenum { - #ifndef MAGNUM_TARGET_GLES - /** - * Count of samples passed from fragment shader - * @requires_gl Only boolean query is available in OpenGL ES. - */ - SamplesPassed = GL_SAMPLES_PASSED, - #endif - - /** - * Whether any samples passed from fragment shader - * @requires_gl33 %Extension @extension{ARB,occlusion_query2} - */ - #ifndef MAGNUM_TARGET_GLES2 - AnySamplesPassed = GL_ANY_SAMPLES_PASSED, - #else - AnySamplesPassed = GL_ANY_SAMPLES_PASSED_EXT, - #endif - - /** - * Whether any samples passed from fragment shader (conservative) - * - * An implementation may choose a less precise version of the - * test at the expense of some false positives. - * @requires_gl43 %Extension @extension{ARB,ES3_compatibility} - */ - #ifndef MAGNUM_TARGET_GLES2 - AnySamplesPassedConservative = GL_ANY_SAMPLES_PASSED_CONSERVATIVE - #else - AnySamplesPassedConservative = GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT - #endif - }; - - #ifndef MAGNUM_TARGET_GLES - /** - * @brief Conditional render mode - * - * @requires_gl30 %Extension @extension{NV,conditional_render} - * @requires_gl Conditional rendering is not available in OpenGL ES. - */ - enum class ConditionalRenderMode: GLenum { - /** - * If query result is not yet available, waits for it and - * then begins conditional rendering based on result value. - */ - Wait = GL_QUERY_WAIT, - - /** - * If query result is not yet available, OpenGL may begin - * rendering like if the result value was nonzero. - */ - NoWait = GL_QUERY_NO_WAIT, - - /** - * The same as Wait, but regions untouched by the sample query may - * not be rendered at all. - */ - ByRegionWait = GL_QUERY_BY_REGION_WAIT, - - /** - * The same as NoWait, but regions untouched by the sample query - * may not be rendered at all. - */ - ByRegionNoWait = GL_QUERY_BY_REGION_NO_WAIT - }; - #endif - - explicit SampleQuery() {} - - /** @copydoc PrimitiveQuery::begin() */ - void begin(Target target) { - AbstractQuery::begin(GLenum(target)); - } - - #ifndef MAGNUM_TARGET_GLES - /** - * @brief Begin conditional rendering based on result value - * - * @see @fn_gl{BeginConditionalRender} - * @requires_gl30 %Extension @extension{NV,conditional_render} - * @requires_gl Conditional rendering is not available in OpenGL ES. - */ - void beginConditionalRender(ConditionalRenderMode mode) { - glBeginConditionalRender(id(), GLenum(mode)); - } - - /** - * @brief End conditional render - * - * @see @fn_gl{EndConditionalRender} - * @requires_gl30 %Extension @extension{NV,conditional_render} - * @requires_gl Conditional rendering is not available in OpenGL ES. - */ - void endConditionalRender() { - glEndConditionalRender(); - } - #endif - - /* Overloads to remove WTF-factor from method chaining order */ - #ifndef DOXYGEN_GENERATING_OUTPUT - SampleQuery& setLabel(const std::string& label) { - AbstractQuery::setLabel(label); - return *this; - } - template SampleQuery& setLabel(const char(&label)[size]) { - AbstractQuery::setLabel(label); - return *this; - } - #endif -}; - -/** -@brief Query for elapsed time - -Queries timestamp after all previous OpenGL calls have been processed. It can -query either duration of sequence of commands or absolute timestamp. Example -usage of both methods: -@code -TimeQuery q1, q2; -q1.begin(TimeQuery::Target::TimeElapsed); -// rendering... -q1.end(); -q2.begin(TimeQuery::Target::TimeElapsed); -// another rendering... -q2.end(); -UnsignedInt timeElapsed1 = q1.result(); -UnsignedInt timeElapsed2 = q2.result(); -@endcode -@code -TimeQuery q1, q2, q3; -q1.timestamp(); -// rendering... -q2.timestamp(); -// another rendering... -q3.timestamp(); -UnsignedInt tmp = q2.result(); -UnsignedInt timeElapsed1 = tmp-q1.result(); -UnsignedInt timeElapsed2 = q3.result()-tmp; -@endcode -Using the latter results in fewer OpenGL calls when doing more measures. -@requires_gl33 %Extension @extension{ARB,timer_query} -@requires_es_extension %Extension @es_extension{EXT,disjoint_timer_query} - -@see @ref PrimitiveQuery, @ref SampleQuery -@todo timestamp with glGet + example usage -@todo @es_extension{EXT,disjoint_timer_query} -- GL_GPU_DISJOINT_EXT support? where? -*/ -class TimeQuery: public AbstractQuery { - public: - /** @brief Query target */ - enum class Target: GLenum { - /** Elapsed time */ - #ifndef MAGNUM_TARGET_GLES - TimeElapsed = GL_TIME_ELAPSED - #else - TimeElapsed = GL_TIME_ELAPSED_EXT - #endif - }; - - explicit TimeQuery() {} - - /** - * @brief Query timestamp - * - * @see @fn_gl{QueryCounter} with @def_gl{TIMESTAMP} - */ - void timestamp() { - #ifndef MAGNUM_TARGET_GLES - glQueryCounter(id(), GL_TIMESTAMP); - #elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) - glQueryCounterEXT(id(), GL_TIMESTAMP_EXT); - #else - CORRADE_ASSERT_UNREACHABLE(); - #endif - } - - /** @copydoc PrimitiveQuery::begin() */ - void begin(Target target) { - AbstractQuery::begin(GLenum(target)); - } - - /* Overloads to remove WTF-factor from method chaining order */ - #ifndef DOXYGEN_GENERATING_OUTPUT - TimeQuery& setLabel(const std::string& label) { - AbstractQuery::setLabel(label); - return *this; - } - template TimeQuery& setLabel(const char(&label)[size]) { - AbstractQuery::setLabel(label); - return *this; - } - #endif -}; - -inline AbstractQuery::AbstractQuery(AbstractQuery&& other) noexcept: _id(other._id), _target(other._target) { - other._id = 0; -} - -inline AbstractQuery& AbstractQuery::operator=(AbstractQuery&& other) noexcept { - std::swap(_id, other._id); - std::swap(_target, other._target); - return *this; -} - -} - #endif diff --git a/src/Magnum/SampleQuery.h b/src/Magnum/SampleQuery.h new file mode 100644 index 000000000..0d8459ed7 --- /dev/null +++ b/src/Magnum/SampleQuery.h @@ -0,0 +1,191 @@ +#ifndef Magnum_SampleQuery_h +#define Magnum_SampleQuery_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::SampleQuery + */ + +#include "Magnum/AbstractQuery.h" + +namespace Magnum { + +/** +@brief Query for samples + +Queries count of samples passed from fragment shader or boolean value +indicating whether any samples passed. Can be used for example for conditional +rendering: +@code +SampleQuery q; + +q.begin(SampleQuery::Target::AnySamplesPassed); +// render simplified object to test whether it is visible at all... +q.end(); + +// render full version of the object only if it is visible +if(q.result()) { + // ... +} +@endcode +This approach has some drawbacks, as the rendering is blocked until result is +available for the CPU to decide. This can be improved by using conditional +rendering on GPU itself. The drawing commands will be sent to the GPU and +processed or discarded later, so CPU can continue executing the code without +waiting for the result. +@code +SampleQuery q; + +q.begin(SampleQuery::Target::AnySamplesPassed); +// render simplified object to test whether it is visible at all... +q.end(); + +q.beginConditionalRender(SampleQuery::ConditionalRenderMode::Wait); +// render full version of the object only if the query returns nonzero result +q.endConditionalRender(); +@endcode + +@see @ref PrimitiveQuery, @ref TimeQuery +@requires_gles30 %Extension @es_extension{EXT,occlusion_query_boolean} in + OpenGL ES 2.0 +*/ +class SampleQuery: public AbstractQuery { + public: + /** @brief Query target */ + enum class Target: GLenum { + #ifndef MAGNUM_TARGET_GLES + /** + * Count of samples passed from fragment shader + * @requires_gl Only boolean query is available in OpenGL ES. + */ + SamplesPassed = GL_SAMPLES_PASSED, + #endif + + /** + * Whether any samples passed from fragment shader + * @requires_gl33 %Extension @extension{ARB,occlusion_query2} + */ + #ifndef MAGNUM_TARGET_GLES2 + AnySamplesPassed = GL_ANY_SAMPLES_PASSED, + #else + AnySamplesPassed = GL_ANY_SAMPLES_PASSED_EXT, + #endif + + /** + * Whether any samples passed from fragment shader (conservative) + * + * An implementation may choose a less precise version of the + * test at the expense of some false positives. + * @requires_gl43 %Extension @extension{ARB,ES3_compatibility} + */ + #ifndef MAGNUM_TARGET_GLES2 + AnySamplesPassedConservative = GL_ANY_SAMPLES_PASSED_CONSERVATIVE + #else + AnySamplesPassedConservative = GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT + #endif + }; + + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Conditional render mode + * + * @requires_gl30 %Extension @extension{NV,conditional_render} + * @requires_gl Conditional rendering is not available in OpenGL ES. + */ + enum class ConditionalRenderMode: GLenum { + /** + * If query result is not yet available, waits for it and + * then begins conditional rendering based on result value. + */ + Wait = GL_QUERY_WAIT, + + /** + * If query result is not yet available, OpenGL may begin + * rendering like if the result value was nonzero. + */ + NoWait = GL_QUERY_NO_WAIT, + + /** + * The same as Wait, but regions untouched by the sample query may + * not be rendered at all. + */ + ByRegionWait = GL_QUERY_BY_REGION_WAIT, + + /** + * The same as NoWait, but regions untouched by the sample query + * may not be rendered at all. + */ + ByRegionNoWait = GL_QUERY_BY_REGION_NO_WAIT + }; + #endif + + explicit SampleQuery() {} + + /** @copydoc PrimitiveQuery::begin() */ + void begin(Target target) { + AbstractQuery::begin(GLenum(target)); + } + + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Begin conditional rendering based on result value + * + * @see @fn_gl{BeginConditionalRender} + * @requires_gl30 %Extension @extension{NV,conditional_render} + * @requires_gl Conditional rendering is not available in OpenGL ES. + */ + void beginConditionalRender(ConditionalRenderMode mode) { + glBeginConditionalRender(id(), GLenum(mode)); + } + + /** + * @brief End conditional render + * + * @see @fn_gl{EndConditionalRender} + * @requires_gl30 %Extension @extension{NV,conditional_render} + * @requires_gl Conditional rendering is not available in OpenGL ES. + */ + void endConditionalRender() { + glEndConditionalRender(); + } + #endif + + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + SampleQuery& setLabel(const std::string& label) { + AbstractQuery::setLabel(label); + return *this; + } + template SampleQuery& setLabel(const char(&label)[size]) { + AbstractQuery::setLabel(label); + return *this; + } + #endif +}; + +} + +#endif diff --git a/src/Magnum/Test/AbstractQueryGLTest.cpp b/src/Magnum/Test/AbstractQueryGLTest.cpp index 0706be23c..256fc236e 100644 --- a/src/Magnum/Test/AbstractQueryGLTest.cpp +++ b/src/Magnum/Test/AbstractQueryGLTest.cpp @@ -23,7 +23,7 @@ DEALINGS IN THE SOFTWARE. */ -#include "Magnum/Query.h" +#include "Magnum/SampleQuery.h" #include "Magnum/Test/AbstractOpenGLTester.h" namespace Magnum { namespace Test { diff --git a/src/Magnum/Test/PrimitiveQueryGLTest.cpp b/src/Magnum/Test/PrimitiveQueryGLTest.cpp index c85a70f05..dcb2574a1 100644 --- a/src/Magnum/Test/PrimitiveQueryGLTest.cpp +++ b/src/Magnum/Test/PrimitiveQueryGLTest.cpp @@ -30,7 +30,7 @@ #include "Magnum/Buffer.h" #include "Magnum/Framebuffer.h" #include "Magnum/Mesh.h" -#include "Magnum/Query.h" +#include "Magnum/PrimitiveQuery.h" #include "Magnum/Renderbuffer.h" #include "Magnum/RenderbufferFormat.h" #include "Magnum/Shader.h" diff --git a/src/Magnum/Test/SampleQueryGLTest.cpp b/src/Magnum/Test/SampleQueryGLTest.cpp index e3f305f2b..9d71a36bd 100644 --- a/src/Magnum/Test/SampleQueryGLTest.cpp +++ b/src/Magnum/Test/SampleQueryGLTest.cpp @@ -30,9 +30,9 @@ #include "Magnum/Buffer.h" #include "Magnum/Framebuffer.h" #include "Magnum/Mesh.h" -#include "Magnum/Query.h" #include "Magnum/Renderbuffer.h" #include "Magnum/RenderbufferFormat.h" +#include "Magnum/SampleQuery.h" #include "Magnum/Shader.h" #include "Magnum/Test/AbstractOpenGLTester.h" diff --git a/src/Magnum/Test/TimeQueryGLTest.cpp b/src/Magnum/Test/TimeQueryGLTest.cpp index 680f95544..c1741bd1f 100644 --- a/src/Magnum/Test/TimeQueryGLTest.cpp +++ b/src/Magnum/Test/TimeQueryGLTest.cpp @@ -23,7 +23,7 @@ DEALINGS IN THE SOFTWARE. */ -#include "Magnum/Query.h" +#include "Magnum/TimeQuery.h" #include "Magnum/Test/AbstractOpenGLTester.h" namespace Magnum { namespace Test { diff --git a/src/Magnum/TimeQuery.h b/src/Magnum/TimeQuery.h new file mode 100644 index 000000000..23a005b21 --- /dev/null +++ b/src/Magnum/TimeQuery.h @@ -0,0 +1,121 @@ +#ifndef Magnum_TimeQuery_h +#define Magnum_TimeQuery_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013, 2014 + Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class @ref Magnum::TimeQuery + */ + +#include "Magnum/AbstractQuery.h" + +namespace Magnum { + +/** +@brief Query for elapsed time + +Queries timestamp after all previous OpenGL calls have been processed. It can +query either duration of sequence of commands or absolute timestamp. Example +usage of both methods: +@code +TimeQuery q1, q2; +q1.begin(TimeQuery::Target::TimeElapsed); +// rendering... +q1.end(); +q2.begin(TimeQuery::Target::TimeElapsed); +// another rendering... +q2.end(); +UnsignedInt timeElapsed1 = q1.result(); +UnsignedInt timeElapsed2 = q2.result(); +@endcode +@code +TimeQuery q1, q2, q3; +q1.timestamp(); +// rendering... +q2.timestamp(); +// another rendering... +q3.timestamp(); +UnsignedInt tmp = q2.result(); +UnsignedInt timeElapsed1 = tmp-q1.result(); +UnsignedInt timeElapsed2 = q3.result()-tmp; +@endcode +Using the latter results in fewer OpenGL calls when doing more measures. +@requires_gl33 %Extension @extension{ARB,timer_query} +@requires_es_extension %Extension @es_extension{EXT,disjoint_timer_query} + +@see @ref PrimitiveQuery, @ref SampleQuery +@todo timestamp with glGet + example usage +@todo @es_extension{EXT,disjoint_timer_query} -- GL_GPU_DISJOINT_EXT support? where? +*/ +class TimeQuery: public AbstractQuery { + public: + /** @brief Query target */ + enum class Target: GLenum { + /** Elapsed time */ + #ifndef MAGNUM_TARGET_GLES + TimeElapsed = GL_TIME_ELAPSED + #else + TimeElapsed = GL_TIME_ELAPSED_EXT + #endif + }; + + explicit TimeQuery() {} + + /** + * @brief Query timestamp + * + * @see @fn_gl{QueryCounter} with @def_gl{TIMESTAMP} + */ + void timestamp() { + #ifndef MAGNUM_TARGET_GLES + glQueryCounter(id(), GL_TIMESTAMP); + #elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) + glQueryCounterEXT(id(), GL_TIMESTAMP_EXT); + #else + CORRADE_ASSERT_UNREACHABLE(); + #endif + } + + /** @copydoc PrimitiveQuery::begin() */ + void begin(Target target) { + AbstractQuery::begin(GLenum(target)); + } + + /* Overloads to remove WTF-factor from method chaining order */ + #ifndef DOXYGEN_GENERATING_OUTPUT + TimeQuery& setLabel(const std::string& label) { + AbstractQuery::setLabel(label); + return *this; + } + template TimeQuery& setLabel(const char(&label)[size]) { + AbstractQuery::setLabel(label); + return *this; + } + #endif +}; + +} + +#endif