| /*------------------------------------------------------------------------- |
| * drawElements Quality Program OpenGL ES 3.0 Module |
| * ------------------------------------------------- |
| * |
| * Copyright 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Occlusion query stress tests |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "es3sOcclusionQueryTests.hpp" |
| |
| #include "deRandom.hpp" |
| #include "deStringUtil.hpp" |
| #include "deString.h" |
| #include "tcuTestLog.hpp" |
| #include "tcuVector.hpp" |
| #include "tcuSurface.hpp" |
| #include "gluShaderProgram.hpp" |
| #include "deClock.h" |
| |
| #include "glw.h" |
| |
| #include <vector> |
| |
| using std::vector; |
| using tcu::TestLog; |
| |
| namespace deqp |
| { |
| namespace gles3 |
| { |
| namespace Stress |
| { |
| |
| static const tcu::Vec4 OCCLUDER_COLOR = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f); |
| static const tcu::Vec4 TARGET_COLOR = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f); |
| static const int NUM_CASE_ITERATIONS = 3; |
| static const int NUM_GENERATED_VERTICES = 100; |
| static const int WATCHDOG_INTERVAL = 50; // Touch watchdog every N iterations. |
| |
| class OcclusionQueryStressCase : public TestCase |
| { |
| public: |
| OcclusionQueryStressCase (Context& ctx, const char* name, const char* desc, int m_numOccluderDraws, int m_numOccludersPerDraw, int m_numTargetDraws, int m_numTargetsPerDraw, int m_numQueries, deUint32 m_queryMode); |
| ~OcclusionQueryStressCase (void); |
| |
| void init (void); |
| void deinit (void); |
| IterateResult iterate (void); |
| |
| private: |
| OcclusionQueryStressCase (const OcclusionQueryStressCase&); |
| OcclusionQueryStressCase& operator= (const OcclusionQueryStressCase&); |
| |
| int m_numOccluderDraws; |
| int m_numOccludersPerDraw; |
| int m_numTargetDraws; |
| int m_numTargetsPerDraw; |
| int m_numQueries; |
| deUint32 m_queryMode; |
| |
| glu::RenderContext& m_renderCtx; |
| glu::ShaderProgram* m_program; |
| int m_iterNdx; |
| de::Random m_rnd; |
| |
| }; |
| |
| OcclusionQueryStressCase::OcclusionQueryStressCase (Context& ctx, const char* name, const char* desc, int numOccluderDraws, int numOccludersPerDraw, int numTargetDraws, int numTargetsPerDraw, int numQueries, deUint32 queryMode) |
| : TestCase (ctx, name, desc) |
| , m_numOccluderDraws (numOccluderDraws) |
| , m_numOccludersPerDraw (numOccludersPerDraw) |
| , m_numTargetDraws (numTargetDraws) |
| , m_numTargetsPerDraw (numTargetsPerDraw) |
| , m_numQueries (numQueries) |
| , m_queryMode (queryMode) |
| , m_renderCtx (ctx.getRenderContext()) |
| , m_program (DE_NULL) |
| , m_iterNdx (0) |
| , m_rnd (deStringHash(name)) |
| { |
| } |
| |
| OcclusionQueryStressCase::~OcclusionQueryStressCase (void) |
| { |
| OcclusionQueryStressCase::deinit(); |
| } |
| |
| void OcclusionQueryStressCase::init (void) |
| { |
| const char* vertShaderSource = |
| "#version 300 es\n" |
| "layout(location = 0) in mediump vec4 a_position;\n" |
| "\n" |
| "void main (void)\n" |
| "{\n" |
| " gl_Position = a_position;\n" |
| "}\n"; |
| |
| const char* fragShaderSource = |
| "#version 300 es\n" |
| "layout(location = 0) out mediump vec4 dEQP_FragColor;\n" |
| "uniform mediump vec4 u_color;\n" |
| "\n" |
| "void main (void)\n" |
| "{\n" |
| " mediump float depth_gradient = gl_FragCoord.z;\n" |
| " mediump float bias = 0.1;\n" |
| " dEQP_FragColor = vec4(u_color.xyz * (depth_gradient + bias), 1.0);\n" |
| "}\n"; |
| |
| DE_ASSERT(!m_program); |
| m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertShaderSource, fragShaderSource)); |
| |
| if (!m_program->isOk()) |
| { |
| m_testCtx.getLog() << *m_program; |
| TCU_FAIL("Failed to compile shader program"); |
| } |
| |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); // Initialize test result to pass. |
| GLU_CHECK_MSG ("Case initialization finished"); |
| } |
| |
| void OcclusionQueryStressCase::deinit (void) |
| { |
| delete m_program; |
| m_program = DE_NULL; |
| } |
| |
| |
| OcclusionQueryStressCase::IterateResult OcclusionQueryStressCase::iterate (void) |
| { |
| tcu::TestLog& log = m_testCtx.getLog(); |
| deUint32 colorUnif = glGetUniformLocation(m_program->getProgram(), "u_color"); |
| |
| std::vector<float> vertices; |
| std::vector<float> occluderVertices; |
| std::vector<float> targetVertices; |
| std::vector<deUint32> queryIds (m_numQueries, 0); |
| std::vector<deUint32> queryResultReady (m_numQueries, 0); |
| std::vector<deUint32> queryResult (m_numQueries, 0); |
| |
| std::string sectionName ("Case iteration " + de::toString(m_iterNdx+1) + "/" + de::toString(NUM_CASE_ITERATIONS)); |
| tcu::ScopedLogSection section (log, sectionName.c_str(), sectionName.c_str()); |
| |
| log << tcu::TestLog::Message << "Parameters:\n" |
| << "- Number of occlusion queries: " << m_numQueries << ".\n" |
| << "- Number of occluder draws per query: " << m_numOccluderDraws << ", primitives per draw: " << m_numOccludersPerDraw << ".\n" |
| << "- Number of target draws per query: " << m_numTargetDraws << ", primitives per draw: " << m_numTargetsPerDraw << ".\n" |
| << tcu::TestLog::EndMessage; |
| |
| int numOccluderIndicesPerDraw = 3*m_numOccludersPerDraw; |
| int numTargetIndicesPerDraw = 3*m_numTargetsPerDraw; |
| |
| // Generate vertex data |
| |
| vertices.resize(4*NUM_GENERATED_VERTICES); |
| |
| for (int i = 0; i < NUM_GENERATED_VERTICES; i++) |
| { |
| vertices[4*i ] = m_rnd.getFloat(-1.0f, 1.0f); |
| vertices[4*i + 1] = m_rnd.getFloat(-1.0f, 1.0f); |
| vertices[4*i + 2] = m_rnd.getFloat(0.0f, 1.0f); |
| vertices[4*i + 3] = 1.0f; |
| } |
| |
| // Generate primitives |
| |
| occluderVertices.resize(4*numOccluderIndicesPerDraw * m_numOccluderDraws); |
| |
| for (int i = 0; i < numOccluderIndicesPerDraw * m_numOccluderDraws; i++) |
| { |
| int vtxNdx = m_rnd.getInt(0, NUM_GENERATED_VERTICES-1); |
| occluderVertices[4*i ] = vertices[4*vtxNdx]; |
| occluderVertices[4*i + 1] = vertices[4*vtxNdx + 1]; |
| occluderVertices[4*i + 2] = vertices[4*vtxNdx + 2]; |
| occluderVertices[4*i + 3] = vertices[4*vtxNdx + 3]; |
| } |
| |
| targetVertices.resize(4*numTargetIndicesPerDraw * m_numTargetDraws); |
| |
| for (int i = 0; i < numTargetIndicesPerDraw * m_numTargetDraws; i++) |
| { |
| int vtxNdx = m_rnd.getInt(0, NUM_GENERATED_VERTICES-1); |
| targetVertices[4*i ] = vertices[4*vtxNdx]; |
| targetVertices[4*i + 1] = vertices[4*vtxNdx + 1]; |
| targetVertices[4*i + 2] = vertices[4*vtxNdx + 2]; |
| targetVertices[4*i + 3] = vertices[4*vtxNdx + 3]; |
| } |
| |
| TCU_CHECK(m_program); |
| |
| glClearColor (0.0f, 0.0f, 0.0f, 1.0f); |
| glClearDepthf (1.0f); |
| glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
| glEnable (GL_DEPTH_TEST); |
| glUseProgram (m_program->getProgram()); |
| glEnableVertexAttribArray (0); |
| |
| deUint64 time = deGetMicroseconds(); |
| |
| for (int queryIter = 0; queryIter < m_numQueries; queryIter++) |
| { |
| // Draw occluders |
| |
| glUniform4f (colorUnif, OCCLUDER_COLOR.x(), OCCLUDER_COLOR.y(), OCCLUDER_COLOR.z(), OCCLUDER_COLOR.w()); |
| |
| for (int drawIter = 0; drawIter < m_numOccluderDraws; drawIter++) |
| { |
| glVertexAttribPointer (0, 4, GL_FLOAT, GL_FALSE, 0, &occluderVertices[drawIter * numOccluderIndicesPerDraw]); |
| glDrawArrays (GL_TRIANGLES, 0, numOccluderIndicesPerDraw); |
| } |
| |
| // Begin occlusion query |
| |
| glGenQueries (1, &queryIds[queryIter]); |
| glBeginQuery (m_queryMode, queryIds[queryIter]); |
| |
| // Draw targets |
| |
| glUniform4f (colorUnif, TARGET_COLOR.x(), TARGET_COLOR.y(), TARGET_COLOR.z(), TARGET_COLOR.w()); |
| |
| for (int drawIter = 0; drawIter < m_numTargetDraws; drawIter++) |
| { |
| glVertexAttribPointer (0, 4, GL_FLOAT, GL_FALSE, 0, &targetVertices[drawIter * numTargetIndicesPerDraw]); |
| glDrawArrays (GL_TRIANGLES, 0, numTargetIndicesPerDraw); |
| } |
| |
| // End occlusion query |
| |
| glEndQuery (m_queryMode); |
| |
| if ((queryIter % WATCHDOG_INTERVAL) == 0 && m_testCtx.getWatchDog()) |
| qpWatchDog_touch(m_testCtx.getWatchDog()); |
| } |
| |
| glFinish(); |
| glDisable(GL_DEPTH_TEST); |
| |
| deUint64 dTime = deGetMicroseconds() - time; |
| log << tcu::TestLog::Message << "Total duration: " << dTime/1000 << " ms" << tcu::TestLog::EndMessage; |
| |
| // Get results |
| |
| for (int queryIter = 0; queryIter < m_numQueries; queryIter++) |
| { |
| glGetQueryObjectuiv(queryIds[queryIter], GL_QUERY_RESULT_AVAILABLE, &queryResultReady[queryIter]); |
| |
| if (queryResultReady[queryIter] == GL_TRUE) |
| { |
| glGetQueryObjectuiv(queryIds[queryIter], GL_QUERY_RESULT, &queryResult[queryIter]); |
| } |
| else |
| TCU_FAIL("Occlusion query failed to return a result after glFinish()"); |
| |
| if ((queryIter % WATCHDOG_INTERVAL) == 0 && m_testCtx.getWatchDog()) |
| qpWatchDog_touch(m_testCtx.getWatchDog()); |
| } |
| |
| glDeleteQueries (m_numQueries, &queryIds[0]); |
| GLU_CHECK_MSG ("Occlusion queries finished"); |
| |
| log << tcu::TestLog::Message << "Case passed!" << tcu::TestLog::EndMessage; |
| |
| return (++m_iterNdx < NUM_CASE_ITERATIONS) ? CONTINUE : STOP; |
| } |
| |
| |
| OcclusionQueryTests::OcclusionQueryTests (Context& testCtx) |
| : TestCaseGroup(testCtx, "occlusion_query", "Occlusion query stress tests") |
| { |
| } |
| |
| OcclusionQueryTests::~OcclusionQueryTests(void) |
| { |
| } |
| |
| void OcclusionQueryTests::init (void) |
| { |
| addChild(new OcclusionQueryStressCase(m_context, "10_queries_2500_triangles_per_query", "10_queries_2500_triangles_per_query", 49, 50, 1, 50, 10, GL_ANY_SAMPLES_PASSED)); |
| addChild(new OcclusionQueryStressCase(m_context, "100_queries_2500_triangles_per_query", "100_queries_2500_triangles_per_query", 49, 50, 1, 50, 100, GL_ANY_SAMPLES_PASSED)); |
| addChild(new OcclusionQueryStressCase(m_context, "1000_queries_500_triangles_per_query", "1000_queries_500_triangles_per_query", 49, 10, 1, 10, 1000, GL_ANY_SAMPLES_PASSED)); |
| addChild(new OcclusionQueryStressCase(m_context, "10000_queries_20_triangles_per_query", "10000_queries_20_triangles_per_query", 1, 19, 1, 1, 10000, GL_ANY_SAMPLES_PASSED)); |
| } |
| |
| } // Stress |
| } // gles3 |
| } // deqp |