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 Depth buffer performance tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es3pDepthTests.hpp"
25
26 #include "glsCalibration.hpp"
27
28 #include "gluShaderProgram.hpp"
29 #include "gluObjectWrapper.hpp"
30 #include "gluPixelTransfer.hpp"
31
32 #include "glwFunctions.hpp"
33 #include "glwEnums.hpp"
34
35 #include "tcuTestLog.hpp"
36 #include "tcuStringTemplate.hpp"
37 #include "tcuCPUWarmup.hpp"
38 #include "tcuCommandLine.hpp"
39 #include "tcuResultCollector.hpp"
40
41 #include "deClock.h"
42 #include "deString.h"
43 #include "deMath.h"
44 #include "deStringUtil.hpp"
45 #include "deRandom.hpp"
46 #include "deUniquePtr.hpp"
47
48 #include <vector>
49 #include <algorithm>
50
51 namespace deqp
52 {
53 namespace gles3
54 {
55 namespace Performance
56 {
57 namespace
58 {
59 using namespace glw;
60 using de::MovePtr;
61 using glu::ProgramSources;
62 using glu::RenderContext;
63 using glu::ShaderSource;
64 using std::map;
65 using std::string;
66 using std::vector;
67 using tcu::TestContext;
68 using tcu::TestLog;
69 using tcu::Vec2;
70 using tcu::Vec3;
71 using tcu::Vec4;
72
73 struct Sample
74 {
75 int64_t nullTime;
76 int64_t baseTime;
77 int64_t testTime;
78 int order;
79 int workload;
80 };
81
82 struct SampleParams
83 {
84 int step;
85 int measurement;
86
SampleParamsdeqp::gles3::Performance::__anon5a4bff6a0111::SampleParams87 SampleParams(int step_, int measurement_) : step(step_), measurement(measurement_)
88 {
89 }
90 };
91
92 typedef vector<float> Geometry;
93
94 struct ObjectData
95 {
96 ProgramSources shader;
97 Geometry geometry;
98
ObjectDatadeqp::gles3::Performance::__anon5a4bff6a0111::ObjectData99 ObjectData(const ProgramSources &shader_, const Geometry &geometry_) : shader(shader_), geometry(geometry_)
100 {
101 }
102 };
103
104 class RenderData
105 {
106 public:
107 RenderData(const ObjectData &object, const glu::RenderContext &renderCtx, TestLog &log);
~RenderData(void)108 ~RenderData(void)
109 {
110 }
111
112 const glu::ShaderProgram m_program;
113 const glu::VertexArray m_vao;
114 const glu::Buffer m_vbo;
115
116 const int m_numVertices;
117 };
118
RenderData(const ObjectData & object,const glu::RenderContext & renderCtx,TestLog & log)119 RenderData::RenderData(const ObjectData &object, const glu::RenderContext &renderCtx, TestLog &log)
120 : m_program(renderCtx, object.shader)
121 , m_vao(renderCtx.getFunctions())
122 , m_vbo(renderCtx.getFunctions())
123 , m_numVertices(int(object.geometry.size()) / 4)
124 {
125 const glw::Functions &gl = renderCtx.getFunctions();
126
127 if (!m_program.isOk())
128 log << m_program;
129
130 gl.bindBuffer(GL_ARRAY_BUFFER, *m_vbo);
131 gl.bufferData(GL_ARRAY_BUFFER, object.geometry.size() * sizeof(float), &object.geometry[0], GL_STATIC_DRAW);
132 gl.bindAttribLocation(m_program.getProgram(), 0, "a_position");
133
134 gl.bindVertexArray(*m_vao);
135 gl.vertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
136 gl.enableVertexAttribArray(0);
137 gl.bindVertexArray(0);
138 }
139
140 namespace Utils
141 {
getFullscreenQuad(float depth)142 vector<float> getFullscreenQuad(float depth)
143 {
144 const float data[] = {
145 +1.0f, +1.0f, depth, 0.0f, // .w is gl_VertexId%3 since Nexus 4&5 can't handle that on their own
146 +1.0f, -1.0f, depth, 1.0f, -1.0f, -1.0f, depth, 2.0f, -1.0f, -1.0f,
147 depth, 0.0f, -1.0f, +1.0f, depth, 1.0f, +1.0f, +1.0f, depth, 2.0f,
148 };
149
150 return vector<float>(DE_ARRAY_BEGIN(data), DE_ARRAY_END(data));
151 }
152
getFullscreenQuadWithGradient(float depth0,float depth1)153 vector<float> getFullscreenQuadWithGradient(float depth0, float depth1)
154 {
155 const float data[] = {
156 +1.0f, +1.0f, depth0, 0.0f, +1.0f, -1.0f, depth0, 1.0f, -1.0f, -1.0f, depth1, 2.0f,
157 -1.0f, -1.0f, depth1, 0.0f, -1.0f, +1.0f, depth1, 1.0f, +1.0f, +1.0f, depth0, 2.0f,
158 };
159
160 return vector<float>(DE_ARRAY_BEGIN(data), DE_ARRAY_END(data));
161 }
162
getPartScreenQuad(float coverage,float depth)163 vector<float> getPartScreenQuad(float coverage, float depth)
164 {
165 const float xMax = -1.0f + 2.0f * coverage;
166 const float data[] = {
167 xMax, +1.0f, depth, 0.0f, xMax, -1.0f, depth, 1.0f, -1.0f, -1.0f, depth, 2.0f,
168 -1.0f, -1.0f, depth, 0.0f, -1.0f, +1.0f, depth, 1.0f, xMax, +1.0f, depth, 2.0f,
169 };
170
171 return vector<float>(DE_ARRAY_BEGIN(data), DE_ARRAY_END(data));
172 }
173
174 // Axis aligned grid. Depth of vertices is baseDepth +/- depthNoise
getFullScreenGrid(int resolution,uint32_t seed,float baseDepth,float depthNoise,float xyNoise)175 vector<float> getFullScreenGrid(int resolution, uint32_t seed, float baseDepth, float depthNoise, float xyNoise)
176 {
177 const int gridsize = resolution + 1;
178 vector<Vec3> vertices(gridsize * gridsize);
179 vector<float> retval;
180 de::Random rng(seed);
181
182 for (int y = 0; y < gridsize; y++)
183 for (int x = 0; x < gridsize; x++)
184 {
185 const bool isEdge = x == 0 || y == 0 || x == resolution || y == resolution;
186 const float x_ =
187 float(x) / float(resolution) * 2.0f - 1.0f + (isEdge ? 0.0f : rng.getFloat(-xyNoise, +xyNoise));
188 const float y_ =
189 float(y) / float(resolution) * 2.0f - 1.0f + (isEdge ? 0.0f : rng.getFloat(-xyNoise, +xyNoise));
190 const float z_ = baseDepth + rng.getFloat(-depthNoise, +depthNoise);
191
192 vertices[y * gridsize + x] = Vec3(x_, y_, z_);
193 }
194
195 retval.reserve(resolution * resolution * 6);
196
197 for (int y = 0; y < resolution; y++)
198 for (int x = 0; x < resolution; x++)
199 {
200 const Vec3 &p0 = vertices[(y + 0) * gridsize + (x + 0)];
201 const Vec3 &p1 = vertices[(y + 0) * gridsize + (x + 1)];
202 const Vec3 &p2 = vertices[(y + 1) * gridsize + (x + 0)];
203 const Vec3 &p3 = vertices[(y + 1) * gridsize + (x + 1)];
204
205 const float temp[6 * 4] = {
206 p0.x(), p0.y(), p0.z(), 0.0f, p2.x(), p2.y(), p2.z(), 1.0f, p1.x(), p1.y(), p1.z(), 2.0f,
207
208 p3.x(), p3.y(), p3.z(), 0.0f, p1.x(), p1.y(), p1.z(), 1.0f, p2.x(), p2.y(), p2.z(), 2.0f,
209 };
210
211 retval.insert(retval.end(), DE_ARRAY_BEGIN(temp), DE_ARRAY_END(temp));
212 }
213
214 return retval;
215 }
216
217 // Outputs barycentric coordinates as v_bcoords. Otherwise a passthrough shader
getBaseVertexShader(void)218 string getBaseVertexShader(void)
219 {
220 return "#version 300 es\n"
221 "in highp vec4 a_position;\n"
222 "out mediump vec3 v_bcoords;\n"
223 "void main()\n"
224 "{\n"
225 " v_bcoords = vec3(0, 0, 0);\n"
226 " v_bcoords[int(a_position.w)] = 1.0;\n"
227 " gl_Position = vec4(a_position.xyz, 1.0);\n"
228 "}\n";
229 }
230
231 // Adds noise to coordinates based on InstanceID Outputs barycentric coordinates as v_bcoords
getInstanceNoiseVertexShader(void)232 string getInstanceNoiseVertexShader(void)
233 {
234 return "#version 300 es\n"
235 "in highp vec4 a_position;\n"
236 "out mediump vec3 v_bcoords;\n"
237 "void main()\n"
238 "{\n"
239 " v_bcoords = vec3(0, 0, 0);\n"
240 " v_bcoords[int(a_position.w)] = 1.0;\n"
241 " vec3 noise = vec3(sin(float(gl_InstanceID)*1.05), sin(float(gl_InstanceID)*1.23), "
242 "sin(float(gl_InstanceID)*1.71));\n"
243 " gl_Position = vec4(a_position.xyz + noise * 0.005, 1.0);\n"
244 "}\n";
245 }
246
247 // Renders green triangles with edges highlighted. Exact shade depends on depth.
getDepthAsGreenFragmentShader(void)248 string getDepthAsGreenFragmentShader(void)
249 {
250 return "#version 300 es\n"
251 "in mediump vec3 v_bcoords;\n"
252 "out mediump vec4 fragColor;\n"
253 "void main()\n"
254 "{\n"
255 " mediump float d = gl_FragCoord.z;\n"
256 " if (v_bcoords.x < 0.02 || v_bcoords.y < 0.02 || v_bcoords.z < 0.02)\n"
257 " fragColor = vec4(d,1,d,1);\n"
258 " else\n"
259 " fragColor = vec4(0,d,0,1);\n"
260 "}\n";
261 }
262
263 // Renders green triangles with edges highlighted. Exact shade depends on depth.
getDepthAsRedFragmentShader(void)264 string getDepthAsRedFragmentShader(void)
265 {
266 return "#version 300 es\n"
267 "in mediump vec3 v_bcoords;\n"
268 "out mediump vec4 fragColor;\n"
269 "void main()\n"
270 "{\n"
271 " mediump float d = gl_FragCoord.z;\n"
272 " if (v_bcoords.x < 0.02 || v_bcoords.y < 0.02 || v_bcoords.z < 0.02)\n"
273 " fragColor = vec4(1,d,d,1);\n"
274 " else\n"
275 " fragColor = vec4(d,0,0,1);\n"
276 "}\n";
277 }
278
279 // Basic time waster. Renders red triangles with edges highlighted. Exact shade depends on depth.
getArithmeticWorkloadFragmentShader(void)280 string getArithmeticWorkloadFragmentShader(void)
281 {
282
283 return "#version 300 es\n"
284 "in mediump vec3 v_bcoords;\n"
285 "out mediump vec4 fragColor;\n"
286 "uniform mediump int u_iterations;\n"
287 "void main()\n"
288 "{\n"
289 " mediump float d = gl_FragCoord.z;\n"
290 " for (int i = 0; i<u_iterations; i++)\n"
291 // cos(a)^2 + sin(a)^2 == 1. since d is in range [0,1] this will lose a few ULP's of precision per iteration but should not significantly change the value of d without extreme iteration counts
292 " d = d*sin(d)*sin(d) + d*cos(d)*cos(d);\n"
293 " if (v_bcoords.x < 0.02 || v_bcoords.y < 0.02 || v_bcoords.z < 0.02)\n"
294 " fragColor = vec4(1,d,d,1);\n"
295 " else\n"
296 " fragColor = vec4(d,0,0,1);\n"
297 "}\n";
298 }
299
300 // Arithmetic workload shader but contains discard
getArithmeticWorkloadDiscardFragmentShader(void)301 string getArithmeticWorkloadDiscardFragmentShader(void)
302 {
303 return "#version 300 es\n"
304 "in mediump vec3 v_bcoords;\n"
305 "out mediump vec4 fragColor;\n"
306 "uniform mediump int u_iterations;\n"
307 "void main()\n"
308 "{\n"
309 " mediump float d = gl_FragCoord.z;\n"
310 " for (int i = 0; i<u_iterations; i++)\n"
311 " d = d*sin(d)*sin(d) + d*cos(d)*cos(d);\n"
312 " if (d < 0.5) discard;\n"
313 " if (v_bcoords.x < 0.02 || v_bcoords.y < 0.02 || v_bcoords.z < 0.02)\n"
314 " fragColor = vec4(1,d,d,1);\n"
315 " else\n"
316 " fragColor = vec4(d,0,0,1);\n"
317 "}\n";
318 }
319
320 // Texture fetch based time waster. Renders red triangles with edges highlighted. Exact shade depends on depth.
getTextureWorkloadFragmentShader(void)321 string getTextureWorkloadFragmentShader(void)
322 {
323 return "#version 300 es\n"
324 "in mediump vec3 v_bcoords;\n"
325 "out mediump vec4 fragColor;\n"
326 "uniform mediump int u_iterations;\n"
327 "uniform sampler2D u_texture;\n"
328 "void main()\n"
329 "{\n"
330 " mediump float d = gl_FragCoord.z;\n"
331 " for (int i = 0; i<u_iterations; i++)\n"
332 " d *= texture(u_texture, (gl_FragCoord.xy+vec2(i))/512.0).r;\n" // Texture is expected to be fully white
333 " if (v_bcoords.x < 0.02 || v_bcoords.y < 0.02 || v_bcoords.z < 0.02)\n"
334 " fragColor = vec4(1,1,1,1);\n"
335 " else\n"
336 " fragColor = vec4(d,0,0,1);\n"
337 "}\n";
338 }
339
340 // Discard fragments in a grid pattern
getGridDiscardFragmentShader(int gridsize)341 string getGridDiscardFragmentShader(int gridsize)
342 {
343 const string fragSrc =
344 "#version 300 es\n"
345 "in mediump vec3 v_bcoords;\n"
346 "out mediump vec4 fragColor;\n"
347 "void main()\n"
348 "{\n"
349 " mediump float d = gl_FragCoord.z;\n"
350 " if ((int(gl_FragCoord.x)/${GRIDRENDER_SIZE} + int(gl_FragCoord.y)/${GRIDRENDER_SIZE})%2 == 0)\n"
351 " discard;\n"
352 " if (v_bcoords.x < 0.02 || v_bcoords.y < 0.02 || v_bcoords.z < 0.02)\n"
353 " fragColor = vec4(d,1,d,1);\n"
354 " else\n"
355 " fragColor = vec4(0,d,0,1);\n"
356 "}\n";
357 map<string, string> params;
358
359 params["GRIDRENDER_SIZE"] = de::toString(gridsize);
360
361 return tcu::StringTemplate(fragSrc).specialize(params);
362 }
363
364 // A static increment to frag depth
getStaticFragDepthFragmentShader(void)365 string getStaticFragDepthFragmentShader(void)
366 {
367 return "#version 300 es\n"
368 "in mediump vec3 v_bcoords;\n"
369 "out mediump vec4 fragColor;\n"
370 "void main()\n"
371 "{\n"
372 " mediump float d = gl_FragCoord.z;\n"
373 " gl_FragDepth = gl_FragCoord.z + 0.1;\n"
374 " if (v_bcoords.x < 0.02 || v_bcoords.y < 0.02 || v_bcoords.z < 0.02)\n"
375 " fragColor = vec4(d,1,d,1);\n"
376 " else\n"
377 " fragColor = vec4(0,d,0,1);\n"
378 "}\n";
379 }
380
381 // A trivial dynamic change to frag depth
getDynamicFragDepthFragmentShader(void)382 string getDynamicFragDepthFragmentShader(void)
383 {
384 return "#version 300 es\n"
385 "in mediump vec3 v_bcoords;\n"
386 "out mediump vec4 fragColor;\n"
387 "void main()\n"
388 "{\n"
389 " mediump float d = gl_FragCoord.z;\n"
390 " gl_FragDepth = gl_FragCoord.z + (v_bcoords.x + v_bcoords.y + v_bcoords.z)*0.05;\n" // Sum of v_bcoords components is allways 1
391 " if (v_bcoords.x < 0.02 || v_bcoords.y < 0.02 || v_bcoords.z < 0.02)\n"
392 " fragColor = vec4(d,1,d,1);\n"
393 " else\n"
394 " fragColor = vec4(0,d,0,1);\n"
395 "}\n";
396 }
397
398 // A static increment to frag depth
getStaticFragDepthArithmeticWorkloadFragmentShader(void)399 string getStaticFragDepthArithmeticWorkloadFragmentShader(void)
400 {
401 return "#version 300 es\n"
402 "in mediump vec3 v_bcoords;\n"
403 "out mediump vec4 fragColor;\n"
404 "uniform mediump int u_iterations;\n"
405 "void main()\n"
406 "{\n"
407 " mediump float d = gl_FragCoord.z;\n"
408 " gl_FragDepth = gl_FragCoord.z + 0.1;\n"
409 " for (int i = 0; i<u_iterations; i++)\n"
410 " d = d*sin(d)*sin(d) + d*cos(d)*cos(d);\n"
411 " if (v_bcoords.x < 0.02 || v_bcoords.y < 0.02 || v_bcoords.z < 0.02)\n"
412 " fragColor = vec4(1,d,d,1);\n"
413 " else\n"
414 " fragColor = vec4(d,0,0,1);\n"
415 "}\n";
416 }
417
418 // A trivial dynamic change to frag depth
getDynamicFragDepthArithmeticWorkloadFragmentShader(void)419 string getDynamicFragDepthArithmeticWorkloadFragmentShader(void)
420 {
421 return "#version 300 es\n"
422 "in mediump vec3 v_bcoords;\n"
423 "out mediump vec4 fragColor;\n"
424 "uniform mediump int u_iterations;\n"
425 "void main()\n"
426 "{\n"
427 " mediump float d = gl_FragCoord.z;\n"
428 " gl_FragDepth = gl_FragCoord.z + (v_bcoords.x + v_bcoords.y + v_bcoords.z)*0.05;\n" // Sum of v_bcoords components is allways 1
429 " for (int i = 0; i<u_iterations; i++)\n"
430 " d = d*sin(d)*sin(d) + d*cos(d)*cos(d);\n"
431 " if (v_bcoords.x < 0.02 || v_bcoords.y < 0.02 || v_bcoords.z < 0.02)\n"
432 " fragColor = vec4(1,d,d,1);\n"
433 " else\n"
434 " fragColor = vec4(d,0,0,1);\n"
435 "}\n";
436 }
437
getBaseShader(void)438 glu::ProgramSources getBaseShader(void)
439 {
440 return glu::makeVtxFragSources(getBaseVertexShader(), getDepthAsGreenFragmentShader());
441 }
442
getArithmeticWorkloadShader(void)443 glu::ProgramSources getArithmeticWorkloadShader(void)
444 {
445 return glu::makeVtxFragSources(getBaseVertexShader(), getArithmeticWorkloadFragmentShader());
446 }
447
getArithmeticWorkloadDiscardShader(void)448 glu::ProgramSources getArithmeticWorkloadDiscardShader(void)
449 {
450 return glu::makeVtxFragSources(getBaseVertexShader(), getArithmeticWorkloadDiscardFragmentShader());
451 }
452
getTextureWorkloadShader(void)453 glu::ProgramSources getTextureWorkloadShader(void)
454 {
455 return glu::makeVtxFragSources(getBaseVertexShader(), getTextureWorkloadFragmentShader());
456 }
457
getGridDiscardShader(int gridsize)458 glu::ProgramSources getGridDiscardShader(int gridsize)
459 {
460 return glu::makeVtxFragSources(getBaseVertexShader(), getGridDiscardFragmentShader(gridsize));
461 }
462
quadWith(const glu::ProgramSources & shader,float depth)463 inline ObjectData quadWith(const glu::ProgramSources &shader, float depth)
464 {
465 return ObjectData(shader, getFullscreenQuad(depth));
466 }
467
quadWith(const string & fragShader,float depth)468 inline ObjectData quadWith(const string &fragShader, float depth)
469 {
470 return ObjectData(glu::makeVtxFragSources(getBaseVertexShader(), fragShader), getFullscreenQuad(depth));
471 }
472
variableQuad(float depth)473 inline ObjectData variableQuad(float depth)
474 {
475 return ObjectData(glu::makeVtxFragSources(getInstanceNoiseVertexShader(), getDepthAsRedFragmentShader()),
476 getFullscreenQuad(depth));
477 }
478
fastQuad(float depth)479 inline ObjectData fastQuad(float depth)
480 {
481 return ObjectData(getBaseShader(), getFullscreenQuad(depth));
482 }
483
slowQuad(float depth)484 inline ObjectData slowQuad(float depth)
485 {
486 return ObjectData(getArithmeticWorkloadShader(), getFullscreenQuad(depth));
487 }
488
fastQuadWithGradient(float depth0,float depth1)489 inline ObjectData fastQuadWithGradient(float depth0, float depth1)
490 {
491 return ObjectData(getBaseShader(), getFullscreenQuadWithGradient(depth0, depth1));
492 }
493 } // namespace Utils
494
495 // Shared base
496 class BaseCase : public tcu::TestCase
497 {
498 public:
499 enum
500 {
501 RENDER_SIZE = 512
502 };
503
504 BaseCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name, const char *desc);
~BaseCase(void)505 virtual ~BaseCase(void)
506 {
507 }
508
509 virtual IterateResult iterate(void);
510
511 protected:
512 void logSamples(const vector<Sample> &samples, const string &name, const string &desc);
513 void logGeometry(const tcu::ConstPixelBufferAccess &sample, const glu::ShaderProgram &occluderProg,
514 const glu::ShaderProgram &occludedProg);
515 virtual void logAnalysis(const vector<Sample> &samples) = 0;
516 virtual void logDescription(void) = 0;
517
518 virtual ObjectData genOccluderGeometry(void) const = 0;
519 virtual ObjectData genOccludedGeometry(void) const = 0;
520
521 virtual int calibrate(void) const = 0;
522 virtual Sample renderSample(const RenderData &occluder, const RenderData &occluded, int workload) const = 0;
523
524 void render(const RenderData &data) const;
525 void render(const RenderData &data, int instances) const;
526
527 const RenderContext &m_renderCtx;
528 tcu::ResultCollector m_results;
529
530 enum
531 {
532 ITERATION_STEPS = 10,
533 ITERATION_SAMPLES = 16
534 };
535 };
536
BaseCase(TestContext & testCtx,const RenderContext & renderCtx,const char * name,const char * desc)537 BaseCase::BaseCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name, const char *desc)
538 : TestCase(testCtx, tcu::NODETYPE_PERFORMANCE, name, desc)
539 , m_renderCtx(renderCtx)
540 {
541 }
542
iterate(void)543 BaseCase::IterateResult BaseCase::iterate(void)
544 {
545 typedef de::MovePtr<RenderData> RenderDataP;
546
547 const glw::Functions &gl = m_renderCtx.getFunctions();
548 TestLog &log = m_testCtx.getLog();
549
550 const glu::Framebuffer framebuffer(gl);
551 const glu::Renderbuffer renderbuffer(gl);
552 const glu::Renderbuffer depthbuffer(gl);
553
554 vector<Sample> results;
555 vector<int> params;
556 RenderDataP occluderData;
557 RenderDataP occludedData;
558 tcu::TextureLevel resultTex(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
559 RENDER_SIZE, RENDER_SIZE);
560 int maxWorkload = 0;
561 de::Random rng(deInt32Hash(deStringHash(getName())) ^ m_testCtx.getCommandLine().getBaseSeed());
562
563 logDescription();
564
565 gl.bindRenderbuffer(GL_RENDERBUFFER, *renderbuffer);
566 gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, RENDER_SIZE, RENDER_SIZE);
567 gl.bindRenderbuffer(GL_RENDERBUFFER, *depthbuffer);
568 gl.renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, RENDER_SIZE, RENDER_SIZE);
569
570 gl.bindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
571 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *renderbuffer);
572 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, *depthbuffer);
573 gl.viewport(0, 0, RENDER_SIZE, RENDER_SIZE);
574 gl.clearColor(0.125f, 0.25f, 0.5f, 1.0f);
575
576 maxWorkload = calibrate();
577
578 // Setup data
579 occluderData = RenderDataP(new RenderData(genOccluderGeometry(), m_renderCtx, log));
580 occludedData = RenderDataP(new RenderData(genOccludedGeometry(), m_renderCtx, log));
581
582 TCU_CHECK(occluderData->m_program.isOk());
583 TCU_CHECK(occludedData->m_program.isOk());
584
585 // Force initialization of GPU resources
586 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
587 gl.enable(GL_DEPTH_TEST);
588
589 render(*occluderData);
590 render(*occludedData);
591 glu::readPixels(m_renderCtx, 0, 0, resultTex.getAccess());
592
593 logGeometry(resultTex.getAccess(), occluderData->m_program, occludedData->m_program);
594
595 params.reserve(ITERATION_STEPS * ITERATION_SAMPLES);
596
597 // Setup parameters
598 for (int step = 0; step < ITERATION_STEPS; step++)
599 {
600 const int workload = maxWorkload * step / ITERATION_STEPS;
601
602 for (int count = 0; count < ITERATION_SAMPLES; count++)
603 params.push_back(workload);
604 }
605
606 rng.shuffle(params.begin(), params.end());
607
608 // Render samples
609 for (size_t ndx = 0; ndx < params.size(); ndx++)
610 {
611 const int workload = params[ndx];
612 Sample sample = renderSample(*occluderData, *occludedData, workload);
613
614 sample.workload = workload;
615 sample.order = int(ndx);
616
617 results.push_back(sample);
618 }
619
620 logSamples(results, "Samples", "Samples");
621 logAnalysis(results);
622
623 m_results.setTestContextResult(m_testCtx);
624
625 return STOP;
626 }
627
logSamples(const vector<Sample> & samples,const string & name,const string & desc)628 void BaseCase::logSamples(const vector<Sample> &samples, const string &name, const string &desc)
629 {
630 TestLog &log = m_testCtx.getLog();
631
632 bool testOnly = true;
633
634 for (size_t ndx = 0; ndx < samples.size(); ndx++)
635 {
636 if (samples[ndx].baseTime != 0 || samples[ndx].nullTime != 0)
637 {
638 testOnly = false;
639 break;
640 }
641 }
642
643 log << TestLog::SampleList(name, desc);
644
645 if (testOnly)
646 {
647 log << TestLog::SampleInfo << TestLog::ValueInfo("Workload", "Workload", "", QP_SAMPLE_VALUE_TAG_PREDICTOR)
648 << TestLog::ValueInfo("Order", "Order of sample", "", QP_SAMPLE_VALUE_TAG_PREDICTOR)
649 << TestLog::ValueInfo("TestTime", "Test render time", "us", QP_SAMPLE_VALUE_TAG_RESPONSE)
650 << TestLog::EndSampleInfo;
651
652 for (size_t sampleNdx = 0; sampleNdx < samples.size(); sampleNdx++)
653 {
654 const Sample &sample = samples[sampleNdx];
655
656 log << TestLog::Sample << sample.workload << sample.order << sample.testTime << TestLog::EndSample;
657 }
658 }
659 else
660 {
661 log << TestLog::SampleInfo << TestLog::ValueInfo("Workload", "Workload", "", QP_SAMPLE_VALUE_TAG_PREDICTOR)
662 << TestLog::ValueInfo("Order", "Order of sample", "", QP_SAMPLE_VALUE_TAG_PREDICTOR)
663 << TestLog::ValueInfo("TestTime", "Test render time", "us", QP_SAMPLE_VALUE_TAG_RESPONSE)
664 << TestLog::ValueInfo("NullTime", "Read pixels time", "us", QP_SAMPLE_VALUE_TAG_RESPONSE)
665 << TestLog::ValueInfo("BaseTime", "Base render time", "us", QP_SAMPLE_VALUE_TAG_RESPONSE)
666 << TestLog::EndSampleInfo;
667
668 for (size_t sampleNdx = 0; sampleNdx < samples.size(); sampleNdx++)
669 {
670 const Sample &sample = samples[sampleNdx];
671
672 log << TestLog::Sample << sample.workload << sample.order << sample.testTime << sample.nullTime
673 << sample.baseTime << TestLog::EndSample;
674 }
675 }
676
677 log << TestLog::EndSampleList;
678 }
679
logGeometry(const tcu::ConstPixelBufferAccess & sample,const glu::ShaderProgram & occluderProg,const glu::ShaderProgram & occludedProg)680 void BaseCase::logGeometry(const tcu::ConstPixelBufferAccess &sample, const glu::ShaderProgram &occluderProg,
681 const glu::ShaderProgram &occludedProg)
682 {
683 TestLog &log = m_testCtx.getLog();
684
685 log << TestLog::Section("Geometry", "Geometry");
686 log << TestLog::Message << "Occluding geometry is green with shade dependent on depth (rgb == 0, depth, 0)"
687 << TestLog::EndMessage;
688 log << TestLog::Message << "Occluded geometry is red with shade dependent on depth (rgb == depth, 0, 0)"
689 << TestLog::EndMessage;
690 log << TestLog::Message << "Primitive edges are a lighter shade of red/green" << TestLog::EndMessage;
691
692 log << TestLog::Image("Test Geometry", "Test Geometry", sample);
693 log << TestLog::EndSection;
694
695 log << TestLog::Section("Occluder", "Occluder");
696 log << occluderProg;
697 log << TestLog::EndSection;
698
699 log << TestLog::Section("Occluded", "Occluded");
700 log << occludedProg;
701 log << TestLog::EndSection;
702 }
703
render(const RenderData & data) const704 void BaseCase::render(const RenderData &data) const
705 {
706 const glw::Functions &gl = m_renderCtx.getFunctions();
707
708 gl.useProgram(data.m_program.getProgram());
709
710 gl.bindVertexArray(*data.m_vao);
711 gl.drawArrays(GL_TRIANGLES, 0, data.m_numVertices);
712 gl.bindVertexArray(0);
713 }
714
render(const RenderData & data,int instances) const715 void BaseCase::render(const RenderData &data, int instances) const
716 {
717 const glw::Functions &gl = m_renderCtx.getFunctions();
718
719 gl.useProgram(data.m_program.getProgram());
720
721 gl.bindVertexArray(*data.m_vao);
722 gl.drawArraysInstanced(GL_TRIANGLES, 0, data.m_numVertices, instances);
723 gl.bindVertexArray(0);
724 }
725
726 // Render occluder once, then repeatedly render occluded geometry. Sample with multiple repetition counts & establish time per call with linear regression
727 class RenderCountCase : public BaseCase
728 {
729 public:
730 RenderCountCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name, const char *desc);
~RenderCountCase(void)731 ~RenderCountCase(void)
732 {
733 }
734
735 protected:
736 virtual void logAnalysis(const vector<Sample> &samples);
737
738 private:
739 virtual int calibrate(void) const;
740 virtual Sample renderSample(const RenderData &occluder, const RenderData &occluded, int callcount) const;
741 };
742
RenderCountCase(TestContext & testCtx,const RenderContext & renderCtx,const char * name,const char * desc)743 RenderCountCase::RenderCountCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name,
744 const char *desc)
745 : BaseCase(testCtx, renderCtx, name, desc)
746 {
747 }
748
logAnalysis(const vector<Sample> & samples)749 void RenderCountCase::logAnalysis(const vector<Sample> &samples)
750 {
751 using namespace gls;
752
753 TestLog &log = m_testCtx.getLog();
754 int maxWorkload = 0;
755 vector<Vec2> testSamples(samples.size());
756
757 for (size_t ndx = 0; ndx < samples.size(); ndx++)
758 {
759 const Sample &sample = samples[ndx];
760
761 testSamples[ndx] = Vec2((float)sample.workload, (float)sample.testTime);
762
763 maxWorkload = de::max(maxWorkload, sample.workload);
764 }
765
766 {
767 const float confidence = 0.60f;
768 const LineParametersWithConfidence testParam = theilSenSiegelLinearRegression(testSamples, confidence);
769 const float usPerCall = testParam.coefficient;
770 const float pxPerCall = RENDER_SIZE * RENDER_SIZE;
771 const float pxPerUs = pxPerCall / usPerCall;
772 const float mpxPerS = pxPerUs;
773
774 log << TestLog::Section("Linear Regression", "Linear Regression");
775 log << TestLog::Message
776 << "Offset & coefficient presented as [confidence interval min, estimate, confidence interval max]. "
777 "Reported confidence interval for this test is "
778 << confidence << TestLog::EndMessage;
779 log << TestLog::Message << "Render time for scene with depth test was\n\t"
780 << "[" << testParam.offsetConfidenceLower << ", " << testParam.offset << ", "
781 << testParam.offsetConfidenceUpper << "]us +"
782 << "[" << testParam.coefficientConfidenceLower << ", " << testParam.coefficient << ", "
783 << testParam.coefficientConfidenceUpper << "]"
784 << "us/workload" << TestLog::EndMessage;
785 log << TestLog::EndSection;
786
787 log << TestLog::Section("Result", "Result");
788
789 if (testParam.coefficientConfidenceLower < 0.0f)
790 {
791 log << TestLog::Message
792 << "Coefficient confidence bounds include values below 0.0, the operation likely has neglible "
793 "per-pixel cost"
794 << TestLog::EndMessage;
795 m_results.addResult(QP_TEST_RESULT_PASS, "Pass");
796 }
797 else if (testParam.coefficientConfidenceLower < testParam.coefficientConfidenceUpper * 0.25)
798 {
799 log << TestLog::Message << "Coefficient confidence range is extremely large, cannot give reliable result"
800 << TestLog::EndMessage;
801 m_results.addResult(QP_TEST_RESULT_PASS, "Result confidence extremely low");
802 }
803 else
804 {
805 log << TestLog::Message << "Culled hidden pixels @ " << mpxPerS << "Mpx/s" << TestLog::EndMessage;
806 m_results.addResult(QP_TEST_RESULT_PASS, de::floatToString(mpxPerS, 2));
807 }
808
809 log << TestLog::EndSection;
810 }
811 }
812
renderSample(const RenderData & occluder,const RenderData & occluded,int callcount) const813 Sample RenderCountCase::renderSample(const RenderData &occluder, const RenderData &occluded, int callcount) const
814 {
815 const glw::Functions &gl = m_renderCtx.getFunctions();
816 Sample sample;
817 uint64_t now = 0;
818 uint64_t prev = 0;
819 uint8_t buffer[4];
820
821 // Stabilize
822 {
823 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
824 gl.enable(GL_DEPTH_TEST);
825 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
826 }
827
828 prev = deGetMicroseconds();
829
830 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
831 gl.enable(GL_DEPTH_TEST);
832
833 render(occluder);
834 render(occluded, callcount);
835
836 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
837
838 now = deGetMicroseconds();
839
840 sample.testTime = now - prev;
841 sample.baseTime = 0;
842 sample.nullTime = 0;
843 sample.workload = callcount;
844
845 return sample;
846 }
847
calibrate(void) const848 int RenderCountCase::calibrate(void) const
849 {
850 using namespace gls;
851
852 const glw::Functions &gl = m_renderCtx.getFunctions();
853 TestLog &log = m_testCtx.getLog();
854
855 const RenderData occluderGeometry(genOccluderGeometry(), m_renderCtx, log);
856 const RenderData occludedGeometry(genOccludedGeometry(), m_renderCtx, log);
857
858 TheilSenCalibrator calibrator(CalibratorParameters(20, // Initial workload
859 10, // Max iteration frames
860 20.0f, // Iteration shortcut threshold ms
861 20, // Max iterations
862 33.0f, // Target frame time
863 40.0f, // Frame time cap
864 1000.0f // Target measurement duration
865 ));
866
867 while (true)
868 {
869 switch (calibrator.getState())
870 {
871 case TheilSenCalibrator::STATE_FINISHED:
872 logCalibrationInfo(m_testCtx.getLog(), calibrator);
873 return calibrator.getCallCount();
874
875 case TheilSenCalibrator::STATE_MEASURE:
876 {
877 uint8_t buffer[4];
878 int64_t now;
879 int64_t prev;
880
881 prev = deGetMicroseconds();
882
883 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
884 gl.disable(GL_DEPTH_TEST);
885
886 render(occluderGeometry);
887 render(occludedGeometry, calibrator.getCallCount());
888
889 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
890
891 now = deGetMicroseconds();
892
893 calibrator.recordIteration(now - prev);
894 break;
895 }
896
897 case TheilSenCalibrator::STATE_RECOMPUTE_PARAMS:
898 calibrator.recomputeParameters();
899 break;
900 default:
901 DE_ASSERT(false);
902 return 1;
903 }
904 }
905 }
906
907 // Compares time/workload gradients of same geometry with and without depth testing
908 class RelativeChangeCase : public BaseCase
909 {
910 public:
911 RelativeChangeCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name, const char *desc);
~RelativeChangeCase(void)912 virtual ~RelativeChangeCase(void)
913 {
914 }
915
916 protected:
917 Sample renderSample(const RenderData &occluder, const RenderData &occluded, int workload) const;
918
919 virtual void logAnalysis(const vector<Sample> &samples);
920
921 private:
922 int calibrate(void) const;
923 };
924
RelativeChangeCase(TestContext & testCtx,const RenderContext & renderCtx,const char * name,const char * desc)925 RelativeChangeCase::RelativeChangeCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name,
926 const char *desc)
927 : BaseCase(testCtx, renderCtx, name, desc)
928 {
929 }
930
calibrate(void) const931 int RelativeChangeCase::calibrate(void) const
932 {
933 using namespace gls;
934
935 const glw::Functions &gl = m_renderCtx.getFunctions();
936 TestLog &log = m_testCtx.getLog();
937
938 const RenderData geom(genOccludedGeometry(), m_renderCtx, log);
939
940 TheilSenCalibrator calibrator(CalibratorParameters(20, // Initial workload
941 10, // Max iteration frames
942 20.0f, // Iteration shortcut threshold ms
943 20, // Max iterations
944 33.0f, // Target frame time
945 40.0f, // Frame time cap
946 1000.0f // Target measurement duration
947 ));
948
949 while (true)
950 {
951 switch (calibrator.getState())
952 {
953 case TheilSenCalibrator::STATE_FINISHED:
954 logCalibrationInfo(m_testCtx.getLog(), calibrator);
955 return calibrator.getCallCount();
956
957 case TheilSenCalibrator::STATE_MEASURE:
958 {
959 uint8_t buffer[4];
960 const GLuint program = geom.m_program.getProgram();
961
962 gl.useProgram(program);
963 gl.uniform1i(gl.getUniformLocation(program, "u_iterations"), calibrator.getCallCount());
964
965 const int64_t prev = deGetMicroseconds();
966
967 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
968 gl.disable(GL_DEPTH_TEST);
969
970 render(geom);
971
972 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
973
974 const int64_t now = deGetMicroseconds();
975
976 calibrator.recordIteration(now - prev);
977 break;
978 }
979
980 case TheilSenCalibrator::STATE_RECOMPUTE_PARAMS:
981 calibrator.recomputeParameters();
982 break;
983 default:
984 DE_ASSERT(false);
985 return 1;
986 }
987 }
988 }
989
renderSample(const RenderData & occluder,const RenderData & occluded,int workload) const990 Sample RelativeChangeCase::renderSample(const RenderData &occluder, const RenderData &occluded, int workload) const
991 {
992 const glw::Functions &gl = m_renderCtx.getFunctions();
993 const GLuint program = occluded.m_program.getProgram();
994 Sample sample;
995 uint64_t now = 0;
996 uint64_t prev = 0;
997 uint8_t buffer[4];
998
999 gl.useProgram(program);
1000 gl.uniform1i(gl.getUniformLocation(program, "u_iterations"), workload);
1001
1002 // Warmup (this workload seems to reduce variation in following workloads)
1003 {
1004 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1005 gl.disable(GL_DEPTH_TEST);
1006
1007 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
1008 }
1009
1010 // Null time
1011 {
1012 prev = deGetMicroseconds();
1013
1014 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1015 gl.disable(GL_DEPTH_TEST);
1016
1017 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
1018
1019 now = deGetMicroseconds();
1020
1021 sample.nullTime = now - prev;
1022 }
1023
1024 // Test time
1025 {
1026 prev = deGetMicroseconds();
1027
1028 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1029 gl.enable(GL_DEPTH_TEST);
1030
1031 render(occluder);
1032 render(occluded);
1033
1034 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
1035
1036 now = deGetMicroseconds();
1037
1038 sample.testTime = now - prev;
1039 }
1040
1041 // Base time
1042 {
1043 prev = deGetMicroseconds();
1044
1045 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1046 gl.disable(GL_DEPTH_TEST);
1047
1048 render(occluder);
1049 render(occluded);
1050
1051 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
1052
1053 now = deGetMicroseconds();
1054
1055 sample.baseTime = now - prev;
1056 }
1057
1058 sample.workload = 0;
1059
1060 return sample;
1061 }
1062
logAnalysis(const vector<Sample> & samples)1063 void RelativeChangeCase::logAnalysis(const vector<Sample> &samples)
1064 {
1065 using namespace gls;
1066
1067 TestLog &log = m_testCtx.getLog();
1068
1069 int maxWorkload = 0;
1070
1071 vector<Vec2> nullSamples(samples.size());
1072 vector<Vec2> baseSamples(samples.size());
1073 vector<Vec2> testSamples(samples.size());
1074
1075 for (size_t ndx = 0; ndx < samples.size(); ndx++)
1076 {
1077 const Sample &sample = samples[ndx];
1078
1079 nullSamples[ndx] = Vec2((float)sample.workload, (float)sample.nullTime);
1080 baseSamples[ndx] = Vec2((float)sample.workload, (float)sample.baseTime);
1081 testSamples[ndx] = Vec2((float)sample.workload, (float)sample.testTime);
1082
1083 maxWorkload = de::max(maxWorkload, sample.workload);
1084 }
1085
1086 {
1087 const float confidence = 0.60f;
1088
1089 const LineParametersWithConfidence nullParam = theilSenSiegelLinearRegression(nullSamples, confidence);
1090 const LineParametersWithConfidence baseParam = theilSenSiegelLinearRegression(baseSamples, confidence);
1091 const LineParametersWithConfidence testParam = theilSenSiegelLinearRegression(testSamples, confidence);
1092
1093 if (!de::inRange(0.0f, nullParam.coefficientConfidenceLower, nullParam.coefficientConfidenceUpper))
1094 {
1095 m_results.addResult(QP_TEST_RESULT_FAIL, "Constant operation sequence duration not constant");
1096 log << TestLog::Message
1097 << "Constant operation sequence timing may vary as a function of workload. Result quality extremely low"
1098 << TestLog::EndMessage;
1099 }
1100
1101 if (de::inRange(0.0f, baseParam.coefficientConfidenceLower, baseParam.coefficientConfidenceUpper))
1102 {
1103 m_results.addResult(QP_TEST_RESULT_FAIL, "Workload has no effect on duration");
1104 log << TestLog::Message << "Workload factor has no effect on duration of sample (smart optimizer?)"
1105 << TestLog::EndMessage;
1106 }
1107
1108 log << TestLog::Section("Linear Regression", "Linear Regression");
1109 log << TestLog::Message
1110 << "Offset & coefficient presented as [confidence interval min, estimate, confidence interval max]. "
1111 "Reported confidence interval for this test is "
1112 << confidence << TestLog::EndMessage;
1113
1114 log << TestLog::Message << "Render time for empty scene was\n\t"
1115 << "[" << nullParam.offsetConfidenceLower << ", " << nullParam.offset << ", "
1116 << nullParam.offsetConfidenceUpper << "]us +"
1117 << "[" << nullParam.coefficientConfidenceLower << ", " << nullParam.coefficient << ", "
1118 << nullParam.coefficientConfidenceUpper << "]"
1119 << "us/workload" << TestLog::EndMessage;
1120
1121 log << TestLog::Message << "Render time for scene without depth test was\n\t"
1122 << "[" << baseParam.offsetConfidenceLower << ", " << baseParam.offset << ", "
1123 << baseParam.offsetConfidenceUpper << "]us +"
1124 << "[" << baseParam.coefficientConfidenceLower << ", " << baseParam.coefficient << ", "
1125 << baseParam.coefficientConfidenceUpper << "]"
1126 << "us/workload" << TestLog::EndMessage;
1127
1128 log << TestLog::Message << "Render time for scene with depth test was\n\t"
1129 << "[" << testParam.offsetConfidenceLower << ", " << testParam.offset << ", "
1130 << testParam.offsetConfidenceUpper << "]us +"
1131 << "[" << testParam.coefficientConfidenceLower << ", " << testParam.coefficient << ", "
1132 << testParam.coefficientConfidenceUpper << "]"
1133 << "us/workload" << TestLog::EndMessage;
1134
1135 log << TestLog::EndSection;
1136
1137 if (de::inRange(0.0f, testParam.coefficientConfidenceLower, testParam.coefficientConfidenceUpper))
1138 {
1139 log << TestLog::Message << "Test duration not dependent on culled workload" << TestLog::EndMessage;
1140 m_results.addResult(QP_TEST_RESULT_PASS, "0.0");
1141 }
1142 else if (testParam.coefficientConfidenceLower < testParam.coefficientConfidenceUpper * 0.25)
1143 {
1144 log << TestLog::Message << "Coefficient confidence range is extremely large, cannot give reliable result"
1145 << TestLog::EndMessage;
1146 m_results.addResult(QP_TEST_RESULT_PASS, "Result confidence extremely low");
1147 }
1148 else if (baseParam.coefficientConfidenceLower < baseParam.coefficientConfidenceUpper * 0.25)
1149 {
1150 log << TestLog::Message
1151 << "Coefficient confidence range for base render time is extremely large, cannot give reliable result"
1152 << TestLog::EndMessage;
1153 m_results.addResult(QP_TEST_RESULT_PASS, "Result confidence extremely low");
1154 }
1155 else
1156 {
1157 log << TestLog::Message << "Test duration is dependent on culled workload" << TestLog::EndMessage;
1158 m_results.addResult(QP_TEST_RESULT_PASS,
1159 de::floatToString(de::abs(testParam.coefficient) / de::abs(baseParam.coefficient), 2));
1160 }
1161 }
1162 }
1163
1164 // Speed of trivial culling
1165 class BaseCostCase : public RenderCountCase
1166 {
1167 public:
BaseCostCase(TestContext & testCtx,const RenderContext & renderCtx,const char * name,const char * desc)1168 BaseCostCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name, const char *desc)
1169 : RenderCountCase(testCtx, renderCtx, name, desc)
1170 {
1171 }
1172
~BaseCostCase(void)1173 ~BaseCostCase(void)
1174 {
1175 }
1176
1177 private:
genOccluderGeometry(void) const1178 virtual ObjectData genOccluderGeometry(void) const
1179 {
1180 return Utils::fastQuad(0.2f);
1181 }
genOccludedGeometry(void) const1182 virtual ObjectData genOccludedGeometry(void) const
1183 {
1184 return Utils::variableQuad(0.8f);
1185 }
1186
logDescription(void)1187 virtual void logDescription(void)
1188 {
1189 TestLog &log = m_testCtx.getLog();
1190
1191 log << TestLog::Section("Description", "Test description");
1192 log << TestLog::Message << "Testing hidden fragment culling speed" << TestLog::EndMessage;
1193 log << TestLog::Message
1194 << "Geometry consists of two fullsceen quads. The first (occluding) is rendered once, the second "
1195 "(occluded) is rendered repeatedly"
1196 << TestLog::EndMessage;
1197 log << TestLog::Message << "Workload indicates the number of times the occluded quad is rendered"
1198 << TestLog::EndMessage;
1199 log << TestLog::Message
1200 << "The time per culled pixel is estimated from the rate of change of rendering time as a function of "
1201 "workload"
1202 << TestLog::EndMessage;
1203 log << TestLog::EndSection;
1204 }
1205 };
1206
1207 // Gradient
1208 class GradientCostCase : public RenderCountCase
1209 {
1210 public:
GradientCostCase(TestContext & testCtx,const RenderContext & renderCtx,const char * name,const char * desc,float gradientDistance)1211 GradientCostCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name, const char *desc,
1212 float gradientDistance)
1213 : RenderCountCase(testCtx, renderCtx, name, desc)
1214 , m_gradientDistance(gradientDistance)
1215 {
1216 }
1217
~GradientCostCase(void)1218 ~GradientCostCase(void)
1219 {
1220 }
1221
1222 private:
genOccluderGeometry(void) const1223 virtual ObjectData genOccluderGeometry(void) const
1224 {
1225 return Utils::fastQuadWithGradient(0.0f, 1.0f - m_gradientDistance);
1226 }
genOccludedGeometry(void) const1227 virtual ObjectData genOccludedGeometry(void) const
1228 {
1229 return ObjectData(
1230 glu::makeVtxFragSources(Utils::getInstanceNoiseVertexShader(), Utils::getDepthAsRedFragmentShader()),
1231 Utils::getFullscreenQuadWithGradient(m_gradientDistance, 1.0f));
1232 }
1233
logDescription(void)1234 virtual void logDescription(void)
1235 {
1236 TestLog &log = m_testCtx.getLog();
1237
1238 log << TestLog::Section("Description", "Test description");
1239 log << TestLog::Message << "Testing hidden fragment culling speed" << TestLog::EndMessage;
1240 log << TestLog::Message
1241 << "Geometry consists of two fullsceen quads. The first (occluding) is rendered once, the second "
1242 "(occluded) is rendered repeatedly"
1243 << TestLog::EndMessage;
1244 log << TestLog::Message << "Workload indicates the number of times the occluded quad is rendered"
1245 << TestLog::EndMessage;
1246 log << TestLog::Message
1247 << "The quads are tilted so that the left edge of the occluded quad has a depth of 1.0 and the right edge "
1248 "of the occluding quad has a depth of 0.0."
1249 << TestLog::EndMessage;
1250 log << TestLog::Message << "The quads are spaced to have a depth difference of " << m_gradientDistance
1251 << " at all points." << TestLog::EndMessage;
1252 log << TestLog::Message
1253 << "The time per culled pixel is estimated from the rate of change of rendering time as a function of "
1254 "workload"
1255 << TestLog::EndMessage;
1256 log << TestLog::EndSection;
1257 }
1258
1259 const float m_gradientDistance;
1260 };
1261
1262 // Constant offset to frag depth in occluder
1263 class OccluderStaticFragDepthCostCase : public RenderCountCase
1264 {
1265 public:
OccluderStaticFragDepthCostCase(TestContext & testCtx,const RenderContext & renderCtx,const char * name,const char * desc)1266 OccluderStaticFragDepthCostCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name,
1267 const char *desc)
1268 : RenderCountCase(testCtx, renderCtx, name, desc)
1269 {
1270 }
1271
~OccluderStaticFragDepthCostCase(void)1272 ~OccluderStaticFragDepthCostCase(void)
1273 {
1274 }
1275
1276 private:
genOccluderGeometry(void) const1277 virtual ObjectData genOccluderGeometry(void) const
1278 {
1279 return Utils::quadWith(Utils::getStaticFragDepthFragmentShader(), 0.2f);
1280 }
genOccludedGeometry(void) const1281 virtual ObjectData genOccludedGeometry(void) const
1282 {
1283 return Utils::fastQuad(0.8f);
1284 }
1285
logDescription(void)1286 virtual void logDescription(void)
1287 {
1288 TestLog &log = m_testCtx.getLog();
1289
1290 log << TestLog::Section("Description", "Test description");
1291 log << TestLog::Message << "Testing hidden fragment culling speed" << TestLog::EndMessage;
1292 log << TestLog::Message
1293 << "Geometry consists of two fullsceen quads. The first (occluding) is rendered once, the second "
1294 "(occluded) is rendered repeatedly"
1295 << TestLog::EndMessage;
1296 log << TestLog::Message << "Workload indicates the number of times the occluded quad is rendered"
1297 << TestLog::EndMessage;
1298 log << TestLog::Message << "The occluder quad has a static offset applied to gl_FragDepth"
1299 << TestLog::EndMessage;
1300 log << TestLog::Message
1301 << "The time per culled pixel is estimated from the rate of change of rendering time as a function of "
1302 "workload"
1303 << TestLog::EndMessage;
1304 log << TestLog::EndSection;
1305 }
1306 };
1307
1308 // Dynamic offset to frag depth in occluder
1309 class OccluderDynamicFragDepthCostCase : public RenderCountCase
1310 {
1311 public:
OccluderDynamicFragDepthCostCase(TestContext & testCtx,const RenderContext & renderCtx,const char * name,const char * desc)1312 OccluderDynamicFragDepthCostCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name,
1313 const char *desc)
1314 : RenderCountCase(testCtx, renderCtx, name, desc)
1315 {
1316 }
1317
~OccluderDynamicFragDepthCostCase(void)1318 ~OccluderDynamicFragDepthCostCase(void)
1319 {
1320 }
1321
1322 private:
genOccluderGeometry(void) const1323 virtual ObjectData genOccluderGeometry(void) const
1324 {
1325 return Utils::quadWith(Utils::getDynamicFragDepthFragmentShader(), 0.2f);
1326 }
genOccludedGeometry(void) const1327 virtual ObjectData genOccludedGeometry(void) const
1328 {
1329 return Utils::fastQuad(0.8f);
1330 }
1331
logDescription(void)1332 virtual void logDescription(void)
1333 {
1334 TestLog &log = m_testCtx.getLog();
1335
1336 log << TestLog::Section("Description", "Test description");
1337 log << TestLog::Message << "Testing hidden fragment culling speed" << TestLog::EndMessage;
1338 log << TestLog::Message
1339 << "Geometry consists of two fullsceen quads. The first (occluding) is rendered once, the second "
1340 "(occluded) is rendered repeatedly"
1341 << TestLog::EndMessage;
1342 log << TestLog::Message << "Workload indicates the number of times the occluded quad is rendered"
1343 << TestLog::EndMessage;
1344 log << TestLog::Message << "The occluder quad has a dynamic offset applied to gl_FragDepth"
1345 << TestLog::EndMessage;
1346 log << TestLog::Message
1347 << "The time per culled pixel is estimated from the rate of change of rendering time as a function of "
1348 "workload"
1349 << TestLog::EndMessage;
1350 log << TestLog::EndSection;
1351 }
1352 };
1353
1354 // Constant offset to frag depth in occluder
1355 class OccludedStaticFragDepthCostCase : public RenderCountCase
1356 {
1357 public:
OccludedStaticFragDepthCostCase(TestContext & testCtx,const RenderContext & renderCtx,const char * name,const char * desc)1358 OccludedStaticFragDepthCostCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name,
1359 const char *desc)
1360 : RenderCountCase(testCtx, renderCtx, name, desc)
1361 {
1362 }
1363
~OccludedStaticFragDepthCostCase(void)1364 ~OccludedStaticFragDepthCostCase(void)
1365 {
1366 }
1367
1368 private:
genOccluderGeometry(void) const1369 virtual ObjectData genOccluderGeometry(void) const
1370 {
1371 return Utils::fastQuad(0.2f);
1372 }
genOccludedGeometry(void) const1373 virtual ObjectData genOccludedGeometry(void) const
1374 {
1375 return Utils::quadWith(Utils::getStaticFragDepthFragmentShader(), 0.2f);
1376 }
1377
logDescription(void)1378 virtual void logDescription(void)
1379 {
1380 TestLog &log = m_testCtx.getLog();
1381
1382 log << TestLog::Section("Description", "Test description");
1383 log << TestLog::Message << "Testing hidden fragment culling speed" << TestLog::EndMessage;
1384 log << TestLog::Message
1385 << "Geometry consists of two fullsceen quads. The first (occluding) is rendered once, the second "
1386 "(occluded) is rendered repeatedly"
1387 << TestLog::EndMessage;
1388 log << TestLog::Message << "Workload indicates the number of times the occluded quad is rendered"
1389 << TestLog::EndMessage;
1390 log << TestLog::Message << "The occluded quad has a static offset applied to gl_FragDepth"
1391 << TestLog::EndMessage;
1392 log << TestLog::Message
1393 << "The time per culled pixel is estimated from the rate of change of rendering time as a function of "
1394 "workload"
1395 << TestLog::EndMessage;
1396 log << TestLog::EndSection;
1397 }
1398 };
1399
1400 // Dynamic offset to frag depth in occluder
1401 class OccludedDynamicFragDepthCostCase : public RenderCountCase
1402 {
1403 public:
OccludedDynamicFragDepthCostCase(TestContext & testCtx,const RenderContext & renderCtx,const char * name,const char * desc)1404 OccludedDynamicFragDepthCostCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name,
1405 const char *desc)
1406 : RenderCountCase(testCtx, renderCtx, name, desc)
1407 {
1408 }
1409
~OccludedDynamicFragDepthCostCase(void)1410 ~OccludedDynamicFragDepthCostCase(void)
1411 {
1412 }
1413
1414 private:
genOccluderGeometry(void) const1415 virtual ObjectData genOccluderGeometry(void) const
1416 {
1417 return Utils::fastQuad(0.2f);
1418 }
genOccludedGeometry(void) const1419 virtual ObjectData genOccludedGeometry(void) const
1420 {
1421 return Utils::quadWith(Utils::getDynamicFragDepthFragmentShader(), 0.2f);
1422 }
1423
logDescription(void)1424 virtual void logDescription(void)
1425 {
1426 TestLog &log = m_testCtx.getLog();
1427
1428 log << TestLog::Section("Description", "Test description");
1429 log << TestLog::Message << "Testing hidden fragment culling speed" << TestLog::EndMessage;
1430 log << TestLog::Message
1431 << "Geometry consists of two fullsceen quads. The first (occluding) is rendered once, the second "
1432 "(occluded) is rendered repeatedly"
1433 << TestLog::EndMessage;
1434 log << TestLog::Message << "Workload indicates the number of times the occluded quad is rendered"
1435 << TestLog::EndMessage;
1436 log << TestLog::Message << "The occluded quad has a dynamic offset applied to gl_FragDepth"
1437 << TestLog::EndMessage;
1438 log << TestLog::Message
1439 << "The time per culled pixel is estimated from the rate of change of rendering time as a function of "
1440 "workload"
1441 << TestLog::EndMessage;
1442 log << TestLog::EndSection;
1443 }
1444 };
1445
1446 // Culling speed with slightly less trivial geometry
1447 class OccludingGeometryComplexityCostCase : public RenderCountCase
1448 {
1449 public:
OccludingGeometryComplexityCostCase(TestContext & testCtx,const RenderContext & renderCtx,const char * name,const char * desc,int resolution,float xyNoise,float zNoise)1450 OccludingGeometryComplexityCostCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name,
1451 const char *desc, int resolution, float xyNoise, float zNoise)
1452 : RenderCountCase(testCtx, renderCtx, name, desc)
1453 , m_resolution(resolution)
1454 , m_xyNoise(xyNoise)
1455 , m_zNoise(zNoise)
1456 {
1457 }
1458
~OccludingGeometryComplexityCostCase(void)1459 ~OccludingGeometryComplexityCostCase(void)
1460 {
1461 }
1462
1463 private:
genOccluderGeometry(void) const1464 virtual ObjectData genOccluderGeometry(void) const
1465 {
1466 return ObjectData(Utils::getBaseShader(), Utils::getFullScreenGrid(m_resolution,
1467 deInt32Hash(deStringHash(getName())) ^
1468 m_testCtx.getCommandLine().getBaseSeed(),
1469 0.2f, m_zNoise, m_xyNoise));
1470 }
1471
genOccludedGeometry(void) const1472 virtual ObjectData genOccludedGeometry(void) const
1473 {
1474 return Utils::variableQuad(0.8f);
1475 }
1476
logDescription(void)1477 virtual void logDescription(void)
1478 {
1479 TestLog &log = m_testCtx.getLog();
1480
1481 log << TestLog::Section("Description", "Test description");
1482 log << TestLog::Message << "Testing hidden fragment culling speed" << TestLog::EndMessage;
1483 log << TestLog::Message
1484 << "Geometry consists of an occluding grid and an occluded fullsceen quad. The occluding geometry is "
1485 "rendered once, the occluded one is rendered repeatedly"
1486 << TestLog::EndMessage;
1487 log << TestLog::Message << "Workload indicates the number of times the occluded quad is rendered"
1488 << TestLog::EndMessage;
1489 log << TestLog::Message
1490 << "The time per culled pixel is estimated from the rate of change of rendering time as a function of "
1491 "workload"
1492 << TestLog::EndMessage;
1493 log << TestLog::EndSection;
1494 }
1495
1496 const int m_resolution;
1497 const float m_xyNoise;
1498 const float m_zNoise;
1499 };
1500
1501 // Cases with varying workloads in the fragment shader
1502 class FragmentWorkloadCullCase : public RelativeChangeCase
1503 {
1504 public:
1505 FragmentWorkloadCullCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name, const char *desc);
~FragmentWorkloadCullCase(void)1506 virtual ~FragmentWorkloadCullCase(void)
1507 {
1508 }
1509
1510 private:
genOccluderGeometry(void) const1511 virtual ObjectData genOccluderGeometry(void) const
1512 {
1513 return Utils::fastQuad(0.2f);
1514 }
1515
1516 virtual void logDescription(void);
1517 };
1518
FragmentWorkloadCullCase(TestContext & testCtx,const RenderContext & renderCtx,const char * name,const char * desc)1519 FragmentWorkloadCullCase::FragmentWorkloadCullCase(TestContext &testCtx, const RenderContext &renderCtx,
1520 const char *name, const char *desc)
1521 : RelativeChangeCase(testCtx, renderCtx, name, desc)
1522 {
1523 }
1524
logDescription(void)1525 void FragmentWorkloadCullCase::logDescription(void)
1526 {
1527 TestLog &log = m_testCtx.getLog();
1528
1529 log << TestLog::Section("Description", "Test description");
1530 log << TestLog::Message << "Testing effects of culled fragment workload on render time" << TestLog::EndMessage;
1531 log << TestLog::Message
1532 << "Geometry consists of two fullsceen quads. The first (occluding) quad uses a trivial shader,"
1533 "the second (occluded) contains significant fragment shader work"
1534 << TestLog::EndMessage;
1535 log << TestLog::Message
1536 << "Workload indicates the number of iterations of unused work done in the occluded quad's fragment shader"
1537 << TestLog::EndMessage;
1538 log << TestLog::Message << "The ratio of rendering times of this scene with/without depth testing are compared"
1539 << TestLog::EndMessage;
1540 log << TestLog::Message
1541 << "Successfull early Z-testing should result in no correlation between workload and render time"
1542 << TestLog::EndMessage;
1543 log << TestLog::EndSection;
1544 }
1545
1546 // Additional workload consists of texture lookups
1547 class FragmentTextureWorkloadCullCase : public FragmentWorkloadCullCase
1548 {
1549 public:
1550 FragmentTextureWorkloadCullCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name,
1551 const char *desc);
~FragmentTextureWorkloadCullCase(void)1552 virtual ~FragmentTextureWorkloadCullCase(void)
1553 {
1554 }
1555
1556 virtual void init(void);
1557 virtual void deinit(void);
1558
1559 private:
1560 typedef MovePtr<glu::Texture> TexPtr;
1561
genOccludedGeometry(void) const1562 virtual ObjectData genOccludedGeometry(void) const
1563 {
1564 return ObjectData(Utils::getTextureWorkloadShader(), Utils::getFullscreenQuad(0.8f));
1565 }
1566
1567 TexPtr m_texture;
1568 };
1569
FragmentTextureWorkloadCullCase(TestContext & testCtx,const RenderContext & renderCtx,const char * name,const char * desc)1570 FragmentTextureWorkloadCullCase::FragmentTextureWorkloadCullCase(TestContext &testCtx, const RenderContext &renderCtx,
1571 const char *name, const char *desc)
1572 : FragmentWorkloadCullCase(testCtx, renderCtx, name, desc)
1573 {
1574 }
1575
init(void)1576 void FragmentTextureWorkloadCullCase::init(void)
1577 {
1578 const glw::Functions &gl = m_renderCtx.getFunctions();
1579 const int size = 128;
1580 const vector<uint8_t> data(size * size * 4, 255);
1581
1582 m_texture = MovePtr<glu::Texture>(new glu::Texture(gl));
1583
1584 gl.bindTexture(GL_TEXTURE_2D, m_texture);
1585 gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
1586 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1587 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1588 }
1589
deinit(void)1590 void FragmentTextureWorkloadCullCase::deinit(void)
1591 {
1592 m_texture.clear();
1593 }
1594
1595 // Additional workload consists of arithmetic
1596 class FragmentArithmeticWorkloadCullCase : public FragmentWorkloadCullCase
1597 {
1598 public:
FragmentArithmeticWorkloadCullCase(TestContext & testCtx,const RenderContext & renderCtx,const char * name,const char * desc)1599 FragmentArithmeticWorkloadCullCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name,
1600 const char *desc)
1601 : FragmentWorkloadCullCase(testCtx, renderCtx, name, desc)
1602 {
1603 }
~FragmentArithmeticWorkloadCullCase(void)1604 virtual ~FragmentArithmeticWorkloadCullCase(void)
1605 {
1606 }
1607
1608 private:
genOccludedGeometry(void) const1609 virtual ObjectData genOccludedGeometry(void) const
1610 {
1611 return ObjectData(Utils::getArithmeticWorkloadShader(), Utils::getFullscreenQuad(0.8f));
1612 }
1613 };
1614
1615 // Contains dynamicly unused discard after a series of calculations
1616 class FragmentDiscardArithmeticWorkloadCullCase : public FragmentWorkloadCullCase
1617 {
1618 public:
FragmentDiscardArithmeticWorkloadCullCase(TestContext & testCtx,const RenderContext & renderCtx,const char * name,const char * desc)1619 FragmentDiscardArithmeticWorkloadCullCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name,
1620 const char *desc)
1621 : FragmentWorkloadCullCase(testCtx, renderCtx, name, desc)
1622 {
1623 }
1624
~FragmentDiscardArithmeticWorkloadCullCase(void)1625 virtual ~FragmentDiscardArithmeticWorkloadCullCase(void)
1626 {
1627 }
1628
1629 private:
genOccludedGeometry(void) const1630 virtual ObjectData genOccludedGeometry(void) const
1631 {
1632 return ObjectData(Utils::getArithmeticWorkloadDiscardShader(), Utils::getFullscreenQuad(0.8f));
1633 }
1634
logDescription(void)1635 virtual void logDescription(void)
1636 {
1637 TestLog &log = m_testCtx.getLog();
1638
1639 log << TestLog::Section("Description", "Test description");
1640 log << TestLog::Message << "Testing effects of culled fragment workload on render time" << TestLog::EndMessage;
1641 log << TestLog::Message
1642 << "Geometry consists of two fullsceen quads. The first (occluding) quad uses a trivial shader,"
1643 "the second (occluded) contains significant fragment shader work and a discard that is never triggers "
1644 "but has a dynamic condition"
1645 << TestLog::EndMessage;
1646 log << TestLog::Message
1647 << "Workload indicates the number of iterations of unused work done in the occluded quad's fragment shader"
1648 << TestLog::EndMessage;
1649 log << TestLog::Message << "The ratio of rendering times of this scene with/without depth testing are compared"
1650 << TestLog::EndMessage;
1651 log << TestLog::Message
1652 << "Successfull early Z-testing should result in no correlation between workload and render time"
1653 << TestLog::EndMessage;
1654 log << TestLog::EndSection;
1655 }
1656 };
1657
1658 // Discards fragments from the occluder in a grid pattern
1659 class PartialOccluderDiscardCullCase : public RelativeChangeCase
1660 {
1661 public:
PartialOccluderDiscardCullCase(TestContext & testCtx,const RenderContext & renderCtx,const char * name,const char * desc,int gridsize)1662 PartialOccluderDiscardCullCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name,
1663 const char *desc, int gridsize)
1664 : RelativeChangeCase(testCtx, renderCtx, name, desc)
1665 , m_gridsize(gridsize)
1666 {
1667 }
~PartialOccluderDiscardCullCase(void)1668 virtual ~PartialOccluderDiscardCullCase(void)
1669 {
1670 }
1671
1672 private:
genOccluderGeometry(void) const1673 virtual ObjectData genOccluderGeometry(void) const
1674 {
1675 return Utils::quadWith(Utils::getGridDiscardShader(m_gridsize), 0.2f);
1676 }
genOccludedGeometry(void) const1677 virtual ObjectData genOccludedGeometry(void) const
1678 {
1679 return Utils::slowQuad(0.8f);
1680 }
1681
logDescription(void)1682 virtual void logDescription(void)
1683 {
1684 TestLog &log = m_testCtx.getLog();
1685
1686 log << TestLog::Section("Description", "Test description");
1687 log << TestLog::Message << "Testing effects of partially discarded occluder on rendering time"
1688 << TestLog::EndMessage;
1689 log << TestLog::Message
1690 << "Geometry consists of two fullsceen quads. The first (occluding) quad discards half the "
1691 "fragments in a grid pattern, the second (partially occluded) contains significant fragment shader work"
1692 << TestLog::EndMessage;
1693 log << TestLog::Message
1694 << "Workload indicates the number of iterations of unused work done in the occluded quad's fragment shader"
1695 << TestLog::EndMessage;
1696 log << TestLog::Message << "The ratio of rendering times of this scene with/without depth testing are compared"
1697 << TestLog::EndMessage;
1698 log << TestLog::Message << "Successfull early Z-testing should result in depth testing halving the render time"
1699 << TestLog::EndMessage;
1700 log << TestLog::EndSection;
1701 }
1702
1703 const int m_gridsize;
1704 };
1705
1706 // Trivial occluder covering part of screen
1707 class PartialOccluderCullCase : public RelativeChangeCase
1708 {
1709 public:
PartialOccluderCullCase(TestContext & testCtx,const RenderContext & renderCtx,const char * name,const char * desc,float coverage)1710 PartialOccluderCullCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name, const char *desc,
1711 float coverage)
1712 : RelativeChangeCase(testCtx, renderCtx, name, desc)
1713 , m_coverage(coverage)
1714 {
1715 }
~PartialOccluderCullCase(void)1716 ~PartialOccluderCullCase(void)
1717 {
1718 }
1719
1720 private:
genOccluderGeometry(void) const1721 virtual ObjectData genOccluderGeometry(void) const
1722 {
1723 return ObjectData(Utils::getBaseShader(), Utils::getPartScreenQuad(m_coverage, 0.2f));
1724 }
genOccludedGeometry(void) const1725 virtual ObjectData genOccludedGeometry(void) const
1726 {
1727 return Utils::slowQuad(0.8f);
1728 }
1729
logDescription(void)1730 virtual void logDescription(void)
1731 {
1732 TestLog &log = m_testCtx.getLog();
1733
1734 log << TestLog::Section("Description", "Test description");
1735 log << TestLog::Message << "Testing effects of partial occluder on rendering time" << TestLog::EndMessage;
1736 log << TestLog::Message << "Geometry consists of two quads. The first (occluding) quad covers "
1737 << m_coverage * 100.0f
1738 << "% of the screen, while the second (partially occluded, fullscreen) contains significant fragment "
1739 "shader work"
1740 << TestLog::EndMessage;
1741 log << TestLog::Message
1742 << "Workload indicates the number of iterations of unused work done in the occluded quad's fragment shader"
1743 << TestLog::EndMessage;
1744 log << TestLog::Message << "The ratio of rendering times of this scene with/without depth testing are compared"
1745 << TestLog::EndMessage;
1746 log << TestLog::Message
1747 << "Successfull early Z-testing should result in render time increasing proportionally with unoccluded area"
1748 << TestLog::EndMessage;
1749 log << TestLog::EndSection;
1750 }
1751
1752 const float m_coverage;
1753 };
1754
1755 // Constant offset to frag depth in occluder
1756 class StaticOccluderFragDepthCullCase : public RelativeChangeCase
1757 {
1758 public:
StaticOccluderFragDepthCullCase(TestContext & testCtx,const RenderContext & renderCtx,const char * name,const char * desc)1759 StaticOccluderFragDepthCullCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name,
1760 const char *desc)
1761 : RelativeChangeCase(testCtx, renderCtx, name, desc)
1762 {
1763 }
1764
~StaticOccluderFragDepthCullCase(void)1765 ~StaticOccluderFragDepthCullCase(void)
1766 {
1767 }
1768
1769 private:
genOccluderGeometry(void) const1770 virtual ObjectData genOccluderGeometry(void) const
1771 {
1772 return Utils::quadWith(Utils::getStaticFragDepthFragmentShader(), 0.2f);
1773 }
genOccludedGeometry(void) const1774 virtual ObjectData genOccludedGeometry(void) const
1775 {
1776 return Utils::slowQuad(0.8f);
1777 }
1778
logDescription(void)1779 virtual void logDescription(void)
1780 {
1781 TestLog &log = m_testCtx.getLog();
1782
1783 log << TestLog::Section("Description", "Test description");
1784 log << TestLog::Message << "Testing effects of non-default frag depth on culling efficiency"
1785 << TestLog::EndMessage;
1786 log << TestLog::Message
1787 << "Geometry consists of two fullscreen quads. The first (occluding) quad is trivial, while the second "
1788 "(occluded) contains significant fragment shader work"
1789 << TestLog::EndMessage;
1790 log << TestLog::Message
1791 << "Workload indicates the number of iterations of unused work done in the occluded quad's fragment shader"
1792 << TestLog::EndMessage;
1793 log << TestLog::Message << "The occluder quad has a static offset applied to gl_FragDepth"
1794 << TestLog::EndMessage;
1795 log << TestLog::Message << "The ratio of rendering times of this scene with/without depth testing are compared"
1796 << TestLog::EndMessage;
1797 log << TestLog::Message
1798 << "Successfull early Z-testing should result in no correlation between workload and render time"
1799 << TestLog::EndMessage;
1800 log << TestLog::EndSection;
1801 }
1802 };
1803
1804 // Dynamic offset to frag depth in occluder
1805 class DynamicOccluderFragDepthCullCase : public RelativeChangeCase
1806 {
1807 public:
DynamicOccluderFragDepthCullCase(TestContext & testCtx,const RenderContext & renderCtx,const char * name,const char * desc)1808 DynamicOccluderFragDepthCullCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name,
1809 const char *desc)
1810 : RelativeChangeCase(testCtx, renderCtx, name, desc)
1811 {
1812 }
1813
~DynamicOccluderFragDepthCullCase(void)1814 ~DynamicOccluderFragDepthCullCase(void)
1815 {
1816 }
1817
1818 private:
genOccluderGeometry(void) const1819 virtual ObjectData genOccluderGeometry(void) const
1820 {
1821 return Utils::quadWith(Utils::getDynamicFragDepthFragmentShader(), 0.2f);
1822 }
genOccludedGeometry(void) const1823 virtual ObjectData genOccludedGeometry(void) const
1824 {
1825 return Utils::slowQuad(0.8f);
1826 }
1827
logDescription(void)1828 virtual void logDescription(void)
1829 {
1830 TestLog &log = m_testCtx.getLog();
1831
1832 log << TestLog::Section("Description", "Test description");
1833 log << TestLog::Message << "Testing effects of non-default frag depth on culling efficiency"
1834 << TestLog::EndMessage;
1835 log << TestLog::Message
1836 << "Geometry consists of two fullscreen quads. The first (occluding) quad is trivial, while the second "
1837 "(occluded) contains significant fragment shader work"
1838 << TestLog::EndMessage;
1839 log << TestLog::Message
1840 << "Workload indicates the number of iterations of unused work done in the occluded quad's fragment shader"
1841 << TestLog::EndMessage;
1842 log << TestLog::Message << "The occluder quad has a dynamic offset applied to gl_FragDepth"
1843 << TestLog::EndMessage;
1844 log << TestLog::Message << "The ratio of rendering times of this scene with/without depth testing are compared"
1845 << TestLog::EndMessage;
1846 log << TestLog::Message
1847 << "Successfull early Z-testing should result in no correlation between workload and render time"
1848 << TestLog::EndMessage;
1849 log << TestLog::EndSection;
1850 }
1851 };
1852
1853 // Constant offset to frag depth in occluded
1854 class StaticOccludedFragDepthCullCase : public RelativeChangeCase
1855 {
1856 public:
StaticOccludedFragDepthCullCase(TestContext & testCtx,const RenderContext & renderCtx,const char * name,const char * desc)1857 StaticOccludedFragDepthCullCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name,
1858 const char *desc)
1859 : RelativeChangeCase(testCtx, renderCtx, name, desc)
1860 {
1861 }
1862
~StaticOccludedFragDepthCullCase(void)1863 ~StaticOccludedFragDepthCullCase(void)
1864 {
1865 }
1866
1867 private:
genOccluderGeometry(void) const1868 virtual ObjectData genOccluderGeometry(void) const
1869 {
1870 return Utils::fastQuad(0.2f);
1871 }
genOccludedGeometry(void) const1872 virtual ObjectData genOccludedGeometry(void) const
1873 {
1874 return Utils::quadWith(Utils::getStaticFragDepthArithmeticWorkloadFragmentShader(), 0.2f);
1875 }
1876
logDescription(void)1877 virtual void logDescription(void)
1878 {
1879 TestLog &log = m_testCtx.getLog();
1880
1881 log << TestLog::Section("Description", "Test description");
1882 log << TestLog::Message << "Testing effects of non-default frag depth on rendering time" << TestLog::EndMessage;
1883 log << TestLog::Message
1884 << "Geometry consists of two fullscreen quads. The first (occluding) quad is trivial, while the second "
1885 "(occluded) contains significant fragment shader work"
1886 << TestLog::EndMessage;
1887 log << TestLog::Message
1888 << "Workload indicates the number of iterations of unused work done in the occluded quad's fragment shader"
1889 << TestLog::EndMessage;
1890 log << TestLog::Message << "The occluded quad has a static offset applied to gl_FragDepth"
1891 << TestLog::EndMessage;
1892 log << TestLog::Message << "The ratio of rendering times of this scene with/without depth testing are compared"
1893 << TestLog::EndMessage;
1894 log << TestLog::Message
1895 << "Successfull early Z-testing should result in no correlation between workload and render time"
1896 << TestLog::EndMessage;
1897 log << TestLog::EndSection;
1898 }
1899 };
1900
1901 // Dynamic offset to frag depth in occluded
1902 class DynamicOccludedFragDepthCullCase : public RelativeChangeCase
1903 {
1904 public:
DynamicOccludedFragDepthCullCase(TestContext & testCtx,const RenderContext & renderCtx,const char * name,const char * desc)1905 DynamicOccludedFragDepthCullCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name,
1906 const char *desc)
1907 : RelativeChangeCase(testCtx, renderCtx, name, desc)
1908 {
1909 }
1910
~DynamicOccludedFragDepthCullCase(void)1911 ~DynamicOccludedFragDepthCullCase(void)
1912 {
1913 }
1914
1915 private:
genOccluderGeometry(void) const1916 virtual ObjectData genOccluderGeometry(void) const
1917 {
1918 return Utils::fastQuad(0.2f);
1919 }
genOccludedGeometry(void) const1920 virtual ObjectData genOccludedGeometry(void) const
1921 {
1922 return Utils::quadWith(Utils::getDynamicFragDepthArithmeticWorkloadFragmentShader(), 0.2f);
1923 }
1924
logDescription(void)1925 virtual void logDescription(void)
1926 {
1927 TestLog &log = m_testCtx.getLog();
1928
1929 log << TestLog::Section("Description", "Test description");
1930 log << TestLog::Message << "Testing effects of non-default frag depth on rendering time" << TestLog::EndMessage;
1931 log << TestLog::Message
1932 << "Geometry consists of two fullscreen quads. The first (occluding) quad is trivial, while the second "
1933 "(occluded) contains significant fragment shader work"
1934 << TestLog::EndMessage;
1935 log << TestLog::Message
1936 << "Workload indicates the number of iterations of unused work done in the occluded quad's fragment shader"
1937 << TestLog::EndMessage;
1938 log << TestLog::Message << "The occluded quad has a dynamic offset applied to gl_FragDepth"
1939 << TestLog::EndMessage;
1940 log << TestLog::Message << "The ratio of rendering times of this scene with/without depth testing are compared"
1941 << TestLog::EndMessage;
1942 log << TestLog::Message
1943 << "Successfull early Z-testing should result in no correlation between workload and render time"
1944 << TestLog::EndMessage;
1945 log << TestLog::EndSection;
1946 }
1947 };
1948
1949 // Dynamic offset to frag depth in occluded
1950 class ReversedDepthOrderCullCase : public RelativeChangeCase
1951 {
1952 public:
ReversedDepthOrderCullCase(TestContext & testCtx,const RenderContext & renderCtx,const char * name,const char * desc)1953 ReversedDepthOrderCullCase(TestContext &testCtx, const RenderContext &renderCtx, const char *name, const char *desc)
1954 : RelativeChangeCase(testCtx, renderCtx, name, desc)
1955 {
1956 }
1957
~ReversedDepthOrderCullCase(void)1958 ~ReversedDepthOrderCullCase(void)
1959 {
1960 }
1961
1962 private:
genOccluderGeometry(void) const1963 virtual ObjectData genOccluderGeometry(void) const
1964 {
1965 return Utils::fastQuad(0.2f);
1966 }
genOccludedGeometry(void) const1967 virtual ObjectData genOccludedGeometry(void) const
1968 {
1969 return Utils::slowQuad(0.8f);
1970 }
1971
logDescription(void)1972 virtual void logDescription(void)
1973 {
1974 TestLog &log = m_testCtx.getLog();
1975
1976 log << TestLog::Section("Description", "Test description");
1977 log << TestLog::Message << "Testing effects of of back first rendering order on culling efficiency"
1978 << TestLog::EndMessage;
1979 log << TestLog::Message
1980 << "Geometry consists of two fullscreen quads. The second (occluding) quad is trivial, while the first "
1981 "(occluded) contains significant fragment shader work"
1982 << TestLog::EndMessage;
1983 log << TestLog::Message
1984 << "Workload indicates the number of iterations of unused work done in the occluded quad's fragment shader"
1985 << TestLog::EndMessage;
1986 log << TestLog::Message << "The ratio of rendering times of this scene with/without depth testing are compared"
1987 << TestLog::EndMessage;
1988 log << TestLog::Message
1989 << "Successfull early Z-testing should result in no correlation between workload and render time"
1990 << TestLog::EndMessage;
1991 log << TestLog::EndSection;
1992 }
1993
1994 // Rendering order of occluder & occluded is reversed, otherwise identical to parent version
renderSample(const RenderData & occluder,const RenderData & occluded,int workload) const1995 Sample renderSample(const RenderData &occluder, const RenderData &occluded, int workload) const
1996 {
1997 const glw::Functions &gl = m_renderCtx.getFunctions();
1998 const GLuint program = occluded.m_program.getProgram();
1999 Sample sample;
2000 uint64_t now = 0;
2001 uint64_t prev = 0;
2002 uint8_t buffer[4];
2003
2004 gl.useProgram(program);
2005 gl.uniform1i(gl.getUniformLocation(program, "u_iterations"), workload);
2006
2007 // Warmup (this workload seems to reduce variation in following workloads)
2008 {
2009 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2010 gl.disable(GL_DEPTH_TEST);
2011
2012 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
2013 }
2014
2015 // Null time
2016 {
2017 prev = deGetMicroseconds();
2018
2019 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2020 gl.disable(GL_DEPTH_TEST);
2021
2022 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
2023
2024 now = deGetMicroseconds();
2025
2026 sample.nullTime = now - prev;
2027 }
2028
2029 // Test time
2030 {
2031 prev = deGetMicroseconds();
2032
2033 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2034 gl.enable(GL_DEPTH_TEST);
2035
2036 render(occluded);
2037 render(occluder);
2038
2039 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
2040
2041 now = deGetMicroseconds();
2042
2043 sample.testTime = now - prev;
2044 }
2045
2046 // Base time
2047 {
2048 prev = deGetMicroseconds();
2049
2050 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2051 gl.disable(GL_DEPTH_TEST);
2052
2053 render(occluded);
2054 render(occluder);
2055
2056 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
2057
2058 now = deGetMicroseconds();
2059
2060 sample.baseTime = now - prev;
2061 }
2062
2063 sample.workload = 0;
2064
2065 return sample;
2066 }
2067 };
2068
2069 } // namespace
2070
DepthTests(Context & context)2071 DepthTests::DepthTests(Context &context) : TestCaseGroup(context, "depth", "Depth culling performance")
2072 {
2073 }
2074
init(void)2075 void DepthTests::init(void)
2076 {
2077 TestContext &testCtx = m_context.getTestContext();
2078 const RenderContext &renderCtx = m_context.getRenderContext();
2079
2080 {
2081 tcu::TestCaseGroup *const cullEfficiencyGroup =
2082 new tcu::TestCaseGroup(m_testCtx, "cull_efficiency", "Fragment cull efficiency");
2083
2084 addChild(cullEfficiencyGroup);
2085
2086 {
2087 tcu::TestCaseGroup *const group = new tcu::TestCaseGroup(m_testCtx, "workload", "Workload");
2088
2089 cullEfficiencyGroup->addChild(group);
2090
2091 group->addChild(new FragmentTextureWorkloadCullCase(testCtx, renderCtx, "workload_texture",
2092 "Fragment shader with texture lookup workload"));
2093 group->addChild(new FragmentArithmeticWorkloadCullCase(testCtx, renderCtx, "workload_arithmetic",
2094 "Fragment shader with arithmetic workload"));
2095 group->addChild(new FragmentDiscardArithmeticWorkloadCullCase(
2096 testCtx, renderCtx, "workload_arithmetic_discard",
2097 "Fragment shader that may discard with arithmetic workload"));
2098 }
2099
2100 {
2101 tcu::TestCaseGroup *const group = new tcu::TestCaseGroup(m_testCtx, "occluder_discard", "Discard");
2102
2103 cullEfficiencyGroup->addChild(group);
2104
2105 group->addChild(new PartialOccluderDiscardCullCase(testCtx, renderCtx, "grid_256",
2106 "Parts of occluder geometry discarded", 256));
2107 group->addChild(new PartialOccluderDiscardCullCase(testCtx, renderCtx, "grid_128",
2108 "Parts of occluder geometry discarded", 128));
2109 group->addChild(new PartialOccluderDiscardCullCase(testCtx, renderCtx, "grid_64",
2110 "Parts of occluder geometry discarded", 64));
2111 group->addChild(new PartialOccluderDiscardCullCase(testCtx, renderCtx, "grid_32",
2112 "Parts of occluder geometry discarded", 32));
2113 group->addChild(new PartialOccluderDiscardCullCase(testCtx, renderCtx, "grid_16",
2114 "Parts of occluder geometry discarded", 16));
2115 group->addChild(new PartialOccluderDiscardCullCase(testCtx, renderCtx, "grid_8",
2116 "Parts of occluder geometry discarded", 8));
2117 group->addChild(new PartialOccluderDiscardCullCase(testCtx, renderCtx, "grid_4",
2118 "Parts of occluder geometry discarded", 4));
2119 group->addChild(new PartialOccluderDiscardCullCase(testCtx, renderCtx, "grid_2",
2120 "Parts of occluder geometry discarded", 2));
2121 group->addChild(new PartialOccluderDiscardCullCase(testCtx, renderCtx, "grid_1",
2122 "Parts of occluder geometry discarded", 1));
2123 }
2124
2125 {
2126 tcu::TestCaseGroup *const group = new tcu::TestCaseGroup(m_testCtx, "partial_coverage", "Partial Coverage");
2127
2128 cullEfficiencyGroup->addChild(group);
2129
2130 group->addChild(new PartialOccluderCullCase(testCtx, renderCtx, "100",
2131 "Occluder covering only part of occluded geometry", 1.00f));
2132 group->addChild(new PartialOccluderCullCase(testCtx, renderCtx, "099",
2133 "Occluder covering only part of occluded geometry", 0.99f));
2134 group->addChild(new PartialOccluderCullCase(testCtx, renderCtx, "095",
2135 "Occluder covering only part of occluded geometry", 0.95f));
2136 group->addChild(new PartialOccluderCullCase(testCtx, renderCtx, "090",
2137 "Occluder covering only part of occluded geometry", 0.90f));
2138 group->addChild(new PartialOccluderCullCase(testCtx, renderCtx, "080",
2139 "Occluder covering only part of occluded geometry", 0.80f));
2140 group->addChild(new PartialOccluderCullCase(testCtx, renderCtx, "070",
2141 "Occluder covering only part of occluded geometry", 0.70f));
2142 group->addChild(new PartialOccluderCullCase(testCtx, renderCtx, "050",
2143 "Occluder covering only part of occluded geometry", 0.50f));
2144 group->addChild(new PartialOccluderCullCase(testCtx, renderCtx, "025",
2145 "Occluder covering only part of occluded geometry", 0.25f));
2146 group->addChild(new PartialOccluderCullCase(testCtx, renderCtx, "010",
2147 "Occluder covering only part of occluded geometry", 0.10f));
2148 }
2149
2150 {
2151 tcu::TestCaseGroup *const group = new tcu::TestCaseGroup(m_testCtx, "frag_depth", "Partial Coverage");
2152
2153 cullEfficiencyGroup->addChild(group);
2154
2155 group->addChild(new StaticOccluderFragDepthCullCase(testCtx, renderCtx, "occluder_static", ""));
2156 group->addChild(new DynamicOccluderFragDepthCullCase(testCtx, renderCtx, "occluder_dynamic", ""));
2157 group->addChild(new StaticOccludedFragDepthCullCase(testCtx, renderCtx, "occluded_static", ""));
2158 group->addChild(new DynamicOccludedFragDepthCullCase(testCtx, renderCtx, "occluded_dynamic", ""));
2159 }
2160
2161 {
2162 tcu::TestCaseGroup *const group = new tcu::TestCaseGroup(m_testCtx, "order", "Rendering order");
2163
2164 cullEfficiencyGroup->addChild(group);
2165
2166 group->addChild(
2167 new ReversedDepthOrderCullCase(testCtx, renderCtx, "reversed", "Back to front rendering order"));
2168 }
2169 }
2170
2171 {
2172 tcu::TestCaseGroup *const testCostGroup =
2173 new tcu::TestCaseGroup(m_testCtx, "culled_pixel_cost", "Fragment cull efficiency");
2174
2175 addChild(testCostGroup);
2176
2177 {
2178 tcu::TestCaseGroup *const group =
2179 new tcu::TestCaseGroup(m_testCtx, "gradient", "Gradients with small depth differences");
2180
2181 testCostGroup->addChild(group);
2182
2183 group->addChild(new BaseCostCase(testCtx, renderCtx, "flat", ""));
2184 group->addChild(new GradientCostCase(testCtx, renderCtx, "gradient_050", "", 0.50f));
2185 group->addChild(new GradientCostCase(testCtx, renderCtx, "gradient_010", "", 0.10f));
2186 group->addChild(new GradientCostCase(testCtx, renderCtx, "gradient_005", "", 0.05f));
2187 group->addChild(new GradientCostCase(testCtx, renderCtx, "gradient_002", "", 0.02f));
2188 group->addChild(new GradientCostCase(testCtx, renderCtx, "gradient_001", "", 0.01f));
2189 }
2190
2191 {
2192 tcu::TestCaseGroup *const group =
2193 new tcu::TestCaseGroup(m_testCtx, "occluder_geometry", "Occluders with varying geometry complexity");
2194
2195 testCostGroup->addChild(group);
2196
2197 group->addChild(
2198 new OccludingGeometryComplexityCostCase(testCtx, renderCtx, "flat_uniform_grid_5", "", 5, 0.0f, 0.0f));
2199 group->addChild(new OccludingGeometryComplexityCostCase(testCtx, renderCtx, "flat_uniform_grid_15", "", 15,
2200 0.0f, 0.0f));
2201 group->addChild(new OccludingGeometryComplexityCostCase(testCtx, renderCtx, "flat_uniform_grid_25", "", 25,
2202 0.0f, 0.0f));
2203 group->addChild(new OccludingGeometryComplexityCostCase(testCtx, renderCtx, "flat_uniform_grid_50", "", 50,
2204 0.0f, 0.0f));
2205 group->addChild(new OccludingGeometryComplexityCostCase(testCtx, renderCtx, "flat_uniform_grid_100", "",
2206 100, 0.0f, 0.0f));
2207
2208 group->addChild(new OccludingGeometryComplexityCostCase(testCtx, renderCtx, "flat_noisy_grid_5", "", 5,
2209 1.0f / 5.0f, 0.0f));
2210 group->addChild(new OccludingGeometryComplexityCostCase(testCtx, renderCtx, "flat_noisy_grid_15", "", 15,
2211 1.0f / 15.0f, 0.0f));
2212 group->addChild(new OccludingGeometryComplexityCostCase(testCtx, renderCtx, "flat_noisy_grid_25", "", 25,
2213 1.0f / 25.0f, 0.0f));
2214 group->addChild(new OccludingGeometryComplexityCostCase(testCtx, renderCtx, "flat_noisy_grid_50", "", 50,
2215 1.0f / 50.0f, 0.0f));
2216 group->addChild(new OccludingGeometryComplexityCostCase(testCtx, renderCtx, "flat_noisy_grid_100", "", 100,
2217 1.0f / 100.0f, 0.0f));
2218
2219 group->addChild(new OccludingGeometryComplexityCostCase(testCtx, renderCtx, "uneven_uniform_grid_5", "", 5,
2220 0.0f, 0.2f));
2221 group->addChild(new OccludingGeometryComplexityCostCase(testCtx, renderCtx, "uneven_uniform_grid_15", "",
2222 15, 0.0f, 0.2f));
2223 group->addChild(new OccludingGeometryComplexityCostCase(testCtx, renderCtx, "uneven_uniform_grid_25", "",
2224 25, 0.0f, 0.2f));
2225 group->addChild(new OccludingGeometryComplexityCostCase(testCtx, renderCtx, "uneven_uniform_grid_50", "",
2226 50, 0.0f, 0.2f));
2227 group->addChild(new OccludingGeometryComplexityCostCase(testCtx, renderCtx, "uneven_uniform_grid_100", "",
2228 100, 0.0f, 0.2f));
2229
2230 group->addChild(new OccludingGeometryComplexityCostCase(testCtx, renderCtx, "uneven_noisy_grid_5", "", 5,
2231 1.0f / 5.0f, 0.2f));
2232 group->addChild(new OccludingGeometryComplexityCostCase(testCtx, renderCtx, "uneven_noisy_grid_15", "", 15,
2233 1.0f / 15.0f, 0.2f));
2234 group->addChild(new OccludingGeometryComplexityCostCase(testCtx, renderCtx, "uneven_noisy_grid_25", "", 25,
2235 1.0f / 25.0f, 0.2f));
2236 group->addChild(new OccludingGeometryComplexityCostCase(testCtx, renderCtx, "uneven_noisy_grid_50", "", 50,
2237 1.0f / 50.0f, 0.2f));
2238 group->addChild(new OccludingGeometryComplexityCostCase(testCtx, renderCtx, "uneven_noisy_grid_100", "",
2239 100, 1.0f / 100.0f, 0.2f));
2240 }
2241
2242 {
2243 tcu::TestCaseGroup *const group = new tcu::TestCaseGroup(m_testCtx, "frag_depth", "Modifying gl_FragDepth");
2244
2245 testCostGroup->addChild(group);
2246
2247 group->addChild(new OccluderStaticFragDepthCostCase(testCtx, renderCtx, "occluder_static", ""));
2248 group->addChild(new OccluderDynamicFragDepthCostCase(testCtx, renderCtx, "occluder_dynamic", ""));
2249 group->addChild(new OccludedStaticFragDepthCostCase(testCtx, renderCtx, "occluded_static", ""));
2250 group->addChild(new OccludedDynamicFragDepthCostCase(testCtx, renderCtx, "occluded_dynamic", ""));
2251 }
2252 }
2253 }
2254
2255 } // namespace Performance
2256 } // namespace gles3
2257 } // namespace deqp
2258