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 & stencil tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es3fDepthStencilTests.hpp"
25 #include "glsFragmentOpUtil.hpp"
26 #include "gluPixelTransfer.hpp"
27 #include "gluStrUtil.hpp"
28 #include "tcuSurface.hpp"
29 #include "tcuRenderTarget.hpp"
30 #include "tcuTestLog.hpp"
31 #include "tcuImageCompare.hpp"
32 #include "tcuCommandLine.hpp"
33 #include "tcuTextureUtil.hpp"
34 #include "deRandom.hpp"
35 #include "deStringUtil.hpp"
36 #include "deMemory.h"
37 #include "deString.h"
38 #include "rrFragmentOperations.hpp"
39 #include "sglrReferenceUtils.hpp"
40
41 #include <algorithm>
42 #include <sstream>
43
44 #include "glw.h"
45
46 namespace deqp
47 {
48 namespace gles3
49 {
50 namespace Functional
51 {
52
53 using std::ostringstream;
54 using std::vector;
55 using tcu::IVec2;
56 using tcu::TestLog;
57 using tcu::Vec2;
58 using tcu::Vec4;
59
60 enum
61 {
62 VIEWPORT_WIDTH = 4 * 3 * 4,
63 VIEWPORT_HEIGHT = 4 * 12,
64
65 NUM_RANDOM_CASES = 25,
66 NUM_RANDOM_SUB_CASES = 10
67 };
68
69 namespace DepthStencilCaseUtil
70 {
71
72 struct StencilParams
73 {
74 uint32_t function;
75 int reference;
76 uint32_t compareMask;
77
78 uint32_t stencilFailOp;
79 uint32_t depthFailOp;
80 uint32_t depthPassOp;
81
82 uint32_t writeMask;
83
StencilParamsdeqp::gles3::Functional::DepthStencilCaseUtil::StencilParams84 StencilParams(void)
85 : function(0)
86 , reference(0)
87 , compareMask(0)
88 , stencilFailOp(0)
89 , depthFailOp(0)
90 , depthPassOp(0)
91 , writeMask(0)
92 {
93 }
94 };
95
96 struct DepthStencilParams
97 {
98 rr::FaceType visibleFace; //!< Quad visible face.
99
100 bool stencilTestEnabled;
101 StencilParams stencil[rr::FACETYPE_LAST];
102
103 bool depthTestEnabled;
104 uint32_t depthFunc;
105 float depth;
106 bool depthWriteMask;
107
DepthStencilParamsdeqp::gles3::Functional::DepthStencilCaseUtil::DepthStencilParams108 DepthStencilParams(void)
109 : visibleFace(rr::FACETYPE_LAST)
110 , stencilTestEnabled(false)
111 , depthTestEnabled(false)
112 , depthFunc(0)
113 , depth(0.0f)
114 , depthWriteMask(false)
115 {
116 }
117 };
118
operator <<(tcu::TestLog & log,const StencilParams & params)119 tcu::TestLog &operator<<(tcu::TestLog &log, const StencilParams ¶ms)
120 {
121 log << TestLog::Message << " func = " << glu::getCompareFuncStr(params.function) << "\n"
122 << " ref = " << params.reference << "\n"
123 << " compare mask = " << tcu::toHex(params.compareMask) << "\n"
124 << " stencil fail = " << glu::getStencilOpStr(params.stencilFailOp) << "\n"
125 << " depth fail = " << glu::getStencilOpStr(params.depthFailOp) << "\n"
126 << " depth pass = " << glu::getStencilOpStr(params.depthPassOp) << "\n"
127 << " write mask = " << tcu::toHex(params.writeMask) << "\n"
128 << TestLog::EndMessage;
129 return log;
130 }
131
operator <<(tcu::TestLog & log,const DepthStencilParams & params)132 tcu::TestLog &operator<<(tcu::TestLog &log, const DepthStencilParams ¶ms)
133 {
134 log << TestLog::Message << "Stencil test: " << (params.stencilTestEnabled ? "enabled" : "disabled")
135 << TestLog::EndMessage;
136 if (params.stencilTestEnabled)
137 {
138 log << TestLog::Message << "Front-face stencil state: " << TestLog::EndMessage;
139 log << params.stencil[rr::FACETYPE_FRONT];
140
141 log << TestLog::Message << "Back-face stencil state: " << TestLog::EndMessage;
142 log << params.stencil[rr::FACETYPE_BACK];
143 }
144
145 log << TestLog::Message << "Depth test: " << (params.depthTestEnabled ? "enabled" : "disabled")
146 << TestLog::EndMessage;
147 if (params.depthTestEnabled)
148 {
149 log << TestLog::Message << " func = " << glu::getCompareFuncStr(params.depthFunc)
150 << "\n"
151 " depth value = "
152 << params.depth
153 << "\n"
154 " write mask = "
155 << (params.depthWriteMask ? "true" : "false") << "\n"
156 << TestLog::EndMessage;
157 }
158
159 log << TestLog::Message << "Triangles are " << (params.visibleFace == rr::FACETYPE_FRONT ? "front" : "back")
160 << "-facing" << TestLog::EndMessage;
161
162 return log;
163 }
164
165 struct ClearCommand
166 {
167 rr::WindowRectangle rect;
168 uint32_t buffers;
169 tcu::Vec4 color;
170 int stencil;
171 // \note No depth here - don't use clears for setting depth values; use quad rendering instead. Cleared depths are in [0, 1] to begin with,
172 // whereas rendered depths are given in [-1, 1] and then mapped to [0, 1]; this discrepancy could cause precision issues in depth tests.
173
ClearCommanddeqp::gles3::Functional::DepthStencilCaseUtil::ClearCommand174 ClearCommand(void) : rect(0, 0, 0, 0), buffers(0), stencil(0)
175 {
176 }
177
ClearCommanddeqp::gles3::Functional::DepthStencilCaseUtil::ClearCommand178 ClearCommand(const rr::WindowRectangle &rect_, uint32_t buffers_, const tcu::Vec4 &color_, int stencil_)
179 : rect(rect_)
180 , buffers(buffers_)
181 , color(color_)
182 , stencil(stencil_)
183 {
184 }
185 };
186
187 struct RenderCommand
188 {
189 DepthStencilParams params;
190 rr::WindowRectangle rect;
191 tcu::Vec4 color;
192 tcu::BVec4 colorMask;
193
RenderCommanddeqp::gles3::Functional::DepthStencilCaseUtil::RenderCommand194 RenderCommand(void) : rect(0, 0, 0, 0)
195 {
196 }
197 };
198
199 struct RefRenderCommand
200 {
201 gls::FragmentOpUtil::IntegerQuad quad;
202 rr::FragmentOperationState state;
203 };
204
205 struct TestRenderTarget
206 {
207 int width;
208 int height;
209 int depthBits;
210 int stencilBits;
211
TestRenderTargetdeqp::gles3::Functional::DepthStencilCaseUtil::TestRenderTarget212 TestRenderTarget(int width_, int height_, int depthBits_, int stencilBits_)
213 : width(width_)
214 , height(height_)
215 , depthBits(depthBits_)
216 , stencilBits(stencilBits_)
217 {
218 }
219
TestRenderTargetdeqp::gles3::Functional::DepthStencilCaseUtil::TestRenderTarget220 TestRenderTarget(void) : width(0), height(0), depthBits(0), stencilBits(0)
221 {
222 }
223 };
224
getStencilTestValues(int stencilBits,int numValues,int * values)225 void getStencilTestValues(int stencilBits, int numValues, int *values)
226 {
227 int numLowest = numValues / 2;
228 int numHighest = numValues - numLowest;
229 int maxVal = (1 << stencilBits) - 1;
230
231 for (int ndx = 0; ndx < numLowest; ndx++)
232 values[ndx] = ndx;
233
234 for (int ndx = 0; ndx < numHighest; ndx++)
235 values[numValues - ndx - 1] = maxVal - ndx;
236 }
237
generateBaseClearAndDepthCommands(const TestRenderTarget & target,vector<ClearCommand> & clearCommands,vector<RenderCommand> & renderCommands)238 void generateBaseClearAndDepthCommands(const TestRenderTarget &target, vector<ClearCommand> &clearCommands,
239 vector<RenderCommand> &renderCommands)
240 {
241 DE_ASSERT(clearCommands.empty());
242 DE_ASSERT(renderCommands.empty());
243
244 const int numL0CellsX = 4;
245 const int numL0CellsY = 4;
246 const int numL1CellsX = 3;
247 const int numL1CellsY = 1;
248 int cellL0Width = target.width / numL0CellsX;
249 int cellL0Height = target.height / numL0CellsY;
250 int cellL1Width = cellL0Width / numL1CellsX;
251 int cellL1Height = cellL0Height / numL1CellsY;
252
253 int stencilValues[numL0CellsX * numL0CellsY];
254 float depthValues[numL1CellsX * numL1CellsY];
255
256 if (cellL0Width <= 0 || cellL1Width <= 0 || cellL0Height <= 0 || cellL1Height <= 0)
257 throw tcu::NotSupportedError("Too small render target");
258
259 // Fullscreen clear to black.
260 clearCommands.push_back(ClearCommand(rr::WindowRectangle(0, 0, target.width, target.height), GL_COLOR_BUFFER_BIT,
261 Vec4(0.0f, 0.0f, 0.0f, 1.0f), 0));
262
263 // Compute stencil values: numL0CellsX*numL0CellsY combinations of lowest and highest bits.
264 getStencilTestValues(target.stencilBits, numL0CellsX * numL0CellsY, &stencilValues[0]);
265
266 // Compute depth values
267 {
268 int numValues = DE_LENGTH_OF_ARRAY(depthValues);
269 float depthStep = 2.0f / (float)(numValues - 1);
270
271 for (int ndx = 0; ndx < numValues; ndx++)
272 depthValues[ndx] = -1.0f + depthStep * (float)ndx;
273 }
274
275 for (int y0 = 0; y0 < numL0CellsY; y0++)
276 {
277 for (int x0 = 0; x0 < numL0CellsX; x0++)
278 {
279 int stencilValue = stencilValues[y0 * numL0CellsX + x0];
280
281 for (int y1 = 0; y1 < numL1CellsY; y1++)
282 {
283 for (int x1 = 0; x1 < numL1CellsX; x1++)
284 {
285 int x = x0 * cellL0Width + x1 * cellL1Width;
286 int y = y0 * cellL0Height + y1 * cellL1Height;
287 rr::WindowRectangle cellL1Rect(x, y, cellL1Width, cellL1Height);
288
289 clearCommands.push_back(ClearCommand(cellL1Rect, GL_STENCIL_BUFFER_BIT, Vec4(0), stencilValue));
290
291 RenderCommand renderCmd;
292 renderCmd.params.visibleFace = rr::FACETYPE_FRONT;
293 renderCmd.params.depth = depthValues[y1 * numL1CellsX + x1];
294 renderCmd.params.depthTestEnabled = true;
295 renderCmd.params.depthFunc = GL_ALWAYS;
296 renderCmd.params.depthWriteMask = true;
297 renderCmd.colorMask = tcu::BVec4(false);
298 renderCmd.rect = cellL1Rect;
299
300 renderCommands.push_back(renderCmd);
301 }
302 }
303 }
304 }
305 }
306
generateDepthVisualizeCommands(const TestRenderTarget & target,vector<RenderCommand> & commands)307 void generateDepthVisualizeCommands(const TestRenderTarget &target, vector<RenderCommand> &commands)
308 {
309 const float epsilon = -0.05f;
310 static const float depthSteps[] = {-1.0f, -0.5f, 0.0f, 0.5f, 1.0f};
311 int numSteps = DE_LENGTH_OF_ARRAY(depthSteps);
312 const float colorStep = 1.0f / (float)(numSteps - 1);
313
314 for (int ndx = 0; ndx < numSteps; ndx++)
315 {
316 RenderCommand cmd;
317
318 cmd.params.visibleFace = rr::FACETYPE_FRONT;
319 cmd.rect = rr::WindowRectangle(0, 0, target.width, target.height);
320 cmd.color = Vec4(0.0f, 0.0f, colorStep * (float)ndx, 0.0f);
321 cmd.colorMask = tcu::BVec4(false, false, true, false);
322 cmd.params.depth = depthSteps[ndx] + epsilon;
323 cmd.params.depthTestEnabled = true;
324 cmd.params.depthFunc = GL_LESS;
325 cmd.params.depthWriteMask = false;
326
327 commands.push_back(cmd);
328 }
329 }
330
generateStencilVisualizeCommands(const TestRenderTarget & target,vector<RenderCommand> & commands)331 void generateStencilVisualizeCommands(const TestRenderTarget &target, vector<RenderCommand> &commands)
332 {
333 const int numValues = 4 * 4;
334 float colorStep = 1.0f / numValues; // 0 is reserved for non-matching.
335 int stencilValues[numValues];
336
337 getStencilTestValues(target.stencilBits, numValues, &stencilValues[0]);
338
339 for (int ndx = 0; ndx < numValues; ndx++)
340 {
341 RenderCommand cmd;
342
343 cmd.params.visibleFace = rr::FACETYPE_FRONT;
344 cmd.rect = rr::WindowRectangle(0, 0, target.width, target.height);
345 cmd.color = Vec4(0.0f, colorStep * float(ndx + 1), 0.0f, 0.0f);
346 cmd.colorMask = tcu::BVec4(false, true, false, false);
347 cmd.params.stencilTestEnabled = true;
348
349 cmd.params.stencil[rr::FACETYPE_FRONT].function = GL_EQUAL;
350 cmd.params.stencil[rr::FACETYPE_FRONT].reference = stencilValues[ndx];
351 cmd.params.stencil[rr::FACETYPE_FRONT].compareMask = ~0u;
352 cmd.params.stencil[rr::FACETYPE_FRONT].stencilFailOp = GL_KEEP;
353 cmd.params.stencil[rr::FACETYPE_FRONT].depthFailOp = GL_KEEP;
354 cmd.params.stencil[rr::FACETYPE_FRONT].depthPassOp = GL_KEEP;
355 cmd.params.stencil[rr::FACETYPE_FRONT].writeMask = 0u;
356
357 cmd.params.stencil[rr::FACETYPE_BACK] = cmd.params.stencil[rr::FACETYPE_FRONT];
358
359 commands.push_back(cmd);
360 }
361 }
362
translateStencilState(const StencilParams & src,rr::StencilState & dst)363 void translateStencilState(const StencilParams &src, rr::StencilState &dst)
364 {
365 dst.func = sglr::rr_util::mapGLTestFunc(src.function);
366 dst.ref = src.reference;
367 dst.compMask = src.compareMask;
368 dst.sFail = sglr::rr_util::mapGLStencilOp(src.stencilFailOp);
369 dst.dpFail = sglr::rr_util::mapGLStencilOp(src.depthFailOp);
370 dst.dpPass = sglr::rr_util::mapGLStencilOp(src.depthPassOp);
371 dst.writeMask = src.writeMask;
372 }
373
translateCommand(const RenderCommand & src,RefRenderCommand & dst,const TestRenderTarget & renderTarget)374 void translateCommand(const RenderCommand &src, RefRenderCommand &dst, const TestRenderTarget &renderTarget)
375 {
376 const float far = 1.0f;
377 const float near = 0.0f;
378 bool hasDepth = renderTarget.depthBits > 0;
379 bool hasStencil = renderTarget.stencilBits > 0;
380 bool isFrontFacing = src.params.visibleFace == rr::FACETYPE_FRONT;
381
382 dst.quad.posA = IVec2(isFrontFacing ? src.rect.left : (src.rect.left + src.rect.width - 1), src.rect.bottom);
383 dst.quad.posB = IVec2(isFrontFacing ? (src.rect.left + src.rect.width - 1) : src.rect.left,
384 src.rect.bottom + src.rect.height - 1);
385
386 std::fill(DE_ARRAY_BEGIN(dst.quad.color), DE_ARRAY_END(dst.quad.color), src.color);
387 std::fill(DE_ARRAY_BEGIN(dst.quad.depth), DE_ARRAY_END(dst.quad.depth),
388 ((far - near) / 2.0f) * src.params.depth + (near + far) / 2.0f);
389
390 dst.state.colorMask = src.colorMask;
391
392 dst.state.scissorTestEnabled = false;
393 dst.state.stencilTestEnabled = hasStencil && src.params.stencilTestEnabled;
394 dst.state.depthTestEnabled = hasDepth && src.params.depthTestEnabled;
395 dst.state.blendMode = rr::BLENDMODE_NONE;
396 dst.state.numStencilBits = renderTarget.stencilBits;
397
398 if (dst.state.depthTestEnabled)
399 {
400 dst.state.depthFunc = sglr::rr_util::mapGLTestFunc(src.params.depthFunc);
401 dst.state.depthMask = src.params.depthWriteMask;
402 }
403
404 if (dst.state.stencilTestEnabled)
405 {
406 translateStencilState(src.params.stencil[rr::FACETYPE_BACK], dst.state.stencilStates[rr::FACETYPE_BACK]);
407 translateStencilState(src.params.stencil[rr::FACETYPE_FRONT], dst.state.stencilStates[rr::FACETYPE_FRONT]);
408 }
409 }
410
render(const vector<ClearCommand> & clears,int viewportX,int viewportY)411 void render(const vector<ClearCommand> &clears, int viewportX, int viewportY)
412 {
413 glEnable(GL_SCISSOR_TEST);
414
415 for (int ndx = 0; ndx < (int)clears.size(); ndx++)
416 {
417 const ClearCommand &clear = clears[ndx];
418
419 if (clear.buffers & GL_COLOR_BUFFER_BIT)
420 glClearColor(clear.color.x(), clear.color.y(), clear.color.z(), clear.color.w());
421 if (clear.buffers & GL_STENCIL_BUFFER_BIT)
422 glClearStencil(clear.stencil);
423
424 DE_ASSERT(clear.buffers ==
425 (clear.buffers & (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))); // \note Don't use clear for depths.
426
427 glScissor(clear.rect.left + viewportX, clear.rect.bottom + viewportY, clear.rect.width, clear.rect.height);
428 glClear(clear.buffers);
429 }
430
431 glDisable(GL_SCISSOR_TEST);
432 }
433
render(gls::FragmentOpUtil::QuadRenderer & renderer,const RenderCommand & command,int viewportX,int viewportY)434 void render(gls::FragmentOpUtil::QuadRenderer &renderer, const RenderCommand &command, int viewportX, int viewportY)
435 {
436 if (command.params.stencilTestEnabled)
437 {
438 glEnable(GL_STENCIL_TEST);
439
440 for (int face = 0; face < rr::FACETYPE_LAST; face++)
441 {
442 uint32_t glFace = face == rr::FACETYPE_BACK ? GL_BACK : GL_FRONT;
443 const StencilParams &sParams = command.params.stencil[face];
444
445 glStencilFuncSeparate(glFace, sParams.function, sParams.reference, sParams.compareMask);
446 glStencilOpSeparate(glFace, sParams.stencilFailOp, sParams.depthFailOp, sParams.depthPassOp);
447 glStencilMaskSeparate(glFace, sParams.writeMask);
448 }
449 }
450 else
451 glDisable(GL_STENCIL_TEST);
452
453 if (command.params.depthTestEnabled)
454 {
455 glEnable(GL_DEPTH_TEST);
456 glDepthFunc(command.params.depthFunc);
457 glDepthMask(command.params.depthWriteMask ? GL_TRUE : GL_FALSE);
458 }
459 else
460 glDisable(GL_DEPTH_TEST);
461
462 glColorMask(command.colorMask[0] ? GL_TRUE : GL_FALSE, command.colorMask[1] ? GL_TRUE : GL_FALSE,
463 command.colorMask[2] ? GL_TRUE : GL_FALSE, command.colorMask[3] ? GL_TRUE : GL_FALSE);
464 glViewport(command.rect.left + viewportX, command.rect.bottom + viewportY, command.rect.width, command.rect.height);
465
466 gls::FragmentOpUtil::Quad quad;
467
468 bool isFrontFacing = command.params.visibleFace == rr::FACETYPE_FRONT;
469 quad.posA = Vec2(isFrontFacing ? -1.0f : 1.0f, -1.0f);
470 quad.posB = Vec2(isFrontFacing ? 1.0f : -1.0f, 1.0f);
471
472 std::fill(DE_ARRAY_BEGIN(quad.color), DE_ARRAY_END(quad.color), command.color);
473 std::fill(DE_ARRAY_BEGIN(quad.depth), DE_ARRAY_END(quad.depth), command.params.depth);
474
475 renderer.render(quad);
476 GLU_CHECK();
477 }
478
renderReference(const vector<ClearCommand> & clears,const tcu::PixelBufferAccess & dstColor,const tcu::PixelBufferAccess & dstStencil,int stencilBits)479 void renderReference(const vector<ClearCommand> &clears, const tcu::PixelBufferAccess &dstColor,
480 const tcu::PixelBufferAccess &dstStencil, int stencilBits)
481 {
482 for (int ndx = 0; ndx < (int)clears.size(); ndx++)
483 {
484 const ClearCommand &clear = clears[ndx];
485
486 if (clear.buffers & GL_COLOR_BUFFER_BIT)
487 tcu::clear(
488 tcu::getSubregion(dstColor, clear.rect.left, clear.rect.bottom, clear.rect.width, clear.rect.height),
489 clear.color);
490
491 if (clear.buffers & GL_STENCIL_BUFFER_BIT && stencilBits > 0)
492 {
493 int maskedVal = clear.stencil & ((1 << stencilBits) - 1);
494 tcu::clearStencil(
495 tcu::getSubregion(dstStencil, clear.rect.left, clear.rect.bottom, clear.rect.width, clear.rect.height),
496 maskedVal);
497 }
498
499 DE_ASSERT(clear.buffers ==
500 (clear.buffers & (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))); // \note Don't use clear for depths.
501 }
502 }
503
504 } // namespace DepthStencilCaseUtil
505
506 using namespace DepthStencilCaseUtil;
507
508 class DepthStencilCase : public TestCase
509 {
510 public:
511 DepthStencilCase(Context &context, const char *name, const char *desc,
512 const std::vector<DepthStencilParams> &cases);
513 ~DepthStencilCase(void);
514
515 void init(void);
516 void deinit(void);
517
518 IterateResult iterate(void);
519
520 private:
521 DepthStencilCase(const DepthStencilCase &other);
522 DepthStencilCase &operator=(const DepthStencilCase &other);
523
524 std::vector<DepthStencilParams> m_cases;
525
526 TestRenderTarget m_renderTarget;
527 std::vector<ClearCommand> m_baseClears;
528 std::vector<RenderCommand> m_baseDepthRenders;
529 std::vector<RenderCommand> m_visualizeCommands;
530 std::vector<RefRenderCommand> m_refBaseDepthRenders;
531 std::vector<RefRenderCommand> m_refVisualizeCommands;
532
533 gls::FragmentOpUtil::QuadRenderer *m_renderer;
534 tcu::Surface *m_refColorBuffer;
535 tcu::TextureLevel *m_refDepthBuffer;
536 tcu::TextureLevel *m_refStencilBuffer;
537 gls::FragmentOpUtil::ReferenceQuadRenderer *m_refRenderer;
538
539 int m_iterNdx;
540 };
541
DepthStencilCase(Context & context,const char * name,const char * desc,const std::vector<DepthStencilParams> & cases)542 DepthStencilCase::DepthStencilCase(Context &context, const char *name, const char *desc,
543 const std::vector<DepthStencilParams> &cases)
544 : TestCase(context, name, desc)
545 , m_cases(cases)
546 , m_renderer(DE_NULL)
547 , m_refColorBuffer(DE_NULL)
548 , m_refDepthBuffer(DE_NULL)
549 , m_refStencilBuffer(DE_NULL)
550 , m_refRenderer(DE_NULL)
551 , m_iterNdx(0)
552 {
553 }
554
~DepthStencilCase(void)555 DepthStencilCase::~DepthStencilCase(void)
556 {
557 delete m_renderer;
558 delete m_refColorBuffer;
559 delete m_refDepthBuffer;
560 delete m_refStencilBuffer;
561 delete m_refRenderer;
562 }
563
init(void)564 void DepthStencilCase::init(void)
565 {
566 DE_ASSERT(!m_renderer && !m_refColorBuffer && !m_refDepthBuffer && !m_refStencilBuffer && !m_refRenderer);
567
568 // Compute render target.
569 int viewportW = de::min<int>(m_context.getRenderTarget().getWidth(), VIEWPORT_WIDTH);
570 int viewportH = de::min<int>(m_context.getRenderTarget().getHeight(), VIEWPORT_HEIGHT);
571 m_renderTarget = TestRenderTarget(viewportW, viewportH, m_context.getRenderTarget().getDepthBits(),
572 m_context.getRenderTarget().getStencilBits());
573
574 // Compute base clears & visualization commands.
575 generateBaseClearAndDepthCommands(m_renderTarget, m_baseClears, m_baseDepthRenders);
576 generateDepthVisualizeCommands(m_renderTarget, m_visualizeCommands);
577 generateStencilVisualizeCommands(m_renderTarget, m_visualizeCommands);
578
579 // Translate to ref commands.
580 m_refBaseDepthRenders.resize(m_baseDepthRenders.size());
581 for (int ndx = 0; ndx < (int)m_baseDepthRenders.size(); ndx++)
582 translateCommand(m_baseDepthRenders[ndx], m_refBaseDepthRenders[ndx], m_renderTarget);
583
584 m_refVisualizeCommands.resize(m_visualizeCommands.size());
585 for (int ndx = 0; ndx < (int)m_visualizeCommands.size(); ndx++)
586 translateCommand(m_visualizeCommands[ndx], m_refVisualizeCommands[ndx], m_renderTarget);
587
588 m_renderer = new gls::FragmentOpUtil::QuadRenderer(m_context.getRenderContext(), glu::GLSL_VERSION_300_ES);
589 m_refColorBuffer = new tcu::Surface(viewportW, viewportH);
590 m_refDepthBuffer = new tcu::TextureLevel(tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT),
591 viewportW, viewportH);
592 m_refStencilBuffer = new tcu::TextureLevel(
593 tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT32), viewportW, viewportH);
594 m_refRenderer = new gls::FragmentOpUtil::ReferenceQuadRenderer();
595
596 m_iterNdx = 0;
597 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
598 }
599
deinit(void)600 void DepthStencilCase::deinit(void)
601 {
602 delete m_renderer;
603 delete m_refColorBuffer;
604 delete m_refDepthBuffer;
605 delete m_refStencilBuffer;
606 delete m_refRenderer;
607
608 m_renderer = DE_NULL;
609 m_refColorBuffer = DE_NULL;
610 m_refDepthBuffer = DE_NULL;
611 m_refStencilBuffer = DE_NULL;
612 m_refRenderer = DE_NULL;
613
614 m_baseClears.clear();
615 m_baseDepthRenders.clear();
616 m_visualizeCommands.clear();
617 m_refBaseDepthRenders.clear();
618 m_refVisualizeCommands.clear();
619 }
620
iterate(void)621 DepthStencilCase::IterateResult DepthStencilCase::iterate(void)
622 {
623 de::Random rnd(deStringHash(getName()) ^ deInt32Hash(m_iterNdx));
624 int viewportX = rnd.getInt(0, m_context.getRenderTarget().getWidth() - m_renderTarget.width);
625 int viewportY = rnd.getInt(0, m_context.getRenderTarget().getHeight() - m_renderTarget.height);
626 RenderCommand testCmd;
627
628 tcu::Surface renderedImg(m_renderTarget.width, m_renderTarget.height);
629 tcu::RGBA threshold = m_context.getRenderTarget().getPixelFormat().getColorThreshold();
630
631 // Fill in test command for this iteration.
632 testCmd.color = Vec4(1.0f, 0.0f, 0.0f, 1.0f);
633 testCmd.colorMask = tcu::BVec4(true);
634 testCmd.rect = rr::WindowRectangle(0, 0, m_renderTarget.width, m_renderTarget.height);
635 testCmd.params = m_cases[m_iterNdx];
636
637 if (m_iterNdx == 0)
638 {
639 m_testCtx.getLog() << TestLog::Message
640 << "Channels:\n"
641 " RED: passing pixels\n"
642 " GREEN: stencil values\n"
643 " BLUE: depth values"
644 << TestLog::EndMessage;
645 }
646
647 if (m_cases.size() > 1)
648 m_testCtx.getLog() << TestLog::Message << "Iteration " << m_iterNdx << "..." << TestLog::EndMessage;
649
650 m_testCtx.getLog() << m_cases[m_iterNdx];
651
652 // Submit render commands to gl GL.
653
654 // Base clears.
655 render(m_baseClears, viewportX, viewportY);
656
657 // Base depths.
658 for (vector<RenderCommand>::const_iterator cmd = m_baseDepthRenders.begin(); cmd != m_baseDepthRenders.end(); ++cmd)
659 render(*m_renderer, *cmd, viewportX, viewportY);
660
661 // Test command.
662 render(*m_renderer, testCmd, viewportX, viewportY);
663
664 // Visualization commands.
665 for (vector<RenderCommand>::const_iterator cmd = m_visualizeCommands.begin(); cmd != m_visualizeCommands.end();
666 ++cmd)
667 render(*m_renderer, *cmd, viewportX, viewportY);
668
669 // Re-enable all write masks.
670 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
671 glDepthMask(GL_TRUE);
672 glStencilMask(~0u);
673
674 // Ask GPU to start rendering.
675 glFlush();
676
677 // Render reference while GPU is doing work.
678 {
679 RefRenderCommand refTestCmd;
680 translateCommand(testCmd, refTestCmd, m_renderTarget);
681
682 // Base clears.
683 renderReference(m_baseClears, m_refColorBuffer->getAccess(), m_refStencilBuffer->getAccess(),
684 m_renderTarget.stencilBits);
685
686 // Base depths.
687 for (vector<RefRenderCommand>::const_iterator cmd = m_refBaseDepthRenders.begin();
688 cmd != m_refBaseDepthRenders.end(); ++cmd)
689 m_refRenderer->render(gls::FragmentOpUtil::getMultisampleAccess(m_refColorBuffer->getAccess()),
690 gls::FragmentOpUtil::getMultisampleAccess(m_refDepthBuffer->getAccess()),
691 gls::FragmentOpUtil::getMultisampleAccess(m_refStencilBuffer->getAccess()), cmd->quad,
692 cmd->state);
693
694 // Test command.
695 m_refRenderer->render(gls::FragmentOpUtil::getMultisampleAccess(m_refColorBuffer->getAccess()),
696 gls::FragmentOpUtil::getMultisampleAccess(m_refDepthBuffer->getAccess()),
697 gls::FragmentOpUtil::getMultisampleAccess(m_refStencilBuffer->getAccess()),
698 refTestCmd.quad, refTestCmd.state);
699
700 // Visualization commands.
701 for (vector<RefRenderCommand>::const_iterator cmd = m_refVisualizeCommands.begin();
702 cmd != m_refVisualizeCommands.end(); ++cmd)
703 m_refRenderer->render(gls::FragmentOpUtil::getMultisampleAccess(m_refColorBuffer->getAccess()),
704 gls::FragmentOpUtil::getMultisampleAccess(m_refDepthBuffer->getAccess()),
705 gls::FragmentOpUtil::getMultisampleAccess(m_refStencilBuffer->getAccess()), cmd->quad,
706 cmd->state);
707 }
708
709 // Read rendered image.
710 glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, renderedImg.getAccess());
711
712 m_iterNdx += 1;
713
714 // Compare to reference.
715 bool isLastIter = m_iterNdx >= (int)m_cases.size();
716 bool compareOk = tcu::pixelThresholdCompare(m_testCtx.getLog(), "CompareResult", "Image Comparison Result",
717 *m_refColorBuffer, renderedImg, threshold, tcu::COMPARE_LOG_RESULT);
718
719 m_testCtx.getLog() << TestLog::Message << (compareOk ? " Passed." : " FAILED!") << TestLog::EndMessage;
720 if (!compareOk)
721 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
722
723 if (compareOk && !isLastIter)
724 return CONTINUE;
725 else
726 return STOP;
727 }
728
DepthStencilTests(Context & context)729 DepthStencilTests::DepthStencilTests(Context &context)
730 : TestCaseGroup(context, "depth_stencil", "Depth and Stencil Op Tests")
731 {
732 }
733
~DepthStencilTests(void)734 DepthStencilTests::~DepthStencilTests(void)
735 {
736 }
737
randomDepthStencilState(de::Random & rnd,DepthStencilParams & params)738 static void randomDepthStencilState(de::Random &rnd, DepthStencilParams ¶ms)
739 {
740 const float stencilTestProbability = 0.8f;
741 const float depthTestProbability = 0.7f;
742
743 static const uint32_t compareFuncs[] = {GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL,
744 GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL};
745
746 static const uint32_t stencilOps[] = {GL_KEEP, GL_ZERO, GL_REPLACE, GL_INCR,
747 GL_DECR, GL_INVERT, GL_INCR_WRAP, GL_DECR_WRAP};
748
749 static const float depthValues[] = {-1.0f, -0.8f, -0.6f, -0.4f, -0.2f, 0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0f};
750
751 params.visibleFace = rnd.getBool() ? rr::FACETYPE_FRONT : rr::FACETYPE_BACK;
752 params.stencilTestEnabled = rnd.getFloat() < stencilTestProbability;
753 params.depthTestEnabled = !params.stencilTestEnabled || (rnd.getFloat() < depthTestProbability);
754
755 if (params.stencilTestEnabled)
756 {
757 for (int ndx = 0; ndx < 2; ndx++)
758 {
759 params.stencil[ndx].function =
760 rnd.choose<uint32_t>(DE_ARRAY_BEGIN(compareFuncs), DE_ARRAY_END(compareFuncs));
761 params.stencil[ndx].reference = rnd.getInt(-2, 260);
762 params.stencil[ndx].compareMask = rnd.getUint32();
763 params.stencil[ndx].stencilFailOp =
764 rnd.choose<uint32_t>(DE_ARRAY_BEGIN(stencilOps), DE_ARRAY_END(stencilOps));
765 params.stencil[ndx].depthFailOp =
766 rnd.choose<uint32_t>(DE_ARRAY_BEGIN(stencilOps), DE_ARRAY_END(stencilOps));
767 params.stencil[ndx].depthPassOp =
768 rnd.choose<uint32_t>(DE_ARRAY_BEGIN(stencilOps), DE_ARRAY_END(stencilOps));
769 params.stencil[ndx].writeMask = rnd.getUint32();
770 }
771 }
772
773 if (params.depthTestEnabled)
774 {
775 params.depthFunc = rnd.choose<uint32_t>(DE_ARRAY_BEGIN(compareFuncs), DE_ARRAY_END(compareFuncs));
776 params.depth = rnd.choose<float>(DE_ARRAY_BEGIN(depthValues), DE_ARRAY_END(depthValues));
777 params.depthWriteMask = rnd.getBool();
778 }
779 }
780
init(void)781 void DepthStencilTests::init(void)
782 {
783 static const struct
784 {
785 const char *name;
786 uint32_t func;
787 } compareFuncs[] = {{"never", GL_NEVER}, {"always", GL_ALWAYS}, {"less", GL_LESS}, {"lequal", GL_LEQUAL},
788 {"equal", GL_EQUAL}, {"gequal", GL_GEQUAL}, {"greater", GL_GREATER}, {"notequal", GL_NOTEQUAL}};
789
790 static const struct
791 {
792 const char *name;
793 uint32_t op;
794 } stencilOps[] = {{"keep", GL_KEEP}, {"zero", GL_ZERO}, {"replace", GL_REPLACE},
795 {"incr", GL_INCR}, {"decr", GL_DECR}, {"invert", GL_INVERT},
796 {"incr_wrap", GL_INCR_WRAP}, {"decr_wrap", GL_DECR_WRAP}};
797
798 static const struct
799 {
800 rr::FaceType visibleFace;
801 uint32_t sFail;
802 uint32_t dFail;
803 uint32_t dPass;
804 int stencilRef;
805 uint32_t compareMask;
806 uint32_t writeMask;
807 float depth;
808 } functionCases[] = {{rr::FACETYPE_BACK, GL_DECR, GL_INCR, GL_INVERT, 4, ~0u, ~0u, -0.7f},
809 {rr::FACETYPE_FRONT, GL_DECR, GL_INCR, GL_INVERT, 2, ~0u, ~0u, 0.0f},
810 {rr::FACETYPE_BACK, GL_DECR, GL_INCR, GL_INVERT, 1, ~0u, ~0u, 0.2f},
811 {rr::FACETYPE_FRONT, GL_DECR_WRAP, GL_INVERT, GL_REPLACE, 4, ~0u, ~0u, 1.0f}};
812
813 // All combinations of depth stencil functions.
814 {
815 tcu::TestCaseGroup *functionsGroup =
816 new tcu::TestCaseGroup(m_testCtx, "stencil_depth_funcs", "Combinations of Depth and Stencil Functions");
817 addChild(functionsGroup);
818
819 for (int stencilFunc = 0; stencilFunc < DE_LENGTH_OF_ARRAY(compareFuncs) + 1; stencilFunc++)
820 {
821 // One extra: depth test disabled.
822 for (int depthFunc = 0; depthFunc < DE_LENGTH_OF_ARRAY(compareFuncs) + 1; depthFunc++)
823 {
824 DepthStencilParams params;
825 ostringstream name;
826 bool hasStencilFunc = de::inBounds(stencilFunc, 0, DE_LENGTH_OF_ARRAY(compareFuncs));
827 bool hasDepthFunc = de::inBounds(depthFunc, 0, DE_LENGTH_OF_ARRAY(compareFuncs));
828
829 if (hasStencilFunc)
830 name << "stencil_" << compareFuncs[stencilFunc].name << "_";
831 else
832 name << "no_stencil_";
833
834 if (hasDepthFunc)
835 name << "depth_" << compareFuncs[depthFunc].name;
836 else
837 name << "no_depth";
838
839 params.depthFunc = hasDepthFunc ? compareFuncs[depthFunc].func : 0;
840 params.depthTestEnabled = hasDepthFunc;
841 params.depthWriteMask = true;
842
843 params.stencilTestEnabled = hasStencilFunc;
844
845 vector<DepthStencilParams> cases;
846 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(functionCases); ndx++)
847 {
848 rr::FaceType visible = functionCases[ndx].visibleFace;
849 rr::FaceType notVisible = visible == rr::FACETYPE_FRONT ? rr::FACETYPE_BACK : rr::FACETYPE_FRONT;
850
851 params.depth = functionCases[ndx].depth;
852 params.visibleFace = visible;
853
854 params.stencil[visible].function = hasStencilFunc ? compareFuncs[stencilFunc].func : 0;
855 params.stencil[visible].reference = functionCases[ndx].stencilRef;
856 params.stencil[visible].stencilFailOp = functionCases[ndx].sFail;
857 params.stencil[visible].depthFailOp = functionCases[ndx].dFail;
858 params.stencil[visible].depthPassOp = functionCases[ndx].dPass;
859 params.stencil[visible].compareMask = functionCases[ndx].compareMask;
860 params.stencil[visible].writeMask = functionCases[ndx].writeMask;
861
862 params.stencil[notVisible].function = GL_ALWAYS;
863 params.stencil[notVisible].reference = 0;
864 params.stencil[notVisible].stencilFailOp = GL_REPLACE;
865 params.stencil[notVisible].depthFailOp = GL_REPLACE;
866 params.stencil[notVisible].depthPassOp = GL_REPLACE;
867 params.stencil[notVisible].compareMask = 0u;
868 params.stencil[notVisible].writeMask = ~0u;
869
870 cases.push_back(params);
871 }
872
873 functionsGroup->addChild(new DepthStencilCase(m_context, name.str().c_str(), "", cases));
874 }
875 }
876 }
877
878 static const struct
879 {
880 rr::FaceType visibleFace;
881 uint32_t func;
882 int ref;
883 uint32_t compareMask;
884 uint32_t writeMask;
885 } opCombinationCases[] = {{rr::FACETYPE_BACK, GL_LESS, 4, ~0u, ~0u},
886 {rr::FACETYPE_FRONT, GL_GREATER, 2, ~0u, ~0u},
887 {rr::FACETYPE_BACK, GL_EQUAL, 3, ~2u, ~0u},
888 {rr::FACETYPE_FRONT, GL_NOTEQUAL, 1, ~0u, ~1u}};
889
890 // All combinations of stencil ops.
891 {
892 tcu::TestCaseGroup *opCombinationGroup =
893 new tcu::TestCaseGroup(m_testCtx, "stencil_ops", "Stencil Op Combinations");
894 addChild(opCombinationGroup);
895
896 for (int sFail = 0; sFail < DE_LENGTH_OF_ARRAY(stencilOps); sFail++)
897 {
898 for (int dFail = 0; dFail < DE_LENGTH_OF_ARRAY(stencilOps); dFail++)
899 {
900 for (int dPass = 0; dPass < DE_LENGTH_OF_ARRAY(stencilOps); dPass++)
901 {
902 DepthStencilParams params;
903 ostringstream name;
904
905 name << stencilOps[sFail].name << "_" << stencilOps[dFail].name << "_" << stencilOps[dPass].name;
906
907 params.depthFunc = GL_LEQUAL;
908 params.depth = 0.0f;
909 params.depthTestEnabled = true;
910 params.depthWriteMask = true;
911
912 params.stencilTestEnabled = true;
913
914 vector<DepthStencilParams> cases;
915 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(opCombinationCases); ndx++)
916 {
917 rr::FaceType visible = opCombinationCases[ndx].visibleFace;
918 rr::FaceType notVisible =
919 visible == rr::FACETYPE_FRONT ? rr::FACETYPE_BACK : rr::FACETYPE_FRONT;
920
921 params.visibleFace = visible;
922
923 params.stencil[visible].function = opCombinationCases[ndx].func;
924 params.stencil[visible].reference = opCombinationCases[ndx].ref;
925 params.stencil[visible].stencilFailOp = stencilOps[sFail].op;
926 params.stencil[visible].depthFailOp = stencilOps[dFail].op;
927 params.stencil[visible].depthPassOp = stencilOps[dPass].op;
928 params.stencil[visible].compareMask = opCombinationCases[ndx].compareMask;
929 params.stencil[visible].writeMask = opCombinationCases[ndx].writeMask;
930
931 params.stencil[notVisible].function = GL_ALWAYS;
932 params.stencil[notVisible].reference = 0;
933 params.stencil[notVisible].stencilFailOp = GL_REPLACE;
934 params.stencil[notVisible].depthFailOp = GL_REPLACE;
935 params.stencil[notVisible].depthPassOp = GL_REPLACE;
936 params.stencil[notVisible].compareMask = 0u;
937 params.stencil[notVisible].writeMask = ~0u;
938
939 cases.push_back(params);
940 }
941
942 opCombinationGroup->addChild(new DepthStencilCase(m_context, name.str().c_str(), "", cases));
943 }
944 }
945 }
946 }
947
948 // Write masks
949 {
950 tcu::TestCaseGroup *writeMaskGroup =
951 new tcu::TestCaseGroup(m_testCtx, "write_mask", "Depth and Stencil Write Masks");
952 addChild(writeMaskGroup);
953
954 // Depth mask
955 {
956 DepthStencilParams params;
957
958 params.depthFunc = GL_LEQUAL;
959 params.depth = 0.0f;
960 params.depthTestEnabled = true;
961 params.stencilTestEnabled = true;
962
963 params.stencil[rr::FACETYPE_FRONT].function = GL_NOTEQUAL;
964 params.stencil[rr::FACETYPE_FRONT].reference = 1;
965 params.stencil[rr::FACETYPE_FRONT].stencilFailOp = GL_INVERT;
966 params.stencil[rr::FACETYPE_FRONT].depthFailOp = GL_INCR;
967 params.stencil[rr::FACETYPE_FRONT].depthPassOp = GL_DECR;
968 params.stencil[rr::FACETYPE_FRONT].compareMask = ~0u;
969 params.stencil[rr::FACETYPE_FRONT].writeMask = ~0u;
970
971 params.stencil[rr::FACETYPE_BACK].function = GL_ALWAYS;
972 params.stencil[rr::FACETYPE_BACK].reference = 0;
973 params.stencil[rr::FACETYPE_BACK].stencilFailOp = GL_REPLACE;
974 params.stencil[rr::FACETYPE_BACK].depthFailOp = GL_INVERT;
975 params.stencil[rr::FACETYPE_BACK].depthPassOp = GL_INCR;
976 params.stencil[rr::FACETYPE_BACK].compareMask = ~0u;
977 params.stencil[rr::FACETYPE_BACK].writeMask = ~0u;
978
979 vector<DepthStencilParams> cases;
980
981 // Case 1: front, depth write enabled
982 params.visibleFace = rr::FACETYPE_FRONT;
983 params.depthWriteMask = true;
984 cases.push_back(params);
985
986 // Case 2: front, depth write disabled
987 params.visibleFace = rr::FACETYPE_FRONT;
988 params.depthWriteMask = false;
989 cases.push_back(params);
990
991 // Case 3: back, depth write enabled
992 params.visibleFace = rr::FACETYPE_BACK;
993 params.depthWriteMask = true;
994 cases.push_back(params);
995
996 // Case 4: back, depth write disabled
997 params.visibleFace = rr::FACETYPE_BACK;
998 params.depthWriteMask = false;
999 cases.push_back(params);
1000
1001 writeMaskGroup->addChild(new DepthStencilCase(m_context, "depth", "Depth Write Mask", cases));
1002 }
1003
1004 // Stencil write masks.
1005 {
1006 static const struct
1007 {
1008 rr::FaceType visibleFace;
1009 uint32_t frontWriteMask;
1010 uint32_t backWriteMask;
1011 } stencilWmaskCases[] = {{rr::FACETYPE_FRONT, ~0u, 0u}, {rr::FACETYPE_FRONT, 0u, ~0u},
1012 {rr::FACETYPE_FRONT, 0xfu, 0xf0u}, {rr::FACETYPE_FRONT, 0x2u, 0x4u},
1013 {rr::FACETYPE_BACK, 0u, ~0u}, {rr::FACETYPE_BACK, ~0u, 0u},
1014 {rr::FACETYPE_BACK, 0xf0u, 0xfu}, {rr::FACETYPE_BACK, 0x4u, 0x2u}};
1015
1016 DepthStencilParams params;
1017
1018 params.depthFunc = GL_LEQUAL;
1019 params.depth = 0.0f;
1020 params.depthTestEnabled = true;
1021 params.depthWriteMask = true;
1022 params.stencilTestEnabled = true;
1023
1024 params.stencil[rr::FACETYPE_FRONT].function = GL_NOTEQUAL;
1025 params.stencil[rr::FACETYPE_FRONT].reference = 1;
1026 params.stencil[rr::FACETYPE_FRONT].stencilFailOp = GL_INVERT;
1027 params.stencil[rr::FACETYPE_FRONT].depthFailOp = GL_INCR;
1028 params.stencil[rr::FACETYPE_FRONT].depthPassOp = GL_DECR;
1029 params.stencil[rr::FACETYPE_FRONT].compareMask = ~0u;
1030
1031 params.stencil[rr::FACETYPE_BACK].function = GL_ALWAYS;
1032 params.stencil[rr::FACETYPE_BACK].reference = 0;
1033 params.stencil[rr::FACETYPE_BACK].stencilFailOp = GL_REPLACE;
1034 params.stencil[rr::FACETYPE_BACK].depthFailOp = GL_INVERT;
1035 params.stencil[rr::FACETYPE_BACK].depthPassOp = GL_INCR;
1036 params.stencil[rr::FACETYPE_BACK].compareMask = ~0u;
1037
1038 vector<DepthStencilParams> cases;
1039 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(stencilWmaskCases); ndx++)
1040 {
1041 params.visibleFace = stencilWmaskCases[ndx].visibleFace;
1042 params.stencil[rr::FACETYPE_FRONT].writeMask = stencilWmaskCases[ndx].frontWriteMask;
1043 params.stencil[rr::FACETYPE_BACK].writeMask = stencilWmaskCases[ndx].backWriteMask;
1044 cases.push_back(params);
1045 }
1046
1047 writeMaskGroup->addChild(new DepthStencilCase(m_context, "stencil", "Stencil Write Mask", cases));
1048 }
1049
1050 // Depth & stencil write masks.
1051 {
1052 static const struct
1053 {
1054 bool depthWriteMask;
1055 rr::FaceType visibleFace;
1056 uint32_t frontWriteMask;
1057 uint32_t backWriteMask;
1058 } depthStencilWmaskCases[] = {
1059 {false, rr::FACETYPE_FRONT, ~0u, 0u}, {false, rr::FACETYPE_FRONT, 0u, ~0u},
1060 {false, rr::FACETYPE_FRONT, 0xfu, 0xf0u}, {true, rr::FACETYPE_FRONT, ~0u, 0u},
1061 {true, rr::FACETYPE_FRONT, 0u, ~0u}, {true, rr::FACETYPE_FRONT, 0xfu, 0xf0u},
1062 {false, rr::FACETYPE_BACK, 0u, ~0u}, {false, rr::FACETYPE_BACK, ~0u, 0u},
1063 {false, rr::FACETYPE_BACK, 0xf0u, 0xfu}, {true, rr::FACETYPE_BACK, 0u, ~0u},
1064 {true, rr::FACETYPE_BACK, ~0u, 0u}, {true, rr::FACETYPE_BACK, 0xf0u, 0xfu}};
1065
1066 DepthStencilParams params;
1067
1068 params.depthFunc = GL_LEQUAL;
1069 params.depth = 0.0f;
1070 params.depthTestEnabled = true;
1071 params.depthWriteMask = true;
1072 params.stencilTestEnabled = true;
1073
1074 params.stencil[rr::FACETYPE_FRONT].function = GL_NOTEQUAL;
1075 params.stencil[rr::FACETYPE_FRONT].reference = 1;
1076 params.stencil[rr::FACETYPE_FRONT].stencilFailOp = GL_INVERT;
1077 params.stencil[rr::FACETYPE_FRONT].depthFailOp = GL_INCR;
1078 params.stencil[rr::FACETYPE_FRONT].depthPassOp = GL_DECR;
1079 params.stencil[rr::FACETYPE_FRONT].compareMask = ~0u;
1080
1081 params.stencil[rr::FACETYPE_BACK].function = GL_ALWAYS;
1082 params.stencil[rr::FACETYPE_BACK].reference = 0;
1083 params.stencil[rr::FACETYPE_BACK].stencilFailOp = GL_REPLACE;
1084 params.stencil[rr::FACETYPE_BACK].depthFailOp = GL_INVERT;
1085 params.stencil[rr::FACETYPE_BACK].depthPassOp = GL_INCR;
1086 params.stencil[rr::FACETYPE_BACK].compareMask = ~0u;
1087
1088 vector<DepthStencilParams> cases;
1089 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthStencilWmaskCases); ndx++)
1090 {
1091 params.depthWriteMask = depthStencilWmaskCases[ndx].depthWriteMask;
1092 params.visibleFace = depthStencilWmaskCases[ndx].visibleFace;
1093 params.stencil[rr::FACETYPE_FRONT].writeMask = depthStencilWmaskCases[ndx].frontWriteMask;
1094 params.stencil[rr::FACETYPE_BACK].writeMask = depthStencilWmaskCases[ndx].backWriteMask;
1095 cases.push_back(params);
1096 }
1097
1098 writeMaskGroup->addChild(new DepthStencilCase(m_context, "both", "Depth and Stencil Write Masks", cases));
1099 }
1100 }
1101
1102 // Randomized cases
1103 {
1104 tcu::TestCaseGroup *randomGroup =
1105 new tcu::TestCaseGroup(m_testCtx, "random", "Randomized Depth and Stencil Test Cases");
1106 addChild(randomGroup);
1107
1108 for (int caseNdx = 0; caseNdx < NUM_RANDOM_CASES; caseNdx++)
1109 {
1110 vector<DepthStencilParams> subCases(NUM_RANDOM_SUB_CASES);
1111 de::Random rnd(deInt32Hash(caseNdx) ^ deInt32Hash(m_testCtx.getCommandLine().getBaseSeed()));
1112
1113 for (vector<DepthStencilParams>::iterator iter = subCases.begin(); iter != subCases.end(); ++iter)
1114 randomDepthStencilState(rnd, *iter);
1115
1116 randomGroup->addChild(new DepthStencilCase(m_context, de::toString(caseNdx).c_str(), "", subCases));
1117 }
1118 }
1119 }
1120
1121 } // namespace Functional
1122 } // namespace gles3
1123 } // namespace deqp
1124