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,
59 int m_numOccludersPerDraw, int m_numTargetDraws, int m_numTargetsPerDraw, int m_numQueries,
60 uint32_t m_queryMode);
61 ~OcclusionQueryStressCase(void);
62
63 void init(void);
64 void deinit(void);
65 IterateResult iterate(void);
66
67 private:
68 OcclusionQueryStressCase(const OcclusionQueryStressCase &);
69 OcclusionQueryStressCase &operator=(const OcclusionQueryStressCase &);
70
71 int m_numOccluderDraws;
72 int m_numOccludersPerDraw;
73 int m_numTargetDraws;
74 int m_numTargetsPerDraw;
75 int m_numQueries;
76 uint32_t m_queryMode;
77
78 glu::RenderContext &m_renderCtx;
79 glu::ShaderProgram *m_program;
80 int m_iterNdx;
81 de::Random m_rnd;
82 };
83
OcclusionQueryStressCase(Context & ctx,const char * name,const char * desc,int numOccluderDraws,int numOccludersPerDraw,int numTargetDraws,int numTargetsPerDraw,int numQueries,uint32_t queryMode)84 OcclusionQueryStressCase::OcclusionQueryStressCase(Context &ctx, const char *name, const char *desc,
85 int numOccluderDraws, int numOccludersPerDraw, int numTargetDraws,
86 int numTargetsPerDraw, int numQueries, uint32_t queryMode)
87 : TestCase(ctx, name, desc)
88 , m_numOccluderDraws(numOccluderDraws)
89 , m_numOccludersPerDraw(numOccludersPerDraw)
90 , m_numTargetDraws(numTargetDraws)
91 , m_numTargetsPerDraw(numTargetsPerDraw)
92 , m_numQueries(numQueries)
93 , m_queryMode(queryMode)
94 , m_renderCtx(ctx.getRenderContext())
95 , m_program(DE_NULL)
96 , m_iterNdx(0)
97 , m_rnd(deStringHash(name))
98 {
99 }
100
~OcclusionQueryStressCase(void)101 OcclusionQueryStressCase::~OcclusionQueryStressCase(void)
102 {
103 OcclusionQueryStressCase::deinit();
104 }
105
init(void)106 void OcclusionQueryStressCase::init(void)
107 {
108 const char *vertShaderSource = "#version 300 es\n"
109 "layout(location = 0) in mediump vec4 a_position;\n"
110 "\n"
111 "void main (void)\n"
112 "{\n"
113 " gl_Position = a_position;\n"
114 "}\n";
115
116 const char *fragShaderSource = "#version 300 es\n"
117 "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
118 "uniform mediump vec4 u_color;\n"
119 "\n"
120 "void main (void)\n"
121 "{\n"
122 " mediump float depth_gradient = gl_FragCoord.z;\n"
123 " mediump float bias = 0.1;\n"
124 " dEQP_FragColor = vec4(u_color.xyz * (depth_gradient + bias), 1.0);\n"
125 "}\n";
126
127 DE_ASSERT(!m_program);
128 m_program = new glu::ShaderProgram(m_context.getRenderContext(),
129 glu::makeVtxFragSources(vertShaderSource, fragShaderSource));
130
131 if (!m_program->isOk())
132 {
133 m_testCtx.getLog() << *m_program;
134 TCU_FAIL("Failed to compile shader program");
135 }
136
137 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); // Initialize test result to pass.
138 GLU_CHECK_MSG("Case initialization finished");
139 }
140
deinit(void)141 void OcclusionQueryStressCase::deinit(void)
142 {
143 delete m_program;
144 m_program = DE_NULL;
145 }
146
iterate(void)147 OcclusionQueryStressCase::IterateResult OcclusionQueryStressCase::iterate(void)
148 {
149 tcu::TestLog &log = m_testCtx.getLog();
150 uint32_t colorUnif = glGetUniformLocation(m_program->getProgram(), "u_color");
151
152 std::vector<float> vertices;
153 std::vector<float> occluderVertices;
154 std::vector<float> targetVertices;
155 std::vector<uint32_t> queryIds(m_numQueries, 0);
156 std::vector<uint32_t> queryResultReady(m_numQueries, 0);
157 std::vector<uint32_t> queryResult(m_numQueries, 0);
158
159 std::string sectionName("Case iteration " + de::toString(m_iterNdx + 1) + "/" + de::toString(NUM_CASE_ITERATIONS));
160 tcu::ScopedLogSection section(log, sectionName.c_str(), sectionName.c_str());
161
162 log << tcu::TestLog::Message << "Parameters:\n"
163 << "- Number of occlusion queries: " << m_numQueries << ".\n"
164 << "- Number of occluder draws per query: " << m_numOccluderDraws
165 << ", primitives per draw: " << m_numOccludersPerDraw << ".\n"
166 << "- Number of target draws per query: " << m_numTargetDraws
167 << ", primitives per draw: " << m_numTargetsPerDraw << ".\n"
168 << tcu::TestLog::EndMessage;
169
170 int numOccluderIndicesPerDraw = 3 * m_numOccludersPerDraw;
171 int numTargetIndicesPerDraw = 3 * m_numTargetsPerDraw;
172
173 // Generate vertex data
174
175 vertices.resize(4 * NUM_GENERATED_VERTICES);
176
177 for (int i = 0; i < NUM_GENERATED_VERTICES; i++)
178 {
179 vertices[4 * i] = m_rnd.getFloat(-1.0f, 1.0f);
180 vertices[4 * i + 1] = m_rnd.getFloat(-1.0f, 1.0f);
181 vertices[4 * i + 2] = m_rnd.getFloat(0.0f, 1.0f);
182 vertices[4 * i + 3] = 1.0f;
183 }
184
185 // Generate primitives
186
187 occluderVertices.resize(4 * numOccluderIndicesPerDraw * m_numOccluderDraws);
188
189 for (int i = 0; i < numOccluderIndicesPerDraw * m_numOccluderDraws; i++)
190 {
191 int vtxNdx = m_rnd.getInt(0, NUM_GENERATED_VERTICES - 1);
192 occluderVertices[4 * i] = vertices[4 * vtxNdx];
193 occluderVertices[4 * i + 1] = vertices[4 * vtxNdx + 1];
194 occluderVertices[4 * i + 2] = vertices[4 * vtxNdx + 2];
195 occluderVertices[4 * i + 3] = vertices[4 * vtxNdx + 3];
196 }
197
198 targetVertices.resize(4 * numTargetIndicesPerDraw * m_numTargetDraws);
199
200 for (int i = 0; i < numTargetIndicesPerDraw * m_numTargetDraws; i++)
201 {
202 int vtxNdx = m_rnd.getInt(0, NUM_GENERATED_VERTICES - 1);
203 targetVertices[4 * i] = vertices[4 * vtxNdx];
204 targetVertices[4 * i + 1] = vertices[4 * vtxNdx + 1];
205 targetVertices[4 * i + 2] = vertices[4 * vtxNdx + 2];
206 targetVertices[4 * i + 3] = vertices[4 * vtxNdx + 3];
207 }
208
209 TCU_CHECK(m_program);
210
211 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
212 glClearDepthf(1.0f);
213 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
214 glEnable(GL_DEPTH_TEST);
215 glUseProgram(m_program->getProgram());
216 glEnableVertexAttribArray(0);
217
218 uint64_t time = deGetMicroseconds();
219
220 for (int queryIter = 0; queryIter < m_numQueries; queryIter++)
221 {
222 // Draw occluders
223
224 glUniform4f(colorUnif, OCCLUDER_COLOR.x(), OCCLUDER_COLOR.y(), OCCLUDER_COLOR.z(), OCCLUDER_COLOR.w());
225
226 for (int drawIter = 0; drawIter < m_numOccluderDraws; drawIter++)
227 {
228 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, &occluderVertices[drawIter * numOccluderIndicesPerDraw]);
229 glDrawArrays(GL_TRIANGLES, 0, numOccluderIndicesPerDraw);
230 }
231
232 // Begin occlusion query
233
234 glGenQueries(1, &queryIds[queryIter]);
235 glBeginQuery(m_queryMode, queryIds[queryIter]);
236
237 // Draw targets
238
239 glUniform4f(colorUnif, TARGET_COLOR.x(), TARGET_COLOR.y(), TARGET_COLOR.z(), TARGET_COLOR.w());
240
241 for (int drawIter = 0; drawIter < m_numTargetDraws; drawIter++)
242 {
243 glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, &targetVertices[drawIter * numTargetIndicesPerDraw]);
244 glDrawArrays(GL_TRIANGLES, 0, numTargetIndicesPerDraw);
245 }
246
247 // End occlusion query
248
249 glEndQuery(m_queryMode);
250
251 if ((queryIter % WATCHDOG_INTERVAL) == 0 && m_testCtx.getWatchDog())
252 qpWatchDog_touch(m_testCtx.getWatchDog());
253 }
254
255 glFinish();
256 glDisable(GL_DEPTH_TEST);
257
258 uint64_t dTime = deGetMicroseconds() - time;
259 log << tcu::TestLog::Message << "Total duration: " << dTime / 1000 << " ms" << tcu::TestLog::EndMessage;
260
261 // Get results
262
263 for (int queryIter = 0; queryIter < m_numQueries; queryIter++)
264 {
265 glGetQueryObjectuiv(queryIds[queryIter], GL_QUERY_RESULT_AVAILABLE, &queryResultReady[queryIter]);
266
267 if (queryResultReady[queryIter] == GL_TRUE)
268 {
269 glGetQueryObjectuiv(queryIds[queryIter], GL_QUERY_RESULT, &queryResult[queryIter]);
270 }
271 else
272 TCU_FAIL("Occlusion query failed to return a result after glFinish()");
273
274 if ((queryIter % WATCHDOG_INTERVAL) == 0 && m_testCtx.getWatchDog())
275 qpWatchDog_touch(m_testCtx.getWatchDog());
276 }
277
278 glDeleteQueries(m_numQueries, &queryIds[0]);
279 GLU_CHECK_MSG("Occlusion queries finished");
280
281 log << tcu::TestLog::Message << "Case passed!" << tcu::TestLog::EndMessage;
282
283 return (++m_iterNdx < NUM_CASE_ITERATIONS) ? CONTINUE : STOP;
284 }
285
OcclusionQueryTests(Context & testCtx)286 OcclusionQueryTests::OcclusionQueryTests(Context &testCtx)
287 : TestCaseGroup(testCtx, "occlusion_query", "Occlusion query stress tests")
288 {
289 }
290
~OcclusionQueryTests(void)291 OcclusionQueryTests::~OcclusionQueryTests(void)
292 {
293 }
294
init(void)295 void OcclusionQueryTests::init(void)
296 {
297 addChild(new OcclusionQueryStressCase(m_context, "10_queries_2500_triangles_per_query",
298 "10_queries_2500_triangles_per_query", 49, 50, 1, 50, 10,
299 GL_ANY_SAMPLES_PASSED));
300 addChild(new OcclusionQueryStressCase(m_context, "100_queries_2500_triangles_per_query",
301 "100_queries_2500_triangles_per_query", 49, 50, 1, 50, 100,
302 GL_ANY_SAMPLES_PASSED));
303 addChild(new OcclusionQueryStressCase(m_context, "1000_queries_500_triangles_per_query",
304 "1000_queries_500_triangles_per_query", 49, 10, 1, 10, 1000,
305 GL_ANY_SAMPLES_PASSED));
306 addChild(new OcclusionQueryStressCase(m_context, "10000_queries_20_triangles_per_query",
307 "10000_queries_20_triangles_per_query", 1, 19, 1, 1, 10000,
308 GL_ANY_SAMPLES_PASSED));
309 }
310
311 } // namespace Stress
312 } // namespace gles3
313 } // namespace deqp
314