Browse Source

Support for indexed primitive queries.

Amazing how it all still fits my original design without needing to
rewrite half of the API.
pull/187/head^2
Vladimír Vondruš 10 years ago
parent
commit
f275143e9f
  1. 2
      doc/opengl-mapping.dox
  2. 2
      doc/opengl-support.dox
  3. 5
      src/Magnum/AbstractQuery.h
  4. 1
      src/Magnum/CMakeLists.txt
  5. 69
      src/Magnum/PrimitiveQuery.cpp
  6. 58
      src/Magnum/PrimitiveQuery.h
  7. 63
      src/Magnum/Test/PrimitiveQueryGLTest.cpp

2
doc/opengl-mapping.dox

@ -52,7 +52,7 @@ OpenGL function | Matching API
--------------------------------------- | ------------
@fn_gl{BeginConditionalRender}, `glEndConditionalRender()` | @ref SampleQuery::beginConditionalRender(), \n @ref SampleQuery::endConditionalRender()
@fn_gl{BeginQuery}, `glEndQuery()` | @ref PrimitiveQuery::begin(), \n @ref SampleQuery::begin(), \n @ref TimeQuery::begin(), \n @ref AbstractQuery::end()
@fn_gl{BeginQueryIndexed}, `glEndQueryIndexed()` | |
@fn_gl{BeginQueryIndexed}, `glEndQueryIndexed()` | @ref PrimitiveQuery::begin(UnsignedInt), \n @ref PrimitiveQuery::end()
@fn_gl{BeginTransformFeedback}, `glEndTransformFeedback()` | @ref TransformFeedback::begin(), @ref TransformFeedback::end()
@fn_gl{BindAttribLocation} | @ref AbstractShaderProgram::bindAttributeLocation()
@fn_gl{BindBuffer} | not needed, handled internally in @ref Buffer and elsewhere

2
doc/opengl-support.dox

@ -132,7 +132,7 @@ GLSL 4.00 | done
@extension{ARB,tessellation_shader} | missing some limit queries and patch parameter specification function
@extension{ARB,texture_buffer_object_rgb32} | done
@extension{ARB,transform_feedback2} | missing transform feedback draw
@extension{ARB,transform_feedback3} | only advanced interleaving
@extension{ARB,transform_feedback3} | missing indexed properties query
@subsection opengl-support-41 OpenGL 4.1

5
src/Magnum/AbstractQuery.h

