1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Occlusion query stress tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "es3sOcclusionQueryTests.hpp"
25
26 #include "deRandom.hpp"
27 #include "deStringUtil.hpp"
28 #include "deString.h"
29 #include "tcuTestLog.hpp"
30 #include "tcuVector.hpp"
31 #include "tcuSurface.hpp"
32 #include "gluShaderProgram.hpp"
33 #include "deClock.h"
34
35 #include "glw.h"
36
37 #include <vector>
38
39 using std::vector;
40 using tcu::TestLog;
41
42 namespace deqp
43 {
44 namespace gles3
45 {
46 namespace Stress
47 {
48
49 static const tcu::Vec4 OCCLUDER_COLOR = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
50 static const tcu::Vec4 TARGET_COLOR = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
51 static const int NUM_CASE_ITERATIONS = 3;
52 static const int NUM_GENERATED_VERTICES = 100;
53 static const int WATCHDOG_INTERVAL = 50; // Touch watchdog every N iterations.
54
55 class OcclusionQueryStressCase : public TestCase
56 {
57 public:
58 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);
59 ~OcclusionQueryStressCase (void);
60
61 void init (void);
62 void deinit (void);
63 IterateResult iterate (void);
64
65 private:
66 OcclusionQueryStressCase (const OcclusionQueryStressCase&);
67 OcclusionQueryStressCase& operator= (const OcclusionQueryStressCase&);
68
69 int m_numOccluderDraws;
70 int m_numOccludersPerDraw;
71 int m_numTargetDraws;
72 int m_numTargetsPerDraw;
73 int m_numQueries;
74 deUint32 m_queryMode;
75
76 glu::RenderContext& m_renderCtx;
77 glu::ShaderProgram* m_program;
78 int m_iterNdx;
79 de::Random m_rnd;
80
81 };
82
OcclusionQueryStressCase(Context & ctx,const char * name,const char * desc,int numOccluderDraws,int numOccludersPerDraw,int numTargetDraws,int numTargetsPerDraw,int numQueries,deUint32 queryMode)83 OcclusionQueryStressCase::OcclusionQueryStressCase (Context& ctx, const char* name, const char* desc, int numOccluderDraws, int numOccludersPerDraw, int numTargetDraws, int numTargetsPerDraw, int numQueries, deUint32 queryMode)
84 : TestCase (ctx, name, desc)
85 , m_numOccluderDraws (numOccluderDraws)
86 , m_numOccludersPerDraw (numOccludersPerDraw)
87 , m_numTargetDraws (numTargetDraws)
88 , m_numTargetsPerDraw (numTargetsPerDraw)
89 , m_numQueries (numQueries)
90 , m_queryMode (queryMode)
91 , m_renderCtx (ctx.getRenderContext())
92 , m_program (DE_NULL)
93 , m_iterNdx (0)
94 , m_rnd (deStringHash(name))
95 {
96 }
97
~OcclusionQueryStressCase(void)98 OcclusionQueryStressCase::~OcclusionQueryStressCase (void)
99 {
100 OcclusionQueryStressCase::deinit();
101 }
102
init(void)103 void OcclusionQueryStressCase::init (void)
104 {
105 const char* vertShaderSource =
106 "#version 300 es\n"
107 "layout(location = 0) in mediump vec4 a_position;\n"
108 "\n"
109 "void main (void)\n"
110 "{\n"
111 " gl_Position = a_position;\n"
112 "}\n";
113
114 const char* fragShaderSource =
115 "#version 300 es\n"
116 "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
117 "uniform mediump vec4 u_color;\n"
118 "\n"
119 "void main (void)\n"
120 "{\n"
121 " mediump float depth_gradient = gl_FragCoord.z;\n"
122 " mediump float bias = 0.1;\n"
123 " dEQP_FragColor = vec4(u_color.xyz * (depth_gradient + bias), 1.0);\n"
124 "}\n";
125
126 DE_ASSERT(!m_program);
127 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertShaderSource, fragShaderSource));
128
129 if (!m_program->isOk())
130 {
131 m_testCtx.getLog() << *m_program;
132 TCU_FAIL("Failed to compile shader program");
133 }
134
135 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); // Initialize test result to pass.
136 GLU_CHECK_MSG ("Case initialization finished");
137 }
138
deinit(void)139 void OcclusionQueryStressCase::deinit (void)
140 {
141 delete m_program;
142 m_program = DE_NULL;
143 }
144
145
iterate(void)146 OcclusionQueryStressCase::IterateResult OcclusionQueryStressCase::iterate (void)
147 {
148 tcu::TestLog& log = m_testCtx.getLog();
149 deUint32 colorUnif = glGetUniformLocation(m_program->getProgram(), "u_color");
150
151 std::vector<float> vertices;
152 std::vector<float> occluderVertices;
153 std::vector<float> targetVertices;
154 std::vector<deUint32> queryIds (m_numQueries, 0);
155 std::vector<deUint32> queryResultReady (m_numQueries, 0);
156 std::vector<deUint32> queryResult (m_numQueries, 0);
157
158 std::string sectionName ("Case iteration " + de::toString(m_iterNdx+1) + "/" + de::toString(NUM_CASE_ITERATIONS));
159 tcu::ScopedLogSection section (log, sectionName.c_str(), sectionName.c_str());
160
161 log << tcu::TestLog::Message << "Parameters:\n"
162 << "- Number of occlusion queries: " << m_numQueries << ".\n"
163 << "- Number of occluder draws per query: " << m_numOccluderDraws << ", primitives per draw: " << m_numOccludersPerDraw << ".\n"
164 << "- Number of target draws per query: " << m_numTargetDraws << ", primitives per draw: " << m_numTargetsPerDraw << ".\n"
165 << tcu::TestLog::EndMessage;
166
167 int numOccluderIndicesPerDraw = 3*m_numOccludersPerDraw;
168 int numTargetIndicesPerDraw = 3*m_numTargetsPerDraw;
169
170 // Generate vertex data
171
172 vertices.resize(4*NUM_GENERATED_VERTICES);
173
174 for (int i = 0; i < NUM_GENERATED_VERTICES; i++)
175 {
176 vertices[4*i ] = m_rnd.getFloat(-1.0f, 1.0f);
177 vertices[4*i + 1] = m_rnd.getFloat(-1.0f, 1.0f);
178 vertices[4*i + 2] = m_rnd.getFloat(0.0f, 1.0f);
179 vertices[4*i + 3] = 1.0f;
180 }
181
182 // Generate primitives
183
184 occluderVertices.resize(4*numOccluderIndicesPerDraw * m_numOccluderDraws);
185
186 for (int i = 0; i < numOccluderIndicesPerDraw * m_numOccluderDraws; i++)
187 {
188 int vtxNdx = m_rnd.getInt(0, NUM_GENERATED_VERTICES-1);
189 occluderVertices[4*i ] = vertices[4*vtxNdx];
190 occluderVertices[4*i + 1] = vertices[4*vtxNdx + 1];
191 occluderVertices[4*i + 2] = vertices[4*vtxNdx + 2];
192 occluderVertices[4*i + 3] = vertices[4*vtxNdx + 3];
193 }
194
195 targetVertices.resize(4*numTargetIndicesPerDraw * m_numTargetDraws);
196
197 for (int i = 0; i < numTargetIndicesPerDraw * m_numTargetDraws; i++)
198 {
199 int vtxNdx = m_rnd.getInt(0, NUM_GENERATED_VERTICES-1);
200 targetVertices[4*i ] = vertices[4*vtxNdx];
201 targetVertices[4*i + 1] = vertices[4*vtxNdx + 1];
202 targetVertices[4*i + 2] = vertices[4*vtxNdx + 2];
203 targetVertices[4*i + 3] = vertices[4*vtxNdx + 3];
204 }
205
206 TCU_CHECK(m_program);
207
208 glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
209 glClearDepthf (1.0f);
210 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
211 glEnable (GL_DEPTH_TEST);
212 glUseProgram (m_program->getProgram());
213 glEnableVertexAttribArray (0);
214
215 deUint64 time = deGetMicroseconds();
216
217 for (int queryIter = 0; queryIter < m_numQueries; queryIter++)
218 {
219 // Draw occluders
220
221 glUniform4f (colorUnif, OCCLUDER_COLOR.x(), OCCLUDER_COLOR.y(), OCCLUDER_COLOR.z(), OCCLUDER_COLOR.w());
222
223 for (int drawIter = 0; drawIter < m_numOccluderDraws; drawIter++)
224 {
225 glVertexAttribPointer (0, 4, GL_FLOAT, GL_FALSE, 0, &occluderVertices[drawIter * numOccluderIndicesPerDraw]);
226 glDrawArrays (GL_TRIANGLES, 0, numOccluderIndicesPerDraw);
227 }
228
229 // Begin occlusion query
230
231 glGenQueries (1, &queryIds[queryIter]);
232 glBeginQuery (m_queryMode, queryIds[queryIter]);
233
234 // Draw targets
235
236 glUniform4f (colorUnif, TARGET_COLOR.x(), TARGET_COLOR.y(), TARGET_COLOR.z(), TARGET_COLOR.w());
237
238 for (int drawIter = 0; drawIter < m_numTargetDraws; drawIter++)
239 {
240 glVertexAttribPointer (0, 4, GL_FLOAT, GL_FALSE, 0, &targetVertices[drawIter * numTargetIndicesPerDraw]);
241 glDrawArrays (GL_TRIANGLES, 0, numTargetIndicesPerDraw);
242 }
243
244 // End occlusion query
245
246 glEndQuery (m_queryMode);
247
248 if ((queryIter % WATCHDOG_INTERVAL) == 0 && m_testCtx.getWatchDog())
249 qpWatchDog_touch(m_testCtx.getWatchDog());
250 }
251
252 glFinish();
253 glDisable(GL_DEPTH_TEST);
254
255 deUint64 dTime = deGetMicroseconds() - time;
256 log << tcu::TestLog::Message << "Total duration: " << dTime/1000 << " ms" << tcu::TestLog::EndMessage;
257
258 // Get results
259
260 for (int queryIter = 0; queryIter < m_numQueries; queryIter++)
261 {
262 glGetQueryObjectuiv(queryIds[queryIter], GL_QUERY_RESULT_AVAILABLE, &queryResultReady[queryIter]);
263
264 if (queryResultReady[queryIter] == GL_TRUE)
265 {
266 glGetQueryObjectuiv(queryIds[queryIter], GL_QUERY_RESULT, &queryResult[queryIter]);
267 }
268 else
269 TCU_FAIL("Occlusion query failed to return a result after glFinish()");
270
271 if ((queryIter % WATCHDOG_INTERVAL) == 0 && m_testCtx.getWatchDog())
272 qpWatchDog_touch(m_testCtx.getWatchDog());
273 }
274
275 glDeleteQueries (m_numQueries, &queryIds[0]);
276 GLU_CHECK_MSG ("Occlusion queries finished");
277
278 log << tcu::TestLog::Message << "Case passed!" << tcu::TestLog::EndMessage;
279
280 return (++m_iterNdx < NUM_CASE_ITERATIONS) ? CONTINUE : STOP;
281 }
282
283
OcclusionQueryTests(Context & testCtx)284 OcclusionQueryTests::OcclusionQueryTests (Context& testCtx)
285 : TestCaseGroup(testCtx, "occlusion_query", "Occlusion query stress tests")
286 {
287 }
288
~OcclusionQueryTests(void)289 OcclusionQueryTests::~OcclusionQueryTests(void)
290 {
291 }
292
init(void)293 void OcclusionQueryTests::init (void)
294 {
295 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));
296 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));
297 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));
298 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));
299 }
300
301 } // Stress
302 } // gles3
303 } // deqp
304