From df69909a121d374a5b0fc8a411190206dbe30ace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 9 Jan 2014 00:08:04 +0100 Subject: [PATCH] Fully test query functionality. The test now fails due to wrong result() implementation. --- src/Test/CMakeLists.txt | 13 ++ src/Test/PrimitiveQueryGLTest.cpp | 118 +++++++++++++ src/Test/QueryGLTestFiles/MyShader.frag | 3 + src/Test/QueryGLTestFiles/MyShader.vert | 5 + src/Test/QueryGLTestFiles/resources.conf | 7 + src/Test/SampleQueryGLTest.cpp | 208 +++++++++++++++++++++++ src/Test/TimeQueryGLTest.cpp | 100 +++++++++++ 7 files changed, 454 insertions(+) create mode 100644 src/Test/PrimitiveQueryGLTest.cpp create mode 100644 src/Test/QueryGLTestFiles/MyShader.frag create mode 100644 src/Test/QueryGLTestFiles/MyShader.vert create mode 100644 src/Test/QueryGLTestFiles/resources.conf create mode 100644 src/Test/SampleQueryGLTest.cpp create mode 100644 src/Test/TimeQueryGLTest.cpp diff --git a/src/Test/CMakeLists.txt b/src/Test/CMakeLists.txt index 9ad7c65f9..f3d69c991 100644 --- a/src/Test/CMakeLists.txt +++ b/src/Test/CMakeLists.txt @@ -50,6 +50,7 @@ if(BUILD_GL_TESTS) corrade_add_test(MeshGLTest MeshGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) corrade_add_test(RenderbufferGLTest RenderbufferGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) corrade_add_test(TextureGLTest TextureGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) + corrade_add_test(TimeQueryGLTest TimeQueryGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) corrade_add_resource(AbstractShaderProgramGLTest_RES AbstractShaderProgramGLTestFiles/resources.conf) corrade_add_test(AbstractShaderProgramGLTest @@ -57,6 +58,18 @@ if(BUILD_GL_TESTS) ${AbstractShaderProgramGLTest_RES} LIBRARIES ${GL_TEST_LIBRARIES}) + corrade_add_resource(QueryGLTest_RES QueryGLTestFiles/resources.conf) + if(NOT MAGNUM_TARGET_GLES2) + corrade_add_test(PrimitiveQueryGLTest + PrimitiveQueryGLTest.cpp + ${QueryGLTest_RES} + LIBRARIES ${GL_TEST_LIBRARIES}) + endif() + corrade_add_test(SampleQueryGLTest + SampleQueryGLTest.cpp + ${QueryGLTest_RES} + LIBRARIES ${GL_TEST_LIBRARIES}) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ShaderGLTestConfigure.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/ShaderGLTestConfigure.h) include_directories(${CMAKE_CURRENT_BINARY_DIR}) diff --git a/src/Test/PrimitiveQueryGLTest.cpp b/src/Test/PrimitiveQueryGLTest.cpp new file mode 100644 index 000000000..7e6691454 --- /dev/null +++ b/src/Test/PrimitiveQueryGLTest.cpp @@ -0,0 +1,118 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 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. +*/ + +#include +#include + +#include "AbstractShaderProgram.h" +#include "Buffer.h" +#include "Framebuffer.h" +#include "Mesh.h" +#include "Query.h" +#include "Renderbuffer.h" +#include "RenderbufferFormat.h" +#include "Shader.h" +#include "Test/AbstractOpenGLTester.h" + +namespace Magnum { namespace Test { + +class PrimitiveQueryGLTest: public AbstractOpenGLTester { + public: + explicit PrimitiveQueryGLTest(); + + void query(); +}; + +PrimitiveQueryGLTest::PrimitiveQueryGLTest() { + addTests({&PrimitiveQueryGLTest::query}); +} + +void PrimitiveQueryGLTest::query() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::transform_feedback::string() + std::string(" is not available.")); + #endif + + #ifndef MAGNUM_TARGET_GLES + class MyShader: public AbstractShaderProgram { + public: + typedef Attribute<0, Vector2> Position; + + explicit MyShader() { + Utility::Resource rs("QueryGLTest"); + Shader vert(Version::GL210, Shader::Type::Vertex); + vert.addSource(rs.get("MyShader.vert")); + CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); + attachShader(vert); + + Shader frag(Version::GL210, Shader::Type::Fragment); + frag.addSource(rs.get("MyShader.frag")); + CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); + attachShader(frag); + + CORRADE_INTERNAL_ASSERT_OUTPUT(link()); + } + } shader; + + Renderbuffer renderbuffer; + renderbuffer.setStorage(RenderbufferFormat::RGBA8, Vector2i(32)); + + Framebuffer framebuffer({{}, Vector2i(32)}); + framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), renderbuffer); + + constexpr Vector2 data[9]; + Buffer vertices; + vertices.setData(data, BufferUsage::StaticDraw); + + Mesh mesh; + mesh.setPrimitive(MeshPrimitive::Triangles) + .setVertexCount(9) + .addVertexBuffer(vertices, 0, MyShader::Position()); + + MAGNUM_VERIFY_NO_ERROR(); + + PrimitiveQuery q; + q.begin(PrimitiveQuery::Target::PrimitivesGenerated); + + framebuffer.bind(FramebufferTarget::ReadDraw); + shader.use(); + mesh.draw(); + + q.end(); + const bool availableBefore = q.resultAvailable(); + const UnsignedInt count = q.result(); + const bool availableAfter = q.resultAvailable(); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_VERIFY(!availableBefore); + CORRADE_VERIFY(availableAfter); + CORRADE_COMPARE(count, 3); + #else + CORRADE_SKIP("Not implemented in OpenGL ES 3.0 yet."); + #endif +} + +}} + +CORRADE_TEST_MAIN(Magnum::Test::PrimitiveQueryGLTest) diff --git a/src/Test/QueryGLTestFiles/MyShader.frag b/src/Test/QueryGLTestFiles/MyShader.frag new file mode 100644 index 000000000..18cf87582 --- /dev/null +++ b/src/Test/QueryGLTestFiles/MyShader.frag @@ -0,0 +1,3 @@ +void main() { + gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); +} diff --git a/src/Test/QueryGLTestFiles/MyShader.vert b/src/Test/QueryGLTestFiles/MyShader.vert new file mode 100644 index 000000000..0fd808f4b --- /dev/null +++ b/src/Test/QueryGLTestFiles/MyShader.vert @@ -0,0 +1,5 @@ +attribute lowp vec4 position; + +void main() { + gl_Position = position; +} diff --git a/src/Test/QueryGLTestFiles/resources.conf b/src/Test/QueryGLTestFiles/resources.conf new file mode 100644 index 000000000..daf955dd7 --- /dev/null +++ b/src/Test/QueryGLTestFiles/resources.conf @@ -0,0 +1,7 @@ +group=QueryGLTest + +[file] +filename=MyShader.vert + +[file] +filename=MyShader.frag diff --git a/src/Test/SampleQueryGLTest.cpp b/src/Test/SampleQueryGLTest.cpp new file mode 100644 index 000000000..d66bd6c39 --- /dev/null +++ b/src/Test/SampleQueryGLTest.cpp @@ -0,0 +1,208 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 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. +*/ + +#include +#include + +#include "AbstractShaderProgram.h" +#include "Buffer.h" +#include "Framebuffer.h" +#include "Mesh.h" +#include "Query.h" +#include "Renderbuffer.h" +#include "RenderbufferFormat.h" +#include "Shader.h" +#include "Test/AbstractOpenGLTester.h" + +namespace Magnum { namespace Test { + +class SampleQueryGLTest: public AbstractOpenGLTester { + public: + explicit SampleQueryGLTest(); + + void querySamplesPassed(); + #ifndef MAGNUM_TARGET_GLES + void conditionalRender(); + #endif +}; + +SampleQueryGLTest::SampleQueryGLTest() { + addTests({ + &SampleQueryGLTest::querySamplesPassed, + #ifndef MAGNUM_TARGET_GLES + &SampleQueryGLTest::conditionalRender + #endif + }); +} + +namespace { + struct MyShader: public AbstractShaderProgram { + typedef Attribute<0, Vector2> Position; + + explicit MyShader(); + }; +} + +MyShader::MyShader() { + Utility::Resource rs("QueryGLTest"); + #ifndef MAGNUM_TARGET_GLES + Shader vert(Version::GL210, Shader::Type::Vertex); + #else + Shader vert(Version::GLES200, Shader::Type::Vertex); + #endif + vert.addSource(rs.get("MyShader.vert")); + CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); + attachShader(vert); + + #ifndef MAGNUM_TARGET_GLES + Shader frag(Version::GL210, Shader::Type::Fragment); + #else + Shader frag(Version::GLES200, Shader::Type::Fragment); + #endif + frag.addSource(rs.get("MyShader.frag")); + CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); + attachShader(frag); + + CORRADE_INTERNAL_ASSERT_OUTPUT(link()); +} + +void SampleQueryGLTest::querySamplesPassed() { + #ifdef MAGNUM_TARGET_GLES2 + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::occlusion_query_boolean::string() + std::string(" is not available.")); + #endif + + Renderbuffer renderbuffer; + #ifndef MAGNUM_TARGET_GLES2 + renderbuffer.setStorage(RenderbufferFormat::RGBA8, Vector2i(32)); + #else + renderbuffer.setStorage(RenderbufferFormat::RGBA4, Vector2i(32)); + #endif + + Framebuffer framebuffer({{}, Vector2i(32)}); + framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), renderbuffer); + + Buffer buffer; + constexpr Vector2 triangle[] = {{-1.0f, 1.0f}, {-1.0f, -3.0f}, {3.0f, 1.0f}}; + buffer.setData(triangle, BufferUsage::StaticDraw); + + Mesh mesh; + mesh.setPrimitive(MeshPrimitive::Triangles) + .setVertexCount(3) + .addVertexBuffer(buffer, 0, AbstractShaderProgram::Attribute<0, Vector2>()); + + MyShader shader; + + MAGNUM_VERIFY_NO_ERROR(); + + SampleQuery q; + #ifndef MAGNUM_TARGET_GLES + q.begin(SampleQuery::Target::SamplesPassed); + #else + q.begin(SampleQuery::Target::AnySamplesPassed); + #endif + + framebuffer.bind(FramebufferTarget::ReadDraw); + shader.use(); + mesh.draw(); + + q.end(); + const bool availableBefore = q.resultAvailable(); + const UnsignedInt count = q.result(); + const bool availableAfter = q.resultAvailable(); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_VERIFY(!availableBefore); + CORRADE_VERIFY(availableAfter); + #ifndef MAGNUM_TARGET_GLES + CORRADE_COMPARE(count, 32*32); + #else + CORRADE_VERIFY(count > 0); + #endif +} + +#ifndef MAGNUM_TARGET_GLES +void SampleQueryGLTest::conditionalRender() { + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::NV::conditional_render::string() + std::string(" is not available.")); + + Renderbuffer renderbuffer; + renderbuffer.setStorage(RenderbufferFormat::RGBA8, Vector2i(32)); + + Framebuffer framebuffer({{}, Vector2i(32)}); + framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), renderbuffer); + + Buffer buffer; + constexpr Vector2 triangle[] = {{-1.0f, 1.0f}, {-1.0f, -3.0f}, {3.0f, 1.0f}}; + buffer.setData(triangle, BufferUsage::StaticDraw); + + Mesh mesh; + mesh.setPrimitive(MeshPrimitive::Triangles) + .setVertexCount(3) + .addVertexBuffer(buffer, 0, AbstractShaderProgram::Attribute<0, Vector2>()); + + MyShader shader; + framebuffer.bind(FramebufferTarget::ReadDraw); + shader.use(); + + MAGNUM_VERIFY_NO_ERROR(); + + SampleQuery qYes, qNo, q; + + /* This should generate some samples */ + qYes.begin(SampleQuery::Target::SamplesPassed); + mesh.draw(); + qYes.end(); + + /* Thus this should be rendered */ + qYes.beginConditionalRender(SampleQuery::ConditionalRenderMode::Wait); + q.begin(SampleQuery::Target::SamplesPassed); + mesh.draw(); + q.end(); + qYes.endConditionalRender(); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_VERIFY(qYes.result()); + CORRADE_VERIFY(q.result()); + + /* This shouldn't generate any samples */ + qNo.begin(SampleQuery::Target::SamplesPassed); + qNo.end(); + + /* Thus this should not be rendered */ + qNo.beginConditionalRender(SampleQuery::ConditionalRenderMode::Wait); + q.begin(SampleQuery::Target::SamplesPassed); + mesh.draw(); + q.end(); + qNo.endConditionalRender(); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_VERIFY(!qNo.result()); + CORRADE_VERIFY(!q.result()); +} +#endif + +}} + +CORRADE_TEST_MAIN(Magnum::Test::SampleQueryGLTest) diff --git a/src/Test/TimeQueryGLTest.cpp b/src/Test/TimeQueryGLTest.cpp new file mode 100644 index 000000000..163f94a83 --- /dev/null +++ b/src/Test/TimeQueryGLTest.cpp @@ -0,0 +1,100 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 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. +*/ + +#include "Query.h" +#include "Test/AbstractOpenGLTester.h" + +namespace Magnum { namespace Test { + +class TimeQueryGLTest: public AbstractOpenGLTester { + public: + explicit TimeQueryGLTest(); + + void queryTime(); + void queryTimestamp(); +}; + +TimeQueryGLTest::TimeQueryGLTest() { + addTests({&TimeQueryGLTest::queryTime, + &TimeQueryGLTest::queryTimestamp}); +} + +void TimeQueryGLTest::queryTime() { + #ifndef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::ARB::timer_query::string() + std::string(" is not available")); + #else + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::disjoint_timer_query::string() + std::string(" is not available")); + #endif + + TimeQuery q1; + q1.begin(TimeQuery::Target::TimeElapsed); + q1.end(); + const auto result1 = q1.result(); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_VERIFY(result1 > 0); + + TimeQuery q2; + q2.begin(TimeQuery::Target::TimeElapsed); + Renderer::setFeature(Renderer::Feature::Blending, true); + Renderer::finish(); + q2.end(); + const auto result2 = q2.result(); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_VERIFY(result2 > result1); +} + +void TimeQueryGLTest::queryTimestamp() { + #ifdef MAGNUM_TARGET_GLES + if(!Context::current()->isExtensionSupported()) + CORRADE_SKIP(Extensions::GL::EXT::disjoint_timer_query::string() + std::string(" is not available")); + #endif + + TimeQuery q1, q2, q; + + q1.timestamp(); + + q.begin(TimeQuery::Target::TimeElapsed); + Renderer::setFeature(Renderer::Feature::Blending, true); + Renderer::finish(); + q.end(); + + q2.timestamp(); + + const auto result = q.result(); + const auto result1 = q1.result(); + const auto result2 = q2.result(); + + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_VERIFY(result > 0); + CORRADE_VERIFY(result2 > result1); + CORRADE_VERIFY(result2-result1 > result); +} + +}} + +CORRADE_TEST_MAIN(Magnum::Test::TimeQueryGLTest)