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