xref: /aosp_15_r20/external/deqp/modules/gles31/functional/es31fSeparateShaderTests.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 Tests for separate shader objects
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "es31fSeparateShaderTests.hpp"
25*35238bceSAndroid Build Coastguard Worker 
26*35238bceSAndroid Build Coastguard Worker #include "deInt32.h"
27*35238bceSAndroid Build Coastguard Worker #include "deString.h"
28*35238bceSAndroid Build Coastguard Worker #include "deStringUtil.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "deUniquePtr.hpp"
30*35238bceSAndroid Build Coastguard Worker #include "deRandom.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "deSTLUtil.hpp"
32*35238bceSAndroid Build Coastguard Worker #include "tcuCommandLine.hpp"
33*35238bceSAndroid Build Coastguard Worker #include "tcuImageCompare.hpp"
34*35238bceSAndroid Build Coastguard Worker #include "tcuRenderTarget.hpp"
35*35238bceSAndroid Build Coastguard Worker #include "tcuResultCollector.hpp"
36*35238bceSAndroid Build Coastguard Worker #include "tcuRGBA.hpp"
37*35238bceSAndroid Build Coastguard Worker #include "tcuSurface.hpp"
38*35238bceSAndroid Build Coastguard Worker #include "tcuStringTemplate.hpp"
39*35238bceSAndroid Build Coastguard Worker #include "gluCallLogWrapper.hpp"
40*35238bceSAndroid Build Coastguard Worker #include "gluPixelTransfer.hpp"
41*35238bceSAndroid Build Coastguard Worker #include "gluRenderContext.hpp"
42*35238bceSAndroid Build Coastguard Worker #include "gluShaderProgram.hpp"
43*35238bceSAndroid Build Coastguard Worker #include "gluVarType.hpp"
44*35238bceSAndroid Build Coastguard Worker #include "glsShaderLibrary.hpp"
45*35238bceSAndroid Build Coastguard Worker #include "glwFunctions.hpp"
46*35238bceSAndroid Build Coastguard Worker #include "glwDefs.hpp"
47*35238bceSAndroid Build Coastguard Worker #include "glwEnums.hpp"
48*35238bceSAndroid Build Coastguard Worker 
49*35238bceSAndroid Build Coastguard Worker #include <cstdarg>
50*35238bceSAndroid Build Coastguard Worker #include <algorithm>
51*35238bceSAndroid Build Coastguard Worker #include <map>
52*35238bceSAndroid Build Coastguard Worker #include <sstream>
53*35238bceSAndroid Build Coastguard Worker #include <string>
54*35238bceSAndroid Build Coastguard Worker #include <set>
55*35238bceSAndroid Build Coastguard Worker #include <vector>
56*35238bceSAndroid Build Coastguard Worker 
57*35238bceSAndroid Build Coastguard Worker namespace deqp
58*35238bceSAndroid Build Coastguard Worker {
59*35238bceSAndroid Build Coastguard Worker namespace gles31
60*35238bceSAndroid Build Coastguard Worker {
61*35238bceSAndroid Build Coastguard Worker namespace Functional
62*35238bceSAndroid Build Coastguard Worker {
63*35238bceSAndroid Build Coastguard Worker namespace
64*35238bceSAndroid Build Coastguard Worker {
65*35238bceSAndroid Build Coastguard Worker 
66*35238bceSAndroid Build Coastguard Worker using de::MovePtr;
67*35238bceSAndroid Build Coastguard Worker using de::Random;
68*35238bceSAndroid Build Coastguard Worker using de::UniquePtr;
69*35238bceSAndroid Build Coastguard Worker using glu::CallLogWrapper;
70*35238bceSAndroid Build Coastguard Worker using glu::DataType;
71*35238bceSAndroid Build Coastguard Worker using glu::FragmentSource;
72*35238bceSAndroid Build Coastguard Worker using glu::Precision;
73*35238bceSAndroid Build Coastguard Worker using glu::Program;
74*35238bceSAndroid Build Coastguard Worker using glu::ProgramPipeline;
75*35238bceSAndroid Build Coastguard Worker using glu::ProgramSeparable;
76*35238bceSAndroid Build Coastguard Worker using glu::ProgramSources;
77*35238bceSAndroid Build Coastguard Worker using glu::RenderContext;
78*35238bceSAndroid Build Coastguard Worker using glu::ShaderProgram;
79*35238bceSAndroid Build Coastguard Worker using glu::ShaderType;
80*35238bceSAndroid Build Coastguard Worker using glu::Storage;
81*35238bceSAndroid Build Coastguard Worker using glu::VariableDeclaration;
82*35238bceSAndroid Build Coastguard Worker using glu::VarType;
83*35238bceSAndroid Build Coastguard Worker using glu::VertexSource;
84*35238bceSAndroid Build Coastguard Worker using std::map;
85*35238bceSAndroid Build Coastguard Worker using std::ostringstream;
86*35238bceSAndroid Build Coastguard Worker using std::set;
87*35238bceSAndroid Build Coastguard Worker using std::string;
88*35238bceSAndroid Build Coastguard Worker using std::vector;
89*35238bceSAndroid Build Coastguard Worker using tcu::MessageBuilder;
90*35238bceSAndroid Build Coastguard Worker using tcu::RenderTarget;
91*35238bceSAndroid Build Coastguard Worker using tcu::ResultCollector;
92*35238bceSAndroid Build Coastguard Worker using tcu::StringTemplate;
93*35238bceSAndroid Build Coastguard Worker using tcu::Surface;
94*35238bceSAndroid Build Coastguard Worker using tcu::TestLog;
95*35238bceSAndroid Build Coastguard Worker 
96*35238bceSAndroid Build Coastguard Worker using namespace glw;
97*35238bceSAndroid Build Coastguard Worker 
98*35238bceSAndroid Build Coastguard Worker #define LOG_CALL(CALL)        \
99*35238bceSAndroid Build Coastguard Worker     do                        \
100*35238bceSAndroid Build Coastguard Worker     {                         \
101*35238bceSAndroid Build Coastguard Worker         enableLogging(true);  \
102*35238bceSAndroid Build Coastguard Worker         CALL;                 \
103*35238bceSAndroid Build Coastguard Worker         enableLogging(false); \
104*35238bceSAndroid Build Coastguard Worker     } while (false)
105*35238bceSAndroid Build Coastguard Worker 
106*35238bceSAndroid Build Coastguard Worker enum
107*35238bceSAndroid Build Coastguard Worker {
108*35238bceSAndroid Build Coastguard Worker     VIEWPORT_SIZE = 128
109*35238bceSAndroid Build Coastguard Worker };
110*35238bceSAndroid Build Coastguard Worker 
111*35238bceSAndroid Build Coastguard Worker enum VaryingInterpolation
112*35238bceSAndroid Build Coastguard Worker {
113*35238bceSAndroid Build Coastguard Worker     VARYINGINTERPOLATION_SMOOTH = 0,
114*35238bceSAndroid Build Coastguard Worker     VARYINGINTERPOLATION_FLAT,
115*35238bceSAndroid Build Coastguard Worker     VARYINGINTERPOLATION_CENTROID,
116*35238bceSAndroid Build Coastguard Worker     VARYINGINTERPOLATION_DEFAULT,
117*35238bceSAndroid Build Coastguard Worker     VARYINGINTERPOLATION_RANDOM,
118*35238bceSAndroid Build Coastguard Worker 
119*35238bceSAndroid Build Coastguard Worker     VARYINGINTERPOLATION_LAST
120*35238bceSAndroid Build Coastguard Worker };
121*35238bceSAndroid Build Coastguard Worker 
randomType(Random & rnd)122*35238bceSAndroid Build Coastguard Worker DataType randomType(Random &rnd)
123*35238bceSAndroid Build Coastguard Worker {
124*35238bceSAndroid Build Coastguard Worker     using namespace glu;
125*35238bceSAndroid Build Coastguard Worker 
126*35238bceSAndroid Build Coastguard Worker     if (rnd.getInt(0, 7) == 0)
127*35238bceSAndroid Build Coastguard Worker     {
128*35238bceSAndroid Build Coastguard Worker         const int numCols = rnd.getInt(2, 4), numRows = rnd.getInt(2, 4);
129*35238bceSAndroid Build Coastguard Worker 
130*35238bceSAndroid Build Coastguard Worker         return getDataTypeMatrix(numCols, numRows);
131*35238bceSAndroid Build Coastguard Worker     }
132*35238bceSAndroid Build Coastguard Worker     else
133*35238bceSAndroid Build Coastguard Worker     {
134*35238bceSAndroid Build Coastguard Worker         static const DataType s_types[] = {TYPE_FLOAT, TYPE_INT, TYPE_UINT};
135*35238bceSAndroid Build Coastguard Worker         static const float s_weights[]  = {3.0, 1.0, 1.0};
136*35238bceSAndroid Build Coastguard Worker         const int size                  = rnd.getInt(1, 4);
137*35238bceSAndroid Build Coastguard Worker         const DataType scalarType =
138*35238bceSAndroid Build Coastguard Worker             rnd.chooseWeighted<DataType>(DE_ARRAY_BEGIN(s_types), DE_ARRAY_END(s_types), DE_ARRAY_BEGIN(s_weights));
139*35238bceSAndroid Build Coastguard Worker         return getDataTypeVector(scalarType, size);
140*35238bceSAndroid Build Coastguard Worker     }
141*35238bceSAndroid Build Coastguard Worker 
142*35238bceSAndroid Build Coastguard Worker     DE_FATAL("Impossible");
143*35238bceSAndroid Build Coastguard Worker     return TYPE_INVALID;
144*35238bceSAndroid Build Coastguard Worker }
145*35238bceSAndroid Build Coastguard Worker 
randomInterpolation(Random & rnd)146*35238bceSAndroid Build Coastguard Worker VaryingInterpolation randomInterpolation(Random &rnd)
147*35238bceSAndroid Build Coastguard Worker {
148*35238bceSAndroid Build Coastguard Worker     static const VaryingInterpolation s_validInterpolations[] = {
149*35238bceSAndroid Build Coastguard Worker         VARYINGINTERPOLATION_SMOOTH,
150*35238bceSAndroid Build Coastguard Worker         VARYINGINTERPOLATION_FLAT,
151*35238bceSAndroid Build Coastguard Worker         VARYINGINTERPOLATION_CENTROID,
152*35238bceSAndroid Build Coastguard Worker         VARYINGINTERPOLATION_DEFAULT,
153*35238bceSAndroid Build Coastguard Worker     };
154*35238bceSAndroid Build Coastguard Worker     return s_validInterpolations[rnd.getInt(0, DE_LENGTH_OF_ARRAY(s_validInterpolations) - 1)];
155*35238bceSAndroid Build Coastguard Worker }
156*35238bceSAndroid Build Coastguard Worker 
getGluInterpolation(VaryingInterpolation interpolation)157*35238bceSAndroid Build Coastguard Worker glu::Interpolation getGluInterpolation(VaryingInterpolation interpolation)
158*35238bceSAndroid Build Coastguard Worker {
159*35238bceSAndroid Build Coastguard Worker     switch (interpolation)
160*35238bceSAndroid Build Coastguard Worker     {
161*35238bceSAndroid Build Coastguard Worker     case VARYINGINTERPOLATION_SMOOTH:
162*35238bceSAndroid Build Coastguard Worker         return glu::INTERPOLATION_SMOOTH;
163*35238bceSAndroid Build Coastguard Worker     case VARYINGINTERPOLATION_FLAT:
164*35238bceSAndroid Build Coastguard Worker         return glu::INTERPOLATION_FLAT;
165*35238bceSAndroid Build Coastguard Worker     case VARYINGINTERPOLATION_CENTROID:
166*35238bceSAndroid Build Coastguard Worker         return glu::INTERPOLATION_CENTROID;
167*35238bceSAndroid Build Coastguard Worker     case VARYINGINTERPOLATION_DEFAULT:
168*35238bceSAndroid Build Coastguard Worker         return glu::INTERPOLATION_LAST; //!< Last means no qualifier, i.e. default
169*35238bceSAndroid Build Coastguard Worker     default:
170*35238bceSAndroid Build Coastguard Worker         DE_FATAL("Invalid interpolation");
171*35238bceSAndroid Build Coastguard Worker         return glu::INTERPOLATION_LAST;
172*35238bceSAndroid Build Coastguard Worker     }
173*35238bceSAndroid Build Coastguard Worker }
174*35238bceSAndroid Build Coastguard Worker 
175*35238bceSAndroid Build Coastguard Worker // used only for debug quick checks
176*35238bceSAndroid Build Coastguard Worker #if defined(DE_DEBUG)
getVaryingInterpolation(glu::Interpolation interpolation)177*35238bceSAndroid Build Coastguard Worker VaryingInterpolation getVaryingInterpolation(glu::Interpolation interpolation)
178*35238bceSAndroid Build Coastguard Worker {
179*35238bceSAndroid Build Coastguard Worker     switch (interpolation)
180*35238bceSAndroid Build Coastguard Worker     {
181*35238bceSAndroid Build Coastguard Worker     case glu::INTERPOLATION_SMOOTH:
182*35238bceSAndroid Build Coastguard Worker         return VARYINGINTERPOLATION_SMOOTH;
183*35238bceSAndroid Build Coastguard Worker     case glu::INTERPOLATION_FLAT:
184*35238bceSAndroid Build Coastguard Worker         return VARYINGINTERPOLATION_FLAT;
185*35238bceSAndroid Build Coastguard Worker     case glu::INTERPOLATION_CENTROID:
186*35238bceSAndroid Build Coastguard Worker         return VARYINGINTERPOLATION_CENTROID;
187*35238bceSAndroid Build Coastguard Worker     case glu::INTERPOLATION_LAST:
188*35238bceSAndroid Build Coastguard Worker         return VARYINGINTERPOLATION_DEFAULT; //!< Last means no qualifier, i.e. default
189*35238bceSAndroid Build Coastguard Worker     default:
190*35238bceSAndroid Build Coastguard Worker         DE_FATAL("Invalid interpolation");
191*35238bceSAndroid Build Coastguard Worker         return VARYINGINTERPOLATION_LAST;
192*35238bceSAndroid Build Coastguard Worker     }
193*35238bceSAndroid Build Coastguard Worker }
194*35238bceSAndroid Build Coastguard Worker #endif
195*35238bceSAndroid Build Coastguard Worker 
196*35238bceSAndroid Build Coastguard Worker enum BindingKind
197*35238bceSAndroid Build Coastguard Worker {
198*35238bceSAndroid Build Coastguard Worker     BINDING_NAME,
199*35238bceSAndroid Build Coastguard Worker     BINDING_LOCATION,
200*35238bceSAndroid Build Coastguard Worker     BINDING_LAST
201*35238bceSAndroid Build Coastguard Worker };
202*35238bceSAndroid Build Coastguard Worker 
randomBinding(Random & rnd)203*35238bceSAndroid Build Coastguard Worker BindingKind randomBinding(Random &rnd)
204*35238bceSAndroid Build Coastguard Worker {
205*35238bceSAndroid Build Coastguard Worker     return rnd.getBool() ? BINDING_LOCATION : BINDING_NAME;
206*35238bceSAndroid Build Coastguard Worker }
207*35238bceSAndroid Build Coastguard Worker 
printInputColor(ostringstream & oss,const VariableDeclaration & input)208*35238bceSAndroid Build Coastguard Worker void printInputColor(ostringstream &oss, const VariableDeclaration &input)
209*35238bceSAndroid Build Coastguard Worker {
210*35238bceSAndroid Build Coastguard Worker     using namespace glu;
211*35238bceSAndroid Build Coastguard Worker 
212*35238bceSAndroid Build Coastguard Worker     const DataType basicType = input.varType.getBasicType();
213*35238bceSAndroid Build Coastguard Worker     string exp               = input.name;
214*35238bceSAndroid Build Coastguard Worker 
215*35238bceSAndroid Build Coastguard Worker     switch (getDataTypeScalarType(basicType))
216*35238bceSAndroid Build Coastguard Worker     {
217*35238bceSAndroid Build Coastguard Worker     case TYPE_FLOAT:
218*35238bceSAndroid Build Coastguard Worker         break;
219*35238bceSAndroid Build Coastguard Worker 
220*35238bceSAndroid Build Coastguard Worker     case TYPE_INT:
221*35238bceSAndroid Build Coastguard Worker     case TYPE_UINT:
222*35238bceSAndroid Build Coastguard Worker     {
223*35238bceSAndroid Build Coastguard Worker         DataType floatType = getDataTypeFloatScalars(basicType);
224*35238bceSAndroid Build Coastguard Worker         exp                = string() + "(" + getDataTypeName(floatType) + "(" + exp + ") / 255.0" + ")";
225*35238bceSAndroid Build Coastguard Worker         break;
226*35238bceSAndroid Build Coastguard Worker     }
227*35238bceSAndroid Build Coastguard Worker 
228*35238bceSAndroid Build Coastguard Worker     default:
229*35238bceSAndroid Build Coastguard Worker         DE_FATAL("Impossible");
230*35238bceSAndroid Build Coastguard Worker     }
231*35238bceSAndroid Build Coastguard Worker 
232*35238bceSAndroid Build Coastguard Worker     if (isDataTypeScalarOrVector(basicType))
233*35238bceSAndroid Build Coastguard Worker     {
234*35238bceSAndroid Build Coastguard Worker         switch (getDataTypeScalarSize(basicType))
235*35238bceSAndroid Build Coastguard Worker         {
236*35238bceSAndroid Build Coastguard Worker         case 1:
237*35238bceSAndroid Build Coastguard Worker             oss << "hsv(vec3(" << exp << ", 1.0, 1.0))";
238*35238bceSAndroid Build Coastguard Worker             break;
239*35238bceSAndroid Build Coastguard Worker         case 2:
240*35238bceSAndroid Build Coastguard Worker             oss << "hsv(vec3(" << exp << ", 1.0))";
241*35238bceSAndroid Build Coastguard Worker             break;
242*35238bceSAndroid Build Coastguard Worker         case 3:
243*35238bceSAndroid Build Coastguard Worker             oss << "vec4(" << exp << ", 1.0)";
244*35238bceSAndroid Build Coastguard Worker             break;
245*35238bceSAndroid Build Coastguard Worker         case 4:
246*35238bceSAndroid Build Coastguard Worker             oss << exp;
247*35238bceSAndroid Build Coastguard Worker             break;
248*35238bceSAndroid Build Coastguard Worker         default:
249*35238bceSAndroid Build Coastguard Worker             DE_FATAL("Impossible");
250*35238bceSAndroid Build Coastguard Worker         }
251*35238bceSAndroid Build Coastguard Worker     }
252*35238bceSAndroid Build Coastguard Worker     else if (isDataTypeMatrix(basicType))
253*35238bceSAndroid Build Coastguard Worker     {
254*35238bceSAndroid Build Coastguard Worker         int rows    = getDataTypeMatrixNumRows(basicType);
255*35238bceSAndroid Build Coastguard Worker         int columns = getDataTypeMatrixNumColumns(basicType);
256*35238bceSAndroid Build Coastguard Worker 
257*35238bceSAndroid Build Coastguard Worker         if (rows == columns)
258*35238bceSAndroid Build Coastguard Worker             oss << "hsv(vec3(determinant(" << exp << ")))";
259*35238bceSAndroid Build Coastguard Worker         else
260*35238bceSAndroid Build Coastguard Worker         {
261*35238bceSAndroid Build Coastguard Worker             if (rows != 3 && columns >= 3)
262*35238bceSAndroid Build Coastguard Worker             {
263*35238bceSAndroid Build Coastguard Worker                 exp = "transpose(" + exp + ")";
264*35238bceSAndroid Build Coastguard Worker                 std::swap(rows, columns);
265*35238bceSAndroid Build Coastguard Worker             }
266*35238bceSAndroid Build Coastguard Worker             exp = exp + "[0]";
267*35238bceSAndroid Build Coastguard Worker             if (rows > 3)
268*35238bceSAndroid Build Coastguard Worker                 exp = exp + ".xyz";
269*35238bceSAndroid Build Coastguard Worker             oss << "hsv(" << exp << ")";
270*35238bceSAndroid Build Coastguard Worker         }
271*35238bceSAndroid Build Coastguard Worker     }
272*35238bceSAndroid Build Coastguard Worker     else
273*35238bceSAndroid Build Coastguard Worker         DE_FATAL("Impossible");
274*35238bceSAndroid Build Coastguard Worker }
275*35238bceSAndroid Build Coastguard Worker 
276*35238bceSAndroid Build Coastguard Worker // Representation for the varyings between vertex and fragment shaders
277*35238bceSAndroid Build Coastguard Worker 
278*35238bceSAndroid Build Coastguard Worker struct VaryingParams
279*35238bceSAndroid Build Coastguard Worker {
VaryingParamsdeqp::gles31::Functional::__anonf652bf1a0111::VaryingParams280*35238bceSAndroid Build Coastguard Worker     VaryingParams(void)
281*35238bceSAndroid Build Coastguard Worker         : count(0)
282*35238bceSAndroid Build Coastguard Worker         , type(glu::TYPE_LAST)
283*35238bceSAndroid Build Coastguard Worker         , binding(BINDING_LAST)
284*35238bceSAndroid Build Coastguard Worker         , vtxInterp(VARYINGINTERPOLATION_LAST)
285*35238bceSAndroid Build Coastguard Worker         , frgInterp(VARYINGINTERPOLATION_LAST)
286*35238bceSAndroid Build Coastguard Worker     {
287*35238bceSAndroid Build Coastguard Worker     }
288*35238bceSAndroid Build Coastguard Worker 
289*35238bceSAndroid Build Coastguard Worker     int count;
290*35238bceSAndroid Build Coastguard Worker     DataType type;
291*35238bceSAndroid Build Coastguard Worker     BindingKind binding;
292*35238bceSAndroid Build Coastguard Worker     VaryingInterpolation vtxInterp;
293*35238bceSAndroid Build Coastguard Worker     VaryingInterpolation frgInterp;
294*35238bceSAndroid Build Coastguard Worker };
295*35238bceSAndroid Build Coastguard Worker 
296*35238bceSAndroid Build Coastguard Worker struct VaryingInterface
297*35238bceSAndroid Build Coastguard Worker {
298*35238bceSAndroid Build Coastguard Worker     vector<VariableDeclaration> vtxOutputs;
299*35238bceSAndroid Build Coastguard Worker     vector<VariableDeclaration> frgInputs;
300*35238bceSAndroid Build Coastguard Worker };
301*35238bceSAndroid Build Coastguard Worker 
302*35238bceSAndroid Build Coastguard Worker // Generate corresponding input and output variable declarations that may vary
303*35238bceSAndroid Build Coastguard Worker // in compatible ways.
304*35238bceSAndroid Build Coastguard Worker 
chooseInterpolation(VaryingInterpolation param,DataType type,Random & rnd)305*35238bceSAndroid Build Coastguard Worker VaryingInterpolation chooseInterpolation(VaryingInterpolation param, DataType type, Random &rnd)
306*35238bceSAndroid Build Coastguard Worker {
307*35238bceSAndroid Build Coastguard Worker     if (glu::getDataTypeScalarType(type) != glu::TYPE_FLOAT)
308*35238bceSAndroid Build Coastguard Worker         return VARYINGINTERPOLATION_FLAT;
309*35238bceSAndroid Build Coastguard Worker 
310*35238bceSAndroid Build Coastguard Worker     if (param == VARYINGINTERPOLATION_RANDOM)
311*35238bceSAndroid Build Coastguard Worker         return randomInterpolation(rnd);
312*35238bceSAndroid Build Coastguard Worker 
313*35238bceSAndroid Build Coastguard Worker     return param;
314*35238bceSAndroid Build Coastguard Worker }
315*35238bceSAndroid Build Coastguard Worker 
isSSOCompatibleInterpolation(VaryingInterpolation vertexInterpolation,VaryingInterpolation fragmentInterpolation)316*35238bceSAndroid Build Coastguard Worker bool isSSOCompatibleInterpolation(VaryingInterpolation vertexInterpolation, VaryingInterpolation fragmentInterpolation)
317*35238bceSAndroid Build Coastguard Worker {
318*35238bceSAndroid Build Coastguard Worker     // interpolations must be fully specified
319*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(vertexInterpolation != VARYINGINTERPOLATION_RANDOM);
320*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(vertexInterpolation < VARYINGINTERPOLATION_LAST);
321*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(fragmentInterpolation != VARYINGINTERPOLATION_RANDOM);
322*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(fragmentInterpolation < VARYINGINTERPOLATION_LAST);
323*35238bceSAndroid Build Coastguard Worker 
324*35238bceSAndroid Build Coastguard Worker     // interpolation can only be either smooth or flat. Auxiliary storage does not matter.
325*35238bceSAndroid Build Coastguard Worker     const bool isSmoothVtx =
326*35238bceSAndroid Build Coastguard Worker         (vertexInterpolation == VARYINGINTERPOLATION_SMOOTH) ||  //!< trivial
327*35238bceSAndroid Build Coastguard Worker         (vertexInterpolation == VARYINGINTERPOLATION_DEFAULT) || //!< default to smooth
328*35238bceSAndroid Build Coastguard Worker         (vertexInterpolation == VARYINGINTERPOLATION_CENTROID);  //!< default to smooth, ignore storage
329*35238bceSAndroid Build Coastguard Worker     const bool isSmoothFrag =
330*35238bceSAndroid Build Coastguard Worker         (fragmentInterpolation == VARYINGINTERPOLATION_SMOOTH) ||  //!< trivial
331*35238bceSAndroid Build Coastguard Worker         (fragmentInterpolation == VARYINGINTERPOLATION_DEFAULT) || //!< default to smooth
332*35238bceSAndroid Build Coastguard Worker         (fragmentInterpolation == VARYINGINTERPOLATION_CENTROID);  //!< default to smooth, ignore storage
333*35238bceSAndroid Build Coastguard Worker     // Khronos bug #12630: flat / smooth qualifiers must match in SSO
334*35238bceSAndroid Build Coastguard Worker     return isSmoothVtx == isSmoothFrag;
335*35238bceSAndroid Build Coastguard Worker }
336*35238bceSAndroid Build Coastguard Worker 
genVaryingInterface(const VaryingParams & params,Random & rnd)337*35238bceSAndroid Build Coastguard Worker VaryingInterface genVaryingInterface(const VaryingParams &params, Random &rnd)
338*35238bceSAndroid Build Coastguard Worker {
339*35238bceSAndroid Build Coastguard Worker     using namespace glu;
340*35238bceSAndroid Build Coastguard Worker 
341*35238bceSAndroid Build Coastguard Worker     VaryingInterface ret;
342*35238bceSAndroid Build Coastguard Worker     int offset = 0;
343*35238bceSAndroid Build Coastguard Worker 
344*35238bceSAndroid Build Coastguard Worker     for (int varNdx = 0; varNdx < params.count; ++varNdx)
345*35238bceSAndroid Build Coastguard Worker     {
346*35238bceSAndroid Build Coastguard Worker         const BindingKind binding            = ((params.binding == BINDING_LAST) ? randomBinding(rnd) : params.binding);
347*35238bceSAndroid Build Coastguard Worker         const DataType type                  = ((params.type == TYPE_LAST) ? randomType(rnd) : params.type);
348*35238bceSAndroid Build Coastguard Worker         const VaryingInterpolation vtxInterp = chooseInterpolation(params.vtxInterp, type, rnd);
349*35238bceSAndroid Build Coastguard Worker         const VaryingInterpolation frgInterp = chooseInterpolation(params.frgInterp, type, rnd);
350*35238bceSAndroid Build Coastguard Worker         const VaryingInterpolation vtxCompatInterp =
351*35238bceSAndroid Build Coastguard Worker             (isSSOCompatibleInterpolation(vtxInterp, frgInterp)) ? (vtxInterp) : (frgInterp);
352*35238bceSAndroid Build Coastguard Worker         const int loc        = ((binding == BINDING_LOCATION) ? offset : -1);
353*35238bceSAndroid Build Coastguard Worker         const string ndxStr  = de::toString(varNdx);
354*35238bceSAndroid Build Coastguard Worker         const string vtxName = ((binding == BINDING_NAME) ? "var" + ndxStr : "vtxVar" + ndxStr);
355*35238bceSAndroid Build Coastguard Worker         const string frgName = ((binding == BINDING_NAME) ? "var" + ndxStr : "frgVar" + ndxStr);
356*35238bceSAndroid Build Coastguard Worker         const VarType varType(type, PRECISION_HIGHP);
357*35238bceSAndroid Build Coastguard Worker 
358*35238bceSAndroid Build Coastguard Worker         offset += getDataTypeNumLocations(type);
359*35238bceSAndroid Build Coastguard Worker 
360*35238bceSAndroid Build Coastguard Worker         // Over 16 locations aren't necessarily supported, so halt here.
361*35238bceSAndroid Build Coastguard Worker         if (offset > 16)
362*35238bceSAndroid Build Coastguard Worker             break;
363*35238bceSAndroid Build Coastguard Worker 
364*35238bceSAndroid Build Coastguard Worker         ret.vtxOutputs.push_back(
365*35238bceSAndroid Build Coastguard Worker             VariableDeclaration(varType, vtxName, STORAGE_OUT, getGluInterpolation(vtxCompatInterp), loc));
366*35238bceSAndroid Build Coastguard Worker         ret.frgInputs.push_back(VariableDeclaration(varType, frgName, STORAGE_IN, getGluInterpolation(frgInterp), loc));
367*35238bceSAndroid Build Coastguard Worker     }
368*35238bceSAndroid Build Coastguard Worker 
369*35238bceSAndroid Build Coastguard Worker     return ret;
370*35238bceSAndroid Build Coastguard Worker }
371*35238bceSAndroid Build Coastguard Worker 
372*35238bceSAndroid Build Coastguard Worker // Create vertex output variable declarations that are maximally compatible
373*35238bceSAndroid Build Coastguard Worker // with the fragment input variables.
374*35238bceSAndroid Build Coastguard Worker 
varyingCompatVtxOutputs(const VaryingInterface & varyings)375*35238bceSAndroid Build Coastguard Worker vector<VariableDeclaration> varyingCompatVtxOutputs(const VaryingInterface &varyings)
376*35238bceSAndroid Build Coastguard Worker {
377*35238bceSAndroid Build Coastguard Worker     vector<VariableDeclaration> outputs = varyings.vtxOutputs;
378*35238bceSAndroid Build Coastguard Worker 
379*35238bceSAndroid Build Coastguard Worker     for (size_t i = 0; i < outputs.size(); ++i)
380*35238bceSAndroid Build Coastguard Worker     {
381*35238bceSAndroid Build Coastguard Worker         outputs[i].interpolation = varyings.frgInputs[i].interpolation;
382*35238bceSAndroid Build Coastguard Worker         outputs[i].name          = varyings.frgInputs[i].name;
383*35238bceSAndroid Build Coastguard Worker     }
384*35238bceSAndroid Build Coastguard Worker 
385*35238bceSAndroid Build Coastguard Worker     return outputs;
386*35238bceSAndroid Build Coastguard Worker }
387*35238bceSAndroid Build Coastguard Worker 
388*35238bceSAndroid Build Coastguard Worker // Shader source generation
389*35238bceSAndroid Build Coastguard Worker 
printFloat(ostringstream & oss,double d)390*35238bceSAndroid Build Coastguard Worker void printFloat(ostringstream &oss, double d)
391*35238bceSAndroid Build Coastguard Worker {
392*35238bceSAndroid Build Coastguard Worker     oss.setf(oss.fixed | oss.internal);
393*35238bceSAndroid Build Coastguard Worker     oss.precision(4);
394*35238bceSAndroid Build Coastguard Worker     oss.width(7);
395*35238bceSAndroid Build Coastguard Worker     oss << d;
396*35238bceSAndroid Build Coastguard Worker }
397*35238bceSAndroid Build Coastguard Worker 
printFloatDeclaration(ostringstream & oss,const string & varName,bool uniform,GLfloat value=0.0)398*35238bceSAndroid Build Coastguard Worker void printFloatDeclaration(ostringstream &oss, const string &varName, bool uniform, GLfloat value = 0.0)
399*35238bceSAndroid Build Coastguard Worker {
400*35238bceSAndroid Build Coastguard Worker     using namespace glu;
401*35238bceSAndroid Build Coastguard Worker 
402*35238bceSAndroid Build Coastguard Worker     const VarType varType(TYPE_FLOAT, PRECISION_HIGHP);
403*35238bceSAndroid Build Coastguard Worker 
404*35238bceSAndroid Build Coastguard Worker     if (uniform)
405*35238bceSAndroid Build Coastguard Worker         oss << VariableDeclaration(varType, varName, STORAGE_UNIFORM) << ";\n";
406*35238bceSAndroid Build Coastguard Worker     else
407*35238bceSAndroid Build Coastguard Worker         oss << VariableDeclaration(varType, varName, STORAGE_CONST) << " = " << de::floatToString(value, 6) << ";\n";
408*35238bceSAndroid Build Coastguard Worker }
409*35238bceSAndroid Build Coastguard Worker 
printRandomInitializer(ostringstream & oss,DataType type,Random & rnd)410*35238bceSAndroid Build Coastguard Worker void printRandomInitializer(ostringstream &oss, DataType type, Random &rnd)
411*35238bceSAndroid Build Coastguard Worker {
412*35238bceSAndroid Build Coastguard Worker     using namespace glu;
413*35238bceSAndroid Build Coastguard Worker     const int size = getDataTypeScalarSize(type);
414*35238bceSAndroid Build Coastguard Worker 
415*35238bceSAndroid Build Coastguard Worker     if (size > 0)
416*35238bceSAndroid Build Coastguard Worker         oss << getDataTypeName(type) << "(";
417*35238bceSAndroid Build Coastguard Worker 
418*35238bceSAndroid Build Coastguard Worker     for (int i = 0; i < size; ++i)
419*35238bceSAndroid Build Coastguard Worker     {
420*35238bceSAndroid Build Coastguard Worker         oss << (i == 0 ? "" : ", ");
421*35238bceSAndroid Build Coastguard Worker         switch (getDataTypeScalarType(type))
422*35238bceSAndroid Build Coastguard Worker         {
423*35238bceSAndroid Build Coastguard Worker         case TYPE_FLOAT:
424*35238bceSAndroid Build Coastguard Worker             printFloat(oss, rnd.getInt(0, 16) / 16.0);
425*35238bceSAndroid Build Coastguard Worker             break;
426*35238bceSAndroid Build Coastguard Worker 
427*35238bceSAndroid Build Coastguard Worker         case TYPE_INT:
428*35238bceSAndroid Build Coastguard Worker         case TYPE_UINT:
429*35238bceSAndroid Build Coastguard Worker             oss << rnd.getInt(0, 255);
430*35238bceSAndroid Build Coastguard Worker             break;
431*35238bceSAndroid Build Coastguard Worker 
432*35238bceSAndroid Build Coastguard Worker         case TYPE_BOOL:
433*35238bceSAndroid Build Coastguard Worker             oss << (rnd.getBool() ? "true" : "false");
434*35238bceSAndroid Build Coastguard Worker             break;
435*35238bceSAndroid Build Coastguard Worker 
436*35238bceSAndroid Build Coastguard Worker         default:
437*35238bceSAndroid Build Coastguard Worker             DE_FATAL("Impossible");
438*35238bceSAndroid Build Coastguard Worker         }
439*35238bceSAndroid Build Coastguard Worker     }
440*35238bceSAndroid Build Coastguard Worker 
441*35238bceSAndroid Build Coastguard Worker     if (size > 0)
442*35238bceSAndroid Build Coastguard Worker         oss << ")";
443*35238bceSAndroid Build Coastguard Worker }
444*35238bceSAndroid Build Coastguard Worker 
genVtxShaderSrc(uint32_t seed,const vector<VariableDeclaration> & outputs,const string & varName,bool uniform,float value=0.0)445*35238bceSAndroid Build Coastguard Worker string genVtxShaderSrc(uint32_t seed, const vector<VariableDeclaration> &outputs, const string &varName, bool uniform,
446*35238bceSAndroid Build Coastguard Worker                        float value = 0.0)
447*35238bceSAndroid Build Coastguard Worker {
448*35238bceSAndroid Build Coastguard Worker     ostringstream oss;
449*35238bceSAndroid Build Coastguard Worker     Random rnd(seed);
450*35238bceSAndroid Build Coastguard Worker     enum
451*35238bceSAndroid Build Coastguard Worker     {
452*35238bceSAndroid Build Coastguard Worker         NUM_COMPONENTS = 2
453*35238bceSAndroid Build Coastguard Worker     };
454*35238bceSAndroid Build Coastguard Worker     static const int s_quadrants[][NUM_COMPONENTS] = {{1, 1}, {-1, 1}, {1, -1}};
455*35238bceSAndroid Build Coastguard Worker 
456*35238bceSAndroid Build Coastguard Worker     oss << "#version 310 es\n";
457*35238bceSAndroid Build Coastguard Worker 
458*35238bceSAndroid Build Coastguard Worker     printFloatDeclaration(oss, varName, uniform, value);
459*35238bceSAndroid Build Coastguard Worker 
460*35238bceSAndroid Build Coastguard Worker     for (vector<VariableDeclaration>::const_iterator it = outputs.begin(); it != outputs.end(); ++it)
461*35238bceSAndroid Build Coastguard Worker         oss << *it << ";\n";
462*35238bceSAndroid Build Coastguard Worker 
463*35238bceSAndroid Build Coastguard Worker     oss << "const vec2 triangle[3] = vec2[3](\n";
464*35238bceSAndroid Build Coastguard Worker 
465*35238bceSAndroid Build Coastguard Worker     for (int vertexNdx = 0; vertexNdx < DE_LENGTH_OF_ARRAY(s_quadrants); ++vertexNdx)
466*35238bceSAndroid Build Coastguard Worker     {
467*35238bceSAndroid Build Coastguard Worker         oss << "\tvec2(";
468*35238bceSAndroid Build Coastguard Worker 
469*35238bceSAndroid Build Coastguard Worker         for (int componentNdx = 0; componentNdx < NUM_COMPONENTS; ++componentNdx)
470*35238bceSAndroid Build Coastguard Worker         {
471*35238bceSAndroid Build Coastguard Worker             printFloat(oss, s_quadrants[vertexNdx][componentNdx] * rnd.getInt(4, 16) / 16.0);
472*35238bceSAndroid Build Coastguard Worker             oss << (componentNdx < 1 ? ", " : "");
473*35238bceSAndroid Build Coastguard Worker         }
474*35238bceSAndroid Build Coastguard Worker 
475*35238bceSAndroid Build Coastguard Worker         oss << ")" << (vertexNdx < 2 ? "," : "") << "\n";
476*35238bceSAndroid Build Coastguard Worker     }
477*35238bceSAndroid Build Coastguard Worker     oss << ");\n";
478*35238bceSAndroid Build Coastguard Worker 
479*35238bceSAndroid Build Coastguard Worker     for (vector<VariableDeclaration>::const_iterator it = outputs.begin(); it != outputs.end(); ++it)
480*35238bceSAndroid Build Coastguard Worker     {
481*35238bceSAndroid Build Coastguard Worker         const DataType type   = it->varType.getBasicType();
482*35238bceSAndroid Build Coastguard Worker         const string typeName = glu::getDataTypeName(type);
483*35238bceSAndroid Build Coastguard Worker 
484*35238bceSAndroid Build Coastguard Worker         oss << "const " << typeName << " " << it->name << "Inits[3] = " << typeName << "[3](\n";
485*35238bceSAndroid Build Coastguard Worker         for (int i = 0; i < 3; ++i)
486*35238bceSAndroid Build Coastguard Worker         {
487*35238bceSAndroid Build Coastguard Worker             oss << (i == 0 ? "\t" : ",\n\t");
488*35238bceSAndroid Build Coastguard Worker             printRandomInitializer(oss, type, rnd);
489*35238bceSAndroid Build Coastguard Worker         }
490*35238bceSAndroid Build Coastguard Worker         oss << ");\n";
491*35238bceSAndroid Build Coastguard Worker     }
492*35238bceSAndroid Build Coastguard Worker 
493*35238bceSAndroid Build Coastguard Worker     oss << "void main (void)\n"
494*35238bceSAndroid Build Coastguard Worker         << "{\n"
495*35238bceSAndroid Build Coastguard Worker         << "\tgl_Position = vec4(" << varName << " * triangle[gl_VertexID], 0.0, 1.0);\n";
496*35238bceSAndroid Build Coastguard Worker 
497*35238bceSAndroid Build Coastguard Worker     for (vector<VariableDeclaration>::const_iterator it = outputs.begin(); it != outputs.end(); ++it)
498*35238bceSAndroid Build Coastguard Worker         oss << "\t" << it->name << " = " << it->name << "Inits[gl_VertexID];\n";
499*35238bceSAndroid Build Coastguard Worker 
500*35238bceSAndroid Build Coastguard Worker     oss << "}\n";
501*35238bceSAndroid Build Coastguard Worker 
502*35238bceSAndroid Build Coastguard Worker     return oss.str();
503*35238bceSAndroid Build Coastguard Worker }
504*35238bceSAndroid Build Coastguard Worker 
genFrgShaderSrc(uint32_t seed,const vector<VariableDeclaration> & inputs,const string & varName,bool uniform,float value=0.0)505*35238bceSAndroid Build Coastguard Worker string genFrgShaderSrc(uint32_t seed, const vector<VariableDeclaration> &inputs, const string &varName, bool uniform,
506*35238bceSAndroid Build Coastguard Worker                        float value = 0.0)
507*35238bceSAndroid Build Coastguard Worker {
508*35238bceSAndroid Build Coastguard Worker     Random rnd(seed);
509*35238bceSAndroid Build Coastguard Worker     ostringstream oss;
510*35238bceSAndroid Build Coastguard Worker 
511*35238bceSAndroid Build Coastguard Worker     oss.precision(4);
512*35238bceSAndroid Build Coastguard Worker     oss.width(7);
513*35238bceSAndroid Build Coastguard Worker     oss << "#version 310 es\n";
514*35238bceSAndroid Build Coastguard Worker 
515*35238bceSAndroid Build Coastguard Worker     oss << "precision highp float;\n";
516*35238bceSAndroid Build Coastguard Worker 
517*35238bceSAndroid Build Coastguard Worker     oss << "out vec4 fragColor;\n";
518*35238bceSAndroid Build Coastguard Worker 
519*35238bceSAndroid Build Coastguard Worker     printFloatDeclaration(oss, varName, uniform, value);
520*35238bceSAndroid Build Coastguard Worker 
521*35238bceSAndroid Build Coastguard Worker     for (vector<VariableDeclaration>::const_iterator it = inputs.begin(); it != inputs.end(); ++it)
522*35238bceSAndroid Build Coastguard Worker         oss << *it << ";\n";
523*35238bceSAndroid Build Coastguard Worker 
524*35238bceSAndroid Build Coastguard Worker     // glsl % isn't defined for negative numbers
525*35238bceSAndroid Build Coastguard Worker     oss << "int imod (int n, int d)"
526*35238bceSAndroid Build Coastguard Worker         << "\n"
527*35238bceSAndroid Build Coastguard Worker         << "{"
528*35238bceSAndroid Build Coastguard Worker         << "\n"
529*35238bceSAndroid Build Coastguard Worker         << "\t"
530*35238bceSAndroid Build Coastguard Worker         << "return (n < 0 ? d - 1 - (-1 - n) % d : n % d);"
531*35238bceSAndroid Build Coastguard Worker         << "\n"
532*35238bceSAndroid Build Coastguard Worker         << "}"
533*35238bceSAndroid Build Coastguard Worker         << "\n";
534*35238bceSAndroid Build Coastguard Worker 
535*35238bceSAndroid Build Coastguard Worker     oss << "vec4 hsv (vec3 hsv)"
536*35238bceSAndroid Build Coastguard Worker         << "{"
537*35238bceSAndroid Build Coastguard Worker         << "\n"
538*35238bceSAndroid Build Coastguard Worker         << "\tfloat h = hsv.x * 3.0;\n"
539*35238bceSAndroid Build Coastguard Worker         << "\tfloat r = max(0.0, 1.0 - h) + max(0.0, h - 2.0);\n"
540*35238bceSAndroid Build Coastguard Worker         << "\tfloat g = max(0.0, 1.0 - abs(h - 1.0));\n"
541*35238bceSAndroid Build Coastguard Worker         << "\tfloat b = max(0.0, 1.0 - abs(h - 2.0));\n"
542*35238bceSAndroid Build Coastguard Worker         << "\tvec3 hs = mix(vec3(1.0), vec3(r, g, b), hsv.y);\n"
543*35238bceSAndroid Build Coastguard Worker         << "\treturn vec4(hsv.z * hs, 1.0);\n"
544*35238bceSAndroid Build Coastguard Worker         << "}\n";
545*35238bceSAndroid Build Coastguard Worker 
546*35238bceSAndroid Build Coastguard Worker     oss << "void main (void)\n"
547*35238bceSAndroid Build Coastguard Worker         << "{\n";
548*35238bceSAndroid Build Coastguard Worker 
549*35238bceSAndroid Build Coastguard Worker     oss << "\t"
550*35238bceSAndroid Build Coastguard Worker         << "fragColor = vec4(vec3(" << varName << "), 1.0);"
551*35238bceSAndroid Build Coastguard Worker         << "\n";
552*35238bceSAndroid Build Coastguard Worker 
553*35238bceSAndroid Build Coastguard Worker     if (inputs.size() > 0)
554*35238bceSAndroid Build Coastguard Worker     {
555*35238bceSAndroid Build Coastguard Worker         oss << "\t"
556*35238bceSAndroid Build Coastguard Worker             << "switch (imod(int(0.5 * (";
557*35238bceSAndroid Build Coastguard Worker 
558*35238bceSAndroid Build Coastguard Worker         printFloat(oss, rnd.getFloat(0.5f, 2.0f));
559*35238bceSAndroid Build Coastguard Worker         oss << " * gl_FragCoord.x - ";
560*35238bceSAndroid Build Coastguard Worker 
561*35238bceSAndroid Build Coastguard Worker         printFloat(oss, rnd.getFloat(0.5f, 2.0f));
562*35238bceSAndroid Build Coastguard Worker         oss << " * gl_FragCoord.y)), " << inputs.size() << "))"
563*35238bceSAndroid Build Coastguard Worker             << "\n"
564*35238bceSAndroid Build Coastguard Worker             << "\t"
565*35238bceSAndroid Build Coastguard Worker             << "{"
566*35238bceSAndroid Build Coastguard Worker             << "\n";
567*35238bceSAndroid Build Coastguard Worker 
568*35238bceSAndroid Build Coastguard Worker         for (size_t i = 0; i < inputs.size(); ++i)
569*35238bceSAndroid Build Coastguard Worker         {
570*35238bceSAndroid Build Coastguard Worker             oss << "\t\t"
571*35238bceSAndroid Build Coastguard Worker                 << "case " << i << ":"
572*35238bceSAndroid Build Coastguard Worker                 << "\n"
573*35238bceSAndroid Build Coastguard Worker                 << "\t\t\t"
574*35238bceSAndroid Build Coastguard Worker                 << "fragColor *= ";
575*35238bceSAndroid Build Coastguard Worker 
576*35238bceSAndroid Build Coastguard Worker             printInputColor(oss, inputs[i]);
577*35238bceSAndroid Build Coastguard Worker 
578*35238bceSAndroid Build Coastguard Worker             oss << ";"
579*35238bceSAndroid Build Coastguard Worker                 << "\n"
580*35238bceSAndroid Build Coastguard Worker                 << "\t\t\t"
581*35238bceSAndroid Build Coastguard Worker                 << "break;"
582*35238bceSAndroid Build Coastguard Worker                 << "\n";
583*35238bceSAndroid Build Coastguard Worker         }
584*35238bceSAndroid Build Coastguard Worker 
585*35238bceSAndroid Build Coastguard Worker         oss << "\t\t"
586*35238bceSAndroid Build Coastguard Worker             << "case " << inputs.size() << ":\n"
587*35238bceSAndroid Build Coastguard Worker             << "\t\t\t"
588*35238bceSAndroid Build Coastguard Worker             << "fragColor = vec4(1.0, 0.0, 1.0, 1.0);"
589*35238bceSAndroid Build Coastguard Worker             << "\n";
590*35238bceSAndroid Build Coastguard Worker         oss << "\t\t\t"
591*35238bceSAndroid Build Coastguard Worker             << "break;"
592*35238bceSAndroid Build Coastguard Worker             << "\n";
593*35238bceSAndroid Build Coastguard Worker 
594*35238bceSAndroid Build Coastguard Worker         oss << "\t\t"
595*35238bceSAndroid Build Coastguard Worker             << "case -1:\n"
596*35238bceSAndroid Build Coastguard Worker             << "\t\t\t"
597*35238bceSAndroid Build Coastguard Worker             << "fragColor = vec4(1.0, 1.0, 0.0, 1.0);"
598*35238bceSAndroid Build Coastguard Worker             << "\n";
599*35238bceSAndroid Build Coastguard Worker         oss << "\t\t\t"
600*35238bceSAndroid Build Coastguard Worker             << "break;"
601*35238bceSAndroid Build Coastguard Worker             << "\n";
602*35238bceSAndroid Build Coastguard Worker 
603*35238bceSAndroid Build Coastguard Worker         oss << "\t\t"
604*35238bceSAndroid Build Coastguard Worker             << "default:"
605*35238bceSAndroid Build Coastguard Worker             << "\n"
606*35238bceSAndroid Build Coastguard Worker             << "\t\t\t"
607*35238bceSAndroid Build Coastguard Worker             << "fragColor = vec4(1.0, 1.0, 0.0, 1.0);"
608*35238bceSAndroid Build Coastguard Worker             << "\n";
609*35238bceSAndroid Build Coastguard Worker 
610*35238bceSAndroid Build Coastguard Worker         oss << "\t"
611*35238bceSAndroid Build Coastguard Worker             << "}\n";
612*35238bceSAndroid Build Coastguard Worker     }
613*35238bceSAndroid Build Coastguard Worker 
614*35238bceSAndroid Build Coastguard Worker     oss << "}\n";
615*35238bceSAndroid Build Coastguard Worker 
616*35238bceSAndroid Build Coastguard Worker     return oss.str();
617*35238bceSAndroid Build Coastguard Worker }
618*35238bceSAndroid Build Coastguard Worker 
619*35238bceSAndroid Build Coastguard Worker // ProgramWrapper
620*35238bceSAndroid Build Coastguard Worker 
621*35238bceSAndroid Build Coastguard Worker class ProgramWrapper
622*35238bceSAndroid Build Coastguard Worker {
623*35238bceSAndroid Build Coastguard Worker public:
~ProgramWrapper(void)624*35238bceSAndroid Build Coastguard Worker     virtual ~ProgramWrapper(void)
625*35238bceSAndroid Build Coastguard Worker     {
626*35238bceSAndroid Build Coastguard Worker     }
627*35238bceSAndroid Build Coastguard Worker 
628*35238bceSAndroid Build Coastguard Worker     virtual GLuint getProgramName(void)   = 0;
629*35238bceSAndroid Build Coastguard Worker     virtual void writeToLog(TestLog &log) = 0;
630*35238bceSAndroid Build Coastguard Worker };
631*35238bceSAndroid Build Coastguard Worker 
632*35238bceSAndroid Build Coastguard Worker class ShaderProgramWrapper : public ProgramWrapper
633*35238bceSAndroid Build Coastguard Worker {
634*35238bceSAndroid Build Coastguard Worker public:
ShaderProgramWrapper(const RenderContext & renderCtx,const ProgramSources & sources)635*35238bceSAndroid Build Coastguard Worker     ShaderProgramWrapper(const RenderContext &renderCtx, const ProgramSources &sources)
636*35238bceSAndroid Build Coastguard Worker         : m_shaderProgram(renderCtx, sources)
637*35238bceSAndroid Build Coastguard Worker     {
638*35238bceSAndroid Build Coastguard Worker     }
~ShaderProgramWrapper(void)639*35238bceSAndroid Build Coastguard Worker     ~ShaderProgramWrapper(void)
640*35238bceSAndroid Build Coastguard Worker     {
641*35238bceSAndroid Build Coastguard Worker     }
642*35238bceSAndroid Build Coastguard Worker 
getProgramName(void)643*35238bceSAndroid Build Coastguard Worker     GLuint getProgramName(void)
644*35238bceSAndroid Build Coastguard Worker     {
645*35238bceSAndroid Build Coastguard Worker         return m_shaderProgram.getProgram();
646*35238bceSAndroid Build Coastguard Worker     }
getShaderProgram(void)647*35238bceSAndroid Build Coastguard Worker     ShaderProgram &getShaderProgram(void)
648*35238bceSAndroid Build Coastguard Worker     {
649*35238bceSAndroid Build Coastguard Worker         return m_shaderProgram;
650*35238bceSAndroid Build Coastguard Worker     }
writeToLog(TestLog & log)651*35238bceSAndroid Build Coastguard Worker     void writeToLog(TestLog &log)
652*35238bceSAndroid Build Coastguard Worker     {
653*35238bceSAndroid Build Coastguard Worker         log << m_shaderProgram;
654*35238bceSAndroid Build Coastguard Worker     }
655*35238bceSAndroid Build Coastguard Worker 
656*35238bceSAndroid Build Coastguard Worker private:
657*35238bceSAndroid Build Coastguard Worker     ShaderProgram m_shaderProgram;
658*35238bceSAndroid Build Coastguard Worker };
659*35238bceSAndroid Build Coastguard Worker 
660*35238bceSAndroid Build Coastguard Worker class RawProgramWrapper : public ProgramWrapper
661*35238bceSAndroid Build Coastguard Worker {
662*35238bceSAndroid Build Coastguard Worker public:
RawProgramWrapper(const RenderContext & renderCtx,GLuint programName,ShaderType shaderType,const string & source)663*35238bceSAndroid Build Coastguard Worker     RawProgramWrapper(const RenderContext &renderCtx, GLuint programName, ShaderType shaderType, const string &source)
664*35238bceSAndroid Build Coastguard Worker         : m_program(renderCtx, programName)
665*35238bceSAndroid Build Coastguard Worker         , m_shaderType(shaderType)
666*35238bceSAndroid Build Coastguard Worker         , m_source(source)
667*35238bceSAndroid Build Coastguard Worker     {
668*35238bceSAndroid Build Coastguard Worker     }
~RawProgramWrapper(void)669*35238bceSAndroid Build Coastguard Worker     ~RawProgramWrapper(void)
670*35238bceSAndroid Build Coastguard Worker     {
671*35238bceSAndroid Build Coastguard Worker     }
672*35238bceSAndroid Build Coastguard Worker 
getProgramName(void)673*35238bceSAndroid Build Coastguard Worker     GLuint getProgramName(void)
674*35238bceSAndroid Build Coastguard Worker     {
675*35238bceSAndroid Build Coastguard Worker         return m_program.getProgram();
676*35238bceSAndroid Build Coastguard Worker     }
getProgram(void)677*35238bceSAndroid Build Coastguard Worker     Program &getProgram(void)
678*35238bceSAndroid Build Coastguard Worker     {
679*35238bceSAndroid Build Coastguard Worker         return m_program;
680*35238bceSAndroid Build Coastguard Worker     }
681*35238bceSAndroid Build Coastguard Worker     void writeToLog(TestLog &log);
682*35238bceSAndroid Build Coastguard Worker 
683*35238bceSAndroid Build Coastguard Worker private:
684*35238bceSAndroid Build Coastguard Worker     Program m_program;
685*35238bceSAndroid Build Coastguard Worker     ShaderType m_shaderType;
686*35238bceSAndroid Build Coastguard Worker     const string m_source;
687*35238bceSAndroid Build Coastguard Worker };
688*35238bceSAndroid Build Coastguard Worker 
writeToLog(TestLog & log)689*35238bceSAndroid Build Coastguard Worker void RawProgramWrapper::writeToLog(TestLog &log)
690*35238bceSAndroid Build Coastguard Worker {
691*35238bceSAndroid Build Coastguard Worker     const string info   = m_program.getInfoLog();
692*35238bceSAndroid Build Coastguard Worker     qpShaderType qpType = glu::getLogShaderType(m_shaderType);
693*35238bceSAndroid Build Coastguard Worker 
694*35238bceSAndroid Build Coastguard Worker     log << TestLog::ShaderProgram(true, info)
695*35238bceSAndroid Build Coastguard Worker         << TestLog::Shader(qpType, m_source, true, "[Shader created by glCreateShaderProgramv()]")
696*35238bceSAndroid Build Coastguard Worker         << TestLog::EndShaderProgram;
697*35238bceSAndroid Build Coastguard Worker }
698*35238bceSAndroid Build Coastguard Worker 
699*35238bceSAndroid Build Coastguard Worker // ProgramParams
700*35238bceSAndroid Build Coastguard Worker 
701*35238bceSAndroid Build Coastguard Worker struct ProgramParams
702*35238bceSAndroid Build Coastguard Worker {
ProgramParamsdeqp::gles31::Functional::__anonf652bf1a0111::ProgramParams703*35238bceSAndroid Build Coastguard Worker     ProgramParams(uint32_t vtxSeed_, GLfloat vtxScale_, uint32_t frgSeed_, GLfloat frgScale_)
704*35238bceSAndroid Build Coastguard Worker         : vtxSeed(vtxSeed_)
705*35238bceSAndroid Build Coastguard Worker         , vtxScale(vtxScale_)
706*35238bceSAndroid Build Coastguard Worker         , frgSeed(frgSeed_)
707*35238bceSAndroid Build Coastguard Worker         , frgScale(frgScale_)
708*35238bceSAndroid Build Coastguard Worker     {
709*35238bceSAndroid Build Coastguard Worker     }
710*35238bceSAndroid Build Coastguard Worker     uint32_t vtxSeed;
711*35238bceSAndroid Build Coastguard Worker     GLfloat vtxScale;
712*35238bceSAndroid Build Coastguard Worker     uint32_t frgSeed;
713*35238bceSAndroid Build Coastguard Worker     GLfloat frgScale;
714*35238bceSAndroid Build Coastguard Worker };
715*35238bceSAndroid Build Coastguard Worker 
genProgramParams(Random & rnd)716*35238bceSAndroid Build Coastguard Worker ProgramParams genProgramParams(Random &rnd)
717*35238bceSAndroid Build Coastguard Worker {
718*35238bceSAndroid Build Coastguard Worker     const uint32_t vtxSeed = rnd.getUint32();
719*35238bceSAndroid Build Coastguard Worker     const GLfloat vtxScale = (float)rnd.getInt(8, 16) / 16.0f;
720*35238bceSAndroid Build Coastguard Worker     const uint32_t frgSeed = rnd.getUint32();
721*35238bceSAndroid Build Coastguard Worker     const GLfloat frgScale = (float)rnd.getInt(0, 16) / 16.0f;
722*35238bceSAndroid Build Coastguard Worker 
723*35238bceSAndroid Build Coastguard Worker     return ProgramParams(vtxSeed, vtxScale, frgSeed, frgScale);
724*35238bceSAndroid Build Coastguard Worker }
725*35238bceSAndroid Build Coastguard Worker 
726*35238bceSAndroid Build Coastguard Worker // TestParams
727*35238bceSAndroid Build Coastguard Worker 
728*35238bceSAndroid Build Coastguard Worker struct TestParams
729*35238bceSAndroid Build Coastguard Worker {
730*35238bceSAndroid Build Coastguard Worker     bool initSingle;
731*35238bceSAndroid Build Coastguard Worker     bool switchVtx;
732*35238bceSAndroid Build Coastguard Worker     bool switchFrg;
733*35238bceSAndroid Build Coastguard Worker     bool useUniform;
734*35238bceSAndroid Build Coastguard Worker     bool useSameName;
735*35238bceSAndroid Build Coastguard Worker     bool useCreateHelper;
736*35238bceSAndroid Build Coastguard Worker     bool useProgramUniform;
737*35238bceSAndroid Build Coastguard Worker     VaryingParams varyings;
738*35238bceSAndroid Build Coastguard Worker };
739*35238bceSAndroid Build Coastguard Worker 
paramsSeed(const TestParams & params)740*35238bceSAndroid Build Coastguard Worker uint32_t paramsSeed(const TestParams &params)
741*35238bceSAndroid Build Coastguard Worker {
742*35238bceSAndroid Build Coastguard Worker     uint32_t paramCode =
743*35238bceSAndroid Build Coastguard Worker         (params.initSingle << 0 | params.switchVtx << 1 | params.switchFrg << 2 | params.useUniform << 3 |
744*35238bceSAndroid Build Coastguard Worker          params.useSameName << 4 | params.useCreateHelper << 5 | params.useProgramUniform << 6);
745*35238bceSAndroid Build Coastguard Worker 
746*35238bceSAndroid Build Coastguard Worker     paramCode = deUint32Hash(paramCode) + params.varyings.count;
747*35238bceSAndroid Build Coastguard Worker     paramCode = deUint32Hash(paramCode) + params.varyings.type;
748*35238bceSAndroid Build Coastguard Worker     paramCode = deUint32Hash(paramCode) + params.varyings.binding;
749*35238bceSAndroid Build Coastguard Worker     paramCode = deUint32Hash(paramCode) + params.varyings.vtxInterp;
750*35238bceSAndroid Build Coastguard Worker     paramCode = deUint32Hash(paramCode) + params.varyings.frgInterp;
751*35238bceSAndroid Build Coastguard Worker 
752*35238bceSAndroid Build Coastguard Worker     return deUint32Hash(paramCode);
753*35238bceSAndroid Build Coastguard Worker }
754*35238bceSAndroid Build Coastguard Worker 
paramsCode(const TestParams & params)755*35238bceSAndroid Build Coastguard Worker string paramsCode(const TestParams &params)
756*35238bceSAndroid Build Coastguard Worker {
757*35238bceSAndroid Build Coastguard Worker     using namespace glu;
758*35238bceSAndroid Build Coastguard Worker 
759*35238bceSAndroid Build Coastguard Worker     ostringstream oss;
760*35238bceSAndroid Build Coastguard Worker 
761*35238bceSAndroid Build Coastguard Worker     oss << (params.initSingle ? "1" : "2") << (params.switchVtx ? "v" : "") << (params.switchFrg ? "f" : "")
762*35238bceSAndroid Build Coastguard Worker         << (params.useProgramUniform ? "p" : "") << (params.useUniform ? "u" : "") << (params.useSameName ? "s" : "")
763*35238bceSAndroid Build Coastguard Worker         << (params.useCreateHelper ? "c" : "") << de::toString(params.varyings.count)
764*35238bceSAndroid Build Coastguard Worker         << (params.varyings.binding == BINDING_NAME     ? "n" :
765*35238bceSAndroid Build Coastguard Worker             params.varyings.binding == BINDING_LOCATION ? "l" :
766*35238bceSAndroid Build Coastguard Worker             params.varyings.binding == BINDING_LAST     ? "r" :
767*35238bceSAndroid Build Coastguard Worker                                                           "")
768*35238bceSAndroid Build Coastguard Worker         << (params.varyings.vtxInterp == VARYINGINTERPOLATION_SMOOTH   ? "m" :
769*35238bceSAndroid Build Coastguard Worker             params.varyings.vtxInterp == VARYINGINTERPOLATION_CENTROID ? "e" :
770*35238bceSAndroid Build Coastguard Worker             params.varyings.vtxInterp == VARYINGINTERPOLATION_FLAT     ? "a" :
771*35238bceSAndroid Build Coastguard Worker             params.varyings.vtxInterp == VARYINGINTERPOLATION_RANDOM   ? "r" :
772*35238bceSAndroid Build Coastguard Worker                                                                          "o")
773*35238bceSAndroid Build Coastguard Worker         << (params.varyings.frgInterp == VARYINGINTERPOLATION_SMOOTH   ? "m" :
774*35238bceSAndroid Build Coastguard Worker             params.varyings.frgInterp == VARYINGINTERPOLATION_CENTROID ? "e" :
775*35238bceSAndroid Build Coastguard Worker             params.varyings.frgInterp == VARYINGINTERPOLATION_FLAT     ? "a" :
776*35238bceSAndroid Build Coastguard Worker             params.varyings.frgInterp == VARYINGINTERPOLATION_RANDOM   ? "r" :
777*35238bceSAndroid Build Coastguard Worker                                                                          "o");
778*35238bceSAndroid Build Coastguard Worker     return oss.str();
779*35238bceSAndroid Build Coastguard Worker }
780*35238bceSAndroid Build Coastguard Worker 
paramsValid(const TestParams & params)781*35238bceSAndroid Build Coastguard Worker bool paramsValid(const TestParams &params)
782*35238bceSAndroid Build Coastguard Worker {
783*35238bceSAndroid Build Coastguard Worker     using namespace glu;
784*35238bceSAndroid Build Coastguard Worker 
785*35238bceSAndroid Build Coastguard Worker     // Final pipeline has a single program?
786*35238bceSAndroid Build Coastguard Worker     if (params.initSingle)
787*35238bceSAndroid Build Coastguard Worker     {
788*35238bceSAndroid Build Coastguard Worker         // Cannot have conflicting names for uniforms or constants
789*35238bceSAndroid Build Coastguard Worker         if (params.useSameName)
790*35238bceSAndroid Build Coastguard Worker             return false;
791*35238bceSAndroid Build Coastguard Worker 
792*35238bceSAndroid Build Coastguard Worker         // CreateShaderProgram would never get called
793*35238bceSAndroid Build Coastguard Worker         if (!params.switchVtx && !params.switchFrg && params.useCreateHelper)
794*35238bceSAndroid Build Coastguard Worker             return false;
795*35238bceSAndroid Build Coastguard Worker 
796*35238bceSAndroid Build Coastguard Worker         // Must switch either all or nothing
797*35238bceSAndroid Build Coastguard Worker         if (params.switchVtx != params.switchFrg)
798*35238bceSAndroid Build Coastguard Worker             return false;
799*35238bceSAndroid Build Coastguard Worker     }
800*35238bceSAndroid Build Coastguard Worker 
801*35238bceSAndroid Build Coastguard Worker     // ProgramUniform would never get called
802*35238bceSAndroid Build Coastguard Worker     if (params.useProgramUniform && !params.useUniform)
803*35238bceSAndroid Build Coastguard Worker         return false;
804*35238bceSAndroid Build Coastguard Worker 
805*35238bceSAndroid Build Coastguard Worker     // Interpolation is meaningless if we don't use an in/out variable.
806*35238bceSAndroid Build Coastguard Worker     if (params.varyings.count == 0 && !(params.varyings.vtxInterp == VARYINGINTERPOLATION_LAST &&
807*35238bceSAndroid Build Coastguard Worker                                         params.varyings.frgInterp == VARYINGINTERPOLATION_LAST))
808*35238bceSAndroid Build Coastguard Worker         return false;
809*35238bceSAndroid Build Coastguard Worker 
810*35238bceSAndroid Build Coastguard Worker     // Mismatch by flat / smooth is not allowed. See Khronos bug #12630
811*35238bceSAndroid Build Coastguard Worker     // \note: iterpolations might be RANDOM, causing generated varyings potentially match / mismatch anyway.
812*35238bceSAndroid Build Coastguard Worker     //        This is checked later on. Here, we just make sure that we don't force the generator to generate
813*35238bceSAndroid Build Coastguard Worker     //        only invalid varying configurations, i.e. there exists a valid varying configuration for this
814*35238bceSAndroid Build Coastguard Worker     //        test param config.
815*35238bceSAndroid Build Coastguard Worker     if ((params.varyings.vtxInterp != VARYINGINTERPOLATION_RANDOM) &&
816*35238bceSAndroid Build Coastguard Worker         (params.varyings.frgInterp != VARYINGINTERPOLATION_RANDOM) &&
817*35238bceSAndroid Build Coastguard Worker         (params.varyings.vtxInterp == VARYINGINTERPOLATION_FLAT) !=
818*35238bceSAndroid Build Coastguard Worker             (params.varyings.frgInterp == VARYINGINTERPOLATION_FLAT))
819*35238bceSAndroid Build Coastguard Worker         return false;
820*35238bceSAndroid Build Coastguard Worker 
821*35238bceSAndroid Build Coastguard Worker     return true;
822*35238bceSAndroid Build Coastguard Worker }
823*35238bceSAndroid Build Coastguard Worker 
824*35238bceSAndroid Build Coastguard Worker // used only for debug quick checks
825*35238bceSAndroid Build Coastguard Worker #if defined(DE_DEBUG)
varyingsValid(const VaryingInterface & varyings)826*35238bceSAndroid Build Coastguard Worker bool varyingsValid(const VaryingInterface &varyings)
827*35238bceSAndroid Build Coastguard Worker {
828*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < (int)varyings.vtxOutputs.size(); ++ndx)
829*35238bceSAndroid Build Coastguard Worker     {
830*35238bceSAndroid Build Coastguard Worker         const VaryingInterpolation vertexInterpolation =
831*35238bceSAndroid Build Coastguard Worker             getVaryingInterpolation(varyings.vtxOutputs[ndx].interpolation);
832*35238bceSAndroid Build Coastguard Worker         const VaryingInterpolation fragmentInterpolation =
833*35238bceSAndroid Build Coastguard Worker             getVaryingInterpolation(varyings.frgInputs[ndx].interpolation);
834*35238bceSAndroid Build Coastguard Worker 
835*35238bceSAndroid Build Coastguard Worker         if (!isSSOCompatibleInterpolation(vertexInterpolation, fragmentInterpolation))
836*35238bceSAndroid Build Coastguard Worker             return false;
837*35238bceSAndroid Build Coastguard Worker     }
838*35238bceSAndroid Build Coastguard Worker 
839*35238bceSAndroid Build Coastguard Worker     return true;
840*35238bceSAndroid Build Coastguard Worker }
841*35238bceSAndroid Build Coastguard Worker #endif
842*35238bceSAndroid Build Coastguard Worker 
logParams(TestLog & log,const TestParams & params)843*35238bceSAndroid Build Coastguard Worker void logParams(TestLog &log, const TestParams &params)
844*35238bceSAndroid Build Coastguard Worker {
845*35238bceSAndroid Build Coastguard Worker     // We don't log operational details here since those are shown
846*35238bceSAndroid Build Coastguard Worker     // in the log messages during execution.
847*35238bceSAndroid Build Coastguard Worker     MessageBuilder msg = log.message();
848*35238bceSAndroid Build Coastguard Worker 
849*35238bceSAndroid Build Coastguard Worker     msg << "Pipeline configuration:\n";
850*35238bceSAndroid Build Coastguard Worker 
851*35238bceSAndroid Build Coastguard Worker     msg << "Vertex and fragment shaders have " << (params.useUniform ? "uniform" : "constant") << "s with "
852*35238bceSAndroid Build Coastguard Worker         << (params.useSameName ? "the same name" : "different names") << ".\n";
853*35238bceSAndroid Build Coastguard Worker 
854*35238bceSAndroid Build Coastguard Worker     if (params.varyings.count == 0)
855*35238bceSAndroid Build Coastguard Worker         msg << "There are no varyings.\n";
856*35238bceSAndroid Build Coastguard Worker     else
857*35238bceSAndroid Build Coastguard Worker     {
858*35238bceSAndroid Build Coastguard Worker         if (params.varyings.count == 1)
859*35238bceSAndroid Build Coastguard Worker             msg << "There is one varying.\n";
860*35238bceSAndroid Build Coastguard Worker         else
861*35238bceSAndroid Build Coastguard Worker             msg << "There are " << params.varyings.count << " varyings.\n";
862*35238bceSAndroid Build Coastguard Worker 
863*35238bceSAndroid Build Coastguard Worker         if (params.varyings.type == glu::TYPE_LAST)
864*35238bceSAndroid Build Coastguard Worker             msg << "Varyings are of random types.\n";
865*35238bceSAndroid Build Coastguard Worker         else
866*35238bceSAndroid Build Coastguard Worker             msg << "Varyings are of type '" << glu::getDataTypeName(params.varyings.type) << "'.\n";
867*35238bceSAndroid Build Coastguard Worker 
868*35238bceSAndroid Build Coastguard Worker         msg << "Varying outputs and inputs correspond ";
869*35238bceSAndroid Build Coastguard Worker         switch (params.varyings.binding)
870*35238bceSAndroid Build Coastguard Worker         {
871*35238bceSAndroid Build Coastguard Worker         case BINDING_NAME:
872*35238bceSAndroid Build Coastguard Worker             msg << "by name.\n";
873*35238bceSAndroid Build Coastguard Worker             break;
874*35238bceSAndroid Build Coastguard Worker         case BINDING_LOCATION:
875*35238bceSAndroid Build Coastguard Worker             msg << "by location.\n";
876*35238bceSAndroid Build Coastguard Worker             break;
877*35238bceSAndroid Build Coastguard Worker         case BINDING_LAST:
878*35238bceSAndroid Build Coastguard Worker             msg << "randomly either by name or by location.\n";
879*35238bceSAndroid Build Coastguard Worker             break;
880*35238bceSAndroid Build Coastguard Worker         default:
881*35238bceSAndroid Build Coastguard Worker             DE_FATAL("Impossible");
882*35238bceSAndroid Build Coastguard Worker         }
883*35238bceSAndroid Build Coastguard Worker 
884*35238bceSAndroid Build Coastguard Worker         msg << "In the vertex shader the varyings are qualified ";
885*35238bceSAndroid Build Coastguard Worker         if (params.varyings.vtxInterp == VARYINGINTERPOLATION_DEFAULT)
886*35238bceSAndroid Build Coastguard Worker             msg << "with no interpolation qualifiers.\n";
887*35238bceSAndroid Build Coastguard Worker         else if (params.varyings.vtxInterp == VARYINGINTERPOLATION_RANDOM)
888*35238bceSAndroid Build Coastguard Worker             msg << "with a random interpolation qualifier.\n";
889*35238bceSAndroid Build Coastguard Worker         else
890*35238bceSAndroid Build Coastguard Worker             msg << "'" << glu::getInterpolationName(getGluInterpolation(params.varyings.vtxInterp)) << "'.\n";
891*35238bceSAndroid Build Coastguard Worker 
892*35238bceSAndroid Build Coastguard Worker         msg << "In the fragment shader the varyings are qualified ";
893*35238bceSAndroid Build Coastguard Worker         if (params.varyings.frgInterp == VARYINGINTERPOLATION_DEFAULT)
894*35238bceSAndroid Build Coastguard Worker             msg << "with no interpolation qualifiers.\n";
895*35238bceSAndroid Build Coastguard Worker         else if (params.varyings.frgInterp == VARYINGINTERPOLATION_RANDOM)
896*35238bceSAndroid Build Coastguard Worker             msg << "with a random interpolation qualifier.\n";
897*35238bceSAndroid Build Coastguard Worker         else
898*35238bceSAndroid Build Coastguard Worker             msg << "'" << glu::getInterpolationName(getGluInterpolation(params.varyings.frgInterp)) << "'.\n";
899*35238bceSAndroid Build Coastguard Worker     }
900*35238bceSAndroid Build Coastguard Worker 
901*35238bceSAndroid Build Coastguard Worker     msg << TestLog::EndMessage;
902*35238bceSAndroid Build Coastguard Worker 
903*35238bceSAndroid Build Coastguard Worker     log.writeMessage("");
904*35238bceSAndroid Build Coastguard Worker }
905*35238bceSAndroid Build Coastguard Worker 
genParams(uint32_t seed)906*35238bceSAndroid Build Coastguard Worker TestParams genParams(uint32_t seed)
907*35238bceSAndroid Build Coastguard Worker {
908*35238bceSAndroid Build Coastguard Worker     Random rnd(seed);
909*35238bceSAndroid Build Coastguard Worker     TestParams params;
910*35238bceSAndroid Build Coastguard Worker     int tryNdx = 0;
911*35238bceSAndroid Build Coastguard Worker 
912*35238bceSAndroid Build Coastguard Worker     do
913*35238bceSAndroid Build Coastguard Worker     {
914*35238bceSAndroid Build Coastguard Worker         params.initSingle        = rnd.getBool();
915*35238bceSAndroid Build Coastguard Worker         params.switchVtx         = rnd.getBool();
916*35238bceSAndroid Build Coastguard Worker         params.switchFrg         = rnd.getBool();
917*35238bceSAndroid Build Coastguard Worker         params.useUniform        = rnd.getBool();
918*35238bceSAndroid Build Coastguard Worker         params.useProgramUniform = params.useUniform && rnd.getBool();
919*35238bceSAndroid Build Coastguard Worker         params.useCreateHelper   = rnd.getBool();
920*35238bceSAndroid Build Coastguard Worker         params.useSameName       = rnd.getBool();
921*35238bceSAndroid Build Coastguard Worker         {
922*35238bceSAndroid Build Coastguard Worker             int i                 = rnd.getInt(-1, 3);
923*35238bceSAndroid Build Coastguard Worker             params.varyings.count = (i == -1 ? 0 : 1 << i);
924*35238bceSAndroid Build Coastguard Worker         }
925*35238bceSAndroid Build Coastguard Worker         if (params.varyings.count > 0)
926*35238bceSAndroid Build Coastguard Worker         {
927*35238bceSAndroid Build Coastguard Worker             params.varyings.type      = glu::TYPE_LAST;
928*35238bceSAndroid Build Coastguard Worker             params.varyings.binding   = BINDING_LAST;
929*35238bceSAndroid Build Coastguard Worker             params.varyings.vtxInterp = VARYINGINTERPOLATION_RANDOM;
930*35238bceSAndroid Build Coastguard Worker             params.varyings.frgInterp = VARYINGINTERPOLATION_RANDOM;
931*35238bceSAndroid Build Coastguard Worker         }
932*35238bceSAndroid Build Coastguard Worker         else
933*35238bceSAndroid Build Coastguard Worker         {
934*35238bceSAndroid Build Coastguard Worker             params.varyings.type      = glu::TYPE_INVALID;
935*35238bceSAndroid Build Coastguard Worker             params.varyings.binding   = BINDING_LAST;
936*35238bceSAndroid Build Coastguard Worker             params.varyings.vtxInterp = VARYINGINTERPOLATION_LAST;
937*35238bceSAndroid Build Coastguard Worker             params.varyings.frgInterp = VARYINGINTERPOLATION_LAST;
938*35238bceSAndroid Build Coastguard Worker         }
939*35238bceSAndroid Build Coastguard Worker 
940*35238bceSAndroid Build Coastguard Worker         tryNdx += 1;
941*35238bceSAndroid Build Coastguard Worker     } while (!paramsValid(params) && tryNdx < 16);
942*35238bceSAndroid Build Coastguard Worker 
943*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(paramsValid(params));
944*35238bceSAndroid Build Coastguard Worker 
945*35238bceSAndroid Build Coastguard Worker     return params;
946*35238bceSAndroid Build Coastguard Worker }
947*35238bceSAndroid Build Coastguard Worker 
948*35238bceSAndroid Build Coastguard Worker // Program pipeline wrapper that retains references to component programs.
949*35238bceSAndroid Build Coastguard Worker 
950*35238bceSAndroid Build Coastguard Worker struct Pipeline
951*35238bceSAndroid Build Coastguard Worker {
Pipelinedeqp::gles31::Functional::__anonf652bf1a0111::Pipeline952*35238bceSAndroid Build Coastguard Worker     Pipeline(MovePtr<ProgramPipeline> pipeline_, MovePtr<ProgramWrapper> fullProg_, MovePtr<ProgramWrapper> vtxProg_,
953*35238bceSAndroid Build Coastguard Worker              MovePtr<ProgramWrapper> frgProg_)
954*35238bceSAndroid Build Coastguard Worker         : pipeline(pipeline_)
955*35238bceSAndroid Build Coastguard Worker         , fullProg(fullProg_)
956*35238bceSAndroid Build Coastguard Worker         , vtxProg(vtxProg_)
957*35238bceSAndroid Build Coastguard Worker         , frgProg(frgProg_)
958*35238bceSAndroid Build Coastguard Worker     {
959*35238bceSAndroid Build Coastguard Worker     }
960*35238bceSAndroid Build Coastguard Worker 
getVertexProgramdeqp::gles31::Functional::__anonf652bf1a0111::Pipeline961*35238bceSAndroid Build Coastguard Worker     ProgramWrapper &getVertexProgram(void) const
962*35238bceSAndroid Build Coastguard Worker     {
963*35238bceSAndroid Build Coastguard Worker         return vtxProg ? *vtxProg : *fullProg;
964*35238bceSAndroid Build Coastguard Worker     }
965*35238bceSAndroid Build Coastguard Worker 
getFragmentProgramdeqp::gles31::Functional::__anonf652bf1a0111::Pipeline966*35238bceSAndroid Build Coastguard Worker     ProgramWrapper &getFragmentProgram(void) const
967*35238bceSAndroid Build Coastguard Worker     {
968*35238bceSAndroid Build Coastguard Worker         return frgProg ? *frgProg : *fullProg;
969*35238bceSAndroid Build Coastguard Worker     }
970*35238bceSAndroid Build Coastguard Worker 
971*35238bceSAndroid Build Coastguard Worker     UniquePtr<ProgramPipeline> pipeline;
972*35238bceSAndroid Build Coastguard Worker     UniquePtr<ProgramWrapper> fullProg;
973*35238bceSAndroid Build Coastguard Worker     UniquePtr<ProgramWrapper> vtxProg;
974*35238bceSAndroid Build Coastguard Worker     UniquePtr<ProgramWrapper> frgProg;
975*35238bceSAndroid Build Coastguard Worker };
976*35238bceSAndroid Build Coastguard Worker 
logPipeline(TestLog & log,const Pipeline & pipeline)977*35238bceSAndroid Build Coastguard Worker void logPipeline(TestLog &log, const Pipeline &pipeline)
978*35238bceSAndroid Build Coastguard Worker {
979*35238bceSAndroid Build Coastguard Worker     ProgramWrapper &vtxProg = pipeline.getVertexProgram();
980*35238bceSAndroid Build Coastguard Worker     ProgramWrapper &frgProg = pipeline.getFragmentProgram();
981*35238bceSAndroid Build Coastguard Worker 
982*35238bceSAndroid Build Coastguard Worker     log.writeMessage("// Failed program pipeline:");
983*35238bceSAndroid Build Coastguard Worker     if (&vtxProg == &frgProg)
984*35238bceSAndroid Build Coastguard Worker     {
985*35238bceSAndroid Build Coastguard Worker         log.writeMessage("// Common program for both vertex and fragment stages:");
986*35238bceSAndroid Build Coastguard Worker         vtxProg.writeToLog(log);
987*35238bceSAndroid Build Coastguard Worker     }
988*35238bceSAndroid Build Coastguard Worker     else
989*35238bceSAndroid Build Coastguard Worker     {
990*35238bceSAndroid Build Coastguard Worker         log.writeMessage("// Vertex stage program:");
991*35238bceSAndroid Build Coastguard Worker         vtxProg.writeToLog(log);
992*35238bceSAndroid Build Coastguard Worker         log.writeMessage("// Fragment stage program:");
993*35238bceSAndroid Build Coastguard Worker         frgProg.writeToLog(log);
994*35238bceSAndroid Build Coastguard Worker     }
995*35238bceSAndroid Build Coastguard Worker }
996*35238bceSAndroid Build Coastguard Worker 
997*35238bceSAndroid Build Coastguard Worker // Rectangle
998*35238bceSAndroid Build Coastguard Worker 
999*35238bceSAndroid Build Coastguard Worker struct Rectangle
1000*35238bceSAndroid Build Coastguard Worker {
Rectangledeqp::gles31::Functional::__anonf652bf1a0111::Rectangle1001*35238bceSAndroid Build Coastguard Worker     Rectangle(int x_, int y_, int width_, int height_) : x(x_), y(y_), width(width_), height(height_)
1002*35238bceSAndroid Build Coastguard Worker     {
1003*35238bceSAndroid Build Coastguard Worker     }
1004*35238bceSAndroid Build Coastguard Worker     int x;
1005*35238bceSAndroid Build Coastguard Worker     int y;
1006*35238bceSAndroid Build Coastguard Worker     int width;
1007*35238bceSAndroid Build Coastguard Worker     int height;
1008*35238bceSAndroid Build Coastguard Worker };
1009*35238bceSAndroid Build Coastguard Worker 
setViewport(const RenderContext & renderCtx,const Rectangle & rect)1010*35238bceSAndroid Build Coastguard Worker void setViewport(const RenderContext &renderCtx, const Rectangle &rect)
1011*35238bceSAndroid Build Coastguard Worker {
1012*35238bceSAndroid Build Coastguard Worker     renderCtx.getFunctions().viewport(rect.x, rect.y, rect.width, rect.height);
1013*35238bceSAndroid Build Coastguard Worker }
1014*35238bceSAndroid Build Coastguard Worker 
readRectangle(const RenderContext & renderCtx,const Rectangle & rect,Surface & dst)1015*35238bceSAndroid Build Coastguard Worker void readRectangle(const RenderContext &renderCtx, const Rectangle &rect, Surface &dst)
1016*35238bceSAndroid Build Coastguard Worker {
1017*35238bceSAndroid Build Coastguard Worker     dst.setSize(rect.width, rect.height);
1018*35238bceSAndroid Build Coastguard Worker     glu::readPixels(renderCtx, rect.x, rect.y, dst.getAccess());
1019*35238bceSAndroid Build Coastguard Worker }
1020*35238bceSAndroid Build Coastguard Worker 
randomViewport(const RenderContext & ctx,Random & rnd,GLint maxWidth,GLint maxHeight)1021*35238bceSAndroid Build Coastguard Worker Rectangle randomViewport(const RenderContext &ctx, Random &rnd, GLint maxWidth, GLint maxHeight)
1022*35238bceSAndroid Build Coastguard Worker {
1023*35238bceSAndroid Build Coastguard Worker     const RenderTarget &target = ctx.getRenderTarget();
1024*35238bceSAndroid Build Coastguard Worker     GLint width                = de::min(target.getWidth(), maxWidth);
1025*35238bceSAndroid Build Coastguard Worker     GLint xOff                 = rnd.getInt(0, target.getWidth() - width);
1026*35238bceSAndroid Build Coastguard Worker     GLint height               = de::min(target.getHeight(), maxHeight);
1027*35238bceSAndroid Build Coastguard Worker     GLint yOff                 = rnd.getInt(0, target.getHeight() - height);
1028*35238bceSAndroid Build Coastguard Worker 
1029*35238bceSAndroid Build Coastguard Worker     return Rectangle(xOff, yOff, width, height);
1030*35238bceSAndroid Build Coastguard Worker }
1031*35238bceSAndroid Build Coastguard Worker 
1032*35238bceSAndroid Build Coastguard Worker // SeparateShaderTest
1033*35238bceSAndroid Build Coastguard Worker 
1034*35238bceSAndroid Build Coastguard Worker class SeparateShaderTest : public TestCase, private CallLogWrapper
1035*35238bceSAndroid Build Coastguard Worker {
1036*35238bceSAndroid Build Coastguard Worker public:
1037*35238bceSAndroid Build Coastguard Worker     typedef void (SeparateShaderTest::*TestFunc)(MovePtr<Pipeline> &pipeOut);
1038*35238bceSAndroid Build Coastguard Worker 
1039*35238bceSAndroid Build Coastguard Worker     SeparateShaderTest(Context &ctx, const string &name, const string &description, int iterations,
1040*35238bceSAndroid Build Coastguard Worker                        const TestParams &params, TestFunc testFunc);
1041*35238bceSAndroid Build Coastguard Worker 
1042*35238bceSAndroid Build Coastguard Worker     IterateResult iterate(void);
1043*35238bceSAndroid Build Coastguard Worker 
1044*35238bceSAndroid Build Coastguard Worker     void testPipelineRendering(MovePtr<Pipeline> &pipeOut);
1045*35238bceSAndroid Build Coastguard Worker     void testCurrentProgPriority(MovePtr<Pipeline> &pipeOut);
1046*35238bceSAndroid Build Coastguard Worker     void testActiveProgramUniform(MovePtr<Pipeline> &pipeOut);
1047*35238bceSAndroid Build Coastguard Worker     void testPipelineQueryActive(MovePtr<Pipeline> &pipeOut);
1048*35238bceSAndroid Build Coastguard Worker     void testPipelineQueryPrograms(MovePtr<Pipeline> &pipeOut);
1049*35238bceSAndroid Build Coastguard Worker 
1050*35238bceSAndroid Build Coastguard Worker private:
1051*35238bceSAndroid Build Coastguard Worker     TestLog &log(void);
1052*35238bceSAndroid Build Coastguard Worker     const RenderContext &getRenderContext(void);
1053*35238bceSAndroid Build Coastguard Worker 
1054*35238bceSAndroid Build Coastguard Worker     void setUniform(ProgramWrapper &program, const string &uniformName, GLfloat value, bool useProgramUni);
1055*35238bceSAndroid Build Coastguard Worker 
1056*35238bceSAndroid Build Coastguard Worker     void drawSurface(Surface &dst, uint32_t seed = 0);
1057*35238bceSAndroid Build Coastguard Worker 
1058*35238bceSAndroid Build Coastguard Worker     MovePtr<ProgramWrapper> createShaderProgram(const string *vtxSource, const string *frgSource, bool separable);
1059*35238bceSAndroid Build Coastguard Worker 
1060*35238bceSAndroid Build Coastguard Worker     MovePtr<ProgramWrapper> createSingleShaderProgram(ShaderType shaderType, const string &src);
1061*35238bceSAndroid Build Coastguard Worker 
1062*35238bceSAndroid Build Coastguard Worker     MovePtr<Pipeline> createPipeline(const ProgramParams &pp);
1063*35238bceSAndroid Build Coastguard Worker 
1064*35238bceSAndroid Build Coastguard Worker     MovePtr<ProgramWrapper> createReferenceProgram(const ProgramParams &pp);
1065*35238bceSAndroid Build Coastguard Worker 
1066*35238bceSAndroid Build Coastguard Worker     int m_iterations;
1067*35238bceSAndroid Build Coastguard Worker     int m_currentIteration;
1068*35238bceSAndroid Build Coastguard Worker     TestParams m_params;
1069*35238bceSAndroid Build Coastguard Worker     TestFunc m_testFunc;
1070*35238bceSAndroid Build Coastguard Worker     Random m_rnd;
1071*35238bceSAndroid Build Coastguard Worker     ResultCollector m_status;
1072*35238bceSAndroid Build Coastguard Worker     VaryingInterface m_varyings;
1073*35238bceSAndroid Build Coastguard Worker 
1074*35238bceSAndroid Build Coastguard Worker     // Per-iteration state required for logging on exception
1075*35238bceSAndroid Build Coastguard Worker     MovePtr<ProgramWrapper> m_fullProg;
1076*35238bceSAndroid Build Coastguard Worker     MovePtr<ProgramWrapper> m_vtxProg;
1077*35238bceSAndroid Build Coastguard Worker     MovePtr<ProgramWrapper> m_frgProg;
1078*35238bceSAndroid Build Coastguard Worker };
1079*35238bceSAndroid Build Coastguard Worker 
getRenderContext(void)1080*35238bceSAndroid Build Coastguard Worker const RenderContext &SeparateShaderTest::getRenderContext(void)
1081*35238bceSAndroid Build Coastguard Worker {
1082*35238bceSAndroid Build Coastguard Worker     return m_context.getRenderContext();
1083*35238bceSAndroid Build Coastguard Worker }
1084*35238bceSAndroid Build Coastguard Worker 
log(void)1085*35238bceSAndroid Build Coastguard Worker TestLog &SeparateShaderTest::log(void)
1086*35238bceSAndroid Build Coastguard Worker {
1087*35238bceSAndroid Build Coastguard Worker     return m_testCtx.getLog();
1088*35238bceSAndroid Build Coastguard Worker }
1089*35238bceSAndroid Build Coastguard Worker 
SeparateShaderTest(Context & ctx,const string & name,const string & description,int iterations,const TestParams & params,TestFunc testFunc)1090*35238bceSAndroid Build Coastguard Worker SeparateShaderTest::SeparateShaderTest(Context &ctx, const string &name, const string &description, int iterations,
1091*35238bceSAndroid Build Coastguard Worker                                        const TestParams &params, TestFunc testFunc)
1092*35238bceSAndroid Build Coastguard Worker     : TestCase(ctx, name.c_str(), description.c_str())
1093*35238bceSAndroid Build Coastguard Worker     , CallLogWrapper(ctx.getRenderContext().getFunctions(), log())
1094*35238bceSAndroid Build Coastguard Worker     , m_iterations(iterations)
1095*35238bceSAndroid Build Coastguard Worker     , m_currentIteration(0)
1096*35238bceSAndroid Build Coastguard Worker     , m_params(params)
1097*35238bceSAndroid Build Coastguard Worker     , m_testFunc(testFunc)
1098*35238bceSAndroid Build Coastguard Worker     , m_rnd(paramsSeed(params))
1099*35238bceSAndroid Build Coastguard Worker     , m_status(log(), "// ")
1100*35238bceSAndroid Build Coastguard Worker     , m_varyings(genVaryingInterface(params.varyings, m_rnd))
1101*35238bceSAndroid Build Coastguard Worker {
1102*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(paramsValid(params));
1103*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(varyingsValid(m_varyings));
1104*35238bceSAndroid Build Coastguard Worker }
1105*35238bceSAndroid Build Coastguard Worker 
createShaderProgram(const string * vtxSource,const string * frgSource,bool separable)1106*35238bceSAndroid Build Coastguard Worker MovePtr<ProgramWrapper> SeparateShaderTest::createShaderProgram(const string *vtxSource, const string *frgSource,
1107*35238bceSAndroid Build Coastguard Worker                                                                 bool separable)
1108*35238bceSAndroid Build Coastguard Worker {
1109*35238bceSAndroid Build Coastguard Worker     ProgramSources sources;
1110*35238bceSAndroid Build Coastguard Worker 
1111*35238bceSAndroid Build Coastguard Worker     if (vtxSource != DE_NULL)
1112*35238bceSAndroid Build Coastguard Worker         sources << VertexSource(*vtxSource);
1113*35238bceSAndroid Build Coastguard Worker     if (frgSource != DE_NULL)
1114*35238bceSAndroid Build Coastguard Worker         sources << FragmentSource(*frgSource);
1115*35238bceSAndroid Build Coastguard Worker     sources << ProgramSeparable(separable);
1116*35238bceSAndroid Build Coastguard Worker 
1117*35238bceSAndroid Build Coastguard Worker     MovePtr<ShaderProgramWrapper> wrapper(new ShaderProgramWrapper(getRenderContext(), sources));
1118*35238bceSAndroid Build Coastguard Worker     if (!wrapper->getShaderProgram().isOk())
1119*35238bceSAndroid Build Coastguard Worker     {
1120*35238bceSAndroid Build Coastguard Worker         log().writeMessage("Couldn't create shader program");
1121*35238bceSAndroid Build Coastguard Worker         wrapper->writeToLog(log());
1122*35238bceSAndroid Build Coastguard Worker         TCU_FAIL("Couldn't create shader program");
1123*35238bceSAndroid Build Coastguard Worker     }
1124*35238bceSAndroid Build Coastguard Worker 
1125*35238bceSAndroid Build Coastguard Worker     return MovePtr<ProgramWrapper>(wrapper.release());
1126*35238bceSAndroid Build Coastguard Worker }
1127*35238bceSAndroid Build Coastguard Worker 
createSingleShaderProgram(ShaderType shaderType,const string & src)1128*35238bceSAndroid Build Coastguard Worker MovePtr<ProgramWrapper> SeparateShaderTest::createSingleShaderProgram(ShaderType shaderType, const string &src)
1129*35238bceSAndroid Build Coastguard Worker {
1130*35238bceSAndroid Build Coastguard Worker     const RenderContext &renderCtx = getRenderContext();
1131*35238bceSAndroid Build Coastguard Worker 
1132*35238bceSAndroid Build Coastguard Worker     if (m_params.useCreateHelper)
1133*35238bceSAndroid Build Coastguard Worker     {
1134*35238bceSAndroid Build Coastguard Worker         const char *const srcStr = src.c_str();
1135*35238bceSAndroid Build Coastguard Worker         const GLenum glType      = glu::getGLShaderType(shaderType);
1136*35238bceSAndroid Build Coastguard Worker         const GLuint programName = glCreateShaderProgramv(glType, 1, &srcStr);
1137*35238bceSAndroid Build Coastguard Worker 
1138*35238bceSAndroid Build Coastguard Worker         if (glGetError() != GL_NO_ERROR || programName == 0)
1139*35238bceSAndroid Build Coastguard Worker         {
1140*35238bceSAndroid Build Coastguard Worker             qpShaderType qpType = glu::getLogShaderType(shaderType);
1141*35238bceSAndroid Build Coastguard Worker 
1142*35238bceSAndroid Build Coastguard Worker             log() << TestLog::Message << "glCreateShaderProgramv() failed" << TestLog::EndMessage
1143*35238bceSAndroid Build Coastguard Worker                   << TestLog::ShaderProgram(false, "[glCreateShaderProgramv() failed]")
1144*35238bceSAndroid Build Coastguard Worker                   << TestLog::Shader(qpType, src, false, "[glCreateShaderProgramv() failed]")
1145*35238bceSAndroid Build Coastguard Worker                   << TestLog::EndShaderProgram;
1146*35238bceSAndroid Build Coastguard Worker             TCU_FAIL("glCreateShaderProgramv() failed");
1147*35238bceSAndroid Build Coastguard Worker         }
1148*35238bceSAndroid Build Coastguard Worker 
1149*35238bceSAndroid Build Coastguard Worker         RawProgramWrapper *const wrapper = new RawProgramWrapper(renderCtx, programName, shaderType, src);
1150*35238bceSAndroid Build Coastguard Worker         MovePtr<ProgramWrapper> wrapperPtr(wrapper);
1151*35238bceSAndroid Build Coastguard Worker         Program &program = wrapper->getProgram();
1152*35238bceSAndroid Build Coastguard Worker 
1153*35238bceSAndroid Build Coastguard Worker         if (!program.getLinkStatus())
1154*35238bceSAndroid Build Coastguard Worker         {
1155*35238bceSAndroid Build Coastguard Worker             log().writeMessage("glCreateShaderProgramv() failed at linking");
1156*35238bceSAndroid Build Coastguard Worker             wrapper->writeToLog(log());
1157*35238bceSAndroid Build Coastguard Worker             TCU_FAIL("glCreateShaderProgram() failed at linking");
1158*35238bceSAndroid Build Coastguard Worker         }
1159*35238bceSAndroid Build Coastguard Worker         return wrapperPtr;
1160*35238bceSAndroid Build Coastguard Worker     }
1161*35238bceSAndroid Build Coastguard Worker     else
1162*35238bceSAndroid Build Coastguard Worker     {
1163*35238bceSAndroid Build Coastguard Worker         switch (shaderType)
1164*35238bceSAndroid Build Coastguard Worker         {
1165*35238bceSAndroid Build Coastguard Worker         case glu::SHADERTYPE_VERTEX:
1166*35238bceSAndroid Build Coastguard Worker             return createShaderProgram(&src, DE_NULL, true);
1167*35238bceSAndroid Build Coastguard Worker         case glu::SHADERTYPE_FRAGMENT:
1168*35238bceSAndroid Build Coastguard Worker             return createShaderProgram(DE_NULL, &src, true);
1169*35238bceSAndroid Build Coastguard Worker         default:
1170*35238bceSAndroid Build Coastguard Worker             DE_FATAL("Impossible case");
1171*35238bceSAndroid Build Coastguard Worker         }
1172*35238bceSAndroid Build Coastguard Worker     }
1173*35238bceSAndroid Build Coastguard Worker     return MovePtr<ProgramWrapper>(); // Shut up compiler warnings.
1174*35238bceSAndroid Build Coastguard Worker }
1175*35238bceSAndroid Build Coastguard Worker 
setUniform(ProgramWrapper & program,const string & uniformName,GLfloat value,bool useProgramUniform)1176*35238bceSAndroid Build Coastguard Worker void SeparateShaderTest::setUniform(ProgramWrapper &program, const string &uniformName, GLfloat value,
1177*35238bceSAndroid Build Coastguard Worker                                     bool useProgramUniform)
1178*35238bceSAndroid Build Coastguard Worker {
1179*35238bceSAndroid Build Coastguard Worker     const GLuint progName = program.getProgramName();
1180*35238bceSAndroid Build Coastguard Worker     const GLint location  = glGetUniformLocation(progName, uniformName.c_str());
1181*35238bceSAndroid Build Coastguard Worker     MessageBuilder msg    = log().message();
1182*35238bceSAndroid Build Coastguard Worker 
1183*35238bceSAndroid Build Coastguard Worker     msg << "// Set program " << progName << "'s uniform '" << uniformName << "' to " << value;
1184*35238bceSAndroid Build Coastguard Worker     if (useProgramUniform)
1185*35238bceSAndroid Build Coastguard Worker     {
1186*35238bceSAndroid Build Coastguard Worker         msg << " using glProgramUniform1f";
1187*35238bceSAndroid Build Coastguard Worker         glProgramUniform1f(progName, location, value);
1188*35238bceSAndroid Build Coastguard Worker     }
1189*35238bceSAndroid Build Coastguard Worker     else
1190*35238bceSAndroid Build Coastguard Worker     {
1191*35238bceSAndroid Build Coastguard Worker         msg << " using glUseProgram and glUniform1f";
1192*35238bceSAndroid Build Coastguard Worker         glUseProgram(progName);
1193*35238bceSAndroid Build Coastguard Worker         glUniform1f(location, value);
1194*35238bceSAndroid Build Coastguard Worker         glUseProgram(0);
1195*35238bceSAndroid Build Coastguard Worker     }
1196*35238bceSAndroid Build Coastguard Worker     msg << TestLog::EndMessage;
1197*35238bceSAndroid Build Coastguard Worker }
1198*35238bceSAndroid Build Coastguard Worker 
createPipeline(const ProgramParams & pp)1199*35238bceSAndroid Build Coastguard Worker MovePtr<Pipeline> SeparateShaderTest::createPipeline(const ProgramParams &pp)
1200*35238bceSAndroid Build Coastguard Worker {
1201*35238bceSAndroid Build Coastguard Worker     const bool useUniform      = m_params.useUniform;
1202*35238bceSAndroid Build Coastguard Worker     const string vtxName       = m_params.useSameName ? "scale" : "vtxScale";
1203*35238bceSAndroid Build Coastguard Worker     const uint32_t initVtxSeed = m_params.switchVtx ? m_rnd.getUint32() : pp.vtxSeed;
1204*35238bceSAndroid Build Coastguard Worker 
1205*35238bceSAndroid Build Coastguard Worker     const string frgName       = m_params.useSameName ? "scale" : "frgScale";
1206*35238bceSAndroid Build Coastguard Worker     const uint32_t initFrgSeed = m_params.switchFrg ? m_rnd.getUint32() : pp.frgSeed;
1207*35238bceSAndroid Build Coastguard Worker     const string frgSource     = genFrgShaderSrc(initFrgSeed, m_varyings.frgInputs, frgName, useUniform, pp.frgScale);
1208*35238bceSAndroid Build Coastguard Worker 
1209*35238bceSAndroid Build Coastguard Worker     const RenderContext &renderCtx = getRenderContext();
1210*35238bceSAndroid Build Coastguard Worker     MovePtr<ProgramPipeline> pipeline(new ProgramPipeline(renderCtx));
1211*35238bceSAndroid Build Coastguard Worker     MovePtr<ProgramWrapper> fullProg;
1212*35238bceSAndroid Build Coastguard Worker     MovePtr<ProgramWrapper> vtxProg;
1213*35238bceSAndroid Build Coastguard Worker     MovePtr<ProgramWrapper> frgProg;
1214*35238bceSAndroid Build Coastguard Worker 
1215*35238bceSAndroid Build Coastguard Worker     // We cannot allow a situation where we have a single program with a
1216*35238bceSAndroid Build Coastguard Worker     // single uniform, because then the vertex and fragment shader uniforms
1217*35238bceSAndroid Build Coastguard Worker     // would not be distinct in the final pipeline, and we are going to test
1218*35238bceSAndroid Build Coastguard Worker     // that altering one uniform will not affect the other.
1219*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!(m_params.initSingle && m_params.useSameName && !m_params.switchVtx && !m_params.switchFrg));
1220*35238bceSAndroid Build Coastguard Worker 
1221*35238bceSAndroid Build Coastguard Worker     if (m_params.initSingle)
1222*35238bceSAndroid Build Coastguard Worker     {
1223*35238bceSAndroid Build Coastguard Worker         string vtxSource =
1224*35238bceSAndroid Build Coastguard Worker             genVtxShaderSrc(initVtxSeed, varyingCompatVtxOutputs(m_varyings), vtxName, useUniform, pp.vtxScale);
1225*35238bceSAndroid Build Coastguard Worker         fullProg = createShaderProgram(&vtxSource, &frgSource, true);
1226*35238bceSAndroid Build Coastguard Worker         pipeline->useProgramStages(GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, fullProg->getProgramName());
1227*35238bceSAndroid Build Coastguard Worker         log() << TestLog::Message << "// Created pipeline " << pipeline->getPipeline() << " with two-shader program "
1228*35238bceSAndroid Build Coastguard Worker               << fullProg->getProgramName() << TestLog::EndMessage;
1229*35238bceSAndroid Build Coastguard Worker     }
1230*35238bceSAndroid Build Coastguard Worker     else
1231*35238bceSAndroid Build Coastguard Worker     {
1232*35238bceSAndroid Build Coastguard Worker         string vtxSource = genVtxShaderSrc(initVtxSeed, m_varyings.vtxOutputs, vtxName, useUniform, pp.vtxScale);
1233*35238bceSAndroid Build Coastguard Worker         vtxProg          = createSingleShaderProgram(glu::SHADERTYPE_VERTEX, vtxSource);
1234*35238bceSAndroid Build Coastguard Worker         pipeline->useProgramStages(GL_VERTEX_SHADER_BIT, vtxProg->getProgramName());
1235*35238bceSAndroid Build Coastguard Worker 
1236*35238bceSAndroid Build Coastguard Worker         frgProg = createSingleShaderProgram(glu::SHADERTYPE_FRAGMENT, frgSource);
1237*35238bceSAndroid Build Coastguard Worker         pipeline->useProgramStages(GL_FRAGMENT_SHADER_BIT, frgProg->getProgramName());
1238*35238bceSAndroid Build Coastguard Worker 
1239*35238bceSAndroid Build Coastguard Worker         log() << TestLog::Message << "// Created pipeline " << pipeline->getPipeline() << " with vertex program "
1240*35238bceSAndroid Build Coastguard Worker               << vtxProg->getProgramName() << " and fragment program " << frgProg->getProgramName()
1241*35238bceSAndroid Build Coastguard Worker               << TestLog::EndMessage;
1242*35238bceSAndroid Build Coastguard Worker     }
1243*35238bceSAndroid Build Coastguard Worker 
1244*35238bceSAndroid Build Coastguard Worker     m_status.check(pipeline->isValid(), "Pipeline is invalid after initialization");
1245*35238bceSAndroid Build Coastguard Worker 
1246*35238bceSAndroid Build Coastguard Worker     if (m_params.switchVtx)
1247*35238bceSAndroid Build Coastguard Worker     {
1248*35238bceSAndroid Build Coastguard Worker         string newSource = genVtxShaderSrc(pp.vtxSeed, m_varyings.vtxOutputs, vtxName, useUniform, pp.vtxScale);
1249*35238bceSAndroid Build Coastguard Worker         vtxProg          = createSingleShaderProgram(glu::SHADERTYPE_VERTEX, newSource);
1250*35238bceSAndroid Build Coastguard Worker         pipeline->useProgramStages(GL_VERTEX_SHADER_BIT, vtxProg->getProgramName());
1251*35238bceSAndroid Build Coastguard Worker         log() << TestLog::Message << "// Switched pipeline " << pipeline->getPipeline()
1252*35238bceSAndroid Build Coastguard Worker               << "'s vertex stage to single-shader program " << vtxProg->getProgramName() << TestLog::EndMessage;
1253*35238bceSAndroid Build Coastguard Worker     }
1254*35238bceSAndroid Build Coastguard Worker     if (m_params.switchFrg)
1255*35238bceSAndroid Build Coastguard Worker     {
1256*35238bceSAndroid Build Coastguard Worker         string newSource = genFrgShaderSrc(pp.frgSeed, m_varyings.frgInputs, frgName, useUniform, pp.frgScale);
1257*35238bceSAndroid Build Coastguard Worker         frgProg          = createSingleShaderProgram(glu::SHADERTYPE_FRAGMENT, newSource);
1258*35238bceSAndroid Build Coastguard Worker         pipeline->useProgramStages(GL_FRAGMENT_SHADER_BIT, frgProg->getProgramName());
1259*35238bceSAndroid Build Coastguard Worker         log() << TestLog::Message << "// Switched pipeline " << pipeline->getPipeline()
1260*35238bceSAndroid Build Coastguard Worker               << "'s fragment stage to single-shader program " << frgProg->getProgramName() << TestLog::EndMessage;
1261*35238bceSAndroid Build Coastguard Worker     }
1262*35238bceSAndroid Build Coastguard Worker 
1263*35238bceSAndroid Build Coastguard Worker     if (m_params.switchVtx || m_params.switchFrg)
1264*35238bceSAndroid Build Coastguard Worker         m_status.check(pipeline->isValid(), "Pipeline became invalid after changing a stage's program");
1265*35238bceSAndroid Build Coastguard Worker 
1266*35238bceSAndroid Build Coastguard Worker     if (m_params.useUniform)
1267*35238bceSAndroid Build Coastguard Worker     {
1268*35238bceSAndroid Build Coastguard Worker         ProgramWrapper &vtxStage = *(vtxProg ? vtxProg : fullProg);
1269*35238bceSAndroid Build Coastguard Worker         ProgramWrapper &frgStage = *(frgProg ? frgProg : fullProg);
1270*35238bceSAndroid Build Coastguard Worker 
1271*35238bceSAndroid Build Coastguard Worker         setUniform(vtxStage, vtxName, pp.vtxScale, m_params.useProgramUniform);
1272*35238bceSAndroid Build Coastguard Worker         setUniform(frgStage, frgName, pp.frgScale, m_params.useProgramUniform);
1273*35238bceSAndroid Build Coastguard Worker     }
1274*35238bceSAndroid Build Coastguard Worker     else
1275*35238bceSAndroid Build Coastguard Worker         log().writeMessage("// Programs use constants instead of uniforms");
1276*35238bceSAndroid Build Coastguard Worker 
1277*35238bceSAndroid Build Coastguard Worker     return MovePtr<Pipeline>(new Pipeline(pipeline, fullProg, vtxProg, frgProg));
1278*35238bceSAndroid Build Coastguard Worker }
1279*35238bceSAndroid Build Coastguard Worker 
createReferenceProgram(const ProgramParams & pp)1280*35238bceSAndroid Build Coastguard Worker MovePtr<ProgramWrapper> SeparateShaderTest::createReferenceProgram(const ProgramParams &pp)
1281*35238bceSAndroid Build Coastguard Worker {
1282*35238bceSAndroid Build Coastguard Worker     bool useUniform = m_params.useUniform;
1283*35238bceSAndroid Build Coastguard Worker     const string vtxSrc =
1284*35238bceSAndroid Build Coastguard Worker         genVtxShaderSrc(pp.vtxSeed, varyingCompatVtxOutputs(m_varyings), "vtxScale", useUniform, pp.vtxScale);
1285*35238bceSAndroid Build Coastguard Worker     const string frgSrc = genFrgShaderSrc(pp.frgSeed, m_varyings.frgInputs, "frgScale", useUniform, pp.frgScale);
1286*35238bceSAndroid Build Coastguard Worker     MovePtr<ProgramWrapper> program = createShaderProgram(&vtxSrc, &frgSrc, false);
1287*35238bceSAndroid Build Coastguard Worker     GLuint progName                 = program->getProgramName();
1288*35238bceSAndroid Build Coastguard Worker 
1289*35238bceSAndroid Build Coastguard Worker     log() << TestLog::Message << "// Created monolithic shader program " << progName << TestLog::EndMessage;
1290*35238bceSAndroid Build Coastguard Worker 
1291*35238bceSAndroid Build Coastguard Worker     if (useUniform)
1292*35238bceSAndroid Build Coastguard Worker     {
1293*35238bceSAndroid Build Coastguard Worker         setUniform(*program, "vtxScale", pp.vtxScale, false);
1294*35238bceSAndroid Build Coastguard Worker         setUniform(*program, "frgScale", pp.frgScale, false);
1295*35238bceSAndroid Build Coastguard Worker     }
1296*35238bceSAndroid Build Coastguard Worker 
1297*35238bceSAndroid Build Coastguard Worker     return program;
1298*35238bceSAndroid Build Coastguard Worker }
1299*35238bceSAndroid Build Coastguard Worker 
drawSurface(Surface & dst,uint32_t seed)1300*35238bceSAndroid Build Coastguard Worker void SeparateShaderTest::drawSurface(Surface &dst, uint32_t seed)
1301*35238bceSAndroid Build Coastguard Worker {
1302*35238bceSAndroid Build Coastguard Worker     const RenderContext &renderCtx = getRenderContext();
1303*35238bceSAndroid Build Coastguard Worker     Random rnd(seed > 0 ? seed : m_rnd.getUint32());
1304*35238bceSAndroid Build Coastguard Worker     Rectangle viewport = randomViewport(renderCtx, rnd, VIEWPORT_SIZE, VIEWPORT_SIZE);
1305*35238bceSAndroid Build Coastguard Worker     uint32_t vao       = 0;
1306*35238bceSAndroid Build Coastguard Worker 
1307*35238bceSAndroid Build Coastguard Worker     if (!glu::isContextTypeES(renderCtx.getType()))
1308*35238bceSAndroid Build Coastguard Worker     {
1309*35238bceSAndroid Build Coastguard Worker         glGenVertexArrays(1, &vao);
1310*35238bceSAndroid Build Coastguard Worker         glBindVertexArray(vao);
1311*35238bceSAndroid Build Coastguard Worker     }
1312*35238bceSAndroid Build Coastguard Worker 
1313*35238bceSAndroid Build Coastguard Worker     glClearColor(0.125f, 0.25f, 0.5f, 1.f);
1314*35238bceSAndroid Build Coastguard Worker     setViewport(renderCtx, viewport);
1315*35238bceSAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
1316*35238bceSAndroid Build Coastguard Worker     GLU_CHECK_CALL(glDrawArrays(GL_TRIANGLES, 0, 3));
1317*35238bceSAndroid Build Coastguard Worker     readRectangle(renderCtx, viewport, dst);
1318*35238bceSAndroid Build Coastguard Worker     log().writeMessage("// Drew a triangle");
1319*35238bceSAndroid Build Coastguard Worker 
1320*35238bceSAndroid Build Coastguard Worker     if (vao)
1321*35238bceSAndroid Build Coastguard Worker         glDeleteVertexArrays(1, &vao);
1322*35238bceSAndroid Build Coastguard Worker }
1323*35238bceSAndroid Build Coastguard Worker 
testPipelineRendering(MovePtr<Pipeline> & pipeOut)1324*35238bceSAndroid Build Coastguard Worker void SeparateShaderTest::testPipelineRendering(MovePtr<Pipeline> &pipeOut)
1325*35238bceSAndroid Build Coastguard Worker {
1326*35238bceSAndroid Build Coastguard Worker     ProgramParams pp   = genProgramParams(m_rnd);
1327*35238bceSAndroid Build Coastguard Worker     Pipeline &pipeline = *(pipeOut = createPipeline(pp));
1328*35238bceSAndroid Build Coastguard Worker     GLuint pipeName    = pipeline.pipeline->getPipeline();
1329*35238bceSAndroid Build Coastguard Worker     UniquePtr<ProgramWrapper> refProgram(createReferenceProgram(pp));
1330*35238bceSAndroid Build Coastguard Worker     GLuint refProgName = refProgram->getProgramName();
1331*35238bceSAndroid Build Coastguard Worker     Surface refSurface;
1332*35238bceSAndroid Build Coastguard Worker     Surface pipelineSurface;
1333*35238bceSAndroid Build Coastguard Worker     GLuint drawSeed = m_rnd.getUint32();
1334*35238bceSAndroid Build Coastguard Worker 
1335*35238bceSAndroid Build Coastguard Worker     glUseProgram(refProgName);
1336*35238bceSAndroid Build Coastguard Worker     log() << TestLog::Message << "// Use program " << refProgName << TestLog::EndMessage;
1337*35238bceSAndroid Build Coastguard Worker     drawSurface(refSurface, drawSeed);
1338*35238bceSAndroid Build Coastguard Worker     glUseProgram(0);
1339*35238bceSAndroid Build Coastguard Worker 
1340*35238bceSAndroid Build Coastguard Worker     glBindProgramPipeline(pipeName);
1341*35238bceSAndroid Build Coastguard Worker     log() << TestLog::Message << "// Bind pipeline " << pipeName << TestLog::EndMessage;
1342*35238bceSAndroid Build Coastguard Worker     drawSurface(pipelineSurface, drawSeed);
1343*35238bceSAndroid Build Coastguard Worker     glBindProgramPipeline(0);
1344*35238bceSAndroid Build Coastguard Worker 
1345*35238bceSAndroid Build Coastguard Worker     {
1346*35238bceSAndroid Build Coastguard Worker         const bool result = tcu::fuzzyCompare(m_testCtx.getLog(), "Program pipeline result",
1347*35238bceSAndroid Build Coastguard Worker                                               "Result of comparing a program pipeline with a monolithic program",
1348*35238bceSAndroid Build Coastguard Worker                                               refSurface, pipelineSurface, 0.05f, tcu::COMPARE_LOG_RESULT);
1349*35238bceSAndroid Build Coastguard Worker 
1350*35238bceSAndroid Build Coastguard Worker         m_status.check(result, "Pipeline rendering differs from equivalent monolithic program");
1351*35238bceSAndroid Build Coastguard Worker     }
1352*35238bceSAndroid Build Coastguard Worker }
1353*35238bceSAndroid Build Coastguard Worker 
testCurrentProgPriority(MovePtr<Pipeline> & pipeOut)1354*35238bceSAndroid Build Coastguard Worker void SeparateShaderTest::testCurrentProgPriority(MovePtr<Pipeline> &pipeOut)
1355*35238bceSAndroid Build Coastguard Worker {
1356*35238bceSAndroid Build Coastguard Worker     ProgramParams pipePp    = genProgramParams(m_rnd);
1357*35238bceSAndroid Build Coastguard Worker     ProgramParams programPp = genProgramParams(m_rnd);
1358*35238bceSAndroid Build Coastguard Worker     Pipeline &pipeline      = *(pipeOut = createPipeline(pipePp));
1359*35238bceSAndroid Build Coastguard Worker     GLuint pipeName         = pipeline.pipeline->getPipeline();
1360*35238bceSAndroid Build Coastguard Worker     UniquePtr<ProgramWrapper> program(createReferenceProgram(programPp));
1361*35238bceSAndroid Build Coastguard Worker     Surface pipelineSurface;
1362*35238bceSAndroid Build Coastguard Worker     Surface refSurface;
1363*35238bceSAndroid Build Coastguard Worker     Surface resultSurface;
1364*35238bceSAndroid Build Coastguard Worker     uint32_t drawSeed = m_rnd.getUint32();
1365*35238bceSAndroid Build Coastguard Worker 
1366*35238bceSAndroid Build Coastguard Worker     LOG_CALL(glBindProgramPipeline(pipeName));
1367*35238bceSAndroid Build Coastguard Worker     drawSurface(pipelineSurface, drawSeed);
1368*35238bceSAndroid Build Coastguard Worker     LOG_CALL(glBindProgramPipeline(0));
1369*35238bceSAndroid Build Coastguard Worker 
1370*35238bceSAndroid Build Coastguard Worker     LOG_CALL(glUseProgram(program->getProgramName()));
1371*35238bceSAndroid Build Coastguard Worker     drawSurface(refSurface, drawSeed);
1372*35238bceSAndroid Build Coastguard Worker     LOG_CALL(glUseProgram(0));
1373*35238bceSAndroid Build Coastguard Worker 
1374*35238bceSAndroid Build Coastguard Worker     LOG_CALL(glUseProgram(program->getProgramName()));
1375*35238bceSAndroid Build Coastguard Worker     LOG_CALL(glBindProgramPipeline(pipeName));
1376*35238bceSAndroid Build Coastguard Worker     drawSurface(resultSurface, drawSeed);
1377*35238bceSAndroid Build Coastguard Worker     LOG_CALL(glBindProgramPipeline(0));
1378*35238bceSAndroid Build Coastguard Worker     LOG_CALL(glUseProgram(0));
1379*35238bceSAndroid Build Coastguard Worker 
1380*35238bceSAndroid Build Coastguard Worker     bool result = tcu::pixelThresholdCompare(m_testCtx.getLog(), "Active program rendering result",
1381*35238bceSAndroid Build Coastguard Worker                                              "Active program rendering result", refSurface, resultSurface,
1382*35238bceSAndroid Build Coastguard Worker                                              tcu::RGBA(0, 0, 0, 0), tcu::COMPARE_LOG_RESULT);
1383*35238bceSAndroid Build Coastguard Worker 
1384*35238bceSAndroid Build Coastguard Worker     m_status.check(result, "glBindProgramPipeline() affects glUseProgram()");
1385*35238bceSAndroid Build Coastguard Worker     if (!result)
1386*35238bceSAndroid Build Coastguard Worker         log() << TestLog::Image("Pipeline image", "Image produced by pipeline", pipelineSurface);
1387*35238bceSAndroid Build Coastguard Worker }
1388*35238bceSAndroid Build Coastguard Worker 
testActiveProgramUniform(MovePtr<Pipeline> & pipeOut)1389*35238bceSAndroid Build Coastguard Worker void SeparateShaderTest::testActiveProgramUniform(MovePtr<Pipeline> &pipeOut)
1390*35238bceSAndroid Build Coastguard Worker {
1391*35238bceSAndroid Build Coastguard Worker     ProgramParams refPp = genProgramParams(m_rnd);
1392*35238bceSAndroid Build Coastguard Worker     Surface refSurface;
1393*35238bceSAndroid Build Coastguard Worker     Surface resultSurface;
1394*35238bceSAndroid Build Coastguard Worker     uint32_t drawSeed = m_rnd.getUint32();
1395*35238bceSAndroid Build Coastguard Worker 
1396*35238bceSAndroid Build Coastguard Worker     DE_UNREF(pipeOut);
1397*35238bceSAndroid Build Coastguard Worker     {
1398*35238bceSAndroid Build Coastguard Worker         UniquePtr<ProgramWrapper> refProg(createReferenceProgram(refPp));
1399*35238bceSAndroid Build Coastguard Worker         GLuint refProgName = refProg->getProgramName();
1400*35238bceSAndroid Build Coastguard Worker 
1401*35238bceSAndroid Build Coastguard Worker         glUseProgram(refProgName);
1402*35238bceSAndroid Build Coastguard Worker         log() << TestLog::Message << "// Use reference program " << refProgName << TestLog::EndMessage;
1403*35238bceSAndroid Build Coastguard Worker         drawSurface(refSurface, drawSeed);
1404*35238bceSAndroid Build Coastguard Worker         glUseProgram(0);
1405*35238bceSAndroid Build Coastguard Worker     }
1406*35238bceSAndroid Build Coastguard Worker 
1407*35238bceSAndroid Build Coastguard Worker     {
1408*35238bceSAndroid Build Coastguard Worker         ProgramParams changePp = genProgramParams(m_rnd);
1409*35238bceSAndroid Build Coastguard Worker         changePp.vtxSeed       = refPp.vtxSeed;
1410*35238bceSAndroid Build Coastguard Worker         changePp.frgSeed       = refPp.frgSeed;
1411*35238bceSAndroid Build Coastguard Worker         UniquePtr<ProgramWrapper> changeProg(createReferenceProgram(changePp));
1412*35238bceSAndroid Build Coastguard Worker         GLuint changeName = changeProg->getProgramName();
1413*35238bceSAndroid Build Coastguard Worker         ProgramPipeline pipeline(getRenderContext());
1414*35238bceSAndroid Build Coastguard Worker         GLint vtxLoc = glGetUniformLocation(changeName, "vtxScale");
1415*35238bceSAndroid Build Coastguard Worker         GLint frgLoc = glGetUniformLocation(changeName, "frgScale");
1416*35238bceSAndroid Build Coastguard Worker 
1417*35238bceSAndroid Build Coastguard Worker         LOG_CALL(glBindProgramPipeline(pipeline.getPipeline()));
1418*35238bceSAndroid Build Coastguard Worker 
1419*35238bceSAndroid Build Coastguard Worker         pipeline.activeShaderProgram(changeName);
1420*35238bceSAndroid Build Coastguard Worker         log() << TestLog::Message << "// Set active shader program to " << changeName << TestLog::EndMessage;
1421*35238bceSAndroid Build Coastguard Worker 
1422*35238bceSAndroid Build Coastguard Worker         glUniform1f(vtxLoc, refPp.vtxScale);
1423*35238bceSAndroid Build Coastguard Worker         log() << TestLog::Message << "// Set uniform 'vtxScale' to " << refPp.vtxScale << " using glUniform1f"
1424*35238bceSAndroid Build Coastguard Worker               << TestLog::EndMessage;
1425*35238bceSAndroid Build Coastguard Worker         glUniform1f(frgLoc, refPp.frgScale);
1426*35238bceSAndroid Build Coastguard Worker         log() << TestLog::Message << "// Set uniform 'frgScale' to " << refPp.frgScale << " using glUniform1f"
1427*35238bceSAndroid Build Coastguard Worker               << TestLog::EndMessage;
1428*35238bceSAndroid Build Coastguard Worker 
1429*35238bceSAndroid Build Coastguard Worker         pipeline.activeShaderProgram(0);
1430*35238bceSAndroid Build Coastguard Worker         LOG_CALL(glBindProgramPipeline(0));
1431*35238bceSAndroid Build Coastguard Worker 
1432*35238bceSAndroid Build Coastguard Worker         LOG_CALL(glUseProgram(changeName));
1433*35238bceSAndroid Build Coastguard Worker         drawSurface(resultSurface, drawSeed);
1434*35238bceSAndroid Build Coastguard Worker         LOG_CALL(glUseProgram(0));
1435*35238bceSAndroid Build Coastguard Worker     }
1436*35238bceSAndroid Build Coastguard Worker 
1437*35238bceSAndroid Build Coastguard Worker     bool result =
1438*35238bceSAndroid Build Coastguard Worker         tcu::fuzzyCompare(m_testCtx.getLog(), "Active program uniform result", "Active program uniform result",
1439*35238bceSAndroid Build Coastguard Worker                           refSurface, resultSurface, 0.05f, tcu::COMPARE_LOG_RESULT);
1440*35238bceSAndroid Build Coastguard Worker 
1441*35238bceSAndroid Build Coastguard Worker     m_status.check(result, "glUniform() did not correctly modify "
1442*35238bceSAndroid Build Coastguard Worker                            "the active program of the bound pipeline");
1443*35238bceSAndroid Build Coastguard Worker }
1444*35238bceSAndroid Build Coastguard Worker 
testPipelineQueryPrograms(MovePtr<Pipeline> & pipeOut)1445*35238bceSAndroid Build Coastguard Worker void SeparateShaderTest::testPipelineQueryPrograms(MovePtr<Pipeline> &pipeOut)
1446*35238bceSAndroid Build Coastguard Worker {
1447*35238bceSAndroid Build Coastguard Worker     ProgramParams pipePp = genProgramParams(m_rnd);
1448*35238bceSAndroid Build Coastguard Worker     Pipeline &pipeline   = *(pipeOut = createPipeline(pipePp));
1449*35238bceSAndroid Build Coastguard Worker     GLuint pipeName      = pipeline.pipeline->getPipeline();
1450*35238bceSAndroid Build Coastguard Worker     GLint queryVtx       = 0;
1451*35238bceSAndroid Build Coastguard Worker     GLint queryFrg       = 0;
1452*35238bceSAndroid Build Coastguard Worker 
1453*35238bceSAndroid Build Coastguard Worker     LOG_CALL(GLU_CHECK_CALL(glGetProgramPipelineiv(pipeName, GL_VERTEX_SHADER, &queryVtx)));
1454*35238bceSAndroid Build Coastguard Worker     m_status.check(GLuint(queryVtx) == pipeline.getVertexProgram().getProgramName(),
1455*35238bceSAndroid Build Coastguard Worker                    "Program pipeline query reported wrong vertex shader program");
1456*35238bceSAndroid Build Coastguard Worker 
1457*35238bceSAndroid Build Coastguard Worker     LOG_CALL(GLU_CHECK_CALL(glGetProgramPipelineiv(pipeName, GL_FRAGMENT_SHADER, &queryFrg)));
1458*35238bceSAndroid Build Coastguard Worker     m_status.check(GLuint(queryFrg) == pipeline.getFragmentProgram().getProgramName(),
1459*35238bceSAndroid Build Coastguard Worker                    "Program pipeline query reported wrong fragment shader program");
1460*35238bceSAndroid Build Coastguard Worker }
1461*35238bceSAndroid Build Coastguard Worker 
testPipelineQueryActive(MovePtr<Pipeline> & pipeOut)1462*35238bceSAndroid Build Coastguard Worker void SeparateShaderTest::testPipelineQueryActive(MovePtr<Pipeline> &pipeOut)
1463*35238bceSAndroid Build Coastguard Worker {
1464*35238bceSAndroid Build Coastguard Worker     ProgramParams pipePp = genProgramParams(m_rnd);
1465*35238bceSAndroid Build Coastguard Worker     Pipeline &pipeline   = *(pipeOut = createPipeline(pipePp));
1466*35238bceSAndroid Build Coastguard Worker     GLuint pipeName      = pipeline.pipeline->getPipeline();
1467*35238bceSAndroid Build Coastguard Worker     GLuint newActive     = pipeline.getVertexProgram().getProgramName();
1468*35238bceSAndroid Build Coastguard Worker     GLint queryActive    = 0;
1469*35238bceSAndroid Build Coastguard Worker 
1470*35238bceSAndroid Build Coastguard Worker     LOG_CALL(GLU_CHECK_CALL(glGetProgramPipelineiv(pipeName, GL_ACTIVE_PROGRAM, &queryActive)));
1471*35238bceSAndroid Build Coastguard Worker     m_status.check(queryActive == 0, "Program pipeline query reported non-zero initial active program");
1472*35238bceSAndroid Build Coastguard Worker 
1473*35238bceSAndroid Build Coastguard Worker     pipeline.pipeline->activeShaderProgram(newActive);
1474*35238bceSAndroid Build Coastguard Worker     log() << TestLog::Message << "Set pipeline " << pipeName << "'s active shader program to " << newActive
1475*35238bceSAndroid Build Coastguard Worker           << TestLog::EndMessage;
1476*35238bceSAndroid Build Coastguard Worker 
1477*35238bceSAndroid Build Coastguard Worker     LOG_CALL(GLU_CHECK_CALL(glGetProgramPipelineiv(pipeName, GL_ACTIVE_PROGRAM, &queryActive)));
1478*35238bceSAndroid Build Coastguard Worker     m_status.check(GLuint(queryActive) == newActive, "Program pipeline query reported incorrect active program");
1479*35238bceSAndroid Build Coastguard Worker 
1480*35238bceSAndroid Build Coastguard Worker     pipeline.pipeline->activeShaderProgram(0);
1481*35238bceSAndroid Build Coastguard Worker }
1482*35238bceSAndroid Build Coastguard Worker 
iterate(void)1483*35238bceSAndroid Build Coastguard Worker TestCase::IterateResult SeparateShaderTest::iterate(void)
1484*35238bceSAndroid Build Coastguard Worker {
1485*35238bceSAndroid Build Coastguard Worker     MovePtr<Pipeline> pipeline;
1486*35238bceSAndroid Build Coastguard Worker 
1487*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(m_iterations > 0);
1488*35238bceSAndroid Build Coastguard Worker 
1489*35238bceSAndroid Build Coastguard Worker     if (m_currentIteration == 0)
1490*35238bceSAndroid Build Coastguard Worker         logParams(log(), m_params);
1491*35238bceSAndroid Build Coastguard Worker 
1492*35238bceSAndroid Build Coastguard Worker     ++m_currentIteration;
1493*35238bceSAndroid Build Coastguard Worker 
1494*35238bceSAndroid Build Coastguard Worker     try
1495*35238bceSAndroid Build Coastguard Worker     {
1496*35238bceSAndroid Build Coastguard Worker         (this->*m_testFunc)(pipeline);
1497*35238bceSAndroid Build Coastguard Worker         log().writeMessage("");
1498*35238bceSAndroid Build Coastguard Worker     }
1499*35238bceSAndroid Build Coastguard Worker     catch (const tcu::Exception &)
1500*35238bceSAndroid Build Coastguard Worker     {
1501*35238bceSAndroid Build Coastguard Worker         if (pipeline)
1502*35238bceSAndroid Build Coastguard Worker             logPipeline(log(), *pipeline);
1503*35238bceSAndroid Build Coastguard Worker         throw;
1504*35238bceSAndroid Build Coastguard Worker     }
1505*35238bceSAndroid Build Coastguard Worker 
1506*35238bceSAndroid Build Coastguard Worker     if (m_status.getResult() != QP_TEST_RESULT_PASS)
1507*35238bceSAndroid Build Coastguard Worker     {
1508*35238bceSAndroid Build Coastguard Worker         if (pipeline)
1509*35238bceSAndroid Build Coastguard Worker             logPipeline(log(), *pipeline);
1510*35238bceSAndroid Build Coastguard Worker     }
1511*35238bceSAndroid Build Coastguard Worker     else if (m_currentIteration < m_iterations)
1512*35238bceSAndroid Build Coastguard Worker         return CONTINUE;
1513*35238bceSAndroid Build Coastguard Worker 
1514*35238bceSAndroid Build Coastguard Worker     m_status.setTestContextResult(m_testCtx);
1515*35238bceSAndroid Build Coastguard Worker     return STOP;
1516*35238bceSAndroid Build Coastguard Worker }
1517*35238bceSAndroid Build Coastguard Worker 
1518*35238bceSAndroid Build Coastguard Worker // Group construction utilities
1519*35238bceSAndroid Build Coastguard Worker 
1520*35238bceSAndroid Build Coastguard Worker enum ParamFlags
1521*35238bceSAndroid Build Coastguard Worker {
1522*35238bceSAndroid Build Coastguard Worker     PARAMFLAGS_SWITCH_FRAGMENT = 1 << 0,
1523*35238bceSAndroid Build Coastguard Worker     PARAMFLAGS_SWITCH_VERTEX   = 1 << 1,
1524*35238bceSAndroid Build Coastguard Worker     PARAMFLAGS_INIT_SINGLE     = 1 << 2,
1525*35238bceSAndroid Build Coastguard Worker     PARAMFLAGS_LAST            = 1 << 3,
1526*35238bceSAndroid Build Coastguard Worker     PARAMFLAGS_MASK            = PARAMFLAGS_LAST - 1
1527*35238bceSAndroid Build Coastguard Worker };
1528*35238bceSAndroid Build Coastguard Worker 
areCaseParamFlagsValid(ParamFlags flags)1529*35238bceSAndroid Build Coastguard Worker bool areCaseParamFlagsValid(ParamFlags flags)
1530*35238bceSAndroid Build Coastguard Worker {
1531*35238bceSAndroid Build Coastguard Worker     const ParamFlags switchAll = ParamFlags(PARAMFLAGS_SWITCH_VERTEX | PARAMFLAGS_SWITCH_FRAGMENT);
1532*35238bceSAndroid Build Coastguard Worker 
1533*35238bceSAndroid Build Coastguard Worker     if ((flags & PARAMFLAGS_INIT_SINGLE) != 0)
1534*35238bceSAndroid Build Coastguard Worker         return (flags & switchAll) == 0 || (flags & switchAll) == switchAll;
1535*35238bceSAndroid Build Coastguard Worker     else
1536*35238bceSAndroid Build Coastguard Worker         return true;
1537*35238bceSAndroid Build Coastguard Worker }
1538*35238bceSAndroid Build Coastguard Worker 
addRenderTest(TestCaseGroup & group,const string & namePrefix,const string & descPrefix,int numIterations,ParamFlags flags,TestParams params)1539*35238bceSAndroid Build Coastguard Worker bool addRenderTest(TestCaseGroup &group, const string &namePrefix, const string &descPrefix, int numIterations,
1540*35238bceSAndroid Build Coastguard Worker                    ParamFlags flags, TestParams params)
1541*35238bceSAndroid Build Coastguard Worker {
1542*35238bceSAndroid Build Coastguard Worker     ostringstream name;
1543*35238bceSAndroid Build Coastguard Worker     ostringstream desc;
1544*35238bceSAndroid Build Coastguard Worker 
1545*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(areCaseParamFlagsValid(flags));
1546*35238bceSAndroid Build Coastguard Worker 
1547*35238bceSAndroid Build Coastguard Worker     name << namePrefix;
1548*35238bceSAndroid Build Coastguard Worker     desc << descPrefix;
1549*35238bceSAndroid Build Coastguard Worker 
1550*35238bceSAndroid Build Coastguard Worker     params.initSingle = (flags & PARAMFLAGS_INIT_SINGLE) != 0;
1551*35238bceSAndroid Build Coastguard Worker     params.switchVtx  = (flags & PARAMFLAGS_SWITCH_VERTEX) != 0;
1552*35238bceSAndroid Build Coastguard Worker     params.switchFrg  = (flags & PARAMFLAGS_SWITCH_FRAGMENT) != 0;
1553*35238bceSAndroid Build Coastguard Worker 
1554*35238bceSAndroid Build Coastguard Worker     name << (flags & PARAMFLAGS_INIT_SINGLE ? "single_program" : "separate_programs");
1555*35238bceSAndroid Build Coastguard Worker     desc << (flags & PARAMFLAGS_INIT_SINGLE ? "Single program with two shaders" : "Separate programs for each shader");
1556*35238bceSAndroid Build Coastguard Worker 
1557*35238bceSAndroid Build Coastguard Worker     switch (flags & (PARAMFLAGS_SWITCH_FRAGMENT | PARAMFLAGS_SWITCH_VERTEX))
1558*35238bceSAndroid Build Coastguard Worker     {
1559*35238bceSAndroid Build Coastguard Worker     case 0:
1560*35238bceSAndroid Build Coastguard Worker         break;
1561*35238bceSAndroid Build Coastguard Worker     case PARAMFLAGS_SWITCH_FRAGMENT:
1562*35238bceSAndroid Build Coastguard Worker         name << "_add_fragment";
1563*35238bceSAndroid Build Coastguard Worker         desc << ", then add a fragment program";
1564*35238bceSAndroid Build Coastguard Worker         break;
1565*35238bceSAndroid Build Coastguard Worker     case PARAMFLAGS_SWITCH_VERTEX:
1566*35238bceSAndroid Build Coastguard Worker         name << "_add_vertex";
1567*35238bceSAndroid Build Coastguard Worker         desc << ", then add a vertex program";
1568*35238bceSAndroid Build Coastguard Worker         break;
1569*35238bceSAndroid Build Coastguard Worker     case PARAMFLAGS_SWITCH_FRAGMENT | PARAMFLAGS_SWITCH_VERTEX:
1570*35238bceSAndroid Build Coastguard Worker         name << "_add_both";
1571*35238bceSAndroid Build Coastguard Worker         desc << ", then add both vertex and shader programs";
1572*35238bceSAndroid Build Coastguard Worker         break;
1573*35238bceSAndroid Build Coastguard Worker     }
1574*35238bceSAndroid Build Coastguard Worker 
1575*35238bceSAndroid Build Coastguard Worker     if (!paramsValid(params))
1576*35238bceSAndroid Build Coastguard Worker         return false;
1577*35238bceSAndroid Build Coastguard Worker 
1578*35238bceSAndroid Build Coastguard Worker     group.addChild(new SeparateShaderTest(group.getContext(), name.str(), desc.str(), numIterations, params,
1579*35238bceSAndroid Build Coastguard Worker                                           &SeparateShaderTest::testPipelineRendering));
1580*35238bceSAndroid Build Coastguard Worker 
1581*35238bceSAndroid Build Coastguard Worker     return true;
1582*35238bceSAndroid Build Coastguard Worker }
1583*35238bceSAndroid Build Coastguard Worker 
describeInterpolation(const string & stage,VaryingInterpolation qual,ostringstream & name,ostringstream & desc)1584*35238bceSAndroid Build Coastguard Worker void describeInterpolation(const string &stage, VaryingInterpolation qual, ostringstream &name, ostringstream &desc)
1585*35238bceSAndroid Build Coastguard Worker {
1586*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(qual < VARYINGINTERPOLATION_RANDOM);
1587*35238bceSAndroid Build Coastguard Worker 
1588*35238bceSAndroid Build Coastguard Worker     if (qual == VARYINGINTERPOLATION_DEFAULT)
1589*35238bceSAndroid Build Coastguard Worker     {
1590*35238bceSAndroid Build Coastguard Worker         desc << ", unqualified in " << stage << " shader";
1591*35238bceSAndroid Build Coastguard Worker         return;
1592*35238bceSAndroid Build Coastguard Worker     }
1593*35238bceSAndroid Build Coastguard Worker     else
1594*35238bceSAndroid Build Coastguard Worker     {
1595*35238bceSAndroid Build Coastguard Worker         const string qualName = glu::getInterpolationName(getGluInterpolation(qual));
1596*35238bceSAndroid Build Coastguard Worker 
1597*35238bceSAndroid Build Coastguard Worker         name << "_" << stage << "_" << qualName;
1598*35238bceSAndroid Build Coastguard Worker         desc << ", qualified '" << qualName << "' in " << stage << " shader";
1599*35238bceSAndroid Build Coastguard Worker     }
1600*35238bceSAndroid Build Coastguard Worker }
1601*35238bceSAndroid Build Coastguard Worker 
1602*35238bceSAndroid Build Coastguard Worker } // namespace
1603*35238bceSAndroid Build Coastguard Worker 
createCommonSeparateShaderTests(Context & ctx)1604*35238bceSAndroid Build Coastguard Worker TestCaseGroup *createCommonSeparateShaderTests(Context &ctx)
1605*35238bceSAndroid Build Coastguard Worker {
1606*35238bceSAndroid Build Coastguard Worker     TestParams defaultParams;
1607*35238bceSAndroid Build Coastguard Worker     int numIterations    = 4;
1608*35238bceSAndroid Build Coastguard Worker     TestCaseGroup *group = new TestCaseGroup(ctx, "separate_shader", "Separate shader tests");
1609*35238bceSAndroid Build Coastguard Worker 
1610*35238bceSAndroid Build Coastguard Worker     defaultParams.useUniform         = false;
1611*35238bceSAndroid Build Coastguard Worker     defaultParams.initSingle         = false;
1612*35238bceSAndroid Build Coastguard Worker     defaultParams.switchVtx          = false;
1613*35238bceSAndroid Build Coastguard Worker     defaultParams.switchFrg          = false;
1614*35238bceSAndroid Build Coastguard Worker     defaultParams.useCreateHelper    = false;
1615*35238bceSAndroid Build Coastguard Worker     defaultParams.useProgramUniform  = false;
1616*35238bceSAndroid Build Coastguard Worker     defaultParams.useSameName        = false;
1617*35238bceSAndroid Build Coastguard Worker     defaultParams.varyings.count     = 0;
1618*35238bceSAndroid Build Coastguard Worker     defaultParams.varyings.type      = glu::TYPE_INVALID;
1619*35238bceSAndroid Build Coastguard Worker     defaultParams.varyings.binding   = BINDING_NAME;
1620*35238bceSAndroid Build Coastguard Worker     defaultParams.varyings.vtxInterp = VARYINGINTERPOLATION_LAST;
1621*35238bceSAndroid Build Coastguard Worker     defaultParams.varyings.frgInterp = VARYINGINTERPOLATION_LAST;
1622*35238bceSAndroid Build Coastguard Worker 
1623*35238bceSAndroid Build Coastguard Worker     TestCaseGroup *stagesGroup = new TestCaseGroup(ctx, "pipeline", "Pipeline configuration tests");
1624*35238bceSAndroid Build Coastguard Worker     group->addChild(stagesGroup);
1625*35238bceSAndroid Build Coastguard Worker 
1626*35238bceSAndroid Build Coastguard Worker     for (uint32_t flags = 0; flags < PARAMFLAGS_LAST << 2; ++flags)
1627*35238bceSAndroid Build Coastguard Worker     {
1628*35238bceSAndroid Build Coastguard Worker         TestParams params = defaultParams;
1629*35238bceSAndroid Build Coastguard Worker         ostringstream name;
1630*35238bceSAndroid Build Coastguard Worker         ostringstream desc;
1631*35238bceSAndroid Build Coastguard Worker 
1632*35238bceSAndroid Build Coastguard Worker         if (!areCaseParamFlagsValid(ParamFlags(flags & PARAMFLAGS_MASK)))
1633*35238bceSAndroid Build Coastguard Worker             continue;
1634*35238bceSAndroid Build Coastguard Worker 
1635*35238bceSAndroid Build Coastguard Worker         if (flags & (PARAMFLAGS_LAST << 1))
1636*35238bceSAndroid Build Coastguard Worker         {
1637*35238bceSAndroid Build Coastguard Worker             params.useSameName = true;
1638*35238bceSAndroid Build Coastguard Worker             name << "same_";
1639*35238bceSAndroid Build Coastguard Worker             desc << "Identically named ";
1640*35238bceSAndroid Build Coastguard Worker         }
1641*35238bceSAndroid Build Coastguard Worker         else
1642*35238bceSAndroid Build Coastguard Worker         {
1643*35238bceSAndroid Build Coastguard Worker             name << "different_";
1644*35238bceSAndroid Build Coastguard Worker             desc << "Differently named ";
1645*35238bceSAndroid Build Coastguard Worker         }
1646*35238bceSAndroid Build Coastguard Worker 
1647*35238bceSAndroid Build Coastguard Worker         if (flags & PARAMFLAGS_LAST)
1648*35238bceSAndroid Build Coastguard Worker         {
1649*35238bceSAndroid Build Coastguard Worker             params.useUniform = true;
1650*35238bceSAndroid Build Coastguard Worker             name << "uniform_";
1651*35238bceSAndroid Build Coastguard Worker             desc << "uniforms, ";
1652*35238bceSAndroid Build Coastguard Worker         }
1653*35238bceSAndroid Build Coastguard Worker         else
1654*35238bceSAndroid Build Coastguard Worker         {
1655*35238bceSAndroid Build Coastguard Worker             name << "constant_";
1656*35238bceSAndroid Build Coastguard Worker             desc << "constants, ";
1657*35238bceSAndroid Build Coastguard Worker         }
1658*35238bceSAndroid Build Coastguard Worker 
1659*35238bceSAndroid Build Coastguard Worker         addRenderTest(*stagesGroup, name.str(), desc.str(), numIterations, ParamFlags(flags & PARAMFLAGS_MASK), params);
1660*35238bceSAndroid Build Coastguard Worker     }
1661*35238bceSAndroid Build Coastguard Worker 
1662*35238bceSAndroid Build Coastguard Worker     TestCaseGroup *programUniformGroup = new TestCaseGroup(ctx, "program_uniform", "ProgramUniform tests");
1663*35238bceSAndroid Build Coastguard Worker     group->addChild(programUniformGroup);
1664*35238bceSAndroid Build Coastguard Worker 
1665*35238bceSAndroid Build Coastguard Worker     for (uint32_t flags = 0; flags < PARAMFLAGS_LAST; ++flags)
1666*35238bceSAndroid Build Coastguard Worker     {
1667*35238bceSAndroid Build Coastguard Worker         TestParams params = defaultParams;
1668*35238bceSAndroid Build Coastguard Worker 
1669*35238bceSAndroid Build Coastguard Worker         if (!areCaseParamFlagsValid(ParamFlags(flags)))
1670*35238bceSAndroid Build Coastguard Worker             continue;
1671*35238bceSAndroid Build Coastguard Worker 
1672*35238bceSAndroid Build Coastguard Worker         params.useUniform        = true;
1673*35238bceSAndroid Build Coastguard Worker         params.useProgramUniform = true;
1674*35238bceSAndroid Build Coastguard Worker 
1675*35238bceSAndroid Build Coastguard Worker         addRenderTest(*programUniformGroup, "", "", numIterations, ParamFlags(flags), params);
1676*35238bceSAndroid Build Coastguard Worker     }
1677*35238bceSAndroid Build Coastguard Worker 
1678*35238bceSAndroid Build Coastguard Worker     TestCaseGroup *createShaderProgramGroup =
1679*35238bceSAndroid Build Coastguard Worker         new TestCaseGroup(ctx, "create_shader_program", "CreateShaderProgram tests");
1680*35238bceSAndroid Build Coastguard Worker     group->addChild(createShaderProgramGroup);
1681*35238bceSAndroid Build Coastguard Worker 
1682*35238bceSAndroid Build Coastguard Worker     for (uint32_t flags = 0; flags < PARAMFLAGS_LAST; ++flags)
1683*35238bceSAndroid Build Coastguard Worker     {
1684*35238bceSAndroid Build Coastguard Worker         TestParams params = defaultParams;
1685*35238bceSAndroid Build Coastguard Worker 
1686*35238bceSAndroid Build Coastguard Worker         if (!areCaseParamFlagsValid(ParamFlags(flags)))
1687*35238bceSAndroid Build Coastguard Worker             continue;
1688*35238bceSAndroid Build Coastguard Worker 
1689*35238bceSAndroid Build Coastguard Worker         params.useCreateHelper = true;
1690*35238bceSAndroid Build Coastguard Worker 
1691*35238bceSAndroid Build Coastguard Worker         addRenderTest(*createShaderProgramGroup, "", "", numIterations, ParamFlags(flags), params);
1692*35238bceSAndroid Build Coastguard Worker     }
1693*35238bceSAndroid Build Coastguard Worker 
1694*35238bceSAndroid Build Coastguard Worker     TestCaseGroup *interfaceGroup = new TestCaseGroup(ctx, "interface", "Shader interface compatibility tests");
1695*35238bceSAndroid Build Coastguard Worker     group->addChild(interfaceGroup);
1696*35238bceSAndroid Build Coastguard Worker 
1697*35238bceSAndroid Build Coastguard Worker     enum
1698*35238bceSAndroid Build Coastguard Worker     {
1699*35238bceSAndroid Build Coastguard Worker         NUM_INTERPOLATIONS =
1700*35238bceSAndroid Build Coastguard Worker             VARYINGINTERPOLATION_RANDOM, // VARYINGINTERPOLATION_RANDOM is one after last fully specified interpolation
1701*35238bceSAndroid Build Coastguard Worker         INTERFACEFLAGS_LAST =
1702*35238bceSAndroid Build Coastguard Worker             static_cast<int>(BINDING_LAST) * static_cast<int>(NUM_INTERPOLATIONS) * static_cast<int>(NUM_INTERPOLATIONS)
1703*35238bceSAndroid Build Coastguard Worker     };
1704*35238bceSAndroid Build Coastguard Worker 
1705*35238bceSAndroid Build Coastguard Worker     for (uint32_t flags = 0; flags < INTERFACEFLAGS_LAST; ++flags)
1706*35238bceSAndroid Build Coastguard Worker     {
1707*35238bceSAndroid Build Coastguard Worker         uint32_t tmpFlags              = flags;
1708*35238bceSAndroid Build Coastguard Worker         VaryingInterpolation frgInterp = VaryingInterpolation(tmpFlags % NUM_INTERPOLATIONS);
1709*35238bceSAndroid Build Coastguard Worker         VaryingInterpolation vtxInterp = VaryingInterpolation((tmpFlags /= NUM_INTERPOLATIONS) % NUM_INTERPOLATIONS);
1710*35238bceSAndroid Build Coastguard Worker         BindingKind binding            = BindingKind((tmpFlags /= NUM_INTERPOLATIONS) % BINDING_LAST);
1711*35238bceSAndroid Build Coastguard Worker         TestParams params              = defaultParams;
1712*35238bceSAndroid Build Coastguard Worker         ostringstream name;
1713*35238bceSAndroid Build Coastguard Worker         ostringstream desc;
1714*35238bceSAndroid Build Coastguard Worker 
1715*35238bceSAndroid Build Coastguard Worker         params.varyings.count     = 1;
1716*35238bceSAndroid Build Coastguard Worker         params.varyings.type      = glu::TYPE_FLOAT;
1717*35238bceSAndroid Build Coastguard Worker         params.varyings.binding   = binding;
1718*35238bceSAndroid Build Coastguard Worker         params.varyings.vtxInterp = vtxInterp;
1719*35238bceSAndroid Build Coastguard Worker         params.varyings.frgInterp = frgInterp;
1720*35238bceSAndroid Build Coastguard Worker 
1721*35238bceSAndroid Build Coastguard Worker         switch (binding)
1722*35238bceSAndroid Build Coastguard Worker         {
1723*35238bceSAndroid Build Coastguard Worker         case BINDING_LOCATION:
1724*35238bceSAndroid Build Coastguard Worker             name << "same_location";
1725*35238bceSAndroid Build Coastguard Worker             desc << "Varyings have same location, ";
1726*35238bceSAndroid Build Coastguard Worker             break;
1727*35238bceSAndroid Build Coastguard Worker         case BINDING_NAME:
1728*35238bceSAndroid Build Coastguard Worker             name << "same_name";
1729*35238bceSAndroid Build Coastguard Worker             desc << "Varyings have same name, ";
1730*35238bceSAndroid Build Coastguard Worker             break;
1731*35238bceSAndroid Build Coastguard Worker         default:
1732*35238bceSAndroid Build Coastguard Worker             DE_FATAL("Impossible");
1733*35238bceSAndroid Build Coastguard Worker         }
1734*35238bceSAndroid Build Coastguard Worker 
1735*35238bceSAndroid Build Coastguard Worker         describeInterpolation("vertex", vtxInterp, name, desc);
1736*35238bceSAndroid Build Coastguard Worker         describeInterpolation("fragment", frgInterp, name, desc);
1737*35238bceSAndroid Build Coastguard Worker 
1738*35238bceSAndroid Build Coastguard Worker         if (!paramsValid(params))
1739*35238bceSAndroid Build Coastguard Worker             continue;
1740*35238bceSAndroid Build Coastguard Worker 
1741*35238bceSAndroid Build Coastguard Worker         interfaceGroup->addChild(new SeparateShaderTest(ctx, name.str(), desc.str(), numIterations, params,
1742*35238bceSAndroid Build Coastguard Worker                                                         &SeparateShaderTest::testPipelineRendering));
1743*35238bceSAndroid Build Coastguard Worker     }
1744*35238bceSAndroid Build Coastguard Worker 
1745*35238bceSAndroid Build Coastguard Worker     uint32_t baseSeed = ctx.getTestContext().getCommandLine().getBaseSeed();
1746*35238bceSAndroid Build Coastguard Worker     Random rnd(deStringHash("separate_shader.random") + baseSeed);
1747*35238bceSAndroid Build Coastguard Worker     set<string> seen;
1748*35238bceSAndroid Build Coastguard Worker     TestCaseGroup *randomGroup = new TestCaseGroup(ctx, "random", "Random pipeline configuration tests");
1749*35238bceSAndroid Build Coastguard Worker     group->addChild(randomGroup);
1750*35238bceSAndroid Build Coastguard Worker 
1751*35238bceSAndroid Build Coastguard Worker     for (uint32_t i = 0; i < 128; ++i)
1752*35238bceSAndroid Build Coastguard Worker     {
1753*35238bceSAndroid Build Coastguard Worker         TestParams params;
1754*35238bceSAndroid Build Coastguard Worker         string code;
1755*35238bceSAndroid Build Coastguard Worker         uint32_t genIterations = 4096;
1756*35238bceSAndroid Build Coastguard Worker 
1757*35238bceSAndroid Build Coastguard Worker         do
1758*35238bceSAndroid Build Coastguard Worker         {
1759*35238bceSAndroid Build Coastguard Worker             params = genParams(rnd.getUint32());
1760*35238bceSAndroid Build Coastguard Worker             code   = paramsCode(params);
1761*35238bceSAndroid Build Coastguard Worker         } while (de::contains(seen, code) && --genIterations > 0);
1762*35238bceSAndroid Build Coastguard Worker 
1763*35238bceSAndroid Build Coastguard Worker         seen.insert(code);
1764*35238bceSAndroid Build Coastguard Worker 
1765*35238bceSAndroid Build Coastguard Worker         string name = de::toString(i); // Would be code but baseSeed can change
1766*35238bceSAndroid Build Coastguard Worker 
1767*35238bceSAndroid Build Coastguard Worker         randomGroup->addChild(
1768*35238bceSAndroid Build Coastguard Worker             new SeparateShaderTest(ctx, name, name, numIterations, params, &SeparateShaderTest::testPipelineRendering));
1769*35238bceSAndroid Build Coastguard Worker     }
1770*35238bceSAndroid Build Coastguard Worker 
1771*35238bceSAndroid Build Coastguard Worker     TestCaseGroup *apiGroup = new TestCaseGroup(ctx, "api", "Program pipeline API tests");
1772*35238bceSAndroid Build Coastguard Worker     group->addChild(apiGroup);
1773*35238bceSAndroid Build Coastguard Worker 
1774*35238bceSAndroid Build Coastguard Worker     {
1775*35238bceSAndroid Build Coastguard Worker         // More or less random parameters. These shouldn't have much effect, so just
1776*35238bceSAndroid Build Coastguard Worker         // do a single sample.
1777*35238bceSAndroid Build Coastguard Worker         TestParams params = defaultParams;
1778*35238bceSAndroid Build Coastguard Worker         params.useUniform = true;
1779*35238bceSAndroid Build Coastguard Worker         apiGroup->addChild(new SeparateShaderTest(ctx, "current_program_priority",
1780*35238bceSAndroid Build Coastguard Worker                                                   "Test priority between current program and pipeline binding", 1,
1781*35238bceSAndroid Build Coastguard Worker                                                   params, &SeparateShaderTest::testCurrentProgPriority));
1782*35238bceSAndroid Build Coastguard Worker         apiGroup->addChild(new SeparateShaderTest(ctx, "active_program_uniform",
1783*35238bceSAndroid Build Coastguard Worker                                                   "Test that glUniform() affects a pipeline's active program", 1,
1784*35238bceSAndroid Build Coastguard Worker                                                   params, &SeparateShaderTest::testActiveProgramUniform));
1785*35238bceSAndroid Build Coastguard Worker 
1786*35238bceSAndroid Build Coastguard Worker         apiGroup->addChild(new SeparateShaderTest(ctx, "pipeline_programs",
1787*35238bceSAndroid Build Coastguard Worker                                                   "Test queries for programs in program pipeline stages", 1, params,
1788*35238bceSAndroid Build Coastguard Worker                                                   &SeparateShaderTest::testPipelineQueryPrograms));
1789*35238bceSAndroid Build Coastguard Worker 
1790*35238bceSAndroid Build Coastguard Worker         apiGroup->addChild(new SeparateShaderTest(ctx, "pipeline_active",
1791*35238bceSAndroid Build Coastguard Worker                                                   "Test query for active programs in a program pipeline", 1, params,
1792*35238bceSAndroid Build Coastguard Worker                                                   &SeparateShaderTest::testPipelineQueryActive));
1793*35238bceSAndroid Build Coastguard Worker     }
1794*35238bceSAndroid Build Coastguard Worker 
1795*35238bceSAndroid Build Coastguard Worker     return group;
1796*35238bceSAndroid Build Coastguard Worker }
1797*35238bceSAndroid Build Coastguard Worker 
createGLESSeparateShaderTests(Context & ctx)1798*35238bceSAndroid Build Coastguard Worker TestCaseGroup *createGLESSeparateShaderTests(Context &ctx)
1799*35238bceSAndroid Build Coastguard Worker {
1800*35238bceSAndroid Build Coastguard Worker     TestCaseGroup *group = createCommonSeparateShaderTests(ctx);
1801*35238bceSAndroid Build Coastguard Worker 
1802*35238bceSAndroid Build Coastguard Worker     TestCaseGroup *interfaceMismatchGroup =
1803*35238bceSAndroid Build Coastguard Worker         new TestCaseGroup(ctx, "validation", "Negative program pipeline interface matching");
1804*35238bceSAndroid Build Coastguard Worker     group->addChild(interfaceMismatchGroup);
1805*35238bceSAndroid Build Coastguard Worker 
1806*35238bceSAndroid Build Coastguard Worker     {
1807*35238bceSAndroid Build Coastguard Worker         TestCaseGroup *es31Group = new TestCaseGroup(ctx, "es31", "GLSL ES 3.1 pipeline interface matching");
1808*35238bceSAndroid Build Coastguard Worker         gls::ShaderLibrary shaderLibrary(ctx.getTestContext(), ctx.getRenderContext(), ctx.getContextInfo());
1809*35238bceSAndroid Build Coastguard Worker         const std::vector<tcu::TestNode *> children =
1810*35238bceSAndroid Build Coastguard Worker             shaderLibrary.loadShaderFile("shaders/es31/separate_shader_validation.test");
1811*35238bceSAndroid Build Coastguard Worker 
1812*35238bceSAndroid Build Coastguard Worker         for (int i = 0; i < (int)children.size(); i++)
1813*35238bceSAndroid Build Coastguard Worker             es31Group->addChild(children[i]);
1814*35238bceSAndroid Build Coastguard Worker 
1815*35238bceSAndroid Build Coastguard Worker         interfaceMismatchGroup->addChild(es31Group);
1816*35238bceSAndroid Build Coastguard Worker     }
1817*35238bceSAndroid Build Coastguard Worker 
1818*35238bceSAndroid Build Coastguard Worker     {
1819*35238bceSAndroid Build Coastguard Worker         TestCaseGroup *es32Group = new TestCaseGroup(ctx, "es32", "GLSL ES 3.2 pipeline interface matching");
1820*35238bceSAndroid Build Coastguard Worker         gls::ShaderLibrary shaderLibrary(ctx.getTestContext(), ctx.getRenderContext(), ctx.getContextInfo());
1821*35238bceSAndroid Build Coastguard Worker         const std::vector<tcu::TestNode *> children =
1822*35238bceSAndroid Build Coastguard Worker             shaderLibrary.loadShaderFile("shaders/es32/separate_shader_validation.test");
1823*35238bceSAndroid Build Coastguard Worker 
1824*35238bceSAndroid Build Coastguard Worker         for (int i = 0; i < (int)children.size(); i++)
1825*35238bceSAndroid Build Coastguard Worker             es32Group->addChild(children[i]);
1826*35238bceSAndroid Build Coastguard Worker 
1827*35238bceSAndroid Build Coastguard Worker         interfaceMismatchGroup->addChild(es32Group);
1828*35238bceSAndroid Build Coastguard Worker     }
1829*35238bceSAndroid Build Coastguard Worker 
1830*35238bceSAndroid Build Coastguard Worker     return group;
1831*35238bceSAndroid Build Coastguard Worker }
1832*35238bceSAndroid Build Coastguard Worker } // namespace Functional
1833*35238bceSAndroid Build Coastguard Worker } // namespace gles31
1834*35238bceSAndroid Build Coastguard Worker } // namespace deqp
1835