xref: /aosp_15_r20/external/deqp/modules/gles31/stress/es31sTessellationGeometryInteractionTests.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 Tessellation and geometry shader interaction stress tests.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "es31sTessellationGeometryInteractionTests.hpp"
25*35238bceSAndroid Build Coastguard Worker 
26*35238bceSAndroid Build Coastguard Worker #include "tcuTestLog.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "tcuRenderTarget.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "tcuSurface.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "tcuTextureUtil.hpp"
30*35238bceSAndroid Build Coastguard Worker #include "gluRenderContext.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "gluShaderProgram.hpp"
32*35238bceSAndroid Build Coastguard Worker #include "gluContextInfo.hpp"
33*35238bceSAndroid Build Coastguard Worker #include "gluObjectWrapper.hpp"
34*35238bceSAndroid Build Coastguard Worker #include "gluPixelTransfer.hpp"
35*35238bceSAndroid Build Coastguard Worker #include "glwFunctions.hpp"
36*35238bceSAndroid Build Coastguard Worker #include "glwEnums.hpp"
37*35238bceSAndroid Build Coastguard Worker #include "deStringUtil.hpp"
38*35238bceSAndroid Build Coastguard Worker #include "deUniquePtr.hpp"
39*35238bceSAndroid Build Coastguard Worker 
40*35238bceSAndroid Build Coastguard Worker #include <sstream>
41*35238bceSAndroid Build Coastguard Worker 
42*35238bceSAndroid Build Coastguard Worker namespace deqp
43*35238bceSAndroid Build Coastguard Worker {
44*35238bceSAndroid Build Coastguard Worker namespace gles31
45*35238bceSAndroid Build Coastguard Worker {
46*35238bceSAndroid Build Coastguard Worker namespace Stress
47*35238bceSAndroid Build Coastguard Worker {
48*35238bceSAndroid Build Coastguard Worker namespace
49*35238bceSAndroid Build Coastguard Worker {
50*35238bceSAndroid Build Coastguard Worker 
51*35238bceSAndroid Build Coastguard Worker class AllowedRenderFailureException : public std::runtime_error
52*35238bceSAndroid Build Coastguard Worker {
53*35238bceSAndroid Build Coastguard Worker public:
AllowedRenderFailureException(const char * message)54*35238bceSAndroid Build Coastguard Worker     AllowedRenderFailureException(const char *message) : std::runtime_error(message)
55*35238bceSAndroid Build Coastguard Worker     {
56*35238bceSAndroid Build Coastguard Worker     }
57*35238bceSAndroid Build Coastguard Worker };
58*35238bceSAndroid Build Coastguard Worker 
59*35238bceSAndroid Build Coastguard Worker class GridRenderCase : public TestCase
60*35238bceSAndroid Build Coastguard Worker {
61*35238bceSAndroid Build Coastguard Worker public:
62*35238bceSAndroid Build Coastguard Worker     enum Flags
63*35238bceSAndroid Build Coastguard Worker     {
64*35238bceSAndroid Build Coastguard Worker         FLAG_TESSELLATION_MAX_SPEC                   = 0x0001,
65*35238bceSAndroid Build Coastguard Worker         FLAG_TESSELLATION_MAX_IMPLEMENTATION         = 0x0002,
66*35238bceSAndroid Build Coastguard Worker         FLAG_GEOMETRY_MAX_SPEC                       = 0x0004,
67*35238bceSAndroid Build Coastguard Worker         FLAG_GEOMETRY_MAX_IMPLEMENTATION             = 0x0008,
68*35238bceSAndroid Build Coastguard Worker         FLAG_GEOMETRY_INVOCATIONS_MAX_SPEC           = 0x0010,
69*35238bceSAndroid Build Coastguard Worker         FLAG_GEOMETRY_INVOCATIONS_MAX_IMPLEMENTATION = 0x0020,
70*35238bceSAndroid Build Coastguard Worker     };
71*35238bceSAndroid Build Coastguard Worker 
72*35238bceSAndroid Build Coastguard Worker     GridRenderCase(Context &context, const char *name, const char *description, int flags);
73*35238bceSAndroid Build Coastguard Worker     ~GridRenderCase(void);
74*35238bceSAndroid Build Coastguard Worker 
75*35238bceSAndroid Build Coastguard Worker private:
76*35238bceSAndroid Build Coastguard Worker     void init(void);
77*35238bceSAndroid Build Coastguard Worker     void deinit(void);
78*35238bceSAndroid Build Coastguard Worker     IterateResult iterate(void);
79*35238bceSAndroid Build Coastguard Worker 
80*35238bceSAndroid Build Coastguard Worker     void renderTo(std::vector<tcu::Surface> &dst);
81*35238bceSAndroid Build Coastguard Worker     bool verifyResultLayer(int layerNdx, const tcu::Surface &dst);
82*35238bceSAndroid Build Coastguard Worker 
83*35238bceSAndroid Build Coastguard Worker     const char *getVertexSource(void);
84*35238bceSAndroid Build Coastguard Worker     const char *getFragmentSource(void);
85*35238bceSAndroid Build Coastguard Worker     std::string getTessellationControlSource(int tessLevel);
86*35238bceSAndroid Build Coastguard Worker     std::string getTessellationEvaluationSource(int tessLevel);
87*35238bceSAndroid Build Coastguard Worker     std::string getGeometryShaderSource(int numPrimitives, int numInstances);
88*35238bceSAndroid Build Coastguard Worker 
89*35238bceSAndroid Build Coastguard Worker     enum
90*35238bceSAndroid Build Coastguard Worker     {
91*35238bceSAndroid Build Coastguard Worker         RENDER_SIZE = 256
92*35238bceSAndroid Build Coastguard Worker     };
93*35238bceSAndroid Build Coastguard Worker 
94*35238bceSAndroid Build Coastguard Worker     std::string m_description;
95*35238bceSAndroid Build Coastguard Worker 
96*35238bceSAndroid Build Coastguard Worker     const int m_flags;
97*35238bceSAndroid Build Coastguard Worker 
98*35238bceSAndroid Build Coastguard Worker     glu::ShaderProgram *m_program;
99*35238bceSAndroid Build Coastguard Worker     int m_numLayers;
100*35238bceSAndroid Build Coastguard Worker };
101*35238bceSAndroid Build Coastguard Worker 
GridRenderCase(Context & context,const char * name,const char * description,int flags)102*35238bceSAndroid Build Coastguard Worker GridRenderCase::GridRenderCase(Context &context, const char *name, const char *description, int flags)
103*35238bceSAndroid Build Coastguard Worker     : TestCase(context, name, description)
104*35238bceSAndroid Build Coastguard Worker     , m_description(description)
105*35238bceSAndroid Build Coastguard Worker     , m_flags(flags)
106*35238bceSAndroid Build Coastguard Worker     , m_program(DE_NULL)
107*35238bceSAndroid Build Coastguard Worker     , m_numLayers(1)
108*35238bceSAndroid Build Coastguard Worker {
109*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(((m_flags & FLAG_TESSELLATION_MAX_SPEC) == 0) || ((m_flags & FLAG_TESSELLATION_MAX_IMPLEMENTATION) == 0));
110*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(((m_flags & FLAG_GEOMETRY_MAX_SPEC) == 0) || ((m_flags & FLAG_GEOMETRY_MAX_IMPLEMENTATION) == 0));
111*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(((m_flags & FLAG_GEOMETRY_INVOCATIONS_MAX_SPEC) == 0) ||
112*35238bceSAndroid Build Coastguard Worker               ((m_flags & FLAG_GEOMETRY_INVOCATIONS_MAX_IMPLEMENTATION) == 0));
113*35238bceSAndroid Build Coastguard Worker }
114*35238bceSAndroid Build Coastguard Worker 
~GridRenderCase(void)115*35238bceSAndroid Build Coastguard Worker GridRenderCase::~GridRenderCase(void)
116*35238bceSAndroid Build Coastguard Worker {
117*35238bceSAndroid Build Coastguard Worker     deinit();
118*35238bceSAndroid Build Coastguard Worker }
119*35238bceSAndroid Build Coastguard Worker 
init(void)120*35238bceSAndroid Build Coastguard Worker void GridRenderCase::init(void)
121*35238bceSAndroid Build Coastguard Worker {
122*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
123*35238bceSAndroid Build Coastguard Worker 
124*35238bceSAndroid Build Coastguard Worker     // Requirements
125*35238bceSAndroid Build Coastguard Worker 
126*35238bceSAndroid Build Coastguard Worker     if (!m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader") ||
127*35238bceSAndroid Build Coastguard Worker         !m_context.getContextInfo().isExtensionSupported("GL_EXT_geometry_shader"))
128*35238bceSAndroid Build Coastguard Worker         throw tcu::NotSupportedError("Test requires GL_EXT_tessellation_shader and GL_EXT_geometry_shader extensions");
129*35238bceSAndroid Build Coastguard Worker 
130*35238bceSAndroid Build Coastguard Worker     if (m_context.getRenderTarget().getWidth() < RENDER_SIZE || m_context.getRenderTarget().getHeight() < RENDER_SIZE)
131*35238bceSAndroid Build Coastguard Worker         throw tcu::NotSupportedError("Test requires " + de::toString<int>(RENDER_SIZE) + "x" +
132*35238bceSAndroid Build Coastguard Worker                                      de::toString<int>(RENDER_SIZE) + " or larger render target.");
133*35238bceSAndroid Build Coastguard Worker 
134*35238bceSAndroid Build Coastguard Worker     // Log
135*35238bceSAndroid Build Coastguard Worker 
136*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << tcu::TestLog::Message
137*35238bceSAndroid Build Coastguard Worker                        << "Testing tessellation and geometry shaders that output a large number of primitives.\n"
138*35238bceSAndroid Build Coastguard Worker                        << m_description << tcu::TestLog::EndMessage;
139*35238bceSAndroid Build Coastguard Worker 
140*35238bceSAndroid Build Coastguard Worker     // Gen program
141*35238bceSAndroid Build Coastguard Worker     {
142*35238bceSAndroid Build Coastguard Worker         glu::ProgramSources sources;
143*35238bceSAndroid Build Coastguard Worker         int tessGenLevel = -1;
144*35238bceSAndroid Build Coastguard Worker 
145*35238bceSAndroid Build Coastguard Worker         sources << glu::VertexSource(getVertexSource()) << glu::FragmentSource(getFragmentSource());
146*35238bceSAndroid Build Coastguard Worker 
147*35238bceSAndroid Build Coastguard Worker         // Tessellation limits
148*35238bceSAndroid Build Coastguard Worker         {
149*35238bceSAndroid Build Coastguard Worker             if (m_flags & FLAG_TESSELLATION_MAX_IMPLEMENTATION)
150*35238bceSAndroid Build Coastguard Worker             {
151*35238bceSAndroid Build Coastguard Worker                 gl.getIntegerv(GL_MAX_TESS_GEN_LEVEL, &tessGenLevel);
152*35238bceSAndroid Build Coastguard Worker                 GLU_EXPECT_NO_ERROR(gl.getError(), "query tessellation limits");
153*35238bceSAndroid Build Coastguard Worker             }
154*35238bceSAndroid Build Coastguard Worker             else if (m_flags & FLAG_TESSELLATION_MAX_SPEC)
155*35238bceSAndroid Build Coastguard Worker             {
156*35238bceSAndroid Build Coastguard Worker                 tessGenLevel = 64;
157*35238bceSAndroid Build Coastguard Worker             }
158*35238bceSAndroid Build Coastguard Worker             else
159*35238bceSAndroid Build Coastguard Worker             {
160*35238bceSAndroid Build Coastguard Worker                 tessGenLevel = 5;
161*35238bceSAndroid Build Coastguard Worker             }
162*35238bceSAndroid Build Coastguard Worker 
163*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation level: " << tessGenLevel << ", mode = quad.\n"
164*35238bceSAndroid Build Coastguard Worker                                << "\tEach input patch produces " << (tessGenLevel * tessGenLevel) << " ("
165*35238bceSAndroid Build Coastguard Worker                                << (tessGenLevel * tessGenLevel * 2) << " triangles)\n"
166*35238bceSAndroid Build Coastguard Worker                                << tcu::TestLog::EndMessage;
167*35238bceSAndroid Build Coastguard Worker 
168*35238bceSAndroid Build Coastguard Worker             sources << glu::TessellationControlSource(getTessellationControlSource(tessGenLevel))
169*35238bceSAndroid Build Coastguard Worker                     << glu::TessellationEvaluationSource(getTessellationEvaluationSource(tessGenLevel));
170*35238bceSAndroid Build Coastguard Worker         }
171*35238bceSAndroid Build Coastguard Worker 
172*35238bceSAndroid Build Coastguard Worker         // Geometry limits
173*35238bceSAndroid Build Coastguard Worker         {
174*35238bceSAndroid Build Coastguard Worker             int geometryOutputComponents      = -1;
175*35238bceSAndroid Build Coastguard Worker             int geometryOutputVertices        = -1;
176*35238bceSAndroid Build Coastguard Worker             int geometryTotalOutputComponents = -1;
177*35238bceSAndroid Build Coastguard Worker             int geometryShaderInvocations     = -1;
178*35238bceSAndroid Build Coastguard Worker             bool logGeometryLimits            = false;
179*35238bceSAndroid Build Coastguard Worker             bool logInvocationLimits          = false;
180*35238bceSAndroid Build Coastguard Worker 
181*35238bceSAndroid Build Coastguard Worker             if (m_flags & FLAG_GEOMETRY_MAX_IMPLEMENTATION)
182*35238bceSAndroid Build Coastguard Worker             {
183*35238bceSAndroid Build Coastguard Worker                 m_testCtx.getLog() << tcu::TestLog::Message
184*35238bceSAndroid Build Coastguard Worker                                    << "Using implementation maximum geometry shader output limits."
185*35238bceSAndroid Build Coastguard Worker                                    << tcu::TestLog::EndMessage;
186*35238bceSAndroid Build Coastguard Worker 
187*35238bceSAndroid Build Coastguard Worker                 gl.getIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &geometryOutputComponents);
188*35238bceSAndroid Build Coastguard Worker                 gl.getIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &geometryOutputVertices);
189*35238bceSAndroid Build Coastguard Worker                 gl.getIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, &geometryTotalOutputComponents);
190*35238bceSAndroid Build Coastguard Worker                 GLU_EXPECT_NO_ERROR(gl.getError(), "query geometry limits");
191*35238bceSAndroid Build Coastguard Worker 
192*35238bceSAndroid Build Coastguard Worker                 logGeometryLimits = true;
193*35238bceSAndroid Build Coastguard Worker             }
194*35238bceSAndroid Build Coastguard Worker             else if (m_flags & FLAG_GEOMETRY_MAX_SPEC)
195*35238bceSAndroid Build Coastguard Worker             {
196*35238bceSAndroid Build Coastguard Worker                 m_testCtx.getLog() << tcu::TestLog::Message
197*35238bceSAndroid Build Coastguard Worker                                    << "Using geometry shader extension minimum maximum output limits."
198*35238bceSAndroid Build Coastguard Worker                                    << tcu::TestLog::EndMessage;
199*35238bceSAndroid Build Coastguard Worker 
200*35238bceSAndroid Build Coastguard Worker                 geometryOutputComponents      = 128;
201*35238bceSAndroid Build Coastguard Worker                 geometryOutputVertices        = 256;
202*35238bceSAndroid Build Coastguard Worker                 geometryTotalOutputComponents = 1024;
203*35238bceSAndroid Build Coastguard Worker                 logGeometryLimits             = true;
204*35238bceSAndroid Build Coastguard Worker             }
205*35238bceSAndroid Build Coastguard Worker             else
206*35238bceSAndroid Build Coastguard Worker             {
207*35238bceSAndroid Build Coastguard Worker                 geometryOutputComponents      = 128;
208*35238bceSAndroid Build Coastguard Worker                 geometryOutputVertices        = 16;
209*35238bceSAndroid Build Coastguard Worker                 geometryTotalOutputComponents = 1024;
210*35238bceSAndroid Build Coastguard Worker             }
211*35238bceSAndroid Build Coastguard Worker 
212*35238bceSAndroid Build Coastguard Worker             if (m_flags & FLAG_GEOMETRY_INVOCATIONS_MAX_IMPLEMENTATION)
213*35238bceSAndroid Build Coastguard Worker             {
214*35238bceSAndroid Build Coastguard Worker                 gl.getIntegerv(GL_MAX_GEOMETRY_SHADER_INVOCATIONS, &geometryShaderInvocations);
215*35238bceSAndroid Build Coastguard Worker                 GLU_EXPECT_NO_ERROR(gl.getError(), "query geometry invocation limits");
216*35238bceSAndroid Build Coastguard Worker 
217*35238bceSAndroid Build Coastguard Worker                 logInvocationLimits = true;
218*35238bceSAndroid Build Coastguard Worker             }
219*35238bceSAndroid Build Coastguard Worker             else if (m_flags & FLAG_GEOMETRY_INVOCATIONS_MAX_SPEC)
220*35238bceSAndroid Build Coastguard Worker             {
221*35238bceSAndroid Build Coastguard Worker                 geometryShaderInvocations = 32;
222*35238bceSAndroid Build Coastguard Worker                 logInvocationLimits       = true;
223*35238bceSAndroid Build Coastguard Worker             }
224*35238bceSAndroid Build Coastguard Worker             else
225*35238bceSAndroid Build Coastguard Worker             {
226*35238bceSAndroid Build Coastguard Worker                 geometryShaderInvocations = 4;
227*35238bceSAndroid Build Coastguard Worker             }
228*35238bceSAndroid Build Coastguard Worker 
229*35238bceSAndroid Build Coastguard Worker             if (logGeometryLimits || logInvocationLimits)
230*35238bceSAndroid Build Coastguard Worker             {
231*35238bceSAndroid Build Coastguard Worker                 tcu::MessageBuilder msg(&m_testCtx.getLog());
232*35238bceSAndroid Build Coastguard Worker 
233*35238bceSAndroid Build Coastguard Worker                 msg << "Geometry shader, targeting following limits:\n";
234*35238bceSAndroid Build Coastguard Worker 
235*35238bceSAndroid Build Coastguard Worker                 if (logGeometryLimits)
236*35238bceSAndroid Build Coastguard Worker                     msg << "\tGL_MAX_GEOMETRY_OUTPUT_COMPONENTS = " << geometryOutputComponents << "\n"
237*35238bceSAndroid Build Coastguard Worker                         << "\tGL_MAX_GEOMETRY_OUTPUT_VERTICES = " << geometryOutputVertices << "\n"
238*35238bceSAndroid Build Coastguard Worker                         << "\tGL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS = " << geometryTotalOutputComponents << "\n";
239*35238bceSAndroid Build Coastguard Worker 
240*35238bceSAndroid Build Coastguard Worker                 if (logInvocationLimits)
241*35238bceSAndroid Build Coastguard Worker                     msg << "\tGL_MAX_GEOMETRY_SHADER_INVOCATIONS = " << geometryShaderInvocations;
242*35238bceSAndroid Build Coastguard Worker 
243*35238bceSAndroid Build Coastguard Worker                 msg << tcu::TestLog::EndMessage;
244*35238bceSAndroid Build Coastguard Worker             }
245*35238bceSAndroid Build Coastguard Worker 
246*35238bceSAndroid Build Coastguard Worker             {
247*35238bceSAndroid Build Coastguard Worker                 const int numComponentsPerVertex = 8; // vec4 pos, vec4 color
248*35238bceSAndroid Build Coastguard Worker 
249*35238bceSAndroid Build Coastguard Worker                 // If FLAG_GEOMETRY_SEPARATE_PRIMITIVES is not set, geometry shader fills a rectangle area in slices.
250*35238bceSAndroid Build Coastguard Worker                 // Each slice is a triangle strip and is generated by a single shader invocation.
251*35238bceSAndroid Build Coastguard Worker                 // One slice with 4 segment ends (nodes) and 3 segments:
252*35238bceSAndroid Build Coastguard Worker                 //    .__.__.__.
253*35238bceSAndroid Build Coastguard Worker                 //    |\ |\ |\ |
254*35238bceSAndroid Build Coastguard Worker                 //    |_\|_\|_\|
255*35238bceSAndroid Build Coastguard Worker 
256*35238bceSAndroid Build Coastguard Worker                 const int numSliceNodesComponentLimit =
257*35238bceSAndroid Build Coastguard Worker                     geometryTotalOutputComponents / (2 * numComponentsPerVertex); // each node 2 vertices
258*35238bceSAndroid Build Coastguard Worker                 const int numSliceNodesOutputLimit = geometryOutputVertices / 2;  // each node 2 vertices
259*35238bceSAndroid Build Coastguard Worker                 const int numSliceNodes            = de::min(numSliceNodesComponentLimit, numSliceNodesOutputLimit);
260*35238bceSAndroid Build Coastguard Worker 
261*35238bceSAndroid Build Coastguard Worker                 const int numVerticesPerInvocation   = numSliceNodes * 2;
262*35238bceSAndroid Build Coastguard Worker                 const int numPrimitivesPerInvocation = (numSliceNodes - 1) * 2;
263*35238bceSAndroid Build Coastguard Worker 
264*35238bceSAndroid Build Coastguard Worker                 const int geometryVerticesPerPrimitive      = numVerticesPerInvocation * geometryShaderInvocations;
265*35238bceSAndroid Build Coastguard Worker                 const int geometryPrimitivesOutPerPrimitive = numPrimitivesPerInvocation * geometryShaderInvocations;
266*35238bceSAndroid Build Coastguard Worker 
267*35238bceSAndroid Build Coastguard Worker                 m_testCtx.getLog() << tcu::TestLog::Message << "Geometry shader:\n"
268*35238bceSAndroid Build Coastguard Worker                                    << "\tTotal output vertex count per invocation: " << (numVerticesPerInvocation)
269*35238bceSAndroid Build Coastguard Worker                                    << "\n"
270*35238bceSAndroid Build Coastguard Worker                                    << "\tTotal output primitive count per invocation: " << (numPrimitivesPerInvocation)
271*35238bceSAndroid Build Coastguard Worker                                    << "\n"
272*35238bceSAndroid Build Coastguard Worker                                    << "\tNumber of invocations per primitive: " << geometryShaderInvocations << "\n"
273*35238bceSAndroid Build Coastguard Worker                                    << "\tTotal output vertex count per input primitive: "
274*35238bceSAndroid Build Coastguard Worker                                    << (geometryVerticesPerPrimitive) << "\n"
275*35238bceSAndroid Build Coastguard Worker                                    << "\tTotal output primitive count per input primitive: "
276*35238bceSAndroid Build Coastguard Worker                                    << (geometryPrimitivesOutPerPrimitive) << "\n"
277*35238bceSAndroid Build Coastguard Worker                                    << tcu::TestLog::EndMessage;
278*35238bceSAndroid Build Coastguard Worker 
279*35238bceSAndroid Build Coastguard Worker                 sources << glu::GeometrySource(
280*35238bceSAndroid Build Coastguard Worker                     getGeometryShaderSource(numPrimitivesPerInvocation, geometryShaderInvocations));
281*35238bceSAndroid Build Coastguard Worker 
282*35238bceSAndroid Build Coastguard Worker                 m_testCtx.getLog() << tcu::TestLog::Message << "Program:\n"
283*35238bceSAndroid Build Coastguard Worker                                    << "\tTotal program output vertices count per input patch: "
284*35238bceSAndroid Build Coastguard Worker                                    << (tessGenLevel * tessGenLevel * 2 * geometryVerticesPerPrimitive) << "\n"
285*35238bceSAndroid Build Coastguard Worker                                    << "\tTotal program output primitive count per input patch: "
286*35238bceSAndroid Build Coastguard Worker                                    << (tessGenLevel * tessGenLevel * 2 * geometryPrimitivesOutPerPrimitive) << "\n"
287*35238bceSAndroid Build Coastguard Worker                                    << tcu::TestLog::EndMessage;
288*35238bceSAndroid Build Coastguard Worker             }
289*35238bceSAndroid Build Coastguard Worker         }
290*35238bceSAndroid Build Coastguard Worker 
291*35238bceSAndroid Build Coastguard Worker         m_program = new glu::ShaderProgram(m_context.getRenderContext(), sources);
292*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << *m_program;
293*35238bceSAndroid Build Coastguard Worker         if (!m_program->isOk())
294*35238bceSAndroid Build Coastguard Worker             throw tcu::TestError("failed to build program");
295*35238bceSAndroid Build Coastguard Worker     }
296*35238bceSAndroid Build Coastguard Worker }
297*35238bceSAndroid Build Coastguard Worker 
deinit(void)298*35238bceSAndroid Build Coastguard Worker void GridRenderCase::deinit(void)
299*35238bceSAndroid Build Coastguard Worker {
300*35238bceSAndroid Build Coastguard Worker     delete m_program;
301*35238bceSAndroid Build Coastguard Worker     m_program = DE_NULL;
302*35238bceSAndroid Build Coastguard Worker }
303*35238bceSAndroid Build Coastguard Worker 
iterate(void)304*35238bceSAndroid Build Coastguard Worker GridRenderCase::IterateResult GridRenderCase::iterate(void)
305*35238bceSAndroid Build Coastguard Worker {
306*35238bceSAndroid Build Coastguard Worker     std::vector<tcu::Surface> renderedLayers(m_numLayers);
307*35238bceSAndroid Build Coastguard Worker     bool allLayersOk = true;
308*35238bceSAndroid Build Coastguard Worker 
309*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < m_numLayers; ++ndx)
310*35238bceSAndroid Build Coastguard Worker         renderedLayers[ndx].setSize(RENDER_SIZE, RENDER_SIZE);
311*35238bceSAndroid Build Coastguard Worker 
312*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << tcu::TestLog::Message
313*35238bceSAndroid Build Coastguard Worker                        << "Rendering single point at the origin. Expecting yellow and green colored grid-like image. "
314*35238bceSAndroid Build Coastguard Worker                           "(High-frequency grid may appear unicolored)."
315*35238bceSAndroid Build Coastguard Worker                        << tcu::TestLog::EndMessage;
316*35238bceSAndroid Build Coastguard Worker 
317*35238bceSAndroid Build Coastguard Worker     try
318*35238bceSAndroid Build Coastguard Worker     {
319*35238bceSAndroid Build Coastguard Worker         renderTo(renderedLayers);
320*35238bceSAndroid Build Coastguard Worker     }
321*35238bceSAndroid Build Coastguard Worker     catch (const AllowedRenderFailureException &ex)
322*35238bceSAndroid Build Coastguard Worker     {
323*35238bceSAndroid Build Coastguard Worker         // Got accepted failure
324*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "Could not render, reason: " << ex.what() << "\n"
325*35238bceSAndroid Build Coastguard Worker                            << "Failure is allowed." << tcu::TestLog::EndMessage;
326*35238bceSAndroid Build Coastguard Worker 
327*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
328*35238bceSAndroid Build Coastguard Worker         return STOP;
329*35238bceSAndroid Build Coastguard Worker     }
330*35238bceSAndroid Build Coastguard Worker 
331*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < m_numLayers; ++ndx)
332*35238bceSAndroid Build Coastguard Worker         allLayersOk &= verifyResultLayer(ndx, renderedLayers[ndx]);
333*35238bceSAndroid Build Coastguard Worker 
334*35238bceSAndroid Build Coastguard Worker     if (allLayersOk)
335*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
336*35238bceSAndroid Build Coastguard Worker     else
337*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
338*35238bceSAndroid Build Coastguard Worker     return STOP;
339*35238bceSAndroid Build Coastguard Worker }
340*35238bceSAndroid Build Coastguard Worker 
renderTo(std::vector<tcu::Surface> & dst)341*35238bceSAndroid Build Coastguard Worker void GridRenderCase::renderTo(std::vector<tcu::Surface> &dst)
342*35238bceSAndroid Build Coastguard Worker {
343*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl   = m_context.getRenderContext().getFunctions();
344*35238bceSAndroid Build Coastguard Worker     const int positionLocation = gl.getAttribLocation(m_program->getProgram(), "a_position");
345*35238bceSAndroid Build Coastguard Worker     const glu::VertexArray vao(m_context.getRenderContext());
346*35238bceSAndroid Build Coastguard Worker 
347*35238bceSAndroid Build Coastguard Worker     if (positionLocation == -1)
348*35238bceSAndroid Build Coastguard Worker         throw tcu::TestError("Attribute a_position location was -1");
349*35238bceSAndroid Build Coastguard Worker 
350*35238bceSAndroid Build Coastguard Worker     gl.viewport(0, 0, dst.front().getWidth(), dst.front().getHeight());
351*35238bceSAndroid Build Coastguard Worker     gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
352*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "viewport");
353*35238bceSAndroid Build Coastguard Worker 
354*35238bceSAndroid Build Coastguard Worker     gl.bindVertexArray(*vao);
355*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "bind vao");
356*35238bceSAndroid Build Coastguard Worker 
357*35238bceSAndroid Build Coastguard Worker     gl.useProgram(m_program->getProgram());
358*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "use program");
359*35238bceSAndroid Build Coastguard Worker 
360*35238bceSAndroid Build Coastguard Worker     gl.patchParameteri(GL_PATCH_VERTICES, 1);
361*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "set patch param");
362*35238bceSAndroid Build Coastguard Worker 
363*35238bceSAndroid Build Coastguard Worker     gl.vertexAttrib4f(positionLocation, 0.0f, 0.0f, 0.0f, 1.0f);
364*35238bceSAndroid Build Coastguard Worker 
365*35238bceSAndroid Build Coastguard Worker     // clear viewport
366*35238bceSAndroid Build Coastguard Worker     gl.clear(GL_COLOR_BUFFER_BIT);
367*35238bceSAndroid Build Coastguard Worker 
368*35238bceSAndroid Build Coastguard Worker     // draw
369*35238bceSAndroid Build Coastguard Worker     {
370*35238bceSAndroid Build Coastguard Worker         glw::GLenum glerror;
371*35238bceSAndroid Build Coastguard Worker 
372*35238bceSAndroid Build Coastguard Worker         gl.drawArrays(GL_PATCHES, 0, 1);
373*35238bceSAndroid Build Coastguard Worker 
374*35238bceSAndroid Build Coastguard Worker         // allow always OOM
375*35238bceSAndroid Build Coastguard Worker         glerror = gl.getError();
376*35238bceSAndroid Build Coastguard Worker         if (glerror == GL_OUT_OF_MEMORY)
377*35238bceSAndroid Build Coastguard Worker             throw AllowedRenderFailureException("got GL_OUT_OF_MEMORY while drawing");
378*35238bceSAndroid Build Coastguard Worker 
379*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(glerror, "draw patches");
380*35238bceSAndroid Build Coastguard Worker     }
381*35238bceSAndroid Build Coastguard Worker 
382*35238bceSAndroid Build Coastguard Worker     // Read layers
383*35238bceSAndroid Build Coastguard Worker 
384*35238bceSAndroid Build Coastguard Worker     glu::readPixels(m_context.getRenderContext(), 0, 0, dst.front().getAccess());
385*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "read pixels");
386*35238bceSAndroid Build Coastguard Worker }
387*35238bceSAndroid Build Coastguard Worker 
verifyResultLayer(int layerNdx,const tcu::Surface & image)388*35238bceSAndroid Build Coastguard Worker bool GridRenderCase::verifyResultLayer(int layerNdx, const tcu::Surface &image)
389*35238bceSAndroid Build Coastguard Worker {
390*35238bceSAndroid Build Coastguard Worker     tcu::Surface errorMask(image.getWidth(), image.getHeight());
391*35238bceSAndroid Build Coastguard Worker     bool foundError = false;
392*35238bceSAndroid Build Coastguard Worker 
393*35238bceSAndroid Build Coastguard Worker     tcu::clear(errorMask.getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f));
394*35238bceSAndroid Build Coastguard Worker 
395*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << tcu::TestLog::Message << "Verifying output layer " << layerNdx << tcu::TestLog::EndMessage;
396*35238bceSAndroid Build Coastguard Worker 
397*35238bceSAndroid Build Coastguard Worker     for (int y = 0; y < image.getHeight(); ++y)
398*35238bceSAndroid Build Coastguard Worker         for (int x = 0; x < image.getWidth(); ++x)
399*35238bceSAndroid Build Coastguard Worker         {
400*35238bceSAndroid Build Coastguard Worker             const int threshold   = 8;
401*35238bceSAndroid Build Coastguard Worker             const tcu::RGBA color = image.getPixel(x, y);
402*35238bceSAndroid Build Coastguard Worker 
403*35238bceSAndroid Build Coastguard Worker             // Color must be a linear combination of green and yellow
404*35238bceSAndroid Build Coastguard Worker             if (color.getGreen() < 255 - threshold || color.getBlue() > threshold)
405*35238bceSAndroid Build Coastguard Worker             {
406*35238bceSAndroid Build Coastguard Worker                 errorMask.setPixel(x, y, tcu::RGBA::red());
407*35238bceSAndroid Build Coastguard Worker                 foundError = true;
408*35238bceSAndroid Build Coastguard Worker             }
409*35238bceSAndroid Build Coastguard Worker         }
410*35238bceSAndroid Build Coastguard Worker 
411*35238bceSAndroid Build Coastguard Worker     if (!foundError)
412*35238bceSAndroid Build Coastguard Worker     {
413*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "Image valid." << tcu::TestLog::EndMessage
414*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::ImageSet("ImageVerification", "Image verification")
415*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::Image("Result", "Rendered result", image.getAccess())
416*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndImageSet;
417*35238bceSAndroid Build Coastguard Worker         return true;
418*35238bceSAndroid Build Coastguard Worker     }
419*35238bceSAndroid Build Coastguard Worker     else
420*35238bceSAndroid Build Coastguard Worker     {
421*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "Image verification failed, found invalid pixels."
422*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage
423*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::ImageSet("ImageVerification", "Image verification")
424*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::Image("Result", "Rendered result", image.getAccess())
425*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask.getAccess())
426*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndImageSet;
427*35238bceSAndroid Build Coastguard Worker         return false;
428*35238bceSAndroid Build Coastguard Worker     }
429*35238bceSAndroid Build Coastguard Worker }
430*35238bceSAndroid Build Coastguard Worker 
getVertexSource(void)431*35238bceSAndroid Build Coastguard Worker const char *GridRenderCase::getVertexSource(void)
432*35238bceSAndroid Build Coastguard Worker {
433*35238bceSAndroid Build Coastguard Worker     return "#version 310 es\n"
434*35238bceSAndroid Build Coastguard Worker            "in highp vec4 a_position;\n"
435*35238bceSAndroid Build Coastguard Worker            "void main (void)\n"
436*35238bceSAndroid Build Coastguard Worker            "{\n"
437*35238bceSAndroid Build Coastguard Worker            "    gl_Position = a_position;\n"
438*35238bceSAndroid Build Coastguard Worker            "}\n";
439*35238bceSAndroid Build Coastguard Worker }
440*35238bceSAndroid Build Coastguard Worker 
getFragmentSource(void)441*35238bceSAndroid Build Coastguard Worker const char *GridRenderCase::getFragmentSource(void)
442*35238bceSAndroid Build Coastguard Worker {
443*35238bceSAndroid Build Coastguard Worker     return "#version 310 es\n"
444*35238bceSAndroid Build Coastguard Worker            "flat in mediump vec4 v_color;\n"
445*35238bceSAndroid Build Coastguard Worker            "layout(location = 0) out mediump vec4 fragColor;\n"
446*35238bceSAndroid Build Coastguard Worker            "void main (void)\n"
447*35238bceSAndroid Build Coastguard Worker            "{\n"
448*35238bceSAndroid Build Coastguard Worker            "    fragColor = v_color;\n"
449*35238bceSAndroid Build Coastguard Worker            "}\n";
450*35238bceSAndroid Build Coastguard Worker }
451*35238bceSAndroid Build Coastguard Worker 
getTessellationControlSource(int tessLevel)452*35238bceSAndroid Build Coastguard Worker std::string GridRenderCase::getTessellationControlSource(int tessLevel)
453*35238bceSAndroid Build Coastguard Worker {
454*35238bceSAndroid Build Coastguard Worker     std::ostringstream buf;
455*35238bceSAndroid Build Coastguard Worker 
456*35238bceSAndroid Build Coastguard Worker     buf << "#version 310 es\n"
457*35238bceSAndroid Build Coastguard Worker            "#extension GL_EXT_tessellation_shader : require\n"
458*35238bceSAndroid Build Coastguard Worker            "layout(vertices=1) out;\n"
459*35238bceSAndroid Build Coastguard Worker            "\n"
460*35238bceSAndroid Build Coastguard Worker            "void main()\n"
461*35238bceSAndroid Build Coastguard Worker            "{\n"
462*35238bceSAndroid Build Coastguard Worker            "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
463*35238bceSAndroid Build Coastguard Worker            "    gl_TessLevelOuter[0] = "
464*35238bceSAndroid Build Coastguard Worker         << tessLevel
465*35238bceSAndroid Build Coastguard Worker         << ".0;\n"
466*35238bceSAndroid Build Coastguard Worker            "    gl_TessLevelOuter[1] = "
467*35238bceSAndroid Build Coastguard Worker         << tessLevel
468*35238bceSAndroid Build Coastguard Worker         << ".0;\n"
469*35238bceSAndroid Build Coastguard Worker            "    gl_TessLevelOuter[2] = "
470*35238bceSAndroid Build Coastguard Worker         << tessLevel
471*35238bceSAndroid Build Coastguard Worker         << ".0;\n"
472*35238bceSAndroid Build Coastguard Worker            "    gl_TessLevelOuter[3] = "
473*35238bceSAndroid Build Coastguard Worker         << tessLevel
474*35238bceSAndroid Build Coastguard Worker         << ".0;\n"
475*35238bceSAndroid Build Coastguard Worker            "    gl_TessLevelInner[0] = "
476*35238bceSAndroid Build Coastguard Worker         << tessLevel
477*35238bceSAndroid Build Coastguard Worker         << ".0;\n"
478*35238bceSAndroid Build Coastguard Worker            "    gl_TessLevelInner[1] = "
479*35238bceSAndroid Build Coastguard Worker         << tessLevel
480*35238bceSAndroid Build Coastguard Worker         << ".0;\n"
481*35238bceSAndroid Build Coastguard Worker            "}\n";
482*35238bceSAndroid Build Coastguard Worker 
483*35238bceSAndroid Build Coastguard Worker     return buf.str();
484*35238bceSAndroid Build Coastguard Worker }
485*35238bceSAndroid Build Coastguard Worker 
getTessellationEvaluationSource(int tessLevel)486*35238bceSAndroid Build Coastguard Worker std::string GridRenderCase::getTessellationEvaluationSource(int tessLevel)
487*35238bceSAndroid Build Coastguard Worker {
488*35238bceSAndroid Build Coastguard Worker     std::ostringstream buf;
489*35238bceSAndroid Build Coastguard Worker 
490*35238bceSAndroid Build Coastguard Worker     buf << "#version 310 es\n"
491*35238bceSAndroid Build Coastguard Worker            "#extension GL_EXT_tessellation_shader : require\n"
492*35238bceSAndroid Build Coastguard Worker            "layout(quads) in;\n"
493*35238bceSAndroid Build Coastguard Worker            "\n"
494*35238bceSAndroid Build Coastguard Worker            "out mediump ivec2 v_tessellationGridPosition;\n"
495*35238bceSAndroid Build Coastguard Worker            "\n"
496*35238bceSAndroid Build Coastguard Worker            "// note: No need to use precise gl_Position since position does not depend on order\n"
497*35238bceSAndroid Build Coastguard Worker            "void main (void)\n"
498*35238bceSAndroid Build Coastguard Worker            "{\n"
499*35238bceSAndroid Build Coastguard Worker            "    // Fill the whole viewport\n"
500*35238bceSAndroid Build Coastguard Worker            "    gl_Position = vec4(gl_TessCoord.x * 2.0 - 1.0, gl_TessCoord.y * 2.0 - 1.0, 0.0, 1.0);\n"
501*35238bceSAndroid Build Coastguard Worker            "    // Calculate position in tessellation grid\n"
502*35238bceSAndroid Build Coastguard Worker            "    v_tessellationGridPosition = ivec2(round(gl_TessCoord.xy * float("
503*35238bceSAndroid Build Coastguard Worker         << tessLevel
504*35238bceSAndroid Build Coastguard Worker         << ")));\n"
505*35238bceSAndroid Build Coastguard Worker            "}\n";
506*35238bceSAndroid Build Coastguard Worker 
507*35238bceSAndroid Build Coastguard Worker     return buf.str();
508*35238bceSAndroid Build Coastguard Worker }
509*35238bceSAndroid Build Coastguard Worker 
getGeometryShaderSource(int numPrimitives,int numInstances)510*35238bceSAndroid Build Coastguard Worker std::string GridRenderCase::getGeometryShaderSource(int numPrimitives, int numInstances)
511*35238bceSAndroid Build Coastguard Worker {
512*35238bceSAndroid Build Coastguard Worker     std::ostringstream buf;
513*35238bceSAndroid Build Coastguard Worker 
514*35238bceSAndroid Build Coastguard Worker     buf << "#version 310 es\n"
515*35238bceSAndroid Build Coastguard Worker            "#extension GL_EXT_geometry_shader : require\n"
516*35238bceSAndroid Build Coastguard Worker            "layout(triangles, invocations="
517*35238bceSAndroid Build Coastguard Worker         << numInstances
518*35238bceSAndroid Build Coastguard Worker         << ") in;\n"
519*35238bceSAndroid Build Coastguard Worker            "layout(triangle_strip, max_vertices="
520*35238bceSAndroid Build Coastguard Worker         << (numPrimitives + 2)
521*35238bceSAndroid Build Coastguard Worker         << ") out;\n"
522*35238bceSAndroid Build Coastguard Worker            "\n"
523*35238bceSAndroid Build Coastguard Worker            "in mediump ivec2 v_tessellationGridPosition[];\n"
524*35238bceSAndroid Build Coastguard Worker            "flat out highp vec4 v_color;\n"
525*35238bceSAndroid Build Coastguard Worker            "\n"
526*35238bceSAndroid Build Coastguard Worker            "void main ()\n"
527*35238bceSAndroid Build Coastguard Worker            "{\n"
528*35238bceSAndroid Build Coastguard Worker            "    const float equalThreshold = 0.001;\n"
529*35238bceSAndroid Build Coastguard Worker            "    const float gapOffset = 0.0001; // subdivision performed by the geometry shader might produce gaps. "
530*35238bceSAndroid Build Coastguard Worker            "Fill potential gaps by enlarging the output slice a little.\n"
531*35238bceSAndroid Build Coastguard Worker            "\n"
532*35238bceSAndroid Build Coastguard Worker            "    // Input triangle is generated from an axis-aligned rectangle by splitting it in half\n"
533*35238bceSAndroid Build Coastguard Worker            "    // Original rectangle can be found by finding the bounding AABB of the triangle\n"
534*35238bceSAndroid Build Coastguard Worker            "    vec4 aabb = vec4(min(gl_in[0].gl_Position.x, min(gl_in[1].gl_Position.x, gl_in[2].gl_Position.x)),\n"
535*35238bceSAndroid Build Coastguard Worker            "                     min(gl_in[0].gl_Position.y, min(gl_in[1].gl_Position.y, gl_in[2].gl_Position.y)),\n"
536*35238bceSAndroid Build Coastguard Worker            "                     max(gl_in[0].gl_Position.x, max(gl_in[1].gl_Position.x, gl_in[2].gl_Position.x)),\n"
537*35238bceSAndroid Build Coastguard Worker            "                     max(gl_in[0].gl_Position.y, max(gl_in[1].gl_Position.y, gl_in[2].gl_Position.y)));\n"
538*35238bceSAndroid Build Coastguard Worker            "\n"
539*35238bceSAndroid Build Coastguard Worker            "    // Location in tessellation grid\n"
540*35238bceSAndroid Build Coastguard Worker            "    ivec2 gridPosition = ivec2(min(v_tessellationGridPosition[0], min(v_tessellationGridPosition[1], "
541*35238bceSAndroid Build Coastguard Worker            "v_tessellationGridPosition[2])));\n"
542*35238bceSAndroid Build Coastguard Worker            "\n"
543*35238bceSAndroid Build Coastguard Worker            "    // Which triangle of the two that split the grid cell\n"
544*35238bceSAndroid Build Coastguard Worker            "    int numVerticesOnBottomEdge = 0;\n"
545*35238bceSAndroid Build Coastguard Worker            "    for (int ndx = 0; ndx < 3; ++ndx)\n"
546*35238bceSAndroid Build Coastguard Worker            "        if (abs(gl_in[ndx].gl_Position.y - aabb.w) < equalThreshold)\n"
547*35238bceSAndroid Build Coastguard Worker            "            ++numVerticesOnBottomEdge;\n"
548*35238bceSAndroid Build Coastguard Worker            "    bool isBottomTriangle = numVerticesOnBottomEdge == 2;\n"
549*35238bceSAndroid Build Coastguard Worker            "\n"
550*35238bceSAndroid Build Coastguard Worker            "    // Fill the input area with slices\n"
551*35238bceSAndroid Build Coastguard Worker            "    // Upper triangle produces slices only to the upper half of the quad and vice-versa\n"
552*35238bceSAndroid Build Coastguard Worker            "    float triangleOffset = (isBottomTriangle) ? ((aabb.w + aabb.y) / 2.0) : (aabb.y);\n"
553*35238bceSAndroid Build Coastguard Worker            "    // Each slice is a invocation\n"
554*35238bceSAndroid Build Coastguard Worker            "    float sliceHeight = (aabb.w - aabb.y) / float(2 * "
555*35238bceSAndroid Build Coastguard Worker         << numInstances
556*35238bceSAndroid Build Coastguard Worker         << ");\n"
557*35238bceSAndroid Build Coastguard Worker            "    float invocationOffset = float(gl_InvocationID) * sliceHeight;\n"
558*35238bceSAndroid Build Coastguard Worker            "\n"
559*35238bceSAndroid Build Coastguard Worker            "    vec4 outputSliceArea;\n"
560*35238bceSAndroid Build Coastguard Worker            "    outputSliceArea.x = aabb.x - gapOffset;\n"
561*35238bceSAndroid Build Coastguard Worker            "    outputSliceArea.y = triangleOffset + invocationOffset - gapOffset;\n"
562*35238bceSAndroid Build Coastguard Worker            "    outputSliceArea.z = aabb.z + gapOffset;\n"
563*35238bceSAndroid Build Coastguard Worker            "    outputSliceArea.w = triangleOffset + invocationOffset + sliceHeight + gapOffset;\n"
564*35238bceSAndroid Build Coastguard Worker            "\n"
565*35238bceSAndroid Build Coastguard Worker            "    // Draw slice\n"
566*35238bceSAndroid Build Coastguard Worker            "    for (int ndx = 0; ndx < "
567*35238bceSAndroid Build Coastguard Worker         << ((numPrimitives + 2) / 2)
568*35238bceSAndroid Build Coastguard Worker         << "; ++ndx)\n"
569*35238bceSAndroid Build Coastguard Worker            "    {\n"
570*35238bceSAndroid Build Coastguard Worker            "        vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
571*35238bceSAndroid Build Coastguard Worker            "        vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n"
572*35238bceSAndroid Build Coastguard Worker            "        vec4 outputColor = (((gl_InvocationID + ndx) % 2) == 0) ? (green) : (yellow);\n"
573*35238bceSAndroid Build Coastguard Worker            "        float xpos = mix(outputSliceArea.x, outputSliceArea.z, float(ndx) / float("
574*35238bceSAndroid Build Coastguard Worker         << (numPrimitives / 2)
575*35238bceSAndroid Build Coastguard Worker         << "));\n"
576*35238bceSAndroid Build Coastguard Worker            "\n"
577*35238bceSAndroid Build Coastguard Worker            "        gl_Position = vec4(xpos, outputSliceArea.y, 0.0, 1.0);\n"
578*35238bceSAndroid Build Coastguard Worker            "        v_color = outputColor;\n"
579*35238bceSAndroid Build Coastguard Worker            "        EmitVertex();\n"
580*35238bceSAndroid Build Coastguard Worker            "\n"
581*35238bceSAndroid Build Coastguard Worker            "        gl_Position = vec4(xpos, outputSliceArea.w, 0.0, 1.0);\n"
582*35238bceSAndroid Build Coastguard Worker            "        v_color = outputColor;\n"
583*35238bceSAndroid Build Coastguard Worker            "        EmitVertex();\n"
584*35238bceSAndroid Build Coastguard Worker            "    }\n"
585*35238bceSAndroid Build Coastguard Worker            "}\n";
586*35238bceSAndroid Build Coastguard Worker 
587*35238bceSAndroid Build Coastguard Worker     return buf.str();
588*35238bceSAndroid Build Coastguard Worker }
589*35238bceSAndroid Build Coastguard Worker 
590*35238bceSAndroid Build Coastguard Worker } // namespace
591*35238bceSAndroid Build Coastguard Worker 
TessellationGeometryInteractionTests(Context & context)592*35238bceSAndroid Build Coastguard Worker TessellationGeometryInteractionTests::TessellationGeometryInteractionTests(Context &context)
593*35238bceSAndroid Build Coastguard Worker     : TestCaseGroup(context, "tessellation_geometry_interaction",
594*35238bceSAndroid Build Coastguard Worker                     "Tessellation and geometry shader interaction stress tests")
595*35238bceSAndroid Build Coastguard Worker {
596*35238bceSAndroid Build Coastguard Worker }
597*35238bceSAndroid Build Coastguard Worker 
~TessellationGeometryInteractionTests(void)598*35238bceSAndroid Build Coastguard Worker TessellationGeometryInteractionTests::~TessellationGeometryInteractionTests(void)
599*35238bceSAndroid Build Coastguard Worker {
600*35238bceSAndroid Build Coastguard Worker }
601*35238bceSAndroid Build Coastguard Worker 
init(void)602*35238bceSAndroid Build Coastguard Worker void TessellationGeometryInteractionTests::init(void)
603*35238bceSAndroid Build Coastguard Worker {
604*35238bceSAndroid Build Coastguard Worker     tcu::TestCaseGroup *const multilimitGroup =
605*35238bceSAndroid Build Coastguard Worker         new tcu::TestCaseGroup(m_testCtx, "render_multiple_limits", "Various render tests");
606*35238bceSAndroid Build Coastguard Worker 
607*35238bceSAndroid Build Coastguard Worker     addChild(multilimitGroup);
608*35238bceSAndroid Build Coastguard Worker 
609*35238bceSAndroid Build Coastguard Worker     // .render_multiple_limits
610*35238bceSAndroid Build Coastguard Worker     {
611*35238bceSAndroid Build Coastguard Worker         static const struct LimitCaseDef
612*35238bceSAndroid Build Coastguard Worker         {
613*35238bceSAndroid Build Coastguard Worker             const char *name;
614*35238bceSAndroid Build Coastguard Worker             const char *desc;
615*35238bceSAndroid Build Coastguard Worker             int flags;
616*35238bceSAndroid Build Coastguard Worker         } cases[] = {
617*35238bceSAndroid Build Coastguard Worker             // Test multiple limits at the same time
618*35238bceSAndroid Build Coastguard Worker 
619*35238bceSAndroid Build Coastguard Worker             {"output_required_max_tessellation_max_geometry",
620*35238bceSAndroid Build Coastguard Worker              "Minimum maximum tessellation level and geometry shader output vertices",
621*35238bceSAndroid Build Coastguard Worker              GridRenderCase::FLAG_TESSELLATION_MAX_SPEC | GridRenderCase::FLAG_GEOMETRY_MAX_SPEC},
622*35238bceSAndroid Build Coastguard Worker             {"output_implementation_max_tessellation_max_geometry",
623*35238bceSAndroid Build Coastguard Worker              "Maximum tessellation level and geometry shader output vertices supported by the implementation",
624*35238bceSAndroid Build Coastguard Worker              GridRenderCase::FLAG_TESSELLATION_MAX_IMPLEMENTATION | GridRenderCase::FLAG_GEOMETRY_MAX_IMPLEMENTATION},
625*35238bceSAndroid Build Coastguard Worker             {"output_required_max_tessellation_max_invocations",
626*35238bceSAndroid Build Coastguard Worker              "Minimum maximum tessellation level and geometry shader invocations",
627*35238bceSAndroid Build Coastguard Worker              GridRenderCase::FLAG_TESSELLATION_MAX_SPEC | GridRenderCase::FLAG_GEOMETRY_INVOCATIONS_MAX_SPEC},
628*35238bceSAndroid Build Coastguard Worker             {"output_implementation_max_tessellation_max_invocations",
629*35238bceSAndroid Build Coastguard Worker              "Maximum tessellation level and geometry shader invocations supported by the implementation",
630*35238bceSAndroid Build Coastguard Worker              GridRenderCase::FLAG_TESSELLATION_MAX_IMPLEMENTATION |
631*35238bceSAndroid Build Coastguard Worker                  GridRenderCase::FLAG_GEOMETRY_INVOCATIONS_MAX_IMPLEMENTATION},
632*35238bceSAndroid Build Coastguard Worker             {"output_required_max_geometry_max_invocations",
633*35238bceSAndroid Build Coastguard Worker              "Minimum maximum geometry shader output vertices and invocations",
634*35238bceSAndroid Build Coastguard Worker              GridRenderCase::FLAG_GEOMETRY_MAX_SPEC | GridRenderCase::FLAG_GEOMETRY_INVOCATIONS_MAX_SPEC},
635*35238bceSAndroid Build Coastguard Worker             {"output_implementation_max_geometry_max_invocations",
636*35238bceSAndroid Build Coastguard Worker              "Maximum geometry shader output vertices and invocations invocations supported by the implementation",
637*35238bceSAndroid Build Coastguard Worker              GridRenderCase::FLAG_GEOMETRY_MAX_IMPLEMENTATION |
638*35238bceSAndroid Build Coastguard Worker                  GridRenderCase::FLAG_GEOMETRY_INVOCATIONS_MAX_IMPLEMENTATION},
639*35238bceSAndroid Build Coastguard Worker 
640*35238bceSAndroid Build Coastguard Worker             // Test all limits simultaneously
641*35238bceSAndroid Build Coastguard Worker             {"output_max_required", "Output minimum maximum number of vertices",
642*35238bceSAndroid Build Coastguard Worker              GridRenderCase::FLAG_TESSELLATION_MAX_SPEC | GridRenderCase::FLAG_GEOMETRY_MAX_SPEC |
643*35238bceSAndroid Build Coastguard Worker                  GridRenderCase::FLAG_GEOMETRY_INVOCATIONS_MAX_SPEC},
644*35238bceSAndroid Build Coastguard Worker             {"output_max_implementation", "Output maximum number of vertices supported by the implementation",
645*35238bceSAndroid Build Coastguard Worker              GridRenderCase::FLAG_TESSELLATION_MAX_IMPLEMENTATION | GridRenderCase::FLAG_GEOMETRY_MAX_IMPLEMENTATION |
646*35238bceSAndroid Build Coastguard Worker                  GridRenderCase::FLAG_GEOMETRY_INVOCATIONS_MAX_IMPLEMENTATION},
647*35238bceSAndroid Build Coastguard Worker         };
648*35238bceSAndroid Build Coastguard Worker 
649*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cases); ++ndx)
650*35238bceSAndroid Build Coastguard Worker             multilimitGroup->addChild(
651*35238bceSAndroid Build Coastguard Worker                 new GridRenderCase(m_context, cases[ndx].name, cases[ndx].desc, cases[ndx].flags));
652*35238bceSAndroid Build Coastguard Worker     }
653*35238bceSAndroid Build Coastguard Worker }
654*35238bceSAndroid Build Coastguard Worker 
655*35238bceSAndroid Build Coastguard Worker } // namespace Stress
656*35238bceSAndroid Build Coastguard Worker } // namespace gles31
657*35238bceSAndroid Build Coastguard Worker } // namespace deqp
658