xref: /aosp_15_r20/external/deqp/modules/gles3/stress/es3sLongRunningShaderTests.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 Long running shader stress tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es3sLongRunningShaderTests.hpp"
25 
26 #include "gluShaderProgram.hpp"
27 #include "gluShaderUtil.hpp"
28 #include "gluDrawUtil.hpp"
29 
30 #include "tcuRenderTarget.hpp"
31 #include "tcuVector.hpp"
32 #include "tcuTestLog.hpp"
33 
34 #include "deRandom.hpp"
35 #include "deStringUtil.hpp"
36 #include "deString.h"
37 
38 #include "glwFunctions.hpp"
39 #include "glwEnums.hpp"
40 
41 namespace deqp
42 {
43 namespace gles3
44 {
45 namespace Stress
46 {
47 
48 using std::vector;
49 using tcu::TestLog;
50 using tcu::Vec2;
51 
52 namespace
53 {
54 
55 enum LoopType
56 {
57     LOOPTYPE_FOR = 0,
58     LOOPTYPE_WHILE,
59     LOOPTYPE_DO_WHILE,
60 
61     LOOPTYPE_LAST
62 };
63 
64 enum IterCountType
65 {
66     ITERCOUNTTYPE_STATIC = 0,
67     ITERCOUNTTYPE_UNIFORM,
68     ITERCOUNTTYPE_DYNAMIC,
69 
70     ITERCOUNTTYPE_LAST
71 };
72 
73 class LongRunningShaderCase : public TestCase
74 {
75 public:
76     struct Params
77     {
78         const char *name;
79         const char *description;
80         glu::ShaderType shaderType;
81         LoopType loopType;
82         IterCountType iterCountType;
83         int numInvocations;
84         int minLoopIterCount;
85         int maxLoopIterCount;
86     };
87 
88     LongRunningShaderCase(Context &context, const Params *params);
89     ~LongRunningShaderCase(void);
90 
91     void init(void);
92     void deinit(void);
93     IterateResult iterate(void);
94 
95 private:
96     LongRunningShaderCase(const LongRunningShaderCase &);
97     LongRunningShaderCase &operator=(const LongRunningShaderCase &);
98 
99     static glu::ProgramSources genSources(const Params &params);
100     static uint32_t getSeed(const Params &params);
101 
102     const Params *const m_params;
103     const int m_numCaseIters;
104 
105     glu::ShaderProgram *m_program;
106     int m_caseIterNdx;
107 };
108 
LongRunningShaderCase(Context & context,const Params * params)109 LongRunningShaderCase::LongRunningShaderCase(Context &context, const Params *params)
110     : TestCase(context, params->name, params->description)
111     , m_params(params)
112     , m_numCaseIters(5)
113     , m_program(DE_NULL)
114     , m_caseIterNdx(0)
115 {
116 }
117 
~LongRunningShaderCase(void)118 LongRunningShaderCase::~LongRunningShaderCase(void)
119 {
120     deinit();
121 }
122 
genSources(const Params & params)123 glu::ProgramSources LongRunningShaderCase::genSources(const Params &params)
124 {
125     const bool isVertCase = params.shaderType == glu::SHADERTYPE_VERTEX;
126     std::ostringstream vert, frag;
127 
128     vert << "#version 300 es\n"
129          << "in highp vec2 a_position;\n";
130 
131     frag << "#version 300 es\n";
132 
133     if (params.iterCountType == ITERCOUNTTYPE_DYNAMIC)
134     {
135         vert << "in highp int a_iterCount;\n";
136         if (!isVertCase)
137         {
138             vert << "flat out highp int v_iterCount;\n";
139             frag << "flat in highp int v_iterCount;\n";
140         }
141     }
142     else if (params.iterCountType == ITERCOUNTTYPE_UNIFORM)
143         (isVertCase ? vert : frag) << "uniform highp int u_iterCount;\n";
144 
145     if (isVertCase)
146     {
147         vert << "out mediump vec4 v_color;\n";
148         frag << "in mediump vec4 v_color;\n";
149     }
150 
151     frag << "out mediump vec4 o_color;\n";
152 
153     vert << "\nvoid main (void)\n{\n"
154          << "    gl_Position = vec4(a_position, 0.0, 1.0);\n"
155          << "    gl_PointSize = 1.0;\n";
156 
157     if (!isVertCase && params.iterCountType == ITERCOUNTTYPE_DYNAMIC)
158         vert << "    v_iterCount = a_iterCount;\n";
159 
160     frag << "\nvoid main (void)\n{\n";
161 
162     {
163         const std::string iterCount =
164             params.iterCountType == ITERCOUNTTYPE_DYNAMIC ? (isVertCase ? "a_iterCount" : "v_iterCount") :
165             params.iterCountType == ITERCOUNTTYPE_UNIFORM ? "u_iterCount" :
166             params.iterCountType == ITERCOUNTTYPE_STATIC  ? de::toString(params.maxLoopIterCount) :
167                                                             "<invalid>";
168         const char *const body = "color = cos(sin(color*1.25)*0.8);";
169         std::ostringstream &op = isVertCase ? vert : frag;
170 
171         op << "    mediump vec4 color = " << (isVertCase ? "a_position.xyxy" : "gl_FragCoord") << ";\n";
172 
173         if (params.loopType == LOOPTYPE_FOR)
174         {
175             op << "    for (highp int i = 0; i < " << iterCount << " || " << iterCount << " < 0; ++i)\n"
176                << "        " << body << "\n";
177         }
178         else if (params.loopType == LOOPTYPE_WHILE)
179         {
180             op << "    highp int i = 0;\n"
181                << "    while (i < " << iterCount << " || " << iterCount << " < 0) {\n"
182                << "        i += 1;\n"
183                << "        " << body << "\n"
184                << "    }\n";
185         }
186         else
187         {
188             DE_ASSERT(params.loopType == LOOPTYPE_DO_WHILE);
189             op << "    highp int i = 0;\n"
190                << "    do {\n"
191                << "        i += 1;\n"
192                << "        " << body << "\n"
193                << "    } while (i <= " << iterCount << " || " << iterCount << " < 0);\n";
194         }
195     }
196 
197     if (isVertCase)
198     {
199         vert << "    v_color = color;\n";
200         frag << "    o_color = v_color;\n";
201     }
202     else
203         frag << "    o_color = color;\n";
204 
205     vert << "}\n";
206     frag << "}\n";
207 
208     return glu::ProgramSources() << glu::VertexSource(vert.str()) << glu::FragmentSource(frag.str());
209 }
210 
init(void)211 void LongRunningShaderCase::init(void)
212 {
213     DE_ASSERT(!m_program);
214     m_program = new glu::ShaderProgram(m_context.getRenderContext(), genSources(*m_params));
215 
216     m_testCtx.getLog() << *m_program;
217 
218     if (!m_program->isOk())
219     {
220         deinit();
221         TCU_FAIL("Failed to compile shader program");
222     }
223 
224     m_caseIterNdx = 0;
225 
226     if (m_params->iterCountType != ITERCOUNTTYPE_STATIC)
227     {
228         m_testCtx.getLog() << TestLog::Message << "Loop iteration counts in range: [" << m_params->minLoopIterCount
229                            << ", " << m_params->maxLoopIterCount << "]" << TestLog::EndMessage;
230     }
231 
232     m_testCtx.getLog() << TestLog::Message << "Number of vertices and fragments: " << m_params->numInvocations
233                        << TestLog::EndMessage;
234 
235     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); // Test will pass or timeout, unless driver/device crashes.
236 }
237 
deinit(void)238 void LongRunningShaderCase::deinit(void)
239 {
240     delete m_program;
241     m_program = DE_NULL;
242 }
243 
genPositions(const tcu::RenderTarget & renderTarget,int numPoints,Vec2 * positions)244 void genPositions(const tcu::RenderTarget &renderTarget, int numPoints, Vec2 *positions)
245 {
246     const int width  = renderTarget.getWidth();
247     const int height = renderTarget.getHeight();
248 
249     if (width * height < numPoints)
250         throw tcu::NotSupportedError("Too small viewport to fit all test points");
251 
252     for (int pointNdx = 0; pointNdx < numPoints; pointNdx++)
253     {
254         const int xi   = pointNdx % width;
255         const int yi   = pointNdx / height;
256         const float xf = 2.0f * ((float(xi) + 0.5f) / float(width)) - 1.0f;
257         const float yf = 2.0f * ((float(yi) + 0.5f) / float(height)) - 1.0f;
258 
259         positions[pointNdx] = Vec2(xf, yf);
260     }
261 }
262 
getSeed(const Params & params)263 uint32_t LongRunningShaderCase::getSeed(const Params &params)
264 {
265     const uint32_t seed = deStringHash(params.name) ^ deInt32Hash(params.shaderType) ^ deInt32Hash(params.loopType) ^
266                           deInt32Hash(params.iterCountType) ^ deInt32Hash(params.minLoopIterCount) ^
267                           deInt32Hash(params.maxLoopIterCount) ^ deInt32Hash(params.numInvocations);
268     return seed;
269 }
270 
iterate(void)271 LongRunningShaderCase::IterateResult LongRunningShaderCase::iterate(void)
272 {
273     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
274     de::Random rnd(getSeed(*m_params));
275     vector<Vec2> positions(m_params->numInvocations);
276     vector<int> iterCounts(m_params->iterCountType == ITERCOUNTTYPE_DYNAMIC ? m_params->numInvocations : 1);
277     vector<glu::VertexArrayBinding> vertexArrays;
278 
279     vertexArrays.push_back(glu::va::Float("a_position", 2, (int)positions.size(), 0, positions[0].getPtr()));
280     if (m_params->iterCountType == ITERCOUNTTYPE_DYNAMIC)
281         vertexArrays.push_back(glu::va::Int32("a_iterCount", 1, (int)iterCounts.size(), 0, &iterCounts[0]));
282 
283     genPositions(m_context.getRenderTarget(), (int)positions.size(), &positions[0]);
284 
285     for (vector<int>::iterator i = iterCounts.begin(); i != iterCounts.end(); ++i)
286         *i = rnd.getInt(m_params->minLoopIterCount, m_params->maxLoopIterCount);
287 
288     gl.useProgram(m_program->getProgram());
289 
290     if (m_params->iterCountType == ITERCOUNTTYPE_UNIFORM)
291         gl.uniform1i(gl.getUniformLocation(m_program->getProgram(), "u_iterCount"), iterCounts[0]);
292 
293     glu::draw(m_context.getRenderContext(), m_program->getProgram(), (int)vertexArrays.size(), &vertexArrays[0],
294               glu::pr::Points(m_params->numInvocations));
295 
296     m_caseIterNdx += 1;
297     return (m_caseIterNdx < m_numCaseIters) ? CONTINUE : STOP;
298 }
299 
300 } // namespace
301 
LongRunningShaderTests(Context & context)302 LongRunningShaderTests::LongRunningShaderTests(Context &context)
303     : TestCaseGroup(context, "long_running_shaders", "Long-running shader stress tests")
304 {
305 }
306 
~LongRunningShaderTests(void)307 LongRunningShaderTests::~LongRunningShaderTests(void)
308 {
309 }
310 
init(void)311 void LongRunningShaderTests::init(void)
312 {
313     const int numInvocations = 4096;
314     const int shortLoopMin   = 5;
315     const int shortLoopMax   = 10;
316     const int mediumLoopMin  = 10000;
317     const int mediumLoopMax  = 50000;
318     const int longLoopMin    = 100000;
319     const int longLoopMax    = 500000;
320 
321     static const LongRunningShaderCase::Params s_cases[] = {
322         {"short_for_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations,
323          shortLoopMin, shortLoopMax},
324         {"short_for_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations,
325          shortLoopMin, shortLoopMax},
326         {"short_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations,
327          shortLoopMin, shortLoopMax},
328         {"short_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations,
329          shortLoopMin, shortLoopMax},
330         {"short_do_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations,
331          shortLoopMin, shortLoopMax},
332         {"short_do_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC,
333          numInvocations, shortLoopMin, shortLoopMax},
334 
335         {"medium_static_for_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_FOR, ITERCOUNTTYPE_STATIC, numInvocations,
336          mediumLoopMin, mediumLoopMax},
337         {"medium_static_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_WHILE, ITERCOUNTTYPE_STATIC,
338          numInvocations, mediumLoopMin, mediumLoopMax},
339         {"medium_uniform_do_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_UNIFORM,
340          numInvocations, mediumLoopMin, mediumLoopMax},
341         {"medium_uniform_for_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_FOR, ITERCOUNTTYPE_UNIFORM,
342          numInvocations, mediumLoopMin, mediumLoopMax},
343 
344         {"medium_dynamic_for_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations,
345          mediumLoopMin, mediumLoopMax},
346         {"medium_dynamic_for_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC,
347          numInvocations, mediumLoopMin, mediumLoopMax},
348         {"medium_dynamic_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC,
349          numInvocations, mediumLoopMin, mediumLoopMax},
350         {"medium_dynamic_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC,
351          numInvocations, mediumLoopMin, mediumLoopMax},
352         {"medium_dynamic_do_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC,
353          numInvocations, mediumLoopMin, mediumLoopMax},
354         {"medium_dynamic_do_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC,
355          numInvocations, mediumLoopMin, mediumLoopMax},
356 
357         {"long_static_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_WHILE, ITERCOUNTTYPE_STATIC, numInvocations,
358          longLoopMin, longLoopMax},
359         {"long_static_do_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_STATIC,
360          numInvocations, longLoopMin, longLoopMax},
361         {"long_uniform_for_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_FOR, ITERCOUNTTYPE_UNIFORM, numInvocations,
362          longLoopMin, longLoopMax},
363         {"long_uniform_do_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_UNIFORM,
364          numInvocations, longLoopMin, longLoopMax},
365 
366         {"long_dynamic_for_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations,
367          longLoopMin, longLoopMax},
368         {"long_dynamic_for_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations,
369          longLoopMin, longLoopMax},
370         {"long_dynamic_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations,
371          longLoopMin, longLoopMax},
372         {"long_dynamic_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC,
373          numInvocations, longLoopMin, longLoopMax},
374         {"long_dynamic_do_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC,
375          numInvocations, longLoopMin, longLoopMax},
376         {"long_dynamic_do_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC,
377          numInvocations, longLoopMin, longLoopMax},
378 
379         {"infinite_for_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations, -1,
380          -1},
381         {"infinite_for_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_FOR, ITERCOUNTTYPE_DYNAMIC, numInvocations, -1,
382          -1},
383         {"infinite_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations, -1,
384          -1},
385         {"infinite_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_WHILE, ITERCOUNTTYPE_DYNAMIC, numInvocations,
386          -1, -1},
387         {"infinite_do_while_vertex", "", glu::SHADERTYPE_VERTEX, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC,
388          numInvocations, -1, -1},
389         {"infinite_do_while_fragment", "", glu::SHADERTYPE_FRAGMENT, LOOPTYPE_DO_WHILE, ITERCOUNTTYPE_DYNAMIC,
390          numInvocations, -1, -1},
391     };
392 
393     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_cases); ndx++)
394         addChild(new LongRunningShaderCase(m_context, &s_cases[ndx]));
395 }
396 
397 } // namespace Stress
398 } // namespace gles3
399 } // namespace deqp
400