xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fShaderHelperInvocationTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program OpenGL ES 3.1 Module
3*35238bceSAndroid Build Coastguard Worker  * -------------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief gl_HelperInvocation tests.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "es31fShaderHelperInvocationTests.hpp"
25*35238bceSAndroid Build Coastguard Worker 
26*35238bceSAndroid Build Coastguard Worker #include "gluObjectWrapper.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "gluShaderProgram.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "gluDrawUtil.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "gluPixelTransfer.hpp"
30*35238bceSAndroid Build Coastguard Worker 
31*35238bceSAndroid Build Coastguard Worker #include "glwFunctions.hpp"
32*35238bceSAndroid Build Coastguard Worker #include "glwEnums.hpp"
33*35238bceSAndroid Build Coastguard Worker 
34*35238bceSAndroid Build Coastguard Worker #include "tcuTestLog.hpp"
35*35238bceSAndroid Build Coastguard Worker #include "tcuVector.hpp"
36*35238bceSAndroid Build Coastguard Worker #include "tcuSurface.hpp"
37*35238bceSAndroid Build Coastguard Worker 
38*35238bceSAndroid Build Coastguard Worker #include "deUniquePtr.hpp"
39*35238bceSAndroid Build Coastguard Worker #include "deStringUtil.hpp"
40*35238bceSAndroid Build Coastguard Worker #include "deRandom.hpp"
41*35238bceSAndroid Build Coastguard Worker #include "deString.h"
42*35238bceSAndroid Build Coastguard Worker 
43*35238bceSAndroid Build Coastguard Worker namespace deqp
44*35238bceSAndroid Build Coastguard Worker {
45*35238bceSAndroid Build Coastguard Worker namespace gles31
46*35238bceSAndroid Build Coastguard Worker {
47*35238bceSAndroid Build Coastguard Worker namespace Functional
48*35238bceSAndroid Build Coastguard Worker {
49*35238bceSAndroid Build Coastguard Worker namespace
50*35238bceSAndroid Build Coastguard Worker {
51*35238bceSAndroid Build Coastguard Worker 
52*35238bceSAndroid Build Coastguard Worker using de::MovePtr;
53*35238bceSAndroid Build Coastguard Worker using glu::ShaderProgram;
54*35238bceSAndroid Build Coastguard Worker using std::string;
55*35238bceSAndroid Build Coastguard Worker using std::vector;
56*35238bceSAndroid Build Coastguard Worker using tcu::IVec2;
57*35238bceSAndroid Build Coastguard Worker using tcu::TestLog;
58*35238bceSAndroid Build Coastguard Worker using tcu::Vec2;
59*35238bceSAndroid Build Coastguard Worker 
60*35238bceSAndroid Build Coastguard Worker enum PrimitiveType
61*35238bceSAndroid Build Coastguard Worker {
62*35238bceSAndroid Build Coastguard Worker     PRIMITIVETYPE_TRIANGLE = 0,
63*35238bceSAndroid Build Coastguard Worker     PRIMITIVETYPE_LINE,
64*35238bceSAndroid Build Coastguard Worker     PRIMITIVETYPE_WIDE_LINE,
65*35238bceSAndroid Build Coastguard Worker     PRIMITIVETYPE_POINT,
66*35238bceSAndroid Build Coastguard Worker     PRIMITIVETYPE_WIDE_POINT,
67*35238bceSAndroid Build Coastguard Worker 
68*35238bceSAndroid Build Coastguard Worker     PRIMITIVETYPE_LAST
69*35238bceSAndroid Build Coastguard Worker };
70*35238bceSAndroid Build Coastguard Worker 
getNumVerticesPerPrimitive(PrimitiveType primType)71*35238bceSAndroid Build Coastguard Worker static int getNumVerticesPerPrimitive(PrimitiveType primType)
72*35238bceSAndroid Build Coastguard Worker {
73*35238bceSAndroid Build Coastguard Worker     switch (primType)
74*35238bceSAndroid Build Coastguard Worker     {
75*35238bceSAndroid Build Coastguard Worker     case PRIMITIVETYPE_TRIANGLE:
76*35238bceSAndroid Build Coastguard Worker         return 3;
77*35238bceSAndroid Build Coastguard Worker     case PRIMITIVETYPE_LINE:
78*35238bceSAndroid Build Coastguard Worker         return 2;
79*35238bceSAndroid Build Coastguard Worker     case PRIMITIVETYPE_WIDE_LINE:
80*35238bceSAndroid Build Coastguard Worker         return 2;
81*35238bceSAndroid Build Coastguard Worker     case PRIMITIVETYPE_POINT:
82*35238bceSAndroid Build Coastguard Worker         return 1;
83*35238bceSAndroid Build Coastguard Worker     case PRIMITIVETYPE_WIDE_POINT:
84*35238bceSAndroid Build Coastguard Worker         return 1;
85*35238bceSAndroid Build Coastguard Worker     default:
86*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
87*35238bceSAndroid Build Coastguard Worker         return 0;
88*35238bceSAndroid Build Coastguard Worker     }
89*35238bceSAndroid Build Coastguard Worker }
90*35238bceSAndroid Build Coastguard Worker 
getGluPrimitiveType(PrimitiveType primType)91*35238bceSAndroid Build Coastguard Worker static glu::PrimitiveType getGluPrimitiveType(PrimitiveType primType)
92*35238bceSAndroid Build Coastguard Worker {
93*35238bceSAndroid Build Coastguard Worker     switch (primType)
94*35238bceSAndroid Build Coastguard Worker     {
95*35238bceSAndroid Build Coastguard Worker     case PRIMITIVETYPE_TRIANGLE:
96*35238bceSAndroid Build Coastguard Worker         return glu::PRIMITIVETYPE_TRIANGLES;
97*35238bceSAndroid Build Coastguard Worker     case PRIMITIVETYPE_LINE:
98*35238bceSAndroid Build Coastguard Worker         return glu::PRIMITIVETYPE_LINES;
99*35238bceSAndroid Build Coastguard Worker     case PRIMITIVETYPE_WIDE_LINE:
100*35238bceSAndroid Build Coastguard Worker         return glu::PRIMITIVETYPE_LINES;
101*35238bceSAndroid Build Coastguard Worker     case PRIMITIVETYPE_POINT:
102*35238bceSAndroid Build Coastguard Worker         return glu::PRIMITIVETYPE_POINTS;
103*35238bceSAndroid Build Coastguard Worker     case PRIMITIVETYPE_WIDE_POINT:
104*35238bceSAndroid Build Coastguard Worker         return glu::PRIMITIVETYPE_POINTS;
105*35238bceSAndroid Build Coastguard Worker     default:
106*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
107*35238bceSAndroid Build Coastguard Worker         return glu::PRIMITIVETYPE_LAST;
108*35238bceSAndroid Build Coastguard Worker     }
109*35238bceSAndroid Build Coastguard Worker }
110*35238bceSAndroid Build Coastguard Worker 
genVertices(PrimitiveType primType,int numPrimitives,de::Random * rnd,vector<Vec2> * dst)111*35238bceSAndroid Build Coastguard Worker static void genVertices(PrimitiveType primType, int numPrimitives, de::Random *rnd, vector<Vec2> *dst)
112*35238bceSAndroid Build Coastguard Worker {
113*35238bceSAndroid Build Coastguard Worker     const bool isTri                  = primType == PRIMITIVETYPE_TRIANGLE;
114*35238bceSAndroid Build Coastguard Worker     const float minCoord              = isTri ? -1.5f : -1.0f;
115*35238bceSAndroid Build Coastguard Worker     const float maxCoord              = isTri ? +1.5f : +1.0f;
116*35238bceSAndroid Build Coastguard Worker     const int numVerticesPerPrimitive = getNumVerticesPerPrimitive(primType);
117*35238bceSAndroid Build Coastguard Worker     const int numVert                 = numVerticesPerPrimitive * numPrimitives;
118*35238bceSAndroid Build Coastguard Worker 
119*35238bceSAndroid Build Coastguard Worker     dst->resize(numVert);
120*35238bceSAndroid Build Coastguard Worker 
121*35238bceSAndroid Build Coastguard Worker     for (size_t ndx = 0; ndx < dst->size(); ndx++)
122*35238bceSAndroid Build Coastguard Worker     {
123*35238bceSAndroid Build Coastguard Worker         (*dst)[ndx][0] = rnd->getFloat(minCoord, maxCoord);
124*35238bceSAndroid Build Coastguard Worker         (*dst)[ndx][1] = rnd->getFloat(minCoord, maxCoord);
125*35238bceSAndroid Build Coastguard Worker     }
126*35238bceSAndroid Build Coastguard Worker 
127*35238bceSAndroid Build Coastguard Worker     // Don't produce completely or almost completely discardable primitives.
128*35238bceSAndroid Build Coastguard Worker     // \note: This doesn't guarantee that resulting primitives are visible or
129*35238bceSAndroid Build Coastguard Worker     //        produce any fragments. This just removes trivially discardable
130*35238bceSAndroid Build Coastguard Worker     //        primitives.
131*35238bceSAndroid Build Coastguard Worker     for (int primitiveNdx = 0; primitiveNdx < numPrimitives; ++primitiveNdx)
132*35238bceSAndroid Build Coastguard Worker         for (int component = 0; component < 2; ++component)
133*35238bceSAndroid Build Coastguard Worker         {
134*35238bceSAndroid Build Coastguard Worker             bool negativeClip = true;
135*35238bceSAndroid Build Coastguard Worker             bool positiveClip = true;
136*35238bceSAndroid Build Coastguard Worker 
137*35238bceSAndroid Build Coastguard Worker             for (int vertexNdx = 0; vertexNdx < numVerticesPerPrimitive; ++vertexNdx)
138*35238bceSAndroid Build Coastguard Worker             {
139*35238bceSAndroid Build Coastguard Worker                 const float p = (*dst)[primitiveNdx * numVerticesPerPrimitive + vertexNdx][component];
140*35238bceSAndroid Build Coastguard Worker                 // \note 0.9 instead of 1.0 to avoid just barely visible primitives
141*35238bceSAndroid Build Coastguard Worker                 if (p > -0.9f)
142*35238bceSAndroid Build Coastguard Worker                     negativeClip = false;
143*35238bceSAndroid Build Coastguard Worker                 if (p < +0.9f)
144*35238bceSAndroid Build Coastguard Worker                     positiveClip = false;
145*35238bceSAndroid Build Coastguard Worker             }
146*35238bceSAndroid Build Coastguard Worker 
147*35238bceSAndroid Build Coastguard Worker             // if discardable, just mirror first vertex along center
148*35238bceSAndroid Build Coastguard Worker             if (negativeClip || positiveClip)
149*35238bceSAndroid Build Coastguard Worker             {
150*35238bceSAndroid Build Coastguard Worker                 (*dst)[primitiveNdx * numVerticesPerPrimitive + 0][0] *= -1.0f;
151*35238bceSAndroid Build Coastguard Worker                 (*dst)[primitiveNdx * numVerticesPerPrimitive + 0][1] *= -1.0f;
152*35238bceSAndroid Build Coastguard Worker             }
153*35238bceSAndroid Build Coastguard Worker         }
154*35238bceSAndroid Build Coastguard Worker }
155*35238bceSAndroid Build Coastguard Worker 
getInteger(const glw::Functions & gl,uint32_t pname)156*35238bceSAndroid Build Coastguard Worker static int getInteger(const glw::Functions &gl, uint32_t pname)
157*35238bceSAndroid Build Coastguard Worker {
158*35238bceSAndroid Build Coastguard Worker     int v = 0;
159*35238bceSAndroid Build Coastguard Worker     gl.getIntegerv(pname, &v);
160*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv()");
161*35238bceSAndroid Build Coastguard Worker     return v;
162*35238bceSAndroid Build Coastguard Worker }
163*35238bceSAndroid Build Coastguard Worker 
getRange(const glw::Functions & gl,uint32_t pname)164*35238bceSAndroid Build Coastguard Worker static Vec2 getRange(const glw::Functions &gl, uint32_t pname)
165*35238bceSAndroid Build Coastguard Worker {
166*35238bceSAndroid Build Coastguard Worker     Vec2 v(0.0f);
167*35238bceSAndroid Build Coastguard Worker     gl.getFloatv(pname, v.getPtr());
168*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv()");
169*35238bceSAndroid Build Coastguard Worker     return v;
170*35238bceSAndroid Build Coastguard Worker }
171*35238bceSAndroid Build Coastguard Worker 
drawRandomPrimitives(const glu::RenderContext & renderCtx,uint32_t program,PrimitiveType primType,int numPrimitives,de::Random * rnd)172*35238bceSAndroid Build Coastguard Worker static void drawRandomPrimitives(const glu::RenderContext &renderCtx, uint32_t program, PrimitiveType primType,
173*35238bceSAndroid Build Coastguard Worker                                  int numPrimitives, de::Random *rnd)
174*35238bceSAndroid Build Coastguard Worker {
175*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = renderCtx.getFunctions();
176*35238bceSAndroid Build Coastguard Worker     const float minPointSize = 16.0f;
177*35238bceSAndroid Build Coastguard Worker     const float maxPointSize = 32.0f;
178*35238bceSAndroid Build Coastguard Worker     const float minLineWidth = 16.0f;
179*35238bceSAndroid Build Coastguard Worker     const float maxLineWidth = 32.0f;
180*35238bceSAndroid Build Coastguard Worker     vector<Vec2> vertices;
181*35238bceSAndroid Build Coastguard Worker     vector<glu::VertexArrayBinding> vertexArrays;
182*35238bceSAndroid Build Coastguard Worker 
183*35238bceSAndroid Build Coastguard Worker     genVertices(primType, numPrimitives, rnd, &vertices);
184*35238bceSAndroid Build Coastguard Worker 
185*35238bceSAndroid Build Coastguard Worker     vertexArrays.push_back(glu::va::Float("a_position", 2, (int)vertices.size(), 0, (const float *)&vertices[0]));
186*35238bceSAndroid Build Coastguard Worker 
187*35238bceSAndroid Build Coastguard Worker     gl.useProgram(program);
188*35238bceSAndroid Build Coastguard Worker 
189*35238bceSAndroid Build Coastguard Worker     // Special state for certain primitives
190*35238bceSAndroid Build Coastguard Worker     if (primType == PRIMITIVETYPE_POINT || primType == PRIMITIVETYPE_WIDE_POINT)
191*35238bceSAndroid Build Coastguard Worker     {
192*35238bceSAndroid Build Coastguard Worker         const Vec2 range       = getRange(gl, glu::isContextTypeES(renderCtx.getType()) ? GL_ALIASED_POINT_SIZE_RANGE :
193*35238bceSAndroid Build Coastguard Worker                                                                                           GL_SMOOTH_POINT_SIZE_RANGE);
194*35238bceSAndroid Build Coastguard Worker         const bool isWidePoint = primType == PRIMITIVETYPE_WIDE_POINT;
195*35238bceSAndroid Build Coastguard Worker         const float pointSize  = isWidePoint ? de::min(rnd->getFloat(minPointSize, maxPointSize), range.y()) : 1.0f;
196*35238bceSAndroid Build Coastguard Worker         const int pointSizeLoc = gl.getUniformLocation(program, "u_pointSize");
197*35238bceSAndroid Build Coastguard Worker 
198*35238bceSAndroid Build Coastguard Worker         gl.uniform1f(pointSizeLoc, pointSize);
199*35238bceSAndroid Build Coastguard Worker     }
200*35238bceSAndroid Build Coastguard Worker     else if (primType == PRIMITIVETYPE_WIDE_LINE)
201*35238bceSAndroid Build Coastguard Worker     {
202*35238bceSAndroid Build Coastguard Worker         const Vec2 range      = getRange(gl, GL_ALIASED_LINE_WIDTH_RANGE);
203*35238bceSAndroid Build Coastguard Worker         const float lineWidth = de::min(rnd->getFloat(minLineWidth, maxLineWidth), range.y());
204*35238bceSAndroid Build Coastguard Worker 
205*35238bceSAndroid Build Coastguard Worker         gl.lineWidth(lineWidth);
206*35238bceSAndroid Build Coastguard Worker     }
207*35238bceSAndroid Build Coastguard Worker 
208*35238bceSAndroid Build Coastguard Worker     glu::draw(renderCtx, program, (int)vertexArrays.size(), &vertexArrays[0],
209*35238bceSAndroid Build Coastguard Worker               glu::PrimitiveList(getGluPrimitiveType(primType), (int)vertices.size()));
210*35238bceSAndroid Build Coastguard Worker }
211*35238bceSAndroid Build Coastguard Worker 
212*35238bceSAndroid Build Coastguard Worker class FboHelper
213*35238bceSAndroid Build Coastguard Worker {
214*35238bceSAndroid Build Coastguard Worker public:
215*35238bceSAndroid Build Coastguard Worker     FboHelper(const glu::RenderContext &renderCtx, int width, int height, uint32_t format, int numSamples);
216*35238bceSAndroid Build Coastguard Worker     ~FboHelper(void);
217*35238bceSAndroid Build Coastguard Worker 
218*35238bceSAndroid Build Coastguard Worker     void bindForRendering(void);
219*35238bceSAndroid Build Coastguard Worker     void readPixels(int x, int y, const tcu::PixelBufferAccess &dst);
220*35238bceSAndroid Build Coastguard Worker 
221*35238bceSAndroid Build Coastguard Worker private:
222*35238bceSAndroid Build Coastguard Worker     const glu::RenderContext &m_renderCtx;
223*35238bceSAndroid Build Coastguard Worker     const int m_numSamples;
224*35238bceSAndroid Build Coastguard Worker     const IVec2 m_size;
225*35238bceSAndroid Build Coastguard Worker 
226*35238bceSAndroid Build Coastguard Worker     glu::Renderbuffer m_colorbuffer;
227*35238bceSAndroid Build Coastguard Worker     glu::Framebuffer m_framebuffer;
228*35238bceSAndroid Build Coastguard Worker     glu::Renderbuffer m_resolveColorbuffer;
229*35238bceSAndroid Build Coastguard Worker     glu::Framebuffer m_resolveFramebuffer;
230*35238bceSAndroid Build Coastguard Worker };
231*35238bceSAndroid Build Coastguard Worker 
FboHelper(const glu::RenderContext & renderCtx,int width,int height,uint32_t format,int numSamples)232*35238bceSAndroid Build Coastguard Worker FboHelper::FboHelper(const glu::RenderContext &renderCtx, int width, int height, uint32_t format, int numSamples)
233*35238bceSAndroid Build Coastguard Worker     : m_renderCtx(renderCtx)
234*35238bceSAndroid Build Coastguard Worker     , m_numSamples(numSamples)
235*35238bceSAndroid Build Coastguard Worker     , m_size(width, height)
236*35238bceSAndroid Build Coastguard Worker     , m_colorbuffer(renderCtx)
237*35238bceSAndroid Build Coastguard Worker     , m_framebuffer(renderCtx)
238*35238bceSAndroid Build Coastguard Worker     , m_resolveColorbuffer(renderCtx)
239*35238bceSAndroid Build Coastguard Worker     , m_resolveFramebuffer(renderCtx)
240*35238bceSAndroid Build Coastguard Worker {
241*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = m_renderCtx.getFunctions();
242*35238bceSAndroid Build Coastguard Worker     const int maxSamples     = getInteger(gl, GL_MAX_SAMPLES);
243*35238bceSAndroid Build Coastguard Worker 
244*35238bceSAndroid Build Coastguard Worker     gl.bindRenderbuffer(GL_RENDERBUFFER, *m_colorbuffer);
245*35238bceSAndroid Build Coastguard Worker     gl.renderbufferStorageMultisample(GL_RENDERBUFFER, m_numSamples, format, width, height);
246*35238bceSAndroid Build Coastguard Worker     gl.bindFramebuffer(GL_FRAMEBUFFER, *m_framebuffer);
247*35238bceSAndroid Build Coastguard Worker     gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *m_colorbuffer);
248*35238bceSAndroid Build Coastguard Worker 
249*35238bceSAndroid Build Coastguard Worker     if (m_numSamples > maxSamples && gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
250*35238bceSAndroid Build Coastguard Worker         throw tcu::NotSupportedError("Sample count exceeds GL_MAX_SAMPLES");
251*35238bceSAndroid Build Coastguard Worker 
252*35238bceSAndroid Build Coastguard Worker     TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
253*35238bceSAndroid Build Coastguard Worker 
254*35238bceSAndroid Build Coastguard Worker     if (m_numSamples != 0)
255*35238bceSAndroid Build Coastguard Worker     {
256*35238bceSAndroid Build Coastguard Worker         gl.bindRenderbuffer(GL_RENDERBUFFER, *m_resolveColorbuffer);
257*35238bceSAndroid Build Coastguard Worker         gl.renderbufferStorage(GL_RENDERBUFFER, format, width, height);
258*35238bceSAndroid Build Coastguard Worker         gl.bindFramebuffer(GL_FRAMEBUFFER, *m_resolveFramebuffer);
259*35238bceSAndroid Build Coastguard Worker         gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *m_resolveColorbuffer);
260*35238bceSAndroid Build Coastguard Worker         TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
261*35238bceSAndroid Build Coastguard Worker     }
262*35238bceSAndroid Build Coastguard Worker 
263*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create framebuffer");
264*35238bceSAndroid Build Coastguard Worker }
265*35238bceSAndroid Build Coastguard Worker 
~FboHelper(void)266*35238bceSAndroid Build Coastguard Worker FboHelper::~FboHelper(void)
267*35238bceSAndroid Build Coastguard Worker {
268*35238bceSAndroid Build Coastguard Worker }
269*35238bceSAndroid Build Coastguard Worker 
bindForRendering(void)270*35238bceSAndroid Build Coastguard Worker void FboHelper::bindForRendering(void)
271*35238bceSAndroid Build Coastguard Worker {
272*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = m_renderCtx.getFunctions();
273*35238bceSAndroid Build Coastguard Worker     gl.bindFramebuffer(GL_FRAMEBUFFER, *m_framebuffer);
274*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer()");
275*35238bceSAndroid Build Coastguard Worker     gl.viewport(0, 0, m_size.x(), m_size.y());
276*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "viewport()");
277*35238bceSAndroid Build Coastguard Worker }
278*35238bceSAndroid Build Coastguard Worker 
readPixels(int x,int y,const tcu::PixelBufferAccess & dst)279*35238bceSAndroid Build Coastguard Worker void FboHelper::readPixels(int x, int y, const tcu::PixelBufferAccess &dst)
280*35238bceSAndroid Build Coastguard Worker {
281*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = m_renderCtx.getFunctions();
282*35238bceSAndroid Build Coastguard Worker     const int width          = dst.getWidth();
283*35238bceSAndroid Build Coastguard Worker     const int height         = dst.getHeight();
284*35238bceSAndroid Build Coastguard Worker 
285*35238bceSAndroid Build Coastguard Worker     if (m_numSamples != 0)
286*35238bceSAndroid Build Coastguard Worker     {
287*35238bceSAndroid Build Coastguard Worker         gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, *m_resolveFramebuffer);
288*35238bceSAndroid Build Coastguard Worker         gl.blitFramebuffer(x, y, width, height, x, y, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
289*35238bceSAndroid Build Coastguard Worker         gl.bindFramebuffer(GL_READ_FRAMEBUFFER, *m_resolveFramebuffer);
290*35238bceSAndroid Build Coastguard Worker     }
291*35238bceSAndroid Build Coastguard Worker 
292*35238bceSAndroid Build Coastguard Worker     glu::readPixels(m_renderCtx, x, y, dst);
293*35238bceSAndroid Build Coastguard Worker }
294*35238bceSAndroid Build Coastguard Worker 
295*35238bceSAndroid Build Coastguard Worker enum
296*35238bceSAndroid Build Coastguard Worker {
297*35238bceSAndroid Build Coastguard Worker     FRAMEBUFFER_WIDTH  = 256,
298*35238bceSAndroid Build Coastguard Worker     FRAMEBUFFER_HEIGHT = 256,
299*35238bceSAndroid Build Coastguard Worker     FRAMEBUFFER_FORMAT = GL_RGBA8,
300*35238bceSAndroid Build Coastguard Worker     NUM_SAMPLES_MAX    = -1
301*35238bceSAndroid Build Coastguard Worker };
302*35238bceSAndroid Build Coastguard Worker 
303*35238bceSAndroid Build Coastguard Worker //! Verifies that gl_HelperInvocation is false in all rendered pixels.
304*35238bceSAndroid Build Coastguard Worker class HelperInvocationValueCase : public TestCase
305*35238bceSAndroid Build Coastguard Worker {
306*35238bceSAndroid Build Coastguard Worker public:
307*35238bceSAndroid Build Coastguard Worker     HelperInvocationValueCase(Context &context, const char *name, const char *description, PrimitiveType primType,
308*35238bceSAndroid Build Coastguard Worker                               int numSamples);
309*35238bceSAndroid Build Coastguard Worker     ~HelperInvocationValueCase(void);
310*35238bceSAndroid Build Coastguard Worker 
311*35238bceSAndroid Build Coastguard Worker     void init(void);
312*35238bceSAndroid Build Coastguard Worker     void deinit(void);
313*35238bceSAndroid Build Coastguard Worker     IterateResult iterate(void);
314*35238bceSAndroid Build Coastguard Worker 
315*35238bceSAndroid Build Coastguard Worker private:
316*35238bceSAndroid Build Coastguard Worker     const PrimitiveType m_primitiveType;
317*35238bceSAndroid Build Coastguard Worker     const int m_numSamples;
318*35238bceSAndroid Build Coastguard Worker 
319*35238bceSAndroid Build Coastguard Worker     const int m_numIters;
320*35238bceSAndroid Build Coastguard Worker     const int m_numPrimitivesPerIter;
321*35238bceSAndroid Build Coastguard Worker 
322*35238bceSAndroid Build Coastguard Worker     MovePtr<ShaderProgram> m_program;
323*35238bceSAndroid Build Coastguard Worker     MovePtr<FboHelper> m_fbo;
324*35238bceSAndroid Build Coastguard Worker     int m_iterNdx;
325*35238bceSAndroid Build Coastguard Worker };
326*35238bceSAndroid Build Coastguard Worker 
HelperInvocationValueCase(Context & context,const char * name,const char * description,PrimitiveType primType,int numSamples)327*35238bceSAndroid Build Coastguard Worker HelperInvocationValueCase::HelperInvocationValueCase(Context &context, const char *name, const char *description,
328*35238bceSAndroid Build Coastguard Worker                                                      PrimitiveType primType, int numSamples)
329*35238bceSAndroid Build Coastguard Worker     : TestCase(context, name, description)
330*35238bceSAndroid Build Coastguard Worker     , m_primitiveType(primType)
331*35238bceSAndroid Build Coastguard Worker     , m_numSamples(numSamples)
332*35238bceSAndroid Build Coastguard Worker     , m_numIters(5)
333*35238bceSAndroid Build Coastguard Worker     , m_numPrimitivesPerIter(10)
334*35238bceSAndroid Build Coastguard Worker     , m_iterNdx(0)
335*35238bceSAndroid Build Coastguard Worker {
336*35238bceSAndroid Build Coastguard Worker }
337*35238bceSAndroid Build Coastguard Worker 
~HelperInvocationValueCase(void)338*35238bceSAndroid Build Coastguard Worker HelperInvocationValueCase::~HelperInvocationValueCase(void)
339*35238bceSAndroid Build Coastguard Worker {
340*35238bceSAndroid Build Coastguard Worker     deinit();
341*35238bceSAndroid Build Coastguard Worker }
342*35238bceSAndroid Build Coastguard Worker 
init(void)343*35238bceSAndroid Build Coastguard Worker void HelperInvocationValueCase::init(void)
344*35238bceSAndroid Build Coastguard Worker {
345*35238bceSAndroid Build Coastguard Worker     const glu::RenderContext &renderCtx = m_context.getRenderContext();
346*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl            = renderCtx.getFunctions();
347*35238bceSAndroid Build Coastguard Worker     const int maxSamples                = getInteger(gl, GL_MAX_SAMPLES);
348*35238bceSAndroid Build Coastguard Worker     const int actualSamples             = m_numSamples == NUM_SAMPLES_MAX ? maxSamples : m_numSamples;
349*35238bceSAndroid Build Coastguard Worker 
350*35238bceSAndroid Build Coastguard Worker     m_program = MovePtr<ShaderProgram>(
351*35238bceSAndroid Build Coastguard Worker         new ShaderProgram(m_context.getRenderContext(),
352*35238bceSAndroid Build Coastguard Worker                           glu::ProgramSources() << glu::VertexSource("#version 310 es\n"
353*35238bceSAndroid Build Coastguard Worker                                                                      "in highp vec2 a_position;\n"
354*35238bceSAndroid Build Coastguard Worker                                                                      "uniform highp float u_pointSize;\n"
355*35238bceSAndroid Build Coastguard Worker                                                                      "void main (void)\n"
356*35238bceSAndroid Build Coastguard Worker                                                                      "{\n"
357*35238bceSAndroid Build Coastguard Worker                                                                      "    gl_Position = vec4(a_position, 0.0, 1.0);\n"
358*35238bceSAndroid Build Coastguard Worker                                                                      "    gl_PointSize = u_pointSize;\n"
359*35238bceSAndroid Build Coastguard Worker                                                                      "}\n")
360*35238bceSAndroid Build Coastguard Worker                                                 << glu::FragmentSource("#version 310 es\n"
361*35238bceSAndroid Build Coastguard Worker                                                                        "out mediump vec4 o_color;\n"
362*35238bceSAndroid Build Coastguard Worker                                                                        "void main (void)\n"
363*35238bceSAndroid Build Coastguard Worker                                                                        "{\n"
364*35238bceSAndroid Build Coastguard Worker                                                                        "    if (gl_HelperInvocation)\n"
365*35238bceSAndroid Build Coastguard Worker                                                                        "        o_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
366*35238bceSAndroid Build Coastguard Worker                                                                        "    else\n"
367*35238bceSAndroid Build Coastguard Worker                                                                        "        o_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
368*35238bceSAndroid Build Coastguard Worker                                                                        "}\n")));
369*35238bceSAndroid Build Coastguard Worker 
370*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << *m_program;
371*35238bceSAndroid Build Coastguard Worker 
372*35238bceSAndroid Build Coastguard Worker     if (!m_program->isOk())
373*35238bceSAndroid Build Coastguard Worker     {
374*35238bceSAndroid Build Coastguard Worker         m_program.clear();
375*35238bceSAndroid Build Coastguard Worker         TCU_FAIL("Compile failed");
376*35238bceSAndroid Build Coastguard Worker     }
377*35238bceSAndroid Build Coastguard Worker 
378*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << TestLog::Message << "Using GL_RGBA8 framebuffer with " << actualSamples << " samples"
379*35238bceSAndroid Build Coastguard Worker                        << TestLog::EndMessage;
380*35238bceSAndroid Build Coastguard Worker 
381*35238bceSAndroid Build Coastguard Worker     m_fbo = MovePtr<FboHelper>(
382*35238bceSAndroid Build Coastguard Worker         new FboHelper(renderCtx, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT, FRAMEBUFFER_FORMAT, actualSamples));
383*35238bceSAndroid Build Coastguard Worker 
384*35238bceSAndroid Build Coastguard Worker     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
385*35238bceSAndroid Build Coastguard Worker }
386*35238bceSAndroid Build Coastguard Worker 
deinit(void)387*35238bceSAndroid Build Coastguard Worker void HelperInvocationValueCase::deinit(void)
388*35238bceSAndroid Build Coastguard Worker {
389*35238bceSAndroid Build Coastguard Worker     m_program.clear();
390*35238bceSAndroid Build Coastguard Worker     m_fbo.clear();
391*35238bceSAndroid Build Coastguard Worker }
392*35238bceSAndroid Build Coastguard Worker 
verifyHelperInvocationValue(TestLog & log,const tcu::Surface & result,bool isMultiSample)393*35238bceSAndroid Build Coastguard Worker static bool verifyHelperInvocationValue(TestLog &log, const tcu::Surface &result, bool isMultiSample)
394*35238bceSAndroid Build Coastguard Worker {
395*35238bceSAndroid Build Coastguard Worker     const tcu::RGBA bgRef(0, 0, 0, 255);
396*35238bceSAndroid Build Coastguard Worker     const tcu::RGBA fgRef(0, 255, 0, 255);
397*35238bceSAndroid Build Coastguard Worker     const tcu::RGBA threshold(1, isMultiSample ? 254 : 1, 1, 1);
398*35238bceSAndroid Build Coastguard Worker     int numInvalidPixels   = 0;
399*35238bceSAndroid Build Coastguard Worker     bool renderedSomething = false;
400*35238bceSAndroid Build Coastguard Worker 
401*35238bceSAndroid Build Coastguard Worker     for (int y = 0; y < result.getHeight(); ++y)
402*35238bceSAndroid Build Coastguard Worker     {
403*35238bceSAndroid Build Coastguard Worker         for (int x = 0; x < result.getWidth(); ++x)
404*35238bceSAndroid Build Coastguard Worker         {
405*35238bceSAndroid Build Coastguard Worker             const tcu::RGBA resPix = result.getPixel(x, y);
406*35238bceSAndroid Build Coastguard Worker             const bool isBg        = tcu::compareThreshold(resPix, bgRef, threshold);
407*35238bceSAndroid Build Coastguard Worker             const bool isFg        = tcu::compareThreshold(resPix, fgRef, threshold);
408*35238bceSAndroid Build Coastguard Worker 
409*35238bceSAndroid Build Coastguard Worker             if (!isBg && !isFg)
410*35238bceSAndroid Build Coastguard Worker                 numInvalidPixels += 1;
411*35238bceSAndroid Build Coastguard Worker 
412*35238bceSAndroid Build Coastguard Worker             if (isFg)
413*35238bceSAndroid Build Coastguard Worker                 renderedSomething = true;
414*35238bceSAndroid Build Coastguard Worker         }
415*35238bceSAndroid Build Coastguard Worker     }
416*35238bceSAndroid Build Coastguard Worker 
417*35238bceSAndroid Build Coastguard Worker     if (numInvalidPixels > 0)
418*35238bceSAndroid Build Coastguard Worker     {
419*35238bceSAndroid Build Coastguard Worker         log << TestLog::Image("Result", "Result image", result);
420*35238bceSAndroid Build Coastguard Worker         log << TestLog::Message << "ERROR: Found " << numInvalidPixels << " invalid result pixels!"
421*35238bceSAndroid Build Coastguard Worker             << TestLog::EndMessage;
422*35238bceSAndroid Build Coastguard Worker         return false;
423*35238bceSAndroid Build Coastguard Worker     }
424*35238bceSAndroid Build Coastguard Worker     else if (!renderedSomething)
425*35238bceSAndroid Build Coastguard Worker     {
426*35238bceSAndroid Build Coastguard Worker         log << TestLog::Image("Result", "Result image", result);
427*35238bceSAndroid Build Coastguard Worker         log << TestLog::Message << "ERROR: Result image was empty!" << TestLog::EndMessage;
428*35238bceSAndroid Build Coastguard Worker         return false;
429*35238bceSAndroid Build Coastguard Worker     }
430*35238bceSAndroid Build Coastguard Worker     else
431*35238bceSAndroid Build Coastguard Worker     {
432*35238bceSAndroid Build Coastguard Worker         log << TestLog::Message << "All result pixels are valid" << TestLog::EndMessage;
433*35238bceSAndroid Build Coastguard Worker         return true;
434*35238bceSAndroid Build Coastguard Worker     }
435*35238bceSAndroid Build Coastguard Worker }
436*35238bceSAndroid Build Coastguard Worker 
iterate(void)437*35238bceSAndroid Build Coastguard Worker HelperInvocationValueCase::IterateResult HelperInvocationValueCase::iterate(void)
438*35238bceSAndroid Build Coastguard Worker {
439*35238bceSAndroid Build Coastguard Worker     const glu::RenderContext &renderCtx = m_context.getRenderContext();
440*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl            = renderCtx.getFunctions();
441*35238bceSAndroid Build Coastguard Worker     const string sectionName = string("Iteration ") + de::toString(m_iterNdx + 1) + " / " + de::toString(m_numIters);
442*35238bceSAndroid Build Coastguard Worker     const tcu::ScopedLogSection section(m_testCtx.getLog(), (string("Iter") + de::toString(m_iterNdx)), sectionName);
443*35238bceSAndroid Build Coastguard Worker     de::Random rnd(deStringHash(getName()) ^ deInt32Hash(m_iterNdx));
444*35238bceSAndroid Build Coastguard Worker     tcu::Surface result(FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT);
445*35238bceSAndroid Build Coastguard Worker 
446*35238bceSAndroid Build Coastguard Worker     m_fbo->bindForRendering();
447*35238bceSAndroid Build Coastguard Worker     gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
448*35238bceSAndroid Build Coastguard Worker     gl.clear(GL_COLOR_BUFFER_BIT);
449*35238bceSAndroid Build Coastguard Worker 
450*35238bceSAndroid Build Coastguard Worker     drawRandomPrimitives(renderCtx, m_program->getProgram(), m_primitiveType, m_numPrimitivesPerIter, &rnd);
451*35238bceSAndroid Build Coastguard Worker 
452*35238bceSAndroid Build Coastguard Worker     m_fbo->readPixels(0, 0, result.getAccess());
453*35238bceSAndroid Build Coastguard Worker 
454*35238bceSAndroid Build Coastguard Worker     if (!verifyHelperInvocationValue(m_testCtx.getLog(), result, m_numSamples != 0))
455*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid pixels found");
456*35238bceSAndroid Build Coastguard Worker 
457*35238bceSAndroid Build Coastguard Worker     m_iterNdx += 1;
458*35238bceSAndroid Build Coastguard Worker     return (m_iterNdx < m_numIters) ? CONTINUE : STOP;
459*35238bceSAndroid Build Coastguard Worker }
460*35238bceSAndroid Build Coastguard Worker 
461*35238bceSAndroid Build Coastguard Worker //! Checks derivates when value depends on gl_HelperInvocation.
462*35238bceSAndroid Build Coastguard Worker class HelperInvocationDerivateCase : public TestCase
463*35238bceSAndroid Build Coastguard Worker {
464*35238bceSAndroid Build Coastguard Worker public:
465*35238bceSAndroid Build Coastguard Worker     HelperInvocationDerivateCase(Context &context, const char *name, const char *description, PrimitiveType primType,
466*35238bceSAndroid Build Coastguard Worker                                  int numSamples, const char *derivateFunc, bool checkAbsoluteValue);
467*35238bceSAndroid Build Coastguard Worker     ~HelperInvocationDerivateCase(void);
468*35238bceSAndroid Build Coastguard Worker 
469*35238bceSAndroid Build Coastguard Worker     void init(void);
470*35238bceSAndroid Build Coastguard Worker     void deinit(void);
471*35238bceSAndroid Build Coastguard Worker     IterateResult iterate(void);
472*35238bceSAndroid Build Coastguard Worker 
473*35238bceSAndroid Build Coastguard Worker private:
474*35238bceSAndroid Build Coastguard Worker     const PrimitiveType m_primitiveType;
475*35238bceSAndroid Build Coastguard Worker     const int m_numSamples;
476*35238bceSAndroid Build Coastguard Worker     const std::string m_derivateFunc;
477*35238bceSAndroid Build Coastguard Worker     const bool m_checkAbsoluteValue;
478*35238bceSAndroid Build Coastguard Worker 
479*35238bceSAndroid Build Coastguard Worker     const int m_numIters;
480*35238bceSAndroid Build Coastguard Worker 
481*35238bceSAndroid Build Coastguard Worker     MovePtr<ShaderProgram> m_program;
482*35238bceSAndroid Build Coastguard Worker     MovePtr<FboHelper> m_fbo;
483*35238bceSAndroid Build Coastguard Worker     int m_iterNdx;
484*35238bceSAndroid Build Coastguard Worker };
485*35238bceSAndroid Build Coastguard Worker 
HelperInvocationDerivateCase(Context & context,const char * name,const char * description,PrimitiveType primType,int numSamples,const char * derivateFunc,bool checkAbsoluteValue)486*35238bceSAndroid Build Coastguard Worker HelperInvocationDerivateCase::HelperInvocationDerivateCase(Context &context, const char *name, const char *description,
487*35238bceSAndroid Build Coastguard Worker                                                            PrimitiveType primType, int numSamples,
488*35238bceSAndroid Build Coastguard Worker                                                            const char *derivateFunc, bool checkAbsoluteValue)
489*35238bceSAndroid Build Coastguard Worker     : TestCase(context, name, description)
490*35238bceSAndroid Build Coastguard Worker     , m_primitiveType(primType)
491*35238bceSAndroid Build Coastguard Worker     , m_numSamples(numSamples)
492*35238bceSAndroid Build Coastguard Worker     , m_derivateFunc(derivateFunc)
493*35238bceSAndroid Build Coastguard Worker     , m_checkAbsoluteValue(checkAbsoluteValue)
494*35238bceSAndroid Build Coastguard Worker     , m_numIters(16)
495*35238bceSAndroid Build Coastguard Worker     , m_iterNdx(0)
496*35238bceSAndroid Build Coastguard Worker {
497*35238bceSAndroid Build Coastguard Worker }
498*35238bceSAndroid Build Coastguard Worker 
~HelperInvocationDerivateCase(void)499*35238bceSAndroid Build Coastguard Worker HelperInvocationDerivateCase::~HelperInvocationDerivateCase(void)
500*35238bceSAndroid Build Coastguard Worker {
501*35238bceSAndroid Build Coastguard Worker     deinit();
502*35238bceSAndroid Build Coastguard Worker }
503*35238bceSAndroid Build Coastguard Worker 
init(void)504*35238bceSAndroid Build Coastguard Worker void HelperInvocationDerivateCase::init(void)
505*35238bceSAndroid Build Coastguard Worker {
506*35238bceSAndroid Build Coastguard Worker     const glu::RenderContext &renderCtx = m_context.getRenderContext();
507*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl            = renderCtx.getFunctions();
508*35238bceSAndroid Build Coastguard Worker     const int maxSamples                = getInteger(gl, GL_MAX_SAMPLES);
509*35238bceSAndroid Build Coastguard Worker     const int actualSamples             = m_numSamples == NUM_SAMPLES_MAX ? maxSamples : m_numSamples;
510*35238bceSAndroid Build Coastguard Worker     const std::string funcSource =
511*35238bceSAndroid Build Coastguard Worker         (m_checkAbsoluteValue) ? ("abs(" + m_derivateFunc + "(value))") : (m_derivateFunc + "(value)");
512*35238bceSAndroid Build Coastguard Worker 
513*35238bceSAndroid Build Coastguard Worker     m_program = MovePtr<ShaderProgram>(new ShaderProgram(
514*35238bceSAndroid Build Coastguard Worker         m_context.getRenderContext(),
515*35238bceSAndroid Build Coastguard Worker         glu::ProgramSources() << glu::VertexSource("#version 310 es\n"
516*35238bceSAndroid Build Coastguard Worker                                                    "in highp vec2 a_position;\n"
517*35238bceSAndroid Build Coastguard Worker                                                    "uniform highp float u_pointSize;\n"
518*35238bceSAndroid Build Coastguard Worker                                                    "void main (void)\n"
519*35238bceSAndroid Build Coastguard Worker                                                    "{\n"
520*35238bceSAndroid Build Coastguard Worker                                                    "    gl_Position = vec4(a_position, 0.0, 1.0);\n"
521*35238bceSAndroid Build Coastguard Worker                                                    "    gl_PointSize = u_pointSize;\n"
522*35238bceSAndroid Build Coastguard Worker                                                    "}\n")
523*35238bceSAndroid Build Coastguard Worker                               << glu::FragmentSource(string("#version 310 es\n"
524*35238bceSAndroid Build Coastguard Worker                                                             "out mediump vec4 o_color;\n"
525*35238bceSAndroid Build Coastguard Worker                                                             "void main (void)\n"
526*35238bceSAndroid Build Coastguard Worker                                                             "{\n"
527*35238bceSAndroid Build Coastguard Worker                                                             "    highp float value = gl_HelperInvocation ? 1.0 : 0.0;\n"
528*35238bceSAndroid Build Coastguard Worker                                                             "    highp float derivate = ") +
529*35238bceSAndroid Build Coastguard Worker                                                      funcSource +
530*35238bceSAndroid Build Coastguard Worker                                                      ";\n"
531*35238bceSAndroid Build Coastguard Worker                                                      "    if (gl_HelperInvocation)\n"
532*35238bceSAndroid Build Coastguard Worker                                                      "        o_color = vec4(1.0, 0.0, derivate, 1.0);\n"
533*35238bceSAndroid Build Coastguard Worker                                                      "    else\n"
534*35238bceSAndroid Build Coastguard Worker                                                      "        o_color = vec4(0.0, 1.0, derivate, 1.0);\n"
535*35238bceSAndroid Build Coastguard Worker                                                      "}\n")));
536*35238bceSAndroid Build Coastguard Worker 
537*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << *m_program;
538*35238bceSAndroid Build Coastguard Worker 
539*35238bceSAndroid Build Coastguard Worker     if (!m_program->isOk())
540*35238bceSAndroid Build Coastguard Worker     {
541*35238bceSAndroid Build Coastguard Worker         m_program.clear();
542*35238bceSAndroid Build Coastguard Worker         TCU_FAIL("Compile failed");
543*35238bceSAndroid Build Coastguard Worker     }
544*35238bceSAndroid Build Coastguard Worker 
545*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << TestLog::Message << "Using GL_RGBA8 framebuffer with " << actualSamples << " samples"
546*35238bceSAndroid Build Coastguard Worker                        << TestLog::EndMessage;
547*35238bceSAndroid Build Coastguard Worker 
548*35238bceSAndroid Build Coastguard Worker     m_fbo = MovePtr<FboHelper>(
549*35238bceSAndroid Build Coastguard Worker         new FboHelper(renderCtx, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT, FRAMEBUFFER_FORMAT, actualSamples));
550*35238bceSAndroid Build Coastguard Worker 
551*35238bceSAndroid Build Coastguard Worker     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
552*35238bceSAndroid Build Coastguard Worker }
553*35238bceSAndroid Build Coastguard Worker 
deinit(void)554*35238bceSAndroid Build Coastguard Worker void HelperInvocationDerivateCase::deinit(void)
555*35238bceSAndroid Build Coastguard Worker {
556*35238bceSAndroid Build Coastguard Worker     m_program.clear();
557*35238bceSAndroid Build Coastguard Worker     m_fbo.clear();
558*35238bceSAndroid Build Coastguard Worker }
559*35238bceSAndroid Build Coastguard Worker 
hasNeighborWithColor(const tcu::Surface & surface,int x,int y,tcu::RGBA color,tcu::RGBA threshold)560*35238bceSAndroid Build Coastguard Worker static bool hasNeighborWithColor(const tcu::Surface &surface, int x, int y, tcu::RGBA color, tcu::RGBA threshold)
561*35238bceSAndroid Build Coastguard Worker {
562*35238bceSAndroid Build Coastguard Worker     const int w = surface.getWidth();
563*35238bceSAndroid Build Coastguard Worker     const int h = surface.getHeight();
564*35238bceSAndroid Build Coastguard Worker 
565*35238bceSAndroid Build Coastguard Worker     for (int dx = -1; dx < 2; dx++)
566*35238bceSAndroid Build Coastguard Worker         for (int dy = -1; dy < 2; dy++)
567*35238bceSAndroid Build Coastguard Worker         {
568*35238bceSAndroid Build Coastguard Worker             const IVec2 pos = IVec2(x + dx, y + dy);
569*35238bceSAndroid Build Coastguard Worker 
570*35238bceSAndroid Build Coastguard Worker             if (dx == 0 && dy == 0)
571*35238bceSAndroid Build Coastguard Worker                 continue;
572*35238bceSAndroid Build Coastguard Worker 
573*35238bceSAndroid Build Coastguard Worker             if (de::inBounds(pos.x(), 0, w) && de::inBounds(pos.y(), 0, h))
574*35238bceSAndroid Build Coastguard Worker             {
575*35238bceSAndroid Build Coastguard Worker                 const tcu::RGBA neighborColor = surface.getPixel(pos.x(), pos.y());
576*35238bceSAndroid Build Coastguard Worker 
577*35238bceSAndroid Build Coastguard Worker                 if (tcu::compareThreshold(color, neighborColor, threshold))
578*35238bceSAndroid Build Coastguard Worker                     return true;
579*35238bceSAndroid Build Coastguard Worker             }
580*35238bceSAndroid Build Coastguard Worker             else
581*35238bceSAndroid Build Coastguard Worker                 return true; // Can't know for certain
582*35238bceSAndroid Build Coastguard Worker         }
583*35238bceSAndroid Build Coastguard Worker 
584*35238bceSAndroid Build Coastguard Worker     return false;
585*35238bceSAndroid Build Coastguard Worker }
586*35238bceSAndroid Build Coastguard Worker 
verifyHelperInvocationDerivate(TestLog & log,const tcu::Surface & result,bool isMultiSample)587*35238bceSAndroid Build Coastguard Worker static bool verifyHelperInvocationDerivate(TestLog &log, const tcu::Surface &result, bool isMultiSample)
588*35238bceSAndroid Build Coastguard Worker {
589*35238bceSAndroid Build Coastguard Worker     const tcu::RGBA bgRef(0, 0, 0, 255);
590*35238bceSAndroid Build Coastguard Worker     const tcu::RGBA fgRef(0, 255, 0, 255);
591*35238bceSAndroid Build Coastguard Worker     const tcu::RGBA isBgThreshold(1, isMultiSample ? 254 : 1, 0, 1);
592*35238bceSAndroid Build Coastguard Worker     const tcu::RGBA isFgThreshold(1, isMultiSample ? 254 : 1, 255, 1);
593*35238bceSAndroid Build Coastguard Worker     int numInvalidPixels   = 0;
594*35238bceSAndroid Build Coastguard Worker     int numNonZeroDeriv    = 0;
595*35238bceSAndroid Build Coastguard Worker     bool renderedSomething = false;
596*35238bceSAndroid Build Coastguard Worker 
597*35238bceSAndroid Build Coastguard Worker     for (int y = 0; y < result.getHeight(); ++y)
598*35238bceSAndroid Build Coastguard Worker     {
599*35238bceSAndroid Build Coastguard Worker         for (int x = 0; x < result.getWidth(); ++x)
600*35238bceSAndroid Build Coastguard Worker         {
601*35238bceSAndroid Build Coastguard Worker             const tcu::RGBA resPix  = result.getPixel(x, y);
602*35238bceSAndroid Build Coastguard Worker             const bool isBg         = tcu::compareThreshold(resPix, bgRef, isBgThreshold);
603*35238bceSAndroid Build Coastguard Worker             const bool isFg         = tcu::compareThreshold(resPix, fgRef, isFgThreshold);
604*35238bceSAndroid Build Coastguard Worker             const bool nonZeroDeriv = resPix.getBlue() > 0;
605*35238bceSAndroid Build Coastguard Worker             const bool neighborBg   = nonZeroDeriv ? hasNeighborWithColor(result, x, y, bgRef, isBgThreshold) : false;
606*35238bceSAndroid Build Coastguard Worker 
607*35238bceSAndroid Build Coastguard Worker             if (nonZeroDeriv)
608*35238bceSAndroid Build Coastguard Worker                 numNonZeroDeriv += 1;
609*35238bceSAndroid Build Coastguard Worker 
610*35238bceSAndroid Build Coastguard Worker             if ((!isBg && !isFg) || // Neither of valid colors (ignoring blue channel that has derivate)
611*35238bceSAndroid Build Coastguard Worker                 (nonZeroDeriv && !neighborBg &&
612*35238bceSAndroid Build Coastguard Worker                  !isFg)) // Has non-zero derivate, but sample not at primitive edge or inside primitive
613*35238bceSAndroid Build Coastguard Worker                 numInvalidPixels += 1;
614*35238bceSAndroid Build Coastguard Worker 
615*35238bceSAndroid Build Coastguard Worker             if (isFg)
616*35238bceSAndroid Build Coastguard Worker                 renderedSomething = true;
617*35238bceSAndroid Build Coastguard Worker         }
618*35238bceSAndroid Build Coastguard Worker     }
619*35238bceSAndroid Build Coastguard Worker 
620*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "Found " << numNonZeroDeriv
621*35238bceSAndroid Build Coastguard Worker         << " pixels with non-zero derivate (neighbor sample has gl_HelperInvocation = true)" << TestLog::EndMessage;
622*35238bceSAndroid Build Coastguard Worker 
623*35238bceSAndroid Build Coastguard Worker     if (numInvalidPixels > 0)
624*35238bceSAndroid Build Coastguard Worker     {
625*35238bceSAndroid Build Coastguard Worker         log << TestLog::Image("Result", "Result image", result);
626*35238bceSAndroid Build Coastguard Worker         log << TestLog::Message << "ERROR: Found " << numInvalidPixels << " invalid result pixels!"
627*35238bceSAndroid Build Coastguard Worker             << TestLog::EndMessage;
628*35238bceSAndroid Build Coastguard Worker         return false;
629*35238bceSAndroid Build Coastguard Worker     }
630*35238bceSAndroid Build Coastguard Worker     else if (!renderedSomething)
631*35238bceSAndroid Build Coastguard Worker     {
632*35238bceSAndroid Build Coastguard Worker         log << TestLog::Image("Result", "Result image", result);
633*35238bceSAndroid Build Coastguard Worker         log << TestLog::Message << "ERROR: Result image was empty!" << TestLog::EndMessage;
634*35238bceSAndroid Build Coastguard Worker         return false;
635*35238bceSAndroid Build Coastguard Worker     }
636*35238bceSAndroid Build Coastguard Worker     else
637*35238bceSAndroid Build Coastguard Worker     {
638*35238bceSAndroid Build Coastguard Worker         log << TestLog::Message << "All result pixels are valid" << TestLog::EndMessage;
639*35238bceSAndroid Build Coastguard Worker         return true;
640*35238bceSAndroid Build Coastguard Worker     }
641*35238bceSAndroid Build Coastguard Worker }
642*35238bceSAndroid Build Coastguard Worker 
iterate(void)643*35238bceSAndroid Build Coastguard Worker HelperInvocationDerivateCase::IterateResult HelperInvocationDerivateCase::iterate(void)
644*35238bceSAndroid Build Coastguard Worker {
645*35238bceSAndroid Build Coastguard Worker     const glu::RenderContext &renderCtx = m_context.getRenderContext();
646*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl            = renderCtx.getFunctions();
647*35238bceSAndroid Build Coastguard Worker     const string sectionName = string("Iteration ") + de::toString(m_iterNdx + 1) + " / " + de::toString(m_numIters);
648*35238bceSAndroid Build Coastguard Worker     const tcu::ScopedLogSection section(m_testCtx.getLog(), (string("Iter") + de::toString(m_iterNdx)), sectionName);
649*35238bceSAndroid Build Coastguard Worker     de::Random rnd(deStringHash(getName()) ^ deInt32Hash(m_iterNdx));
650*35238bceSAndroid Build Coastguard Worker     tcu::Surface result(FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT);
651*35238bceSAndroid Build Coastguard Worker 
652*35238bceSAndroid Build Coastguard Worker     m_fbo->bindForRendering();
653*35238bceSAndroid Build Coastguard Worker     gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
654*35238bceSAndroid Build Coastguard Worker     gl.clear(GL_COLOR_BUFFER_BIT);
655*35238bceSAndroid Build Coastguard Worker 
656*35238bceSAndroid Build Coastguard Worker     drawRandomPrimitives(renderCtx, m_program->getProgram(), m_primitiveType, 1, &rnd);
657*35238bceSAndroid Build Coastguard Worker 
658*35238bceSAndroid Build Coastguard Worker     m_fbo->readPixels(0, 0, result.getAccess());
659*35238bceSAndroid Build Coastguard Worker 
660*35238bceSAndroid Build Coastguard Worker     if (!verifyHelperInvocationDerivate(m_testCtx.getLog(), result, m_numSamples != 0))
661*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid pixels found");
662*35238bceSAndroid Build Coastguard Worker 
663*35238bceSAndroid Build Coastguard Worker     m_iterNdx += 1;
664*35238bceSAndroid Build Coastguard Worker     return (m_iterNdx < m_numIters) ? CONTINUE : STOP;
665*35238bceSAndroid Build Coastguard Worker }
666*35238bceSAndroid Build Coastguard Worker 
667*35238bceSAndroid Build Coastguard Worker } // namespace
668*35238bceSAndroid Build Coastguard Worker 
ShaderHelperInvocationTests(Context & context)669*35238bceSAndroid Build Coastguard Worker ShaderHelperInvocationTests::ShaderHelperInvocationTests(Context &context)
670*35238bceSAndroid Build Coastguard Worker     : TestCaseGroup(context, "helper_invocation", "gl_HelperInvocation tests")
671*35238bceSAndroid Build Coastguard Worker {
672*35238bceSAndroid Build Coastguard Worker }
673*35238bceSAndroid Build Coastguard Worker 
~ShaderHelperInvocationTests(void)674*35238bceSAndroid Build Coastguard Worker ShaderHelperInvocationTests::~ShaderHelperInvocationTests(void)
675*35238bceSAndroid Build Coastguard Worker {
676*35238bceSAndroid Build Coastguard Worker }
677*35238bceSAndroid Build Coastguard Worker 
init(void)678*35238bceSAndroid Build Coastguard Worker void ShaderHelperInvocationTests::init(void)
679*35238bceSAndroid Build Coastguard Worker {
680*35238bceSAndroid Build Coastguard Worker     static const struct
681*35238bceSAndroid Build Coastguard Worker     {
682*35238bceSAndroid Build Coastguard Worker         const char *caseName;
683*35238bceSAndroid Build Coastguard Worker         PrimitiveType primType;
684*35238bceSAndroid Build Coastguard Worker     } s_primTypes[] = {{"triangles", PRIMITIVETYPE_TRIANGLE},
685*35238bceSAndroid Build Coastguard Worker                        {"lines", PRIMITIVETYPE_LINE},
686*35238bceSAndroid Build Coastguard Worker                        {"wide_lines", PRIMITIVETYPE_WIDE_LINE},
687*35238bceSAndroid Build Coastguard Worker                        {"points", PRIMITIVETYPE_POINT},
688*35238bceSAndroid Build Coastguard Worker                        {"wide_points", PRIMITIVETYPE_WIDE_POINT}};
689*35238bceSAndroid Build Coastguard Worker 
690*35238bceSAndroid Build Coastguard Worker     static const struct
691*35238bceSAndroid Build Coastguard Worker     {
692*35238bceSAndroid Build Coastguard Worker         const char *suffix;
693*35238bceSAndroid Build Coastguard Worker         int numSamples;
694*35238bceSAndroid Build Coastguard Worker     } s_sampleCounts[] = {{"", 0}, {"_4_samples", 4}, {"_8_samples", 8}, {"_max_samples", NUM_SAMPLES_MAX}};
695*35238bceSAndroid Build Coastguard Worker 
696*35238bceSAndroid Build Coastguard Worker     // value
697*35238bceSAndroid Build Coastguard Worker     {
698*35238bceSAndroid Build Coastguard Worker         tcu::TestCaseGroup *const valueGroup =
699*35238bceSAndroid Build Coastguard Worker             new tcu::TestCaseGroup(m_testCtx, "value", "gl_HelperInvocation value in rendered pixels");
700*35238bceSAndroid Build Coastguard Worker         addChild(valueGroup);
701*35238bceSAndroid Build Coastguard Worker 
702*35238bceSAndroid Build Coastguard Worker         for (int sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(s_sampleCounts); sampleCountNdx++)
703*35238bceSAndroid Build Coastguard Worker         {
704*35238bceSAndroid Build Coastguard Worker             for (int primTypeNdx = 0; primTypeNdx < DE_LENGTH_OF_ARRAY(s_primTypes); primTypeNdx++)
705*35238bceSAndroid Build Coastguard Worker             {
706*35238bceSAndroid Build Coastguard Worker                 const string name = string(s_primTypes[primTypeNdx].caseName) + s_sampleCounts[sampleCountNdx].suffix;
707*35238bceSAndroid Build Coastguard Worker                 const PrimitiveType primType = s_primTypes[primTypeNdx].primType;
708*35238bceSAndroid Build Coastguard Worker                 const int numSamples         = s_sampleCounts[sampleCountNdx].numSamples;
709*35238bceSAndroid Build Coastguard Worker 
710*35238bceSAndroid Build Coastguard Worker                 valueGroup->addChild(new HelperInvocationValueCase(m_context, name.c_str(), "", primType, numSamples));
711*35238bceSAndroid Build Coastguard Worker             }
712*35238bceSAndroid Build Coastguard Worker         }
713*35238bceSAndroid Build Coastguard Worker     }
714*35238bceSAndroid Build Coastguard Worker 
715*35238bceSAndroid Build Coastguard Worker     // derivate
716*35238bceSAndroid Build Coastguard Worker     {
717*35238bceSAndroid Build Coastguard Worker         tcu::TestCaseGroup *const derivateGroup =
718*35238bceSAndroid Build Coastguard Worker             new tcu::TestCaseGroup(m_testCtx, "derivate", "Derivate of gl_HelperInvocation-dependent value");
719*35238bceSAndroid Build Coastguard Worker         addChild(derivateGroup);
720*35238bceSAndroid Build Coastguard Worker 
721*35238bceSAndroid Build Coastguard Worker         for (int sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(s_sampleCounts); sampleCountNdx++)
722*35238bceSAndroid Build Coastguard Worker         {
723*35238bceSAndroid Build Coastguard Worker             for (int primTypeNdx = 0; primTypeNdx < DE_LENGTH_OF_ARRAY(s_primTypes); primTypeNdx++)
724*35238bceSAndroid Build Coastguard Worker             {
725*35238bceSAndroid Build Coastguard Worker                 const string name = string(s_primTypes[primTypeNdx].caseName) + s_sampleCounts[sampleCountNdx].suffix;
726*35238bceSAndroid Build Coastguard Worker                 const PrimitiveType primType = s_primTypes[primTypeNdx].primType;
727*35238bceSAndroid Build Coastguard Worker                 const int numSamples         = s_sampleCounts[sampleCountNdx].numSamples;
728*35238bceSAndroid Build Coastguard Worker 
729*35238bceSAndroid Build Coastguard Worker                 derivateGroup->addChild(new HelperInvocationDerivateCase(m_context, (name + "_dfdx").c_str(), "",
730*35238bceSAndroid Build Coastguard Worker                                                                          primType, numSamples, "dFdx", true));
731*35238bceSAndroid Build Coastguard Worker                 derivateGroup->addChild(new HelperInvocationDerivateCase(m_context, (name + "_dfdy").c_str(), "",
732*35238bceSAndroid Build Coastguard Worker                                                                          primType, numSamples, "dFdy", true));
733*35238bceSAndroid Build Coastguard Worker                 derivateGroup->addChild(new HelperInvocationDerivateCase(m_context, (name + "_fwidth").c_str(), "",
734*35238bceSAndroid Build Coastguard Worker                                                                          primType, numSamples, "fwidth", false));
735*35238bceSAndroid Build Coastguard Worker             }
736*35238bceSAndroid Build Coastguard Worker         }
737*35238bceSAndroid Build Coastguard Worker     }
738*35238bceSAndroid Build Coastguard Worker }
739*35238bceSAndroid Build Coastguard Worker 
740*35238bceSAndroid Build Coastguard Worker } // namespace Functional
741*35238bceSAndroid Build Coastguard Worker } // namespace gles31
742*35238bceSAndroid Build Coastguard Worker } // namespace deqp
743