@ -183,6 +183,9 @@ class MAGNUM_EXPORT AbstractQuery: public AbstractObject {
void begin(GLenum target);
#endif
GLuint _id;
GLenum _target;
private:
#ifndef MAGNUM_TARGET_WEBGL
AbstractQuery& setLabelInternal(Containers::ArrayView<const char> label);
@ -193,8 +196,6 @@ class MAGNUM_EXPORT AbstractQuery: public AbstractObject {
void MAGNUM_LOCAL createImplementationDSA();
#endif
GLuint _id;
GLenum _target;
ObjectFlags _flags;
};

1
src/Magnum/CMakeLists.txt

@ -151,6 +151,7 @@ endif()
if(NOT TARGET_GLES2)
list(APPEND Magnum_SRCS
BufferImage.cpp
PrimitiveQuery.cpp
TextureArray.cpp
TransformFeedback.cpp

69
src/Magnum/PrimitiveQuery.cpp

@ -0,0 +1,69 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016
Vladimír Vondruš <mosra@centrum.cz>
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.
*/
#include "PrimitiveQuery.h"
namespace Magnum {
void PrimitiveQuery::begin() {
#ifndef MAGNUM_TARGET_GLES
_index = 0;
#endif
AbstractQuery::begin();
}
#ifdef MAGNUM_BUILD_DEPRECATED
void PrimitiveQuery::begin(const Target target) {
#ifndef MAGNUM_TARGET_GLES
_index = 0;
#endif
AbstractQuery::begin(GLenum(target));
}
#endif
#ifndef MAGNUM_TARGET_GLES
void PrimitiveQuery::begin(const UnsignedInt index) {
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_INTERNAL_ASSERT(_target);
#endif
glBeginQueryIndexed(_target, _index = index, _id);
}
#endif
void PrimitiveQuery::end() {
#ifdef MAGNUM_BUILD_DEPRECATED
CORRADE_INTERNAL_ASSERT(_target);
#endif
#ifndef MAGNUM_TARGET_GLES
if(!_index) glEndQuery(_target);
else glEndQueryIndexed(_target, _index);
#else
AbstractQuery::end();
#endif
}
}

58
src/Magnum/PrimitiveQuery.h

@ -63,18 +63,19 @@ UnsignedInt primitiveCount = q.result<UnsignedInt>();
@requires_gl30 Extension @extension{EXT,transform_feedback}
@requires_gles30 Only sample queries are available in OpenGL ES 2.0.
@requires_webgl20 Queries are not available in WebGL 1.0.
@todo glBeginQueryIndexed
@todo @extension{ARB,transform_feedback_overflow_query}
*/
class PrimitiveQuery: public AbstractQuery {
class MAGNUM_EXPORT PrimitiveQuery: public AbstractQuery {
public:
/** @brief Query target */
enum class Target: GLenum {
#ifndef MAGNUM_TARGET_GLES2
/**
* Count of primitives generated from vertex shader or geometry
* shader. Use @ref result<UnsignedInt>() or @ref result<Int>() to
* retrieve the result.
* shader. When used with @ref begin(UnsignedInt), the index must
* be lower than @ref TransformFeedback::maxVertexStreams(). Use
* @ref result<UnsignedInt>() or @ref result<Int>() to retrieve the
* result.
* @requires_gles30 Not defined in OpenGL ES 2.0.
* @requires_es_extension Extension @es_extension{ANDROID,extension_pack_es31a}/
* @es_extension{EXT,geometry_shader}
@ -88,7 +89,9 @@ class PrimitiveQuery: public AbstractQuery {
#endif
/**
* Count of primitives written to transform feedback buffer. Use
* Count of primitives written to transform feedback buffer. When
* used with @ref begin(UnsignedInt), the index must be lower than
* @ref TransformFeedback::maxVertexStreams(). Use
* @ref result<UnsignedInt>() or @ref result<Int>() to retrieve the
* result.
*/
@ -140,18 +143,49 @@ class PrimitiveQuery: public AbstractQuery {
*/
explicit PrimitiveQuery(NoCreateT) noexcept: AbstractQuery{NoCreate, GLenum(Target::TransformFeedbackPrimitivesWritten)} {}
/**
* @brief Begin query
*
* Begins counting until @ref end() is called. Equivalent to calling
* @ref begin(UnsignedInt) with @p index set to `0`.
* @see @fn_gl{BeginQuery}
*/
void begin();
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief AbstractQuery::begin()
* @copybrief begin()
* @deprecated Use @ref begin() instead.
*/
CORRADE_DEPRECATED("use begin() instead") void begin(Target target) {
AbstractQuery::begin(GLenum(target));
}
CORRADE_DEPRECATED("use begin() instead") void begin(Target target);
#endif
using AbstractQuery::begin;
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Begin indexed query
*
* Begins counting until @ref end() is called.
* @see @fn_gl{BeginQueryIndexed}
* @requires_gl40 Extension @extension{ARB,transform_feedback3}
* @requires_gl Indexed queries are not available in OpenGL ES or WebGL.
*/
void begin(UnsignedInt index);
#endif
/**
* @brief End query
*
* Ends the non-indexed or indexed query started with @ref begin() or
* @ref begin(UnsignedInt). The result can be then retrieved by calling
* @ref result().
* @see @fn_gl{EndQuery}, @fn_gl2{EndQueryIndexed,BeginQueryIndexed}
* @requires_gl40 Extension @extension{ARB,transform_feedback3} for
* indexed queries
* @requires_gl Indexed queries are not available in OpenGL ES or
* WebGL.
*/
void end();
/* Overloads to remove WTF-factor from method chaining order */
#if !defined(DOXYGEN_GENERATING_OUTPUT) && !defined(MAGNUM_TARGET_WEBGL)
PrimitiveQuery& setLabel(const std::string& label) {
@ -166,6 +200,10 @@ class PrimitiveQuery: public AbstractQuery {
private:
explicit PrimitiveQuery(GLuint id, Target target, ObjectFlags flags) noexcept: AbstractQuery{id, GLenum(target), flags} {}
#ifndef MAGNUM_TARGET_GLES
GLuint _index{};
#endif
};
}

63
src/Magnum/Test/PrimitiveQueryGLTest.cpp

@ -48,6 +48,7 @@ struct PrimitiveQueryGLTest: AbstractOpenGLTester {
#ifndef MAGNUM_TARGET_GLES
void primitivesGenerated();
void primitivesGeneratedIndexed();
#endif
void transformFeedbackPrimitivesWritten();
};
@ -58,6 +59,7 @@ PrimitiveQueryGLTest::PrimitiveQueryGLTest() {
#ifndef MAGNUM_TARGET_GLES
&PrimitiveQueryGLTest::primitivesGenerated,
&PrimitiveQueryGLTest::primitivesGeneratedIndexed,
#endif
&PrimitiveQueryGLTest::transformFeedbackPrimitivesWritten});
}
@ -158,6 +160,67 @@ void PrimitiveQueryGLTest::primitivesGenerated() {
CORRADE_VERIFY(availableAfter);
CORRADE_COMPARE(count, 3);
}
void PrimitiveQueryGLTest::primitivesGeneratedIndexed() {
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::transform_feedback3>())
CORRADE_SKIP(Extensions::GL::ARB::transform_feedback3::string() + std::string(" is not available."));
/* Bind some FB to avoid errors on contexts w/o default FB */
Renderbuffer color;
color.setStorage(RenderbufferFormat::RGBA8, Vector2i{32});
Framebuffer fb{{{}, Vector2i{32}}};
fb.attachRenderbuffer(Framebuffer::ColorAttachment{0}, color)
.bind();
struct MyShader: AbstractShaderProgram {
typedef Attribute<0, Vector2> Position;
explicit MyShader() {
Shader vert(
#ifndef CORRADE_TARGET_APPLE
Version::GL210
#else
Version::GL310
#endif
, Shader::Type::Vertex);
CORRADE_INTERNAL_ASSERT_OUTPUT(vert.addSource(
"#if __VERSION__ >= 130\n"
"#define attribute in\n"
"#endif\n"
"attribute vec4 position;\n"
"void main() {\n"
" gl_Position = position;\n"
"}\n").compile());
attachShader(vert);
bindAttributeLocation(Position::Location, "position");
CORRADE_INTERNAL_ASSERT_OUTPUT(link());
}
} shader;
Buffer vertices;
vertices.setData({nullptr, 9*sizeof(Vector2)}, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setPrimitive(MeshPrimitive::Triangles)
.setCount(9)
.addVertexBuffer(vertices, 0, MyShader::Position());
MAGNUM_VERIFY_NO_ERROR();
PrimitiveQuery q{PrimitiveQuery::Target::PrimitivesGenerated};
q.begin(0);
Renderer::enable(Renderer::Feature::RasterizerDiscard);
mesh.draw(shader);
q.end();
const UnsignedInt count = q.result<UnsignedInt>();
MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(count, 3);
}
#endif
void PrimitiveQueryGLTest::transformFeedbackPrimitivesWritten() {

Loading…
Cancel
Save