xref: /aosp_15_r20/external/deqp/modules/gles3/stress/es3sOcclusionQueryTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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