From 9642869c59d736382d7868da1fb0c2f3d4af56af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 9 Oct 2016 19:58:51 +0200 Subject: [PATCH] Implemented ARB_transform_feedback_overflow_query. --- doc/opengl-support.dox | 2 +- src/Magnum/PrimitiveQuery.h | 26 ++++++- src/Magnum/Test/PrimitiveQueryGLTest.cpp | 94 +++++++++++++++++++++++- 3 files changed, 118 insertions(+), 4 deletions(-) diff --git a/doc/opengl-support.dox b/doc/opengl-support.dox index c4a3ff25f1..9216190c89 100644 --- a/doc/opengl-support.dox +++ b/doc/opengl-support.dox @@ -244,7 +244,7 @@ Extension | Status @extension{ARB,sparse_texture} | | @extension{ARB,pipeline_statistics_query} | | @extension{ARB,sparse_buffer} | | -@extension{ARB,transform_feedback_overflow_query} | | +@extension{ARB,transform_feedback_overflow_query} | done @extension{KHR,blend_equation_advanced} | done @extension3{KHR,blend_equation_advanced_coherent,blend_equation_advanced} | done @extension{KHR,no_error} | done diff --git a/src/Magnum/PrimitiveQuery.h b/src/Magnum/PrimitiveQuery.h index bb6c7bc4f6..37e75553ea 100644 --- a/src/Magnum/PrimitiveQuery.h +++ b/src/Magnum/PrimitiveQuery.h @@ -63,7 +63,6 @@ UnsignedInt primitiveCount = q.result(); @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 @extension{ARB,transform_feedback_overflow_query} */ class MAGNUM_EXPORT PrimitiveQuery: public AbstractQuery { public: @@ -95,7 +94,30 @@ class MAGNUM_EXPORT PrimitiveQuery: public AbstractQuery { * @ref result() or @ref result() to retrieve the * result. */ - TransformFeedbackPrimitivesWritten = GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN + TransformFeedbackPrimitivesWritten = GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, + + #ifndef MAGNUM_TARGET_GLES + /** + * Transform feedback overflow. When used with @ref begin(UnsignedInt), + * the index must be `0`. Use @ref result() to retrieve the + * result. + * @requires_extension Extension @extension{ARB,transform_feedback_overflow_query} + * @requires_gl Transform feedback overflow query is not available + * in OpenGL ES or WebGL. + */ + TransformFeedbackOverflow = GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB, + + /** + * Transform feedback stream overflow. When used with + * @ref begin(UnsignedInt), the index must be lower than + * @ref TransformFeedback::maxVertexStreams(). Use @ref result() + * to retrieve the result. + * @requires_extension Extension @extension{ARB,transform_feedback_overflow_query} + * @requires_gl Transform feedback overflow query is not available + * in OpenGL ES or WebGL. + */ + TransformFeedbackStreamOverflow = GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB + #endif }; /** diff --git a/src/Magnum/Test/PrimitiveQueryGLTest.cpp b/src/Magnum/Test/PrimitiveQueryGLTest.cpp index 0e3320716e..4a7074643f 100644 --- a/src/Magnum/Test/PrimitiveQueryGLTest.cpp +++ b/src/Magnum/Test/PrimitiveQueryGLTest.cpp @@ -51,6 +51,9 @@ struct PrimitiveQueryGLTest: AbstractOpenGLTester { void primitivesGeneratedIndexed(); #endif void transformFeedbackPrimitivesWritten(); + #ifndef MAGNUM_TARGET_GLES + void transformFeedbackOverflow(); + #endif }; PrimitiveQueryGLTest::PrimitiveQueryGLTest() { @@ -61,7 +64,11 @@ PrimitiveQueryGLTest::PrimitiveQueryGLTest() { &PrimitiveQueryGLTest::primitivesGenerated, &PrimitiveQueryGLTest::primitivesGeneratedIndexed, #endif - &PrimitiveQueryGLTest::transformFeedbackPrimitivesWritten}); + &PrimitiveQueryGLTest::transformFeedbackPrimitivesWritten, + #ifndef MAGNUM_TARGET_GLES + &PrimitiveQueryGLTest::transformFeedbackOverflow + #endif + }); } void PrimitiveQueryGLTest::constructNoCreate() { @@ -301,6 +308,91 @@ void PrimitiveQueryGLTest::transformFeedbackPrimitivesWritten() { CORRADE_COMPARE(count, 3); /* Three triangles (9 vertices) */ } +#ifndef MAGNUM_TARGET_GLES +void PrimitiveQueryGLTest::transformFeedbackOverflow() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current().isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::transform_feedback_overflow_query::string() + std::string(" is not available.")); + #endif + + /* 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 { + explicit MyShader() { + #ifndef MAGNUM_TARGET_GLES + Shader vert( + #ifndef CORRADE_TARGET_APPLE + Version::GL300 + #else + Version::GL310 + #endif + , Shader::Type::Vertex); + #else + Shader vert(Version::GLES300, Shader::Type::Vertex); + Shader frag(Version::GLES300, Shader::Type::Fragment); + #endif + + CORRADE_INTERNAL_ASSERT_OUTPUT(vert.addSource( + "out mediump vec2 outputData;\n" + "void main() {\n" + " outputData = vec2(1.0, -1.0);\n" + /* Mesa drivers complain that vertex shader doesn't write to + gl_Position otherwise */ + " gl_Position = vec4(1.0);\n" + "}\n").compile()); + #ifndef MAGNUM_TARGET_GLES + attachShader(vert); + #else + /* ES for some reason needs both vertex and fragment shader */ + CORRADE_INTERNAL_ASSERT_OUTPUT(frag.addSource("void main() {}\n").compile()); + attachShaders({vert, frag}); + #endif + + setTransformFeedbackOutputs({"outputData"}, TransformFeedbackBufferMode::SeparateAttributes); + CORRADE_INTERNAL_ASSERT_OUTPUT(link()); + } + } shader; + + Buffer output; + output.setData({nullptr, 18*sizeof(Vector2)}, BufferUsage::StaticDraw); + + Mesh mesh; + mesh.setPrimitive(MeshPrimitive::Triangles) + .setCount(9); + + MAGNUM_VERIFY_NO_ERROR(); + + TransformFeedback feedback; + /* Deliberately one vertex smaller to not fit two of them */ + feedback.attachBuffer(0, output, 0, 17*sizeof(Vector2)); + + Renderer::enable(Renderer::Feature::RasterizerDiscard); + + feedback.begin(shader, TransformFeedback::PrimitiveMode::Triangles); + PrimitiveQuery q1{PrimitiveQuery::Target::TransformFeedbackOverflow}, + q2{PrimitiveQuery::Target::TransformFeedbackOverflow}; + q1.begin(); + mesh.draw(shader); + q1.end(); + q2.begin(); + mesh.draw(shader); + q2.end(); + feedback.end(); + + const bool overflown1 = q1.result(); + const bool overflown2 = q2.result(); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_VERIFY(!overflown1); + CORRADE_VERIFY(overflown2); /* Got space for only 17 vertices instead of 2*9 */ +} +#endif + }} MAGNUM_GL_TEST_MAIN(Magnum::Test::PrimitiveQueryGLTest)