xref: /aosp_15_r20/external/deqp/modules/gles3/functional/es3fDepthStencilClearTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.0 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Depth and stencil clear tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es3fDepthStencilClearTests.hpp"
25 
26 #include "gluShaderProgram.hpp"
27 #include "gluPixelTransfer.hpp"
28 #include "gluRenderContext.hpp"
29 
30 #include "tcuTestLog.hpp"
31 #include "tcuTexture.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "tcuImageCompare.hpp"
34 #include "tcuSurface.hpp"
35 #include "tcuRenderTarget.hpp"
36 
37 #include "deRandom.hpp"
38 #include "deMath.h"
39 #include "deString.h"
40 
41 #include "glwFunctions.hpp"
42 #include "glwEnums.hpp"
43 
44 namespace deqp
45 {
46 namespace gles3
47 {
48 namespace Functional
49 {
50 
51 using std::string;
52 using std::vector;
53 using tcu::TestLog;
54 using tcu::Vec3;
55 using tcu::Vec4;
56 
57 namespace
58 {
59 
60 enum
61 {
62     STENCIL_STEPS = 32,
63     DEPTH_STEPS   = 32
64 };
65 
66 struct Clear
67 {
Cleardeqp::gles3::Functional::__anonde2a0efa0111::Clear68     Clear(void)
69         : clearMask(0)
70         , clearDepth(0.0f)
71         , clearStencil(0)
72         , useScissor(false)
73         , scissor(0, 0, 0, 0)
74         , depthMask(false)
75         , stencilMask(0)
76     {
77     }
78 
79     uint32_t clearMask;
80     float clearDepth;
81     int clearStencil;
82 
83     bool useScissor;
84     tcu::IVec4 scissor;
85 
86     bool depthMask;
87     uint32_t stencilMask;
88 };
89 
getDepthFormat(int depthBits)90 tcu::TextureFormat getDepthFormat(int depthBits)
91 {
92     switch (depthBits)
93     {
94     case 8:
95         return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT8);
96     case 16:
97         return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
98     case 24:
99         return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT24);
100     case 32:
101         return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT);
102     default:
103         TCU_FAIL("Can't map depth buffer format");
104     }
105 }
106 
getStencilFormat(int stencilBits)107 tcu::TextureFormat getStencilFormat(int stencilBits)
108 {
109     switch (stencilBits)
110     {
111     case 8:
112         return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);
113     case 16:
114         return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT16);
115     case 24:
116         return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT24);
117     case 32:
118         return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT32);
119     default:
120         TCU_FAIL("Can't map depth buffer format");
121     }
122 }
123 
124 } // namespace
125 
126 class DepthStencilClearCase : public TestCase
127 {
128 public:
129     DepthStencilClearCase(Context &context, const char *name, const char *description, int numIters, int numClears,
130                           bool depth, bool stencil, bool scissor, bool masked);
131     ~DepthStencilClearCase(void);
132 
133     void init(void);
134     void deinit(void);
135 
136     IterateResult iterate(void);
137 
138 private:
139     void generateClears(vector<Clear> &dst, uint32_t seed);
140     void renderGL(tcu::Surface &dst, const vector<Clear> &clears);
141     void renderReference(tcu::Surface &dst, const vector<Clear> &clears);
142 
143     bool m_testDepth;
144     bool m_testStencil;
145     bool m_testScissor;
146     bool m_masked;
147     int m_numIters;
148     int m_numClears;
149     int m_curIter;
150 
151     glu::ShaderProgram *m_visProgram;
152 };
153 
DepthStencilClearCase(Context & context,const char * name,const char * description,int numIters,int numClears,bool depth,bool stencil,bool scissor,bool masked)154 DepthStencilClearCase::DepthStencilClearCase(Context &context, const char *name, const char *description, int numIters,
155                                              int numClears, bool depth, bool stencil, bool scissor, bool masked)
156     : TestCase(context, name, description)
157     , m_testDepth(depth)
158     , m_testStencil(stencil)
159     , m_testScissor(scissor)
160     , m_masked(masked)
161     , m_numIters(numIters)
162     , m_numClears(numClears)
163     , m_curIter(0)
164     , m_visProgram(DE_NULL)
165 {
166 }
167 
~DepthStencilClearCase(void)168 DepthStencilClearCase::~DepthStencilClearCase(void)
169 {
170     DepthStencilClearCase::deinit();
171 }
172 
init(void)173 void DepthStencilClearCase::init(void)
174 {
175     TestLog &log = m_testCtx.getLog();
176 
177     m_visProgram =
178         new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(
179                                                                  // Vertex shader.
180                                                                  "#version 300 es\n"
181                                                                  "in highp vec4 a_position;\n"
182                                                                  "void main (void)\n"
183                                                                  "{\n"
184                                                                  "    gl_Position = a_position;\n"
185                                                                  "}\n",
186 
187                                                                  // Fragment shader.
188                                                                  "#version 300 es\n"
189                                                                  "uniform mediump vec4 u_color;\n"
190                                                                  "layout(location = 0) out mediump vec4 o_color;\n"
191                                                                  "void main (void)\n"
192                                                                  "{\n"
193                                                                  "    o_color = u_color;\n"
194                                                                  "}\n"));
195 
196     if (!m_visProgram->isOk())
197     {
198         log << *m_visProgram;
199         delete m_visProgram;
200         m_visProgram = DE_NULL;
201         TCU_FAIL("Compile failed");
202     }
203 
204     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
205 }
206 
deinit(void)207 void DepthStencilClearCase::deinit(void)
208 {
209     delete m_visProgram;
210     m_visProgram = DE_NULL;
211 }
212 
iterate(void)213 DepthStencilClearCase::IterateResult DepthStencilClearCase::iterate(void)
214 {
215     const tcu::RenderTarget &renderTarget = m_context.getRenderTarget();
216     int width                             = renderTarget.getWidth();
217     int height                            = renderTarget.getHeight();
218     tcu::Surface result(width, height);
219     tcu::Surface reference(width, height);
220     tcu::RGBA threshold = renderTarget.getPixelFormat().getColorThreshold() + tcu::RGBA(1, 1, 1, 1);
221     vector<Clear> clears;
222 
223     if ((m_testDepth && renderTarget.getDepthBits() == 0) || (m_testStencil && renderTarget.getStencilBits() == 0))
224         throw tcu::NotSupportedError("No depth/stencil buffers", "", __FILE__, __LINE__);
225 
226     generateClears(clears, deStringHash(getName()) ^ deInt32Hash(m_curIter));
227     renderGL(result, clears);
228     renderReference(reference, clears);
229 
230     bool isLastIter = m_curIter + 1 == m_numIters;
231     bool isOk = tcu::pixelThresholdCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference, result,
232                                            threshold, isLastIter ? tcu::COMPARE_LOG_RESULT : tcu::COMPARE_LOG_ON_ERROR);
233 
234     if (!isOk)
235         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
236 
237     m_curIter += 1;
238     return isLastIter || !isOk ? STOP : CONTINUE;
239 }
240 
generateClears(vector<Clear> & clears,uint32_t seed)241 void DepthStencilClearCase::generateClears(vector<Clear> &clears, uint32_t seed)
242 {
243     const tcu::RenderTarget &renderTarget = m_context.getRenderContext().getRenderTarget();
244     int width                             = renderTarget.getWidth();
245     int height                            = renderTarget.getHeight();
246     de::Random rnd(seed);
247 
248     clears.resize(m_numClears);
249 
250     for (vector<Clear>::iterator clear = clears.begin(); clear != clears.end(); clear++)
251     {
252         if (m_testScissor)
253         {
254             int w = rnd.getInt(1, width);
255             int h = rnd.getInt(1, height);
256             int x = rnd.getInt(0, width - w);
257             int y = rnd.getInt(0, height - h);
258 
259             clear->useScissor = true; // \todo [pyry] Should we randomize?
260             clear->scissor    = tcu::IVec4(x, y, w, h);
261         }
262         else
263             clear->useScissor = false;
264 
265         clear->clearDepth   = rnd.getFloat(-0.2f, 1.2f);
266         clear->clearStencil = rnd.getUint32();
267 
268         clear->depthMask   = m_masked ? rnd.getBool() : true;
269         clear->stencilMask = m_masked ? rnd.getUint32() : 0xffffffffu;
270 
271         if (m_testDepth && m_testStencil)
272         {
273             switch (rnd.getInt(0, 2))
274             {
275             case 0:
276                 clear->clearMask = GL_DEPTH_BUFFER_BIT;
277                 break;
278             case 1:
279                 clear->clearMask = GL_STENCIL_BUFFER_BIT;
280                 break;
281             case 2:
282                 clear->clearMask = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
283                 break;
284             }
285         }
286         else if (m_testDepth)
287             clear->clearMask = GL_DEPTH_BUFFER_BIT;
288         else
289         {
290             DE_ASSERT(m_testStencil);
291             clear->clearMask = GL_STENCIL_BUFFER_BIT;
292         }
293     }
294 }
295 
renderGL(tcu::Surface & dst,const vector<Clear> & clears)296 void DepthStencilClearCase::renderGL(tcu::Surface &dst, const vector<Clear> &clears)
297 {
298     const glw::Functions &gl       = m_context.getRenderContext().getFunctions();
299     int colorLoc                   = gl.getUniformLocation(m_visProgram->getProgram(), "u_color");
300     int positionLoc                = gl.getAttribLocation(m_visProgram->getProgram(), "a_position");
301     static const uint8_t indices[] = {0, 1, 2, 2, 1, 3};
302 
303     // Clear with default values.
304     gl.clearDepthf(1.0f);
305     gl.clearStencil(0);
306     gl.clearColor(1.0f, 0.0f, 0.0f, 1.0f);
307     gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
308 
309     GLU_EXPECT_NO_ERROR(gl.getError(), "Before clears");
310 
311     for (vector<Clear>::const_iterator clear = clears.begin(); clear != clears.end(); clear++)
312     {
313         if (clear->useScissor)
314         {
315             gl.enable(GL_SCISSOR_TEST);
316             gl.scissor(clear->scissor.x(), clear->scissor.y(), clear->scissor.z(), clear->scissor.w());
317         }
318 
319         // Clear values.
320         gl.clearDepthf(clear->clearDepth);
321         gl.clearStencil(clear->clearStencil);
322 
323         // Masks.
324         gl.depthMask(clear->depthMask ? GL_TRUE : GL_FALSE);
325         gl.stencilMask(clear->stencilMask);
326 
327         // Execute clear.
328         gl.clear(clear->clearMask);
329 
330         if (clear->useScissor)
331             gl.disable(GL_SCISSOR_TEST);
332     }
333 
334     // Restore default masks.
335     gl.depthMask(GL_TRUE);
336     gl.stencilMask(0xffffffffu);
337 
338     GLU_EXPECT_NO_ERROR(gl.getError(), "After clears");
339 
340     gl.useProgram(m_visProgram->getProgram());
341     gl.enableVertexAttribArray(positionLoc);
342 
343     // Visualize depth / stencil buffers.
344     if (m_testDepth)
345     {
346         int numSteps = DEPTH_STEPS;
347         float step   = 2.0f / (float)numSteps;
348 
349         gl.enable(GL_DEPTH_TEST);
350         gl.depthFunc(GL_LESS);
351         gl.depthMask(GL_FALSE);
352         gl.colorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE);
353 
354         for (int ndx = 0; ndx < numSteps; ndx++)
355         {
356             float d     = -1.0f + step * (float)ndx;
357             float c     = (float)ndx / (float)(numSteps - 1);
358             float pos[] = {-1.0f, -1.0f, d, -1.0f, 1.0f, d, 1.0f, -1.0f, d, 1.0f, 1.0f, d};
359 
360             gl.uniform4f(colorLoc, 0.0f, 0.0f, c, 1.0f);
361             gl.vertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, &pos[0]);
362             gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(indices), GL_UNSIGNED_BYTE, &indices[0]);
363         }
364 
365         gl.disable(GL_DEPTH_TEST);
366         gl.depthMask(GL_TRUE);
367 
368         GLU_EXPECT_NO_ERROR(gl.getError(), "After depth visualization");
369     }
370 
371     if (m_testStencil)
372     {
373         int numSteps  = STENCIL_STEPS;
374         int numValues = (1 << TestCase::m_context.getRenderContext().getRenderTarget().getStencilBits()); // 2^bits
375         int step      = numValues / numSteps;
376 
377         gl.enable(GL_STENCIL_TEST);
378         gl.stencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
379         gl.colorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
380 
381         static const float pos[] = {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f};
382         gl.vertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, &pos[0]);
383 
384         for (int ndx = 0; ndx < numSteps; ndx++)
385         {
386             int s   = step * ndx;
387             float c = (float)ndx / (float)(numSteps - 1);
388 
389             gl.stencilFunc(GL_LEQUAL, s, 0xffu);
390             gl.uniform4f(colorLoc, 0.0f, c, 0.0f, 1.0f);
391             gl.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(indices), GL_UNSIGNED_BYTE, &indices[0]);
392         }
393 
394         gl.disable(GL_STENCIL_TEST);
395 
396         GLU_EXPECT_NO_ERROR(gl.getError(), "After stencil visualization");
397     }
398 
399     // Restore color mask (changed by visualization).
400     gl.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
401 
402     glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
403 }
404 
renderReference(tcu::Surface & dst,const vector<Clear> & clears)405 void DepthStencilClearCase::renderReference(tcu::Surface &dst, const vector<Clear> &clears)
406 {
407     glu::RenderContext &renderCtx         = TestCase::m_context.getRenderContext();
408     const tcu::RenderTarget &renderTarget = renderCtx.getRenderTarget();
409 
410     // Clear surface to red.
411     tcu::clear(dst.getAccess(), tcu::RGBA::red().toVec());
412 
413     if (m_testDepth)
414     {
415         // Simulated depth buffer span.
416         tcu::TextureLevel depthBufRow(getDepthFormat(renderTarget.getDepthBits()), dst.getWidth(), 1, 1);
417         tcu::PixelBufferAccess rowAccess = depthBufRow.getAccess();
418 
419         for (int y = 0; y < dst.getHeight(); y++)
420         {
421             // Clear to default value.
422             for (int x = 0; x < rowAccess.getWidth(); x++)
423                 rowAccess.setPixel(Vec4(1.0f), x, 0);
424 
425             // Execute clears.
426             for (vector<Clear>::const_iterator clear = clears.begin(); clear != clears.end(); clear++)
427             {
428                 // Clear / mask test.
429                 if ((clear->clearMask & GL_DEPTH_BUFFER_BIT) == 0 || !clear->depthMask)
430                     continue;
431 
432                 tcu::IVec4 clearRect =
433                     clear->useScissor ? clear->scissor : tcu::IVec4(0, 0, dst.getWidth(), dst.getHeight());
434 
435                 // Intersection test.
436                 if (!de::inBounds(y, clearRect.y(), clearRect.y() + clearRect.w()))
437                     continue;
438 
439                 for (int x = clearRect.x(); x < clearRect.x() + clearRect.z(); x++)
440                     rowAccess.setPixDepth(de::clamp(clear->clearDepth, 0.0f, 1.0f), x, 0);
441             }
442 
443             // Map to colors.
444             for (int x = 0; x < dst.getWidth(); x++)
445             {
446                 float depth        = rowAccess.getPixDepth(x, 0);
447                 float step         = deFloatFloor(depth * (float)DEPTH_STEPS) / (float)(DEPTH_STEPS - 1);
448                 tcu::RGBA oldColor = dst.getPixel(x, y);
449                 tcu::RGBA newColor =
450                     tcu::RGBA(oldColor.getRed(), oldColor.getGreen(),
451                               deClamp32(deRoundFloatToInt32(step * 255.0f), 0, 255), oldColor.getAlpha());
452 
453                 dst.setPixel(x, y, newColor);
454             }
455         }
456     }
457 
458     if (m_testStencil)
459     {
460         // Simulated stencil buffer span.
461         int stencilBits = renderTarget.getStencilBits();
462         tcu::TextureLevel depthBufRow(getStencilFormat(stencilBits), dst.getWidth(), 1, 1);
463         tcu::PixelBufferAccess rowAccess = depthBufRow.getAccess();
464         uint32_t bufMask                 = (1u << stencilBits) - 1;
465 
466         for (int y = 0; y < dst.getHeight(); y++)
467         {
468             // Clear to default value.
469             for (int x = 0; x < rowAccess.getWidth(); x++)
470                 rowAccess.setPixel(tcu::UVec4(0), x, 0);
471 
472             // Execute clears.
473             for (vector<Clear>::const_iterator clear = clears.begin(); clear != clears.end(); clear++)
474             {
475                 // Clear / mask test.
476                 if ((clear->clearMask & GL_STENCIL_BUFFER_BIT) == 0 || clear->stencilMask == 0)
477                     continue;
478 
479                 tcu::IVec4 clearRect =
480                     clear->useScissor ? clear->scissor : tcu::IVec4(0, 0, dst.getWidth(), dst.getHeight());
481 
482                 // Intersection test.
483                 if (!de::inBounds(y, clearRect.y(), clearRect.y() + clearRect.w()))
484                     continue;
485 
486                 for (int x = clearRect.x(); x < clearRect.x() + clearRect.z(); x++)
487                 {
488                     uint32_t oldVal = rowAccess.getPixStencil(x, 0);
489                     uint32_t newVal =
490                         ((oldVal & ~clear->stencilMask) | (clear->clearStencil & clear->stencilMask)) & bufMask;
491                     rowAccess.setPixStencil(newVal, x, 0);
492                 }
493             }
494 
495             // Map to colors.
496             for (int x = 0; x < dst.getWidth(); x++)
497             {
498                 uint32_t stencil = rowAccess.getPixStencil(x, 0);
499                 float step =
500                     (float)(stencil / ((1u << stencilBits) / (uint32_t)STENCIL_STEPS)) / (float)(STENCIL_STEPS - 1);
501                 tcu::RGBA oldColor = dst.getPixel(x, y);
502                 tcu::RGBA newColor = tcu::RGBA(oldColor.getRed(), deClamp32(deRoundFloatToInt32(step * 255.0f), 0, 255),
503                                                oldColor.getBlue(), oldColor.getAlpha());
504 
505                 dst.setPixel(x, y, newColor);
506             }
507         }
508     }
509 }
510 
DepthStencilClearTests(Context & context)511 DepthStencilClearTests::DepthStencilClearTests(Context &context)
512     : TestCaseGroup(context, "depth_stencil_clear", "Depth and stencil clear tests")
513 {
514 }
515 
init(void)516 void DepthStencilClearTests::init(void)
517 {
518     //                                                                                    iters    clears    depth    stencil    scissor    masked
519     addChild(new DepthStencilClearCase(m_context, "depth", "", 4, 2, true, false, false, false));
520     addChild(new DepthStencilClearCase(m_context, "depth_scissored", "", 4, 16, true, false, true, false));
521     addChild(new DepthStencilClearCase(m_context, "depth_scissored_masked", "", 4, 16, true, false, true, true));
522 
523     addChild(new DepthStencilClearCase(m_context, "stencil", "", 4, 2, false, true, false, false));
524     addChild(new DepthStencilClearCase(m_context, "stencil_masked", "", 4, 8, false, true, false, true));
525     addChild(new DepthStencilClearCase(m_context, "stencil_scissored", "", 4, 16, false, true, true, false));
526     addChild(new DepthStencilClearCase(m_context, "stencil_scissored_masked", "", 4, 16, false, true, true, true));
527 
528     addChild(new DepthStencilClearCase(m_context, "depth_stencil", "", 4, 2, true, true, false, false));
529     addChild(new DepthStencilClearCase(m_context, "depth_stencil_masked", "", 4, 8, true, true, false, true));
530     addChild(new DepthStencilClearCase(m_context, "depth_stencil_scissored", "", 4, 16, true, true, true, false));
531     addChild(new DepthStencilClearCase(m_context, "depth_stencil_scissored_masked", "", 4, 16, true, true, true, true));
532 }
533 
534 } // namespace Functional
535 } // namespace gles3
536 } // namespace deqp
537