xref: /aosp_15_r20/external/deqp/modules/gles3/functional/es3fTransformFeedbackTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program OpenGL ES 3.0 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 Transform feedback tests.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "es3fTransformFeedbackTests.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "tcuTestLog.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "tcuSurface.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "tcuImageCompare.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "tcuVector.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "tcuFormatUtil.hpp"
30*35238bceSAndroid Build Coastguard Worker #include "tcuRenderTarget.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "gluShaderUtil.hpp"
32*35238bceSAndroid Build Coastguard Worker #include "gluVarType.hpp"
33*35238bceSAndroid Build Coastguard Worker #include "gluVarTypeUtil.hpp"
34*35238bceSAndroid Build Coastguard Worker #include "gluPixelTransfer.hpp"
35*35238bceSAndroid Build Coastguard Worker #include "gluRenderContext.hpp"
36*35238bceSAndroid Build Coastguard Worker #include "gluShaderProgram.hpp"
37*35238bceSAndroid Build Coastguard Worker #include "gluObjectWrapper.hpp"
38*35238bceSAndroid Build Coastguard Worker #include "glwFunctions.hpp"
39*35238bceSAndroid Build Coastguard Worker #include "glwEnums.hpp"
40*35238bceSAndroid Build Coastguard Worker #include "deRandom.hpp"
41*35238bceSAndroid Build Coastguard Worker #include "deStringUtil.hpp"
42*35238bceSAndroid Build Coastguard Worker #include "deMemory.h"
43*35238bceSAndroid Build Coastguard Worker #include "deString.h"
44*35238bceSAndroid Build Coastguard Worker 
45*35238bceSAndroid Build Coastguard Worker #include <set>
46*35238bceSAndroid Build Coastguard Worker #include <map>
47*35238bceSAndroid Build Coastguard Worker #include <algorithm>
48*35238bceSAndroid Build Coastguard Worker 
49*35238bceSAndroid Build Coastguard Worker using std::set;
50*35238bceSAndroid Build Coastguard Worker using std::string;
51*35238bceSAndroid Build Coastguard Worker using std::vector;
52*35238bceSAndroid Build Coastguard Worker 
53*35238bceSAndroid Build Coastguard Worker using std::map;
54*35238bceSAndroid Build Coastguard Worker using std::set;
55*35238bceSAndroid Build Coastguard Worker 
56*35238bceSAndroid Build Coastguard Worker using tcu::TestLog;
57*35238bceSAndroid Build Coastguard Worker 
58*35238bceSAndroid Build Coastguard Worker namespace deqp
59*35238bceSAndroid Build Coastguard Worker {
60*35238bceSAndroid Build Coastguard Worker namespace gles3
61*35238bceSAndroid Build Coastguard Worker {
62*35238bceSAndroid Build Coastguard Worker namespace Functional
63*35238bceSAndroid Build Coastguard Worker {
64*35238bceSAndroid Build Coastguard Worker namespace TransformFeedback
65*35238bceSAndroid Build Coastguard Worker {
66*35238bceSAndroid Build Coastguard Worker 
67*35238bceSAndroid Build Coastguard Worker enum
68*35238bceSAndroid Build Coastguard Worker {
69*35238bceSAndroid Build Coastguard Worker     VIEWPORT_WIDTH  = 128,
70*35238bceSAndroid Build Coastguard Worker     VIEWPORT_HEIGHT = 128,
71*35238bceSAndroid Build Coastguard Worker     BUFFER_GUARD_MULTIPLIER =
72*35238bceSAndroid Build Coastguard Worker         2 //!< stride*BUFFER_GUARD_MULTIPLIER bytes are added to the end of tf buffer and used to check for overruns.
73*35238bceSAndroid Build Coastguard Worker };
74*35238bceSAndroid Build Coastguard Worker 
75*35238bceSAndroid Build Coastguard Worker enum Interpolation
76*35238bceSAndroid Build Coastguard Worker {
77*35238bceSAndroid Build Coastguard Worker     INTERPOLATION_SMOOTH = 0,
78*35238bceSAndroid Build Coastguard Worker     INTERPOLATION_FLAT,
79*35238bceSAndroid Build Coastguard Worker     INTERPOLATION_CENTROID,
80*35238bceSAndroid Build Coastguard Worker 
81*35238bceSAndroid Build Coastguard Worker     INTERPOLATION_LAST
82*35238bceSAndroid Build Coastguard Worker };
83*35238bceSAndroid Build Coastguard Worker 
getInterpolationName(Interpolation interp)84*35238bceSAndroid Build Coastguard Worker static const char *getInterpolationName(Interpolation interp)
85*35238bceSAndroid Build Coastguard Worker {
86*35238bceSAndroid Build Coastguard Worker     switch (interp)
87*35238bceSAndroid Build Coastguard Worker     {
88*35238bceSAndroid Build Coastguard Worker     case INTERPOLATION_SMOOTH:
89*35238bceSAndroid Build Coastguard Worker         return "smooth";
90*35238bceSAndroid Build Coastguard Worker     case INTERPOLATION_FLAT:
91*35238bceSAndroid Build Coastguard Worker         return "flat";
92*35238bceSAndroid Build Coastguard Worker     case INTERPOLATION_CENTROID:
93*35238bceSAndroid Build Coastguard Worker         return "centroid";
94*35238bceSAndroid Build Coastguard Worker     default:
95*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
96*35238bceSAndroid Build Coastguard Worker         return DE_NULL;
97*35238bceSAndroid Build Coastguard Worker     }
98*35238bceSAndroid Build Coastguard Worker }
99*35238bceSAndroid Build Coastguard Worker 
100*35238bceSAndroid Build Coastguard Worker struct Varying
101*35238bceSAndroid Build Coastguard Worker {
Varyingdeqp::gles3::Functional::TransformFeedback::Varying102*35238bceSAndroid Build Coastguard Worker     Varying(const char *name_, const glu::VarType &type_, Interpolation interp_)
103*35238bceSAndroid Build Coastguard Worker         : name(name_)
104*35238bceSAndroid Build Coastguard Worker         , type(type_)
105*35238bceSAndroid Build Coastguard Worker         , interpolation(interp_)
106*35238bceSAndroid Build Coastguard Worker     {
107*35238bceSAndroid Build Coastguard Worker     }
108*35238bceSAndroid Build Coastguard Worker 
109*35238bceSAndroid Build Coastguard Worker     std::string name;            //!< Variable name.
110*35238bceSAndroid Build Coastguard Worker     glu::VarType type;           //!< Variable type.
111*35238bceSAndroid Build Coastguard Worker     Interpolation interpolation; //!< Interpolation mode (smooth, flat, centroid).
112*35238bceSAndroid Build Coastguard Worker };
113*35238bceSAndroid Build Coastguard Worker 
114*35238bceSAndroid Build Coastguard Worker struct VaryingNameEquals
115*35238bceSAndroid Build Coastguard Worker {
VaryingNameEqualsdeqp::gles3::Functional::TransformFeedback::VaryingNameEquals116*35238bceSAndroid Build Coastguard Worker     VaryingNameEquals(const std::string &name_) : name(name_)
117*35238bceSAndroid Build Coastguard Worker     {
118*35238bceSAndroid Build Coastguard Worker     }
operator ()deqp::gles3::Functional::TransformFeedback::VaryingNameEquals119*35238bceSAndroid Build Coastguard Worker     bool operator()(const Varying &var) const
120*35238bceSAndroid Build Coastguard Worker     {
121*35238bceSAndroid Build Coastguard Worker         return var.name == name;
122*35238bceSAndroid Build Coastguard Worker     }
123*35238bceSAndroid Build Coastguard Worker 
124*35238bceSAndroid Build Coastguard Worker     std::string name;
125*35238bceSAndroid Build Coastguard Worker };
126*35238bceSAndroid Build Coastguard Worker 
127*35238bceSAndroid Build Coastguard Worker struct Attribute
128*35238bceSAndroid Build Coastguard Worker {
Attributedeqp::gles3::Functional::TransformFeedback::Attribute129*35238bceSAndroid Build Coastguard Worker     Attribute(const std::string &name_, const glu::VarType &type_, int offset_)
130*35238bceSAndroid Build Coastguard Worker         : name(name_)
131*35238bceSAndroid Build Coastguard Worker         , type(type_)
132*35238bceSAndroid Build Coastguard Worker         , offset(offset_)
133*35238bceSAndroid Build Coastguard Worker     {
134*35238bceSAndroid Build Coastguard Worker     }
135*35238bceSAndroid Build Coastguard Worker 
136*35238bceSAndroid Build Coastguard Worker     std::string name;
137*35238bceSAndroid Build Coastguard Worker     glu::VarType type;
138*35238bceSAndroid Build Coastguard Worker     int offset;
139*35238bceSAndroid Build Coastguard Worker };
140*35238bceSAndroid Build Coastguard Worker 
141*35238bceSAndroid Build Coastguard Worker struct AttributeNameEquals
142*35238bceSAndroid Build Coastguard Worker {
AttributeNameEqualsdeqp::gles3::Functional::TransformFeedback::AttributeNameEquals143*35238bceSAndroid Build Coastguard Worker     AttributeNameEquals(const std::string &name_) : name(name_)
144*35238bceSAndroid Build Coastguard Worker     {
145*35238bceSAndroid Build Coastguard Worker     }
operator ()deqp::gles3::Functional::TransformFeedback::AttributeNameEquals146*35238bceSAndroid Build Coastguard Worker     bool operator()(const Attribute &attr) const
147*35238bceSAndroid Build Coastguard Worker     {
148*35238bceSAndroid Build Coastguard Worker         return attr.name == name;
149*35238bceSAndroid Build Coastguard Worker     }
150*35238bceSAndroid Build Coastguard Worker 
151*35238bceSAndroid Build Coastguard Worker     std::string name;
152*35238bceSAndroid Build Coastguard Worker };
153*35238bceSAndroid Build Coastguard Worker 
154*35238bceSAndroid Build Coastguard Worker struct Output
155*35238bceSAndroid Build Coastguard Worker {
Outputdeqp::gles3::Functional::TransformFeedback::Output156*35238bceSAndroid Build Coastguard Worker     Output(void) : bufferNdx(0), offset(0)
157*35238bceSAndroid Build Coastguard Worker     {
158*35238bceSAndroid Build Coastguard Worker     }
159*35238bceSAndroid Build Coastguard Worker 
160*35238bceSAndroid Build Coastguard Worker     std::string name;
161*35238bceSAndroid Build Coastguard Worker     glu::VarType type;
162*35238bceSAndroid Build Coastguard Worker     int bufferNdx;
163*35238bceSAndroid Build Coastguard Worker     int offset;
164*35238bceSAndroid Build Coastguard Worker     vector<const Attribute *> inputs;
165*35238bceSAndroid Build Coastguard Worker };
166*35238bceSAndroid Build Coastguard Worker 
167*35238bceSAndroid Build Coastguard Worker struct DrawCall
168*35238bceSAndroid Build Coastguard Worker {
DrawCalldeqp::gles3::Functional::TransformFeedback::DrawCall169*35238bceSAndroid Build Coastguard Worker     DrawCall(int numElements_, bool tfEnabled_) : numElements(numElements_), transformFeedbackEnabled(tfEnabled_)
170*35238bceSAndroid Build Coastguard Worker     {
171*35238bceSAndroid Build Coastguard Worker     }
172*35238bceSAndroid Build Coastguard Worker 
DrawCalldeqp::gles3::Functional::TransformFeedback::DrawCall173*35238bceSAndroid Build Coastguard Worker     DrawCall(void) : numElements(0), transformFeedbackEnabled(false)
174*35238bceSAndroid Build Coastguard Worker     {
175*35238bceSAndroid Build Coastguard Worker     }
176*35238bceSAndroid Build Coastguard Worker 
177*35238bceSAndroid Build Coastguard Worker     int numElements;
178*35238bceSAndroid Build Coastguard Worker     bool transformFeedbackEnabled;
179*35238bceSAndroid Build Coastguard Worker };
180*35238bceSAndroid Build Coastguard Worker 
operator <<(std::ostream & str,const DrawCall & call)181*35238bceSAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &str, const DrawCall &call)
182*35238bceSAndroid Build Coastguard Worker {
183*35238bceSAndroid Build Coastguard Worker     return str << "(" << call.numElements << ", " << (call.transformFeedbackEnabled ? "resumed" : "paused") << ")";
184*35238bceSAndroid Build Coastguard Worker }
185*35238bceSAndroid Build Coastguard Worker 
186*35238bceSAndroid Build Coastguard Worker class ProgramSpec
187*35238bceSAndroid Build Coastguard Worker {
188*35238bceSAndroid Build Coastguard Worker public:
189*35238bceSAndroid Build Coastguard Worker     ProgramSpec(void);
190*35238bceSAndroid Build Coastguard Worker     ~ProgramSpec(void);
191*35238bceSAndroid Build Coastguard Worker 
192*35238bceSAndroid Build Coastguard Worker     glu::StructType *createStruct(const char *name);
193*35238bceSAndroid Build Coastguard Worker     void addVarying(const char *name, const glu::VarType &type, Interpolation interp);
194*35238bceSAndroid Build Coastguard Worker     void addTransformFeedbackVarying(const char *name);
195*35238bceSAndroid Build Coastguard Worker 
getStructs(void) const196*35238bceSAndroid Build Coastguard Worker     const vector<glu::StructType *> &getStructs(void) const
197*35238bceSAndroid Build Coastguard Worker     {
198*35238bceSAndroid Build Coastguard Worker         return m_structs;
199*35238bceSAndroid Build Coastguard Worker     }
getVaryings(void) const200*35238bceSAndroid Build Coastguard Worker     const vector<Varying> &getVaryings(void) const
201*35238bceSAndroid Build Coastguard Worker     {
202*35238bceSAndroid Build Coastguard Worker         return m_varyings;
203*35238bceSAndroid Build Coastguard Worker     }
getTransformFeedbackVaryings(void) const204*35238bceSAndroid Build Coastguard Worker     const vector<string> &getTransformFeedbackVaryings(void) const
205*35238bceSAndroid Build Coastguard Worker     {
206*35238bceSAndroid Build Coastguard Worker         return m_transformFeedbackVaryings;
207*35238bceSAndroid Build Coastguard Worker     }
208*35238bceSAndroid Build Coastguard Worker     bool isPointSizeUsed(void) const;
209*35238bceSAndroid Build Coastguard Worker 
210*35238bceSAndroid Build Coastguard Worker private:
211*35238bceSAndroid Build Coastguard Worker     ProgramSpec(const ProgramSpec &other);
212*35238bceSAndroid Build Coastguard Worker     ProgramSpec &operator=(const ProgramSpec &other);
213*35238bceSAndroid Build Coastguard Worker 
214*35238bceSAndroid Build Coastguard Worker     vector<glu::StructType *> m_structs;
215*35238bceSAndroid Build Coastguard Worker     vector<Varying> m_varyings;
216*35238bceSAndroid Build Coastguard Worker     vector<string> m_transformFeedbackVaryings;
217*35238bceSAndroid Build Coastguard Worker };
218*35238bceSAndroid Build Coastguard Worker 
219*35238bceSAndroid Build Coastguard Worker // ProgramSpec
220*35238bceSAndroid Build Coastguard Worker 
ProgramSpec(void)221*35238bceSAndroid Build Coastguard Worker ProgramSpec::ProgramSpec(void)
222*35238bceSAndroid Build Coastguard Worker {
223*35238bceSAndroid Build Coastguard Worker }
224*35238bceSAndroid Build Coastguard Worker 
~ProgramSpec(void)225*35238bceSAndroid Build Coastguard Worker ProgramSpec::~ProgramSpec(void)
226*35238bceSAndroid Build Coastguard Worker {
227*35238bceSAndroid Build Coastguard Worker     for (vector<glu::StructType *>::iterator i = m_structs.begin(); i != m_structs.end(); i++)
228*35238bceSAndroid Build Coastguard Worker         delete *i;
229*35238bceSAndroid Build Coastguard Worker }
230*35238bceSAndroid Build Coastguard Worker 
createStruct(const char * name)231*35238bceSAndroid Build Coastguard Worker glu::StructType *ProgramSpec::createStruct(const char *name)
232*35238bceSAndroid Build Coastguard Worker {
233*35238bceSAndroid Build Coastguard Worker     m_structs.reserve(m_structs.size() + 1);
234*35238bceSAndroid Build Coastguard Worker     m_structs.push_back(new glu::StructType(name));
235*35238bceSAndroid Build Coastguard Worker     return m_structs.back();
236*35238bceSAndroid Build Coastguard Worker }
237*35238bceSAndroid Build Coastguard Worker 
addVarying(const char * name,const glu::VarType & type,Interpolation interp)238*35238bceSAndroid Build Coastguard Worker void ProgramSpec::addVarying(const char *name, const glu::VarType &type, Interpolation interp)
239*35238bceSAndroid Build Coastguard Worker {
240*35238bceSAndroid Build Coastguard Worker     m_varyings.push_back(Varying(name, type, interp));
241*35238bceSAndroid Build Coastguard Worker }
242*35238bceSAndroid Build Coastguard Worker 
addTransformFeedbackVarying(const char * name)243*35238bceSAndroid Build Coastguard Worker void ProgramSpec::addTransformFeedbackVarying(const char *name)
244*35238bceSAndroid Build Coastguard Worker {
245*35238bceSAndroid Build Coastguard Worker     m_transformFeedbackVaryings.push_back(name);
246*35238bceSAndroid Build Coastguard Worker }
247*35238bceSAndroid Build Coastguard Worker 
isPointSizeUsed(void) const248*35238bceSAndroid Build Coastguard Worker bool ProgramSpec::isPointSizeUsed(void) const
249*35238bceSAndroid Build Coastguard Worker {
250*35238bceSAndroid Build Coastguard Worker     return std::find(m_transformFeedbackVaryings.begin(), m_transformFeedbackVaryings.end(), "gl_PointSize") !=
251*35238bceSAndroid Build Coastguard Worker            m_transformFeedbackVaryings.end();
252*35238bceSAndroid Build Coastguard Worker }
253*35238bceSAndroid Build Coastguard Worker 
isProgramSupported(const glw::Functions & gl,const ProgramSpec & spec,uint32_t tfMode)254*35238bceSAndroid Build Coastguard Worker static bool isProgramSupported(const glw::Functions &gl, const ProgramSpec &spec, uint32_t tfMode)
255*35238bceSAndroid Build Coastguard Worker {
256*35238bceSAndroid Build Coastguard Worker     int maxVertexAttribs           = 0;
257*35238bceSAndroid Build Coastguard Worker     int maxTfInterleavedComponents = 0;
258*35238bceSAndroid Build Coastguard Worker     int maxTfSeparateAttribs       = 0;
259*35238bceSAndroid Build Coastguard Worker     int maxTfSeparateComponents    = 0;
260*35238bceSAndroid Build Coastguard Worker 
261*35238bceSAndroid Build Coastguard Worker     gl.getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
262*35238bceSAndroid Build Coastguard Worker     gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &maxTfInterleavedComponents);
263*35238bceSAndroid Build Coastguard Worker     gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &maxTfSeparateAttribs);
264*35238bceSAndroid Build Coastguard Worker     gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &maxTfSeparateComponents);
265*35238bceSAndroid Build Coastguard Worker 
266*35238bceSAndroid Build Coastguard Worker     // Check vertex attribs.
267*35238bceSAndroid Build Coastguard Worker     int totalVertexAttribs = 1 /* a_position */ + (spec.isPointSizeUsed() ? 1 : 0);
268*35238bceSAndroid Build Coastguard Worker     for (vector<Varying>::const_iterator var = spec.getVaryings().begin(); var != spec.getVaryings().end(); var++)
269*35238bceSAndroid Build Coastguard Worker     {
270*35238bceSAndroid Build Coastguard Worker         for (glu::VectorTypeIterator vecIter = glu::VectorTypeIterator::begin(&var->type);
271*35238bceSAndroid Build Coastguard Worker              vecIter != glu::VectorTypeIterator::end(&var->type); vecIter++)
272*35238bceSAndroid Build Coastguard Worker             totalVertexAttribs += 1;
273*35238bceSAndroid Build Coastguard Worker     }
274*35238bceSAndroid Build Coastguard Worker 
275*35238bceSAndroid Build Coastguard Worker     if (totalVertexAttribs > maxVertexAttribs)
276*35238bceSAndroid Build Coastguard Worker         return false; // Vertex attribute count exceeded.
277*35238bceSAndroid Build Coastguard Worker 
278*35238bceSAndroid Build Coastguard Worker     // Check varyings.
279*35238bceSAndroid Build Coastguard Worker     int totalTfComponents = 0;
280*35238bceSAndroid Build Coastguard Worker     int totalTfAttribs    = 0;
281*35238bceSAndroid Build Coastguard Worker     for (vector<string>::const_iterator iter = spec.getTransformFeedbackVaryings().begin();
282*35238bceSAndroid Build Coastguard Worker          iter != spec.getTransformFeedbackVaryings().end(); iter++)
283*35238bceSAndroid Build Coastguard Worker     {
284*35238bceSAndroid Build Coastguard Worker         const string &name = *iter;
285*35238bceSAndroid Build Coastguard Worker         int numComponents  = 0;
286*35238bceSAndroid Build Coastguard Worker 
287*35238bceSAndroid Build Coastguard Worker         if (name == "gl_Position")
288*35238bceSAndroid Build Coastguard Worker             numComponents = 4;
289*35238bceSAndroid Build Coastguard Worker         else if (name == "gl_PointSize")
290*35238bceSAndroid Build Coastguard Worker             numComponents = 1;
291*35238bceSAndroid Build Coastguard Worker         else
292*35238bceSAndroid Build Coastguard Worker         {
293*35238bceSAndroid Build Coastguard Worker             string varName = glu::parseVariableName(name.c_str());
294*35238bceSAndroid Build Coastguard Worker             const Varying &varying =
295*35238bceSAndroid Build Coastguard Worker                 *std::find_if(spec.getVaryings().begin(), spec.getVaryings().end(), VaryingNameEquals(varName));
296*35238bceSAndroid Build Coastguard Worker             glu::TypeComponentVector varPath;
297*35238bceSAndroid Build Coastguard Worker 
298*35238bceSAndroid Build Coastguard Worker             glu::parseTypePath(name.c_str(), varying.type, varPath);
299*35238bceSAndroid Build Coastguard Worker             numComponents = glu::getVarType(varying.type, varPath).getScalarSize();
300*35238bceSAndroid Build Coastguard Worker         }
301*35238bceSAndroid Build Coastguard Worker 
302*35238bceSAndroid Build Coastguard Worker         if (tfMode == GL_SEPARATE_ATTRIBS && numComponents > maxTfSeparateComponents)
303*35238bceSAndroid Build Coastguard Worker             return false; // Per-attribute component count exceeded.
304*35238bceSAndroid Build Coastguard Worker 
305*35238bceSAndroid Build Coastguard Worker         totalTfComponents += numComponents;
306*35238bceSAndroid Build Coastguard Worker         totalTfAttribs += 1;
307*35238bceSAndroid Build Coastguard Worker     }
308*35238bceSAndroid Build Coastguard Worker 
309*35238bceSAndroid Build Coastguard Worker     if (tfMode == GL_SEPARATE_ATTRIBS && totalTfAttribs > maxTfSeparateAttribs)
310*35238bceSAndroid Build Coastguard Worker         return false;
311*35238bceSAndroid Build Coastguard Worker 
312*35238bceSAndroid Build Coastguard Worker     if (tfMode == GL_INTERLEAVED_ATTRIBS && totalTfComponents > maxTfInterleavedComponents)
313*35238bceSAndroid Build Coastguard Worker         return false;
314*35238bceSAndroid Build Coastguard Worker 
315*35238bceSAndroid Build Coastguard Worker     return true;
316*35238bceSAndroid Build Coastguard Worker }
317*35238bceSAndroid Build Coastguard Worker 
318*35238bceSAndroid Build Coastguard Worker // Program
319*35238bceSAndroid Build Coastguard Worker 
getAttributeName(const char * varyingName,const glu::TypeComponentVector & path)320*35238bceSAndroid Build Coastguard Worker static std::string getAttributeName(const char *varyingName, const glu::TypeComponentVector &path)
321*35238bceSAndroid Build Coastguard Worker {
322*35238bceSAndroid Build Coastguard Worker     std::ostringstream str;
323*35238bceSAndroid Build Coastguard Worker 
324*35238bceSAndroid Build Coastguard Worker     str << "a_" << (deStringBeginsWith(varyingName, "v_") ? varyingName + 2 : varyingName);
325*35238bceSAndroid Build Coastguard Worker 
326*35238bceSAndroid Build Coastguard Worker     for (glu::TypeComponentVector::const_iterator iter = path.begin(); iter != path.end(); iter++)
327*35238bceSAndroid Build Coastguard Worker     {
328*35238bceSAndroid Build Coastguard Worker         const char *prefix = DE_NULL;
329*35238bceSAndroid Build Coastguard Worker 
330*35238bceSAndroid Build Coastguard Worker         switch (iter->type)
331*35238bceSAndroid Build Coastguard Worker         {
332*35238bceSAndroid Build Coastguard Worker         case glu::VarTypeComponent::STRUCT_MEMBER:
333*35238bceSAndroid Build Coastguard Worker             prefix = "_m";
334*35238bceSAndroid Build Coastguard Worker             break;
335*35238bceSAndroid Build Coastguard Worker         case glu::VarTypeComponent::ARRAY_ELEMENT:
336*35238bceSAndroid Build Coastguard Worker             prefix = "_e";
337*35238bceSAndroid Build Coastguard Worker             break;
338*35238bceSAndroid Build Coastguard Worker         case glu::VarTypeComponent::MATRIX_COLUMN:
339*35238bceSAndroid Build Coastguard Worker             prefix = "_c";
340*35238bceSAndroid Build Coastguard Worker             break;
341*35238bceSAndroid Build Coastguard Worker         case glu::VarTypeComponent::VECTOR_COMPONENT:
342*35238bceSAndroid Build Coastguard Worker             prefix = "_s";
343*35238bceSAndroid Build Coastguard Worker             break;
344*35238bceSAndroid Build Coastguard Worker         default:
345*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
346*35238bceSAndroid Build Coastguard Worker         }
347*35238bceSAndroid Build Coastguard Worker 
348*35238bceSAndroid Build Coastguard Worker         str << prefix << iter->index;
349*35238bceSAndroid Build Coastguard Worker     }
350*35238bceSAndroid Build Coastguard Worker 
351*35238bceSAndroid Build Coastguard Worker     return str.str();
352*35238bceSAndroid Build Coastguard Worker }
353*35238bceSAndroid Build Coastguard Worker 
genShaderSources(const ProgramSpec & spec,std::string & vertSource,std::string & fragSource,bool pointSizeRequired)354*35238bceSAndroid Build Coastguard Worker static void genShaderSources(const ProgramSpec &spec, std::string &vertSource, std::string &fragSource,
355*35238bceSAndroid Build Coastguard Worker                              bool pointSizeRequired)
356*35238bceSAndroid Build Coastguard Worker {
357*35238bceSAndroid Build Coastguard Worker     std::ostringstream vtx;
358*35238bceSAndroid Build Coastguard Worker     std::ostringstream frag;
359*35238bceSAndroid Build Coastguard Worker     bool addPointSize = spec.isPointSizeUsed();
360*35238bceSAndroid Build Coastguard Worker 
361*35238bceSAndroid Build Coastguard Worker     vtx << "#version 300 es\n"
362*35238bceSAndroid Build Coastguard Worker         << "in highp vec4 a_position;\n";
363*35238bceSAndroid Build Coastguard Worker     frag << "#version 300 es\n"
364*35238bceSAndroid Build Coastguard Worker          << "layout(location = 0) out mediump vec4 o_color;\n"
365*35238bceSAndroid Build Coastguard Worker          << "uniform highp vec4 u_scale;\n"
366*35238bceSAndroid Build Coastguard Worker          << "uniform highp vec4 u_bias;\n";
367*35238bceSAndroid Build Coastguard Worker 
368*35238bceSAndroid Build Coastguard Worker     if (addPointSize)
369*35238bceSAndroid Build Coastguard Worker         vtx << "in highp float a_pointSize;\n";
370*35238bceSAndroid Build Coastguard Worker 
371*35238bceSAndroid Build Coastguard Worker     // Declare attributes.
372*35238bceSAndroid Build Coastguard Worker     for (vector<Varying>::const_iterator var = spec.getVaryings().begin(); var != spec.getVaryings().end(); var++)
373*35238bceSAndroid Build Coastguard Worker     {
374*35238bceSAndroid Build Coastguard Worker         const char *name         = var->name.c_str();
375*35238bceSAndroid Build Coastguard Worker         const glu::VarType &type = var->type;
376*35238bceSAndroid Build Coastguard Worker 
377*35238bceSAndroid Build Coastguard Worker         for (glu::VectorTypeIterator vecIter = glu::VectorTypeIterator::begin(&type);
378*35238bceSAndroid Build Coastguard Worker              vecIter != glu::VectorTypeIterator::end(&type); vecIter++)
379*35238bceSAndroid Build Coastguard Worker         {
380*35238bceSAndroid Build Coastguard Worker             glu::VarType attribType = glu::getVarType(type, vecIter.getPath());
381*35238bceSAndroid Build Coastguard Worker             string attribName       = getAttributeName(name, vecIter.getPath());
382*35238bceSAndroid Build Coastguard Worker 
383*35238bceSAndroid Build Coastguard Worker             vtx << "in " << glu::declare(attribType, attribName.c_str()) << ";\n";
384*35238bceSAndroid Build Coastguard Worker         }
385*35238bceSAndroid Build Coastguard Worker     }
386*35238bceSAndroid Build Coastguard Worker 
387*35238bceSAndroid Build Coastguard Worker     // Declare vayrings.
388*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < 2; ndx++)
389*35238bceSAndroid Build Coastguard Worker     {
390*35238bceSAndroid Build Coastguard Worker         const char *inout       = ndx ? "in" : "out";
391*35238bceSAndroid Build Coastguard Worker         std::ostringstream &str = ndx ? frag : vtx;
392*35238bceSAndroid Build Coastguard Worker 
393*35238bceSAndroid Build Coastguard Worker         // Declare structs that have type name.
394*35238bceSAndroid Build Coastguard Worker         for (vector<glu::StructType *>::const_iterator structIter = spec.getStructs().begin();
395*35238bceSAndroid Build Coastguard Worker              structIter != spec.getStructs().end(); structIter++)
396*35238bceSAndroid Build Coastguard Worker         {
397*35238bceSAndroid Build Coastguard Worker             const glu::StructType *structPtr = *structIter;
398*35238bceSAndroid Build Coastguard Worker             if (structPtr->hasTypeName())
399*35238bceSAndroid Build Coastguard Worker                 str << glu::declare(structPtr) << ";\n";
400*35238bceSAndroid Build Coastguard Worker         }
401*35238bceSAndroid Build Coastguard Worker 
402*35238bceSAndroid Build Coastguard Worker         for (vector<Varying>::const_iterator var = spec.getVaryings().begin(); var != spec.getVaryings().end(); var++)
403*35238bceSAndroid Build Coastguard Worker             str << getInterpolationName(var->interpolation) << " " << inout << " "
404*35238bceSAndroid Build Coastguard Worker                 << glu::declare(var->type, var->name.c_str()) << ";\n";
405*35238bceSAndroid Build Coastguard Worker     }
406*35238bceSAndroid Build Coastguard Worker 
407*35238bceSAndroid Build Coastguard Worker     vtx << "\nvoid main (void)\n{\n"
408*35238bceSAndroid Build Coastguard Worker         << "\tgl_Position = a_position;\n";
409*35238bceSAndroid Build Coastguard Worker     frag << "\nvoid main (void)\n{\n"
410*35238bceSAndroid Build Coastguard Worker          << "\thighp vec4 res = vec4(0.0);\n";
411*35238bceSAndroid Build Coastguard Worker 
412*35238bceSAndroid Build Coastguard Worker     if (addPointSize)
413*35238bceSAndroid Build Coastguard Worker         vtx << "\tgl_PointSize = a_pointSize;\n";
414*35238bceSAndroid Build Coastguard Worker     else if (pointSizeRequired)
415*35238bceSAndroid Build Coastguard Worker         vtx << "\tgl_PointSize = 1.0;\n";
416*35238bceSAndroid Build Coastguard Worker 
417*35238bceSAndroid Build Coastguard Worker     // Generate assignments / usage.
418*35238bceSAndroid Build Coastguard Worker     for (vector<Varying>::const_iterator var = spec.getVaryings().begin(); var != spec.getVaryings().end(); var++)
419*35238bceSAndroid Build Coastguard Worker     {
420*35238bceSAndroid Build Coastguard Worker         const char *name         = var->name.c_str();
421*35238bceSAndroid Build Coastguard Worker         const glu::VarType &type = var->type;
422*35238bceSAndroid Build Coastguard Worker 
423*35238bceSAndroid Build Coastguard Worker         for (glu::VectorTypeIterator vecIter = glu::VectorTypeIterator::begin(&type);
424*35238bceSAndroid Build Coastguard Worker              vecIter != glu::VectorTypeIterator::end(&type); vecIter++)
425*35238bceSAndroid Build Coastguard Worker         {
426*35238bceSAndroid Build Coastguard Worker             glu::VarType subType = glu::getVarType(type, vecIter.getPath());
427*35238bceSAndroid Build Coastguard Worker             string attribName    = getAttributeName(name, vecIter.getPath());
428*35238bceSAndroid Build Coastguard Worker 
429*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(subType.isBasicType() && glu::isDataTypeScalarOrVector(subType.getBasicType()));
430*35238bceSAndroid Build Coastguard Worker 
431*35238bceSAndroid Build Coastguard Worker             // Vertex: assign from attribute.
432*35238bceSAndroid Build Coastguard Worker             vtx << "\t" << name << vecIter << " = " << attribName << ";\n";
433*35238bceSAndroid Build Coastguard Worker 
434*35238bceSAndroid Build Coastguard Worker             // Fragment: add to res variable.
435*35238bceSAndroid Build Coastguard Worker             int scalarSize = glu::getDataTypeScalarSize(subType.getBasicType());
436*35238bceSAndroid Build Coastguard Worker 
437*35238bceSAndroid Build Coastguard Worker             frag << "\tres += ";
438*35238bceSAndroid Build Coastguard Worker             if (scalarSize == 1)
439*35238bceSAndroid Build Coastguard Worker                 frag << "vec4(" << name << vecIter << ")";
440*35238bceSAndroid Build Coastguard Worker             else if (scalarSize == 2)
441*35238bceSAndroid Build Coastguard Worker                 frag << "vec2(" << name << vecIter << ").xxyy";
442*35238bceSAndroid Build Coastguard Worker             else if (scalarSize == 3)
443*35238bceSAndroid Build Coastguard Worker                 frag << "vec3(" << name << vecIter << ").xyzx";
444*35238bceSAndroid Build Coastguard Worker             else if (scalarSize == 4)
445*35238bceSAndroid Build Coastguard Worker                 frag << "vec4(" << name << vecIter << ")";
446*35238bceSAndroid Build Coastguard Worker 
447*35238bceSAndroid Build Coastguard Worker             frag << ";\n";
448*35238bceSAndroid Build Coastguard Worker         }
449*35238bceSAndroid Build Coastguard Worker     }
450*35238bceSAndroid Build Coastguard Worker 
451*35238bceSAndroid Build Coastguard Worker     frag << "\to_color = res * u_scale + u_bias;\n";
452*35238bceSAndroid Build Coastguard Worker 
453*35238bceSAndroid Build Coastguard Worker     vtx << "}\n";
454*35238bceSAndroid Build Coastguard Worker     frag << "}\n";
455*35238bceSAndroid Build Coastguard Worker 
456*35238bceSAndroid Build Coastguard Worker     vertSource = vtx.str();
457*35238bceSAndroid Build Coastguard Worker     fragSource = frag.str();
458*35238bceSAndroid Build Coastguard Worker }
459*35238bceSAndroid Build Coastguard Worker 
createVertexCaptureProgram(const glu::RenderContext & context,const ProgramSpec & spec,uint32_t bufferMode,uint32_t primitiveType)460*35238bceSAndroid Build Coastguard Worker static glu::ShaderProgram *createVertexCaptureProgram(const glu::RenderContext &context, const ProgramSpec &spec,
461*35238bceSAndroid Build Coastguard Worker                                                       uint32_t bufferMode, uint32_t primitiveType)
462*35238bceSAndroid Build Coastguard Worker {
463*35238bceSAndroid Build Coastguard Worker     std::string vertSource, fragSource;
464*35238bceSAndroid Build Coastguard Worker 
465*35238bceSAndroid Build Coastguard Worker     genShaderSources(spec, vertSource, fragSource, primitiveType == GL_POINTS /* Is point size required? */);
466*35238bceSAndroid Build Coastguard Worker 
467*35238bceSAndroid Build Coastguard Worker     return new glu::ShaderProgram(context, glu::ProgramSources()
468*35238bceSAndroid Build Coastguard Worker                                                << glu::VertexSource(vertSource) << glu::FragmentSource(fragSource)
469*35238bceSAndroid Build Coastguard Worker                                                << glu::TransformFeedbackVaryings<vector<string>::const_iterator>(
470*35238bceSAndroid Build Coastguard Worker                                                       spec.getTransformFeedbackVaryings().begin(),
471*35238bceSAndroid Build Coastguard Worker                                                       spec.getTransformFeedbackVaryings().end())
472*35238bceSAndroid Build Coastguard Worker                                                << glu::TransformFeedbackMode(bufferMode));
473*35238bceSAndroid Build Coastguard Worker }
474*35238bceSAndroid Build Coastguard Worker 
475*35238bceSAndroid Build Coastguard Worker // Helpers.
476*35238bceSAndroid Build Coastguard Worker 
computeInputLayout(vector<Attribute> & attributes,int & inputStride,const vector<Varying> & varyings,bool usePointSize)477*35238bceSAndroid Build Coastguard Worker static void computeInputLayout(vector<Attribute> &attributes, int &inputStride, const vector<Varying> &varyings,
478*35238bceSAndroid Build Coastguard Worker                                bool usePointSize)
479*35238bceSAndroid Build Coastguard Worker {
480*35238bceSAndroid Build Coastguard Worker     inputStride = 0;
481*35238bceSAndroid Build Coastguard Worker 
482*35238bceSAndroid Build Coastguard Worker     // Add position.
483*35238bceSAndroid Build Coastguard Worker     attributes.push_back(
484*35238bceSAndroid Build Coastguard Worker         Attribute("a_position", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP), inputStride));
485*35238bceSAndroid Build Coastguard Worker     inputStride += 4 * (int)sizeof(uint32_t);
486*35238bceSAndroid Build Coastguard Worker 
487*35238bceSAndroid Build Coastguard Worker     if (usePointSize)
488*35238bceSAndroid Build Coastguard Worker     {
489*35238bceSAndroid Build Coastguard Worker         attributes.push_back(
490*35238bceSAndroid Build Coastguard Worker             Attribute("a_pointSize", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP), inputStride));
491*35238bceSAndroid Build Coastguard Worker         inputStride += 1 * (int)sizeof(uint32_t);
492*35238bceSAndroid Build Coastguard Worker     }
493*35238bceSAndroid Build Coastguard Worker 
494*35238bceSAndroid Build Coastguard Worker     // Compute attribute vector.
495*35238bceSAndroid Build Coastguard Worker     for (vector<Varying>::const_iterator var = varyings.begin(); var != varyings.end(); var++)
496*35238bceSAndroid Build Coastguard Worker     {
497*35238bceSAndroid Build Coastguard Worker         for (glu::VectorTypeIterator vecIter = glu::VectorTypeIterator::begin(&var->type);
498*35238bceSAndroid Build Coastguard Worker              vecIter != glu::VectorTypeIterator::end(&var->type); vecIter++)
499*35238bceSAndroid Build Coastguard Worker         {
500*35238bceSAndroid Build Coastguard Worker             glu::VarType type = vecIter.getType();
501*35238bceSAndroid Build Coastguard Worker             string name       = getAttributeName(var->name.c_str(), vecIter.getPath());
502*35238bceSAndroid Build Coastguard Worker 
503*35238bceSAndroid Build Coastguard Worker             attributes.push_back(Attribute(name, type, inputStride));
504*35238bceSAndroid Build Coastguard Worker             inputStride += glu::getDataTypeScalarSize(type.getBasicType()) * (int)sizeof(uint32_t);
505*35238bceSAndroid Build Coastguard Worker         }
506*35238bceSAndroid Build Coastguard Worker     }
507*35238bceSAndroid Build Coastguard Worker }
508*35238bceSAndroid Build Coastguard Worker 
computeTransformFeedbackOutputs(vector<Output> & transformFeedbackOutputs,const vector<Attribute> & attributes,const vector<Varying> & varyings,const vector<string> & transformFeedbackVaryings,uint32_t bufferMode)509*35238bceSAndroid Build Coastguard Worker static void computeTransformFeedbackOutputs(vector<Output> &transformFeedbackOutputs,
510*35238bceSAndroid Build Coastguard Worker                                             const vector<Attribute> &attributes, const vector<Varying> &varyings,
511*35238bceSAndroid Build Coastguard Worker                                             const vector<string> &transformFeedbackVaryings, uint32_t bufferMode)
512*35238bceSAndroid Build Coastguard Worker {
513*35238bceSAndroid Build Coastguard Worker     int accumulatedSize = 0;
514*35238bceSAndroid Build Coastguard Worker 
515*35238bceSAndroid Build Coastguard Worker     transformFeedbackOutputs.resize(transformFeedbackVaryings.size());
516*35238bceSAndroid Build Coastguard Worker     for (int varNdx = 0; varNdx < (int)transformFeedbackVaryings.size(); varNdx++)
517*35238bceSAndroid Build Coastguard Worker     {
518*35238bceSAndroid Build Coastguard Worker         const string &name = transformFeedbackVaryings[varNdx];
519*35238bceSAndroid Build Coastguard Worker         int bufNdx         = (bufferMode == GL_SEPARATE_ATTRIBS ? varNdx : 0);
520*35238bceSAndroid Build Coastguard Worker         int offset         = (bufferMode == GL_SEPARATE_ATTRIBS ? 0 : accumulatedSize);
521*35238bceSAndroid Build Coastguard Worker         Output &output     = transformFeedbackOutputs[varNdx];
522*35238bceSAndroid Build Coastguard Worker 
523*35238bceSAndroid Build Coastguard Worker         output.name      = name;
524*35238bceSAndroid Build Coastguard Worker         output.bufferNdx = bufNdx;
525*35238bceSAndroid Build Coastguard Worker         output.offset    = offset;
526*35238bceSAndroid Build Coastguard Worker 
527*35238bceSAndroid Build Coastguard Worker         if (name == "gl_Position")
528*35238bceSAndroid Build Coastguard Worker         {
529*35238bceSAndroid Build Coastguard Worker             const Attribute *posIn =
530*35238bceSAndroid Build Coastguard Worker                 &(*std::find_if(attributes.begin(), attributes.end(), AttributeNameEquals("a_position")));
531*35238bceSAndroid Build Coastguard Worker             output.type = posIn->type;
532*35238bceSAndroid Build Coastguard Worker             output.inputs.push_back(posIn);
533*35238bceSAndroid Build Coastguard Worker         }
534*35238bceSAndroid Build Coastguard Worker         else if (name == "gl_PointSize")
535*35238bceSAndroid Build Coastguard Worker         {
536*35238bceSAndroid Build Coastguard Worker             const Attribute *sizeIn =
537*35238bceSAndroid Build Coastguard Worker                 &(*std::find_if(attributes.begin(), attributes.end(), AttributeNameEquals("a_pointSize")));
538*35238bceSAndroid Build Coastguard Worker             output.type = sizeIn->type;
539*35238bceSAndroid Build Coastguard Worker             output.inputs.push_back(sizeIn);
540*35238bceSAndroid Build Coastguard Worker         }
541*35238bceSAndroid Build Coastguard Worker         else
542*35238bceSAndroid Build Coastguard Worker         {
543*35238bceSAndroid Build Coastguard Worker             string varName         = glu::parseVariableName(name.c_str());
544*35238bceSAndroid Build Coastguard Worker             const Varying &varying = *std::find_if(varyings.begin(), varyings.end(), VaryingNameEquals(varName));
545*35238bceSAndroid Build Coastguard Worker             glu::TypeComponentVector varPath;
546*35238bceSAndroid Build Coastguard Worker 
547*35238bceSAndroid Build Coastguard Worker             glu::parseTypePath(name.c_str(), varying.type, varPath);
548*35238bceSAndroid Build Coastguard Worker 
549*35238bceSAndroid Build Coastguard Worker             output.type = glu::getVarType(varying.type, varPath);
550*35238bceSAndroid Build Coastguard Worker 
551*35238bceSAndroid Build Coastguard Worker             // Add all vectorized attributes as inputs.
552*35238bceSAndroid Build Coastguard Worker             for (glu::VectorTypeIterator iter = glu::VectorTypeIterator::begin(&output.type);
553*35238bceSAndroid Build Coastguard Worker                  iter != glu::VectorTypeIterator::end(&output.type); iter++)
554*35238bceSAndroid Build Coastguard Worker             {
555*35238bceSAndroid Build Coastguard Worker                 // Full path.
556*35238bceSAndroid Build Coastguard Worker                 glu::TypeComponentVector fullPath(varPath.size() + iter.getPath().size());
557*35238bceSAndroid Build Coastguard Worker 
558*35238bceSAndroid Build Coastguard Worker                 std::copy(varPath.begin(), varPath.end(), fullPath.begin());
559*35238bceSAndroid Build Coastguard Worker                 std::copy(iter.getPath().begin(), iter.getPath().end(), fullPath.begin() + varPath.size());
560*35238bceSAndroid Build Coastguard Worker 
561*35238bceSAndroid Build Coastguard Worker                 string attribName = getAttributeName(varName.c_str(), fullPath);
562*35238bceSAndroid Build Coastguard Worker                 const Attribute *attrib =
563*35238bceSAndroid Build Coastguard Worker                     &(*std::find_if(attributes.begin(), attributes.end(), AttributeNameEquals(attribName)));
564*35238bceSAndroid Build Coastguard Worker 
565*35238bceSAndroid Build Coastguard Worker                 output.inputs.push_back(attrib);
566*35238bceSAndroid Build Coastguard Worker             }
567*35238bceSAndroid Build Coastguard Worker         }
568*35238bceSAndroid Build Coastguard Worker 
569*35238bceSAndroid Build Coastguard Worker         accumulatedSize += output.type.getScalarSize() * (int)sizeof(uint32_t);
570*35238bceSAndroid Build Coastguard Worker     }
571*35238bceSAndroid Build Coastguard Worker }
572*35238bceSAndroid Build Coastguard Worker 
signExtend(uint32_t value,uint32_t numBits)573*35238bceSAndroid Build Coastguard Worker static uint32_t signExtend(uint32_t value, uint32_t numBits)
574*35238bceSAndroid Build Coastguard Worker {
575*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(numBits >= 1u && numBits <= 32u);
576*35238bceSAndroid Build Coastguard Worker     if (numBits == 32u)
577*35238bceSAndroid Build Coastguard Worker         return value;
578*35238bceSAndroid Build Coastguard Worker     else if ((value & (1u << (numBits - 1u))) == 0u)
579*35238bceSAndroid Build Coastguard Worker         return value;
580*35238bceSAndroid Build Coastguard Worker     else
581*35238bceSAndroid Build Coastguard Worker         return value | ~((1u << numBits) - 1u);
582*35238bceSAndroid Build Coastguard Worker }
583*35238bceSAndroid Build Coastguard Worker 
genAttributeData(const Attribute & attrib,uint8_t * basePtr,int stride,int numElements,de::Random & rnd)584*35238bceSAndroid Build Coastguard Worker static void genAttributeData(const Attribute &attrib, uint8_t *basePtr, int stride, int numElements, de::Random &rnd)
585*35238bceSAndroid Build Coastguard Worker {
586*35238bceSAndroid Build Coastguard Worker     const int elementSize          = (int)sizeof(uint32_t);
587*35238bceSAndroid Build Coastguard Worker     const bool isFloat             = glu::isDataTypeFloatOrVec(attrib.type.getBasicType());
588*35238bceSAndroid Build Coastguard Worker     const bool isInt               = glu::isDataTypeIntOrIVec(attrib.type.getBasicType());
589*35238bceSAndroid Build Coastguard Worker     const bool isUint              = glu::isDataTypeUintOrUVec(attrib.type.getBasicType());
590*35238bceSAndroid Build Coastguard Worker     const glu::Precision precision = attrib.type.getPrecision();
591*35238bceSAndroid Build Coastguard Worker     const int numComps             = glu::getDataTypeScalarSize(attrib.type.getBasicType());
592*35238bceSAndroid Build Coastguard Worker 
593*35238bceSAndroid Build Coastguard Worker     for (int elemNdx = 0; elemNdx < numElements; elemNdx++)
594*35238bceSAndroid Build Coastguard Worker     {
595*35238bceSAndroid Build Coastguard Worker         for (int compNdx = 0; compNdx < numComps; compNdx++)
596*35238bceSAndroid Build Coastguard Worker         {
597*35238bceSAndroid Build Coastguard Worker             int offset = attrib.offset + elemNdx * stride + compNdx * elementSize;
598*35238bceSAndroid Build Coastguard Worker             if (isFloat)
599*35238bceSAndroid Build Coastguard Worker             {
600*35238bceSAndroid Build Coastguard Worker                 float *comp = (float *)(basePtr + offset);
601*35238bceSAndroid Build Coastguard Worker                 switch (precision)
602*35238bceSAndroid Build Coastguard Worker                 {
603*35238bceSAndroid Build Coastguard Worker                 case glu::PRECISION_LOWP:
604*35238bceSAndroid Build Coastguard Worker                     *comp = 0.0f + 0.25f * (float)rnd.getInt(0, 4);
605*35238bceSAndroid Build Coastguard Worker                     break;
606*35238bceSAndroid Build Coastguard Worker                 case glu::PRECISION_MEDIUMP:
607*35238bceSAndroid Build Coastguard Worker                     *comp = rnd.getFloat(-1e3f, 1e3f);
608*35238bceSAndroid Build Coastguard Worker                     break;
609*35238bceSAndroid Build Coastguard Worker                 case glu::PRECISION_HIGHP:
610*35238bceSAndroid Build Coastguard Worker                     *comp = rnd.getFloat(-1e5f, 1e5f);
611*35238bceSAndroid Build Coastguard Worker                     break;
612*35238bceSAndroid Build Coastguard Worker                 default:
613*35238bceSAndroid Build Coastguard Worker                     DE_ASSERT(false);
614*35238bceSAndroid Build Coastguard Worker                 }
615*35238bceSAndroid Build Coastguard Worker             }
616*35238bceSAndroid Build Coastguard Worker             else if (isInt)
617*35238bceSAndroid Build Coastguard Worker             {
618*35238bceSAndroid Build Coastguard Worker                 int *comp = (int *)(basePtr + offset);
619*35238bceSAndroid Build Coastguard Worker                 switch (precision)
620*35238bceSAndroid Build Coastguard Worker                 {
621*35238bceSAndroid Build Coastguard Worker                 case glu::PRECISION_LOWP:
622*35238bceSAndroid Build Coastguard Worker                     *comp = (int)signExtend(rnd.getUint32() & 0xff, 8);
623*35238bceSAndroid Build Coastguard Worker                     break;
624*35238bceSAndroid Build Coastguard Worker                 case glu::PRECISION_MEDIUMP:
625*35238bceSAndroid Build Coastguard Worker                     *comp = (int)signExtend(rnd.getUint32() & 0xffff, 16);
626*35238bceSAndroid Build Coastguard Worker                     break;
627*35238bceSAndroid Build Coastguard Worker                 case glu::PRECISION_HIGHP:
628*35238bceSAndroid Build Coastguard Worker                     *comp = (int)rnd.getUint32();
629*35238bceSAndroid Build Coastguard Worker                     break;
630*35238bceSAndroid Build Coastguard Worker                 default:
631*35238bceSAndroid Build Coastguard Worker                     DE_ASSERT(false);
632*35238bceSAndroid Build Coastguard Worker                 }
633*35238bceSAndroid Build Coastguard Worker             }
634*35238bceSAndroid Build Coastguard Worker             else if (isUint)
635*35238bceSAndroid Build Coastguard Worker             {
636*35238bceSAndroid Build Coastguard Worker                 uint32_t *comp = (uint32_t *)(basePtr + offset);
637*35238bceSAndroid Build Coastguard Worker                 switch (precision)
638*35238bceSAndroid Build Coastguard Worker                 {
639*35238bceSAndroid Build Coastguard Worker                 case glu::PRECISION_LOWP:
640*35238bceSAndroid Build Coastguard Worker                     *comp = rnd.getUint32() & 0xff;
641*35238bceSAndroid Build Coastguard Worker                     break;
642*35238bceSAndroid Build Coastguard Worker                 case glu::PRECISION_MEDIUMP:
643*35238bceSAndroid Build Coastguard Worker                     *comp = rnd.getUint32() & 0xffff;
644*35238bceSAndroid Build Coastguard Worker                     break;
645*35238bceSAndroid Build Coastguard Worker                 case glu::PRECISION_HIGHP:
646*35238bceSAndroid Build Coastguard Worker                     *comp = rnd.getUint32();
647*35238bceSAndroid Build Coastguard Worker                     break;
648*35238bceSAndroid Build Coastguard Worker                 default:
649*35238bceSAndroid Build Coastguard Worker                     DE_ASSERT(false);
650*35238bceSAndroid Build Coastguard Worker                 }
651*35238bceSAndroid Build Coastguard Worker             }
652*35238bceSAndroid Build Coastguard Worker             else
653*35238bceSAndroid Build Coastguard Worker                 DE_ASSERT(false);
654*35238bceSAndroid Build Coastguard Worker         }
655*35238bceSAndroid Build Coastguard Worker     }
656*35238bceSAndroid Build Coastguard Worker }
657*35238bceSAndroid Build Coastguard Worker 
genInputData(const vector<Attribute> & attributes,int numInputs,int inputStride,uint8_t * inputBasePtr,de::Random & rnd)658*35238bceSAndroid Build Coastguard Worker static void genInputData(const vector<Attribute> &attributes, int numInputs, int inputStride, uint8_t *inputBasePtr,
659*35238bceSAndroid Build Coastguard Worker                          de::Random &rnd)
660*35238bceSAndroid Build Coastguard Worker {
661*35238bceSAndroid Build Coastguard Worker     // Random positions.
662*35238bceSAndroid Build Coastguard Worker     const Attribute &position = *std::find_if(attributes.begin(), attributes.end(), AttributeNameEquals("a_position"));
663*35238bceSAndroid Build Coastguard Worker 
664*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < numInputs; ndx++)
665*35238bceSAndroid Build Coastguard Worker     {
666*35238bceSAndroid Build Coastguard Worker         uint8_t *ptr           = inputBasePtr + position.offset + inputStride * ndx;
667*35238bceSAndroid Build Coastguard Worker         *((float *)(ptr + 0))  = rnd.getFloat(-1.2f, 1.2f);
668*35238bceSAndroid Build Coastguard Worker         *((float *)(ptr + 4))  = rnd.getFloat(-1.2f, 1.2f);
669*35238bceSAndroid Build Coastguard Worker         *((float *)(ptr + 8))  = rnd.getFloat(-1.2f, 1.2f);
670*35238bceSAndroid Build Coastguard Worker         *((float *)(ptr + 12)) = rnd.getFloat(0.1f, 2.0f);
671*35238bceSAndroid Build Coastguard Worker     }
672*35238bceSAndroid Build Coastguard Worker 
673*35238bceSAndroid Build Coastguard Worker     // Point size.
674*35238bceSAndroid Build Coastguard Worker     vector<Attribute>::const_iterator pointSizePos =
675*35238bceSAndroid Build Coastguard Worker         std::find_if(attributes.begin(), attributes.end(), AttributeNameEquals("a_pointSize"));
676*35238bceSAndroid Build Coastguard Worker     if (pointSizePos != attributes.end())
677*35238bceSAndroid Build Coastguard Worker     {
678*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < numInputs; ndx++)
679*35238bceSAndroid Build Coastguard Worker         {
680*35238bceSAndroid Build Coastguard Worker             uint8_t *ptr    = inputBasePtr + pointSizePos->offset + inputStride * ndx;
681*35238bceSAndroid Build Coastguard Worker             *((float *)ptr) = rnd.getFloat(1.0f, 8.0f);
682*35238bceSAndroid Build Coastguard Worker         }
683*35238bceSAndroid Build Coastguard Worker     }
684*35238bceSAndroid Build Coastguard Worker 
685*35238bceSAndroid Build Coastguard Worker     // Random data for rest of components.
686*35238bceSAndroid Build Coastguard Worker     for (vector<Attribute>::const_iterator attrib = attributes.begin(); attrib != attributes.end(); attrib++)
687*35238bceSAndroid Build Coastguard Worker     {
688*35238bceSAndroid Build Coastguard Worker         if (attrib->name == "a_position" || attrib->name == "a_pointSize")
689*35238bceSAndroid Build Coastguard Worker             continue;
690*35238bceSAndroid Build Coastguard Worker 
691*35238bceSAndroid Build Coastguard Worker         genAttributeData(*attrib, inputBasePtr, inputStride, numInputs, rnd);
692*35238bceSAndroid Build Coastguard Worker     }
693*35238bceSAndroid Build Coastguard Worker }
694*35238bceSAndroid Build Coastguard Worker 
getTransformFeedbackOutputCount(uint32_t primitiveType,int numElements)695*35238bceSAndroid Build Coastguard Worker static uint32_t getTransformFeedbackOutputCount(uint32_t primitiveType, int numElements)
696*35238bceSAndroid Build Coastguard Worker {
697*35238bceSAndroid Build Coastguard Worker     switch (primitiveType)
698*35238bceSAndroid Build Coastguard Worker     {
699*35238bceSAndroid Build Coastguard Worker     case GL_TRIANGLES:
700*35238bceSAndroid Build Coastguard Worker         return numElements - numElements % 3;
701*35238bceSAndroid Build Coastguard Worker     case GL_TRIANGLE_STRIP:
702*35238bceSAndroid Build Coastguard Worker         return de::max(0, numElements - 2) * 3;
703*35238bceSAndroid Build Coastguard Worker     case GL_TRIANGLE_FAN:
704*35238bceSAndroid Build Coastguard Worker         return de::max(0, numElements - 2) * 3;
705*35238bceSAndroid Build Coastguard Worker     case GL_LINES:
706*35238bceSAndroid Build Coastguard Worker         return numElements - numElements % 2;
707*35238bceSAndroid Build Coastguard Worker     case GL_LINE_STRIP:
708*35238bceSAndroid Build Coastguard Worker         return de::max(0, numElements - 1) * 2;
709*35238bceSAndroid Build Coastguard Worker     case GL_LINE_LOOP:
710*35238bceSAndroid Build Coastguard Worker         return numElements > 1 ? numElements * 2 : 0;
711*35238bceSAndroid Build Coastguard Worker     case GL_POINTS:
712*35238bceSAndroid Build Coastguard Worker         return numElements;
713*35238bceSAndroid Build Coastguard Worker 
714*35238bceSAndroid Build Coastguard Worker     default:
715*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
716*35238bceSAndroid Build Coastguard Worker         return 0;
717*35238bceSAndroid Build Coastguard Worker     }
718*35238bceSAndroid Build Coastguard Worker }
719*35238bceSAndroid Build Coastguard Worker 
getTransformFeedbackPrimitiveCount(uint32_t primitiveType,int numElements)720*35238bceSAndroid Build Coastguard Worker static uint32_t getTransformFeedbackPrimitiveCount(uint32_t primitiveType, int numElements)
721*35238bceSAndroid Build Coastguard Worker {
722*35238bceSAndroid Build Coastguard Worker     switch (primitiveType)
723*35238bceSAndroid Build Coastguard Worker     {
724*35238bceSAndroid Build Coastguard Worker     case GL_TRIANGLES:
725*35238bceSAndroid Build Coastguard Worker         return numElements / 3;
726*35238bceSAndroid Build Coastguard Worker     case GL_TRIANGLE_STRIP:
727*35238bceSAndroid Build Coastguard Worker         return de::max(0, numElements - 2);
728*35238bceSAndroid Build Coastguard Worker     case GL_TRIANGLE_FAN:
729*35238bceSAndroid Build Coastguard Worker         return de::max(0, numElements - 2);
730*35238bceSAndroid Build Coastguard Worker     case GL_LINES:
731*35238bceSAndroid Build Coastguard Worker         return numElements / 2;
732*35238bceSAndroid Build Coastguard Worker     case GL_LINE_STRIP:
733*35238bceSAndroid Build Coastguard Worker         return de::max(0, numElements - 1);
734*35238bceSAndroid Build Coastguard Worker     case GL_LINE_LOOP:
735*35238bceSAndroid Build Coastguard Worker         return numElements > 1 ? numElements : 0;
736*35238bceSAndroid Build Coastguard Worker     case GL_POINTS:
737*35238bceSAndroid Build Coastguard Worker         return numElements;
738*35238bceSAndroid Build Coastguard Worker 
739*35238bceSAndroid Build Coastguard Worker     default:
740*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
741*35238bceSAndroid Build Coastguard Worker         return 0;
742*35238bceSAndroid Build Coastguard Worker     }
743*35238bceSAndroid Build Coastguard Worker }
744*35238bceSAndroid Build Coastguard Worker 
getTransformFeedbackPrimitiveMode(uint32_t primitiveType)745*35238bceSAndroid Build Coastguard Worker static uint32_t getTransformFeedbackPrimitiveMode(uint32_t primitiveType)
746*35238bceSAndroid Build Coastguard Worker {
747*35238bceSAndroid Build Coastguard Worker     switch (primitiveType)
748*35238bceSAndroid Build Coastguard Worker     {
749*35238bceSAndroid Build Coastguard Worker     case GL_TRIANGLES:
750*35238bceSAndroid Build Coastguard Worker     case GL_TRIANGLE_STRIP:
751*35238bceSAndroid Build Coastguard Worker     case GL_TRIANGLE_FAN:
752*35238bceSAndroid Build Coastguard Worker         return GL_TRIANGLES;
753*35238bceSAndroid Build Coastguard Worker 
754*35238bceSAndroid Build Coastguard Worker     case GL_LINES:
755*35238bceSAndroid Build Coastguard Worker     case GL_LINE_LOOP:
756*35238bceSAndroid Build Coastguard Worker     case GL_LINE_STRIP:
757*35238bceSAndroid Build Coastguard Worker         return GL_LINES;
758*35238bceSAndroid Build Coastguard Worker 
759*35238bceSAndroid Build Coastguard Worker     case GL_POINTS:
760*35238bceSAndroid Build Coastguard Worker         return GL_POINTS;
761*35238bceSAndroid Build Coastguard Worker 
762*35238bceSAndroid Build Coastguard Worker     default:
763*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
764*35238bceSAndroid Build Coastguard Worker         return 0;
765*35238bceSAndroid Build Coastguard Worker     }
766*35238bceSAndroid Build Coastguard Worker }
767*35238bceSAndroid Build Coastguard Worker 
getAttributeIndex(uint32_t primitiveType,int numInputs,int outNdx)768*35238bceSAndroid Build Coastguard Worker static int getAttributeIndex(uint32_t primitiveType, int numInputs, int outNdx)
769*35238bceSAndroid Build Coastguard Worker {
770*35238bceSAndroid Build Coastguard Worker     switch (primitiveType)
771*35238bceSAndroid Build Coastguard Worker     {
772*35238bceSAndroid Build Coastguard Worker     case GL_TRIANGLES:
773*35238bceSAndroid Build Coastguard Worker         return outNdx;
774*35238bceSAndroid Build Coastguard Worker     case GL_LINES:
775*35238bceSAndroid Build Coastguard Worker         return outNdx;
776*35238bceSAndroid Build Coastguard Worker     case GL_POINTS:
777*35238bceSAndroid Build Coastguard Worker         return outNdx;
778*35238bceSAndroid Build Coastguard Worker 
779*35238bceSAndroid Build Coastguard Worker     case GL_TRIANGLE_STRIP:
780*35238bceSAndroid Build Coastguard Worker     {
781*35238bceSAndroid Build Coastguard Worker         int triNdx = outNdx / 3;
782*35238bceSAndroid Build Coastguard Worker         int vtxNdx = outNdx % 3;
783*35238bceSAndroid Build Coastguard Worker         return (triNdx % 2 != 0 && vtxNdx < 2) ? (triNdx + 1 - vtxNdx) : (triNdx + vtxNdx);
784*35238bceSAndroid Build Coastguard Worker     }
785*35238bceSAndroid Build Coastguard Worker 
786*35238bceSAndroid Build Coastguard Worker     case GL_TRIANGLE_FAN:
787*35238bceSAndroid Build Coastguard Worker         return (outNdx % 3 != 0) ? (outNdx / 3 + outNdx % 3) : 0;
788*35238bceSAndroid Build Coastguard Worker 
789*35238bceSAndroid Build Coastguard Worker     case GL_LINE_STRIP:
790*35238bceSAndroid Build Coastguard Worker         return outNdx / 2 + outNdx % 2;
791*35238bceSAndroid Build Coastguard Worker 
792*35238bceSAndroid Build Coastguard Worker     case GL_LINE_LOOP:
793*35238bceSAndroid Build Coastguard Worker     {
794*35238bceSAndroid Build Coastguard Worker         int inNdx = outNdx / 2 + outNdx % 2;
795*35238bceSAndroid Build Coastguard Worker         return inNdx < numInputs ? inNdx : 0;
796*35238bceSAndroid Build Coastguard Worker     }
797*35238bceSAndroid Build Coastguard Worker 
798*35238bceSAndroid Build Coastguard Worker     default:
799*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
800*35238bceSAndroid Build Coastguard Worker         return 0;
801*35238bceSAndroid Build Coastguard Worker     }
802*35238bceSAndroid Build Coastguard Worker }
803*35238bceSAndroid Build Coastguard Worker 
compareTransformFeedbackOutput(tcu::TestLog & log,uint32_t primitiveType,const Output & output,int numInputs,const uint8_t * inBasePtr,int inStride,const uint8_t * outBasePtr,int outStride)804*35238bceSAndroid Build Coastguard Worker static bool compareTransformFeedbackOutput(tcu::TestLog &log, uint32_t primitiveType, const Output &output,
805*35238bceSAndroid Build Coastguard Worker                                            int numInputs, const uint8_t *inBasePtr, int inStride,
806*35238bceSAndroid Build Coastguard Worker                                            const uint8_t *outBasePtr, int outStride)
807*35238bceSAndroid Build Coastguard Worker {
808*35238bceSAndroid Build Coastguard Worker     bool isOk     = true;
809*35238bceSAndroid Build Coastguard Worker     int outOffset = output.offset;
810*35238bceSAndroid Build Coastguard Worker 
811*35238bceSAndroid Build Coastguard Worker     for (int attrNdx = 0; attrNdx < (int)output.inputs.size(); attrNdx++)
812*35238bceSAndroid Build Coastguard Worker     {
813*35238bceSAndroid Build Coastguard Worker         const Attribute &attribute = *output.inputs[attrNdx];
814*35238bceSAndroid Build Coastguard Worker         glu::DataType type         = attribute.type.getBasicType();
815*35238bceSAndroid Build Coastguard Worker         int numComponents          = glu::getDataTypeScalarSize(type);
816*35238bceSAndroid Build Coastguard Worker         glu::Precision precision   = attribute.type.getPrecision();
817*35238bceSAndroid Build Coastguard Worker         glu::DataType scalarType   = glu::getDataTypeScalarType(type);
818*35238bceSAndroid Build Coastguard Worker         int numOutputs             = getTransformFeedbackOutputCount(primitiveType, numInputs);
819*35238bceSAndroid Build Coastguard Worker 
820*35238bceSAndroid Build Coastguard Worker         for (int outNdx = 0; outNdx < numOutputs; outNdx++)
821*35238bceSAndroid Build Coastguard Worker         {
822*35238bceSAndroid Build Coastguard Worker             int inNdx = getAttributeIndex(primitiveType, numInputs, outNdx);
823*35238bceSAndroid Build Coastguard Worker 
824*35238bceSAndroid Build Coastguard Worker             for (int compNdx = 0; compNdx < numComponents; compNdx++)
825*35238bceSAndroid Build Coastguard Worker             {
826*35238bceSAndroid Build Coastguard Worker                 const uint8_t *inPtr  = inBasePtr + inStride * inNdx + attribute.offset + compNdx * sizeof(uint32_t);
827*35238bceSAndroid Build Coastguard Worker                 const uint8_t *outPtr = outBasePtr + outStride * outNdx + outOffset + compNdx * sizeof(uint32_t);
828*35238bceSAndroid Build Coastguard Worker                 uint32_t inVal        = *(const uint32_t *)inPtr;
829*35238bceSAndroid Build Coastguard Worker                 uint32_t outVal       = *(const uint32_t *)outPtr;
830*35238bceSAndroid Build Coastguard Worker                 bool isEqual          = false;
831*35238bceSAndroid Build Coastguard Worker 
832*35238bceSAndroid Build Coastguard Worker                 if (scalarType == glu::TYPE_FLOAT)
833*35238bceSAndroid Build Coastguard Worker                 {
834*35238bceSAndroid Build Coastguard Worker                     // ULP comparison is used for highp and mediump. Lowp uses threshold-comparison.
835*35238bceSAndroid Build Coastguard Worker                     switch (precision)
836*35238bceSAndroid Build Coastguard Worker                     {
837*35238bceSAndroid Build Coastguard Worker                     case glu::PRECISION_HIGHP:
838*35238bceSAndroid Build Coastguard Worker                         isEqual = de::abs((int)inVal - (int)outVal) < 2;
839*35238bceSAndroid Build Coastguard Worker                         break;
840*35238bceSAndroid Build Coastguard Worker                     case glu::PRECISION_MEDIUMP:
841*35238bceSAndroid Build Coastguard Worker                         isEqual = de::abs((int)inVal - (int)outVal) < 2 + (1 << 13);
842*35238bceSAndroid Build Coastguard Worker                         break;
843*35238bceSAndroid Build Coastguard Worker                     case glu::PRECISION_LOWP:
844*35238bceSAndroid Build Coastguard Worker                     {
845*35238bceSAndroid Build Coastguard Worker                         float inF  = *(const float *)inPtr;
846*35238bceSAndroid Build Coastguard Worker                         float outF = *(const float *)outPtr;
847*35238bceSAndroid Build Coastguard Worker                         isEqual    = de::abs(inF - outF) < 0.1f;
848*35238bceSAndroid Build Coastguard Worker                         break;
849*35238bceSAndroid Build Coastguard Worker                     }
850*35238bceSAndroid Build Coastguard Worker                     default:
851*35238bceSAndroid Build Coastguard Worker                         DE_ASSERT(false);
852*35238bceSAndroid Build Coastguard Worker                     }
853*35238bceSAndroid Build Coastguard Worker                 }
854*35238bceSAndroid Build Coastguard Worker                 else
855*35238bceSAndroid Build Coastguard Worker                     isEqual = (inVal == outVal); // Bit-exact match required for integer types.
856*35238bceSAndroid Build Coastguard Worker 
857*35238bceSAndroid Build Coastguard Worker                 if (!isEqual)
858*35238bceSAndroid Build Coastguard Worker                 {
859*35238bceSAndroid Build Coastguard Worker                     log << TestLog::Message << "Mismatch in " << output.name << " (" << attribute.name
860*35238bceSAndroid Build Coastguard Worker                         << "), output = " << outNdx << ", input = " << inNdx << ", component = " << compNdx
861*35238bceSAndroid Build Coastguard Worker                         << TestLog::EndMessage;
862*35238bceSAndroid Build Coastguard Worker                     isOk = false;
863*35238bceSAndroid Build Coastguard Worker                     break;
864*35238bceSAndroid Build Coastguard Worker                 }
865*35238bceSAndroid Build Coastguard Worker             }
866*35238bceSAndroid Build Coastguard Worker 
867*35238bceSAndroid Build Coastguard Worker             if (!isOk)
868*35238bceSAndroid Build Coastguard Worker                 break;
869*35238bceSAndroid Build Coastguard Worker         }
870*35238bceSAndroid Build Coastguard Worker 
871*35238bceSAndroid Build Coastguard Worker         if (!isOk)
872*35238bceSAndroid Build Coastguard Worker             break;
873*35238bceSAndroid Build Coastguard Worker 
874*35238bceSAndroid Build Coastguard Worker         outOffset += numComponents * (int)sizeof(uint32_t);
875*35238bceSAndroid Build Coastguard Worker     }
876*35238bceSAndroid Build Coastguard Worker 
877*35238bceSAndroid Build Coastguard Worker     return isOk;
878*35238bceSAndroid Build Coastguard Worker }
879*35238bceSAndroid Build Coastguard Worker 
computeTransformFeedbackPrimitiveCount(uint32_t primitiveType,const DrawCall * first,const DrawCall * end)880*35238bceSAndroid Build Coastguard Worker static int computeTransformFeedbackPrimitiveCount(uint32_t primitiveType, const DrawCall *first, const DrawCall *end)
881*35238bceSAndroid Build Coastguard Worker {
882*35238bceSAndroid Build Coastguard Worker     int primCount = 0;
883*35238bceSAndroid Build Coastguard Worker 
884*35238bceSAndroid Build Coastguard Worker     for (const DrawCall *call = first; call != end; ++call)
885*35238bceSAndroid Build Coastguard Worker     {
886*35238bceSAndroid Build Coastguard Worker         if (call->transformFeedbackEnabled)
887*35238bceSAndroid Build Coastguard Worker             primCount += getTransformFeedbackPrimitiveCount(primitiveType, call->numElements);
888*35238bceSAndroid Build Coastguard Worker     }
889*35238bceSAndroid Build Coastguard Worker 
890*35238bceSAndroid Build Coastguard Worker     return primCount;
891*35238bceSAndroid Build Coastguard Worker }
892*35238bceSAndroid Build Coastguard Worker 
writeBufferGuard(const glw::Functions & gl,uint32_t target,int bufferSize,int guardSize)893*35238bceSAndroid Build Coastguard Worker static void writeBufferGuard(const glw::Functions &gl, uint32_t target, int bufferSize, int guardSize)
894*35238bceSAndroid Build Coastguard Worker {
895*35238bceSAndroid Build Coastguard Worker     uint8_t *ptr = (uint8_t *)gl.mapBufferRange(target, bufferSize, guardSize, GL_MAP_WRITE_BIT);
896*35238bceSAndroid Build Coastguard Worker     if (ptr)
897*35238bceSAndroid Build Coastguard Worker         deMemset(ptr, 0xcd, guardSize);
898*35238bceSAndroid Build Coastguard Worker     gl.unmapBuffer(target);
899*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "guardband write");
900*35238bceSAndroid Build Coastguard Worker }
901*35238bceSAndroid Build Coastguard Worker 
verifyGuard(const uint8_t * ptr,int guardSize)902*35238bceSAndroid Build Coastguard Worker static bool verifyGuard(const uint8_t *ptr, int guardSize)
903*35238bceSAndroid Build Coastguard Worker {
904*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < guardSize; ndx++)
905*35238bceSAndroid Build Coastguard Worker     {
906*35238bceSAndroid Build Coastguard Worker         if (ptr[ndx] != 0xcd)
907*35238bceSAndroid Build Coastguard Worker             return false;
908*35238bceSAndroid Build Coastguard Worker     }
909*35238bceSAndroid Build Coastguard Worker     return true;
910*35238bceSAndroid Build Coastguard Worker }
911*35238bceSAndroid Build Coastguard Worker 
logTransformFeedbackVaryings(TestLog & log,const glw::Functions & gl,uint32_t program)912*35238bceSAndroid Build Coastguard Worker static void logTransformFeedbackVaryings(TestLog &log, const glw::Functions &gl, uint32_t program)
913*35238bceSAndroid Build Coastguard Worker {
914*35238bceSAndroid Build Coastguard Worker     int numTfVaryings = 0;
915*35238bceSAndroid Build Coastguard Worker     int maxNameLen    = 0;
916*35238bceSAndroid Build Coastguard Worker 
917*35238bceSAndroid Build Coastguard Worker     gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYINGS, &numTfVaryings);
918*35238bceSAndroid Build Coastguard Worker     gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &maxNameLen);
919*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "Query TF varyings");
920*35238bceSAndroid Build Coastguard Worker 
921*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "GL_TRANSFORM_FEEDBACK_VARYINGS = " << numTfVaryings << TestLog::EndMessage;
922*35238bceSAndroid Build Coastguard Worker 
923*35238bceSAndroid Build Coastguard Worker     vector<char> nameBuf(maxNameLen + 1);
924*35238bceSAndroid Build Coastguard Worker 
925*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < numTfVaryings; ndx++)
926*35238bceSAndroid Build Coastguard Worker     {
927*35238bceSAndroid Build Coastguard Worker         glw::GLsizei size = 0;
928*35238bceSAndroid Build Coastguard Worker         glw::GLenum type  = 0;
929*35238bceSAndroid Build Coastguard Worker 
930*35238bceSAndroid Build Coastguard Worker         gl.getTransformFeedbackVarying(program, ndx, (glw::GLsizei)nameBuf.size(), DE_NULL, &size, &type, &nameBuf[0]);
931*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTransformFeedbackVarying()");
932*35238bceSAndroid Build Coastguard Worker 
933*35238bceSAndroid Build Coastguard Worker         const glu::DataType dataType = glu::getDataTypeFromGLType(type);
934*35238bceSAndroid Build Coastguard Worker         const std::string typeName   = dataType != glu::TYPE_LAST ?
935*35238bceSAndroid Build Coastguard Worker                                            std::string(glu::getDataTypeName(dataType)) :
936*35238bceSAndroid Build Coastguard Worker                                            (std::string("unknown(") + tcu::toHex(type).toString() + ")");
937*35238bceSAndroid Build Coastguard Worker 
938*35238bceSAndroid Build Coastguard Worker         log << TestLog::Message << (const char *)&nameBuf[0] << ": " << typeName << "[" << size << "]"
939*35238bceSAndroid Build Coastguard Worker             << TestLog::EndMessage;
940*35238bceSAndroid Build Coastguard Worker     }
941*35238bceSAndroid Build Coastguard Worker }
942*35238bceSAndroid Build Coastguard Worker 
943*35238bceSAndroid Build Coastguard Worker class TransformFeedbackCase : public TestCase
944*35238bceSAndroid Build Coastguard Worker {
945*35238bceSAndroid Build Coastguard Worker public:
946*35238bceSAndroid Build Coastguard Worker     TransformFeedbackCase(Context &context, const char *name, const char *desc, uint32_t bufferMode,
947*35238bceSAndroid Build Coastguard Worker                           uint32_t primitiveType);
948*35238bceSAndroid Build Coastguard Worker     ~TransformFeedbackCase(void);
949*35238bceSAndroid Build Coastguard Worker 
950*35238bceSAndroid Build Coastguard Worker     void init(void);
951*35238bceSAndroid Build Coastguard Worker     void deinit(void);
952*35238bceSAndroid Build Coastguard Worker     IterateResult iterate(void);
953*35238bceSAndroid Build Coastguard Worker 
954*35238bceSAndroid Build Coastguard Worker protected:
955*35238bceSAndroid Build Coastguard Worker     ProgramSpec m_progSpec;
956*35238bceSAndroid Build Coastguard Worker     uint32_t m_bufferMode;
957*35238bceSAndroid Build Coastguard Worker     uint32_t m_primitiveType;
958*35238bceSAndroid Build Coastguard Worker 
959*35238bceSAndroid Build Coastguard Worker private:
960*35238bceSAndroid Build Coastguard Worker     TransformFeedbackCase(const TransformFeedbackCase &other);
961*35238bceSAndroid Build Coastguard Worker     TransformFeedbackCase &operator=(const TransformFeedbackCase &other);
962*35238bceSAndroid Build Coastguard Worker 
963*35238bceSAndroid Build Coastguard Worker     bool runTest(const DrawCall *first, const DrawCall *end, uint32_t seed);
964*35238bceSAndroid Build Coastguard Worker 
965*35238bceSAndroid Build Coastguard Worker     // Derived from ProgramSpec in init()
966*35238bceSAndroid Build Coastguard Worker     int m_inputStride;
967*35238bceSAndroid Build Coastguard Worker     vector<Attribute> m_attributes;
968*35238bceSAndroid Build Coastguard Worker     vector<Output> m_transformFeedbackOutputs;
969*35238bceSAndroid Build Coastguard Worker     vector<int> m_bufferStrides;
970*35238bceSAndroid Build Coastguard Worker 
971*35238bceSAndroid Build Coastguard Worker     // GL state.
972*35238bceSAndroid Build Coastguard Worker     glu::ShaderProgram *m_program;
973*35238bceSAndroid Build Coastguard Worker     glu::TransformFeedback *m_transformFeedback;
974*35238bceSAndroid Build Coastguard Worker     vector<uint32_t> m_outputBuffers;
975*35238bceSAndroid Build Coastguard Worker 
976*35238bceSAndroid Build Coastguard Worker     int m_iterNdx;
977*35238bceSAndroid Build Coastguard Worker };
978*35238bceSAndroid Build Coastguard Worker 
TransformFeedbackCase(Context & context,const char * name,const char * desc,uint32_t bufferMode,uint32_t primitiveType)979*35238bceSAndroid Build Coastguard Worker TransformFeedbackCase::TransformFeedbackCase(Context &context, const char *name, const char *desc, uint32_t bufferMode,
980*35238bceSAndroid Build Coastguard Worker                                              uint32_t primitiveType)
981*35238bceSAndroid Build Coastguard Worker     : TestCase(context, name, desc)
982*35238bceSAndroid Build Coastguard Worker     , m_bufferMode(bufferMode)
983*35238bceSAndroid Build Coastguard Worker     , m_primitiveType(primitiveType)
984*35238bceSAndroid Build Coastguard Worker     , m_inputStride(0)
985*35238bceSAndroid Build Coastguard Worker     , m_program(DE_NULL)
986*35238bceSAndroid Build Coastguard Worker     , m_transformFeedback(DE_NULL)
987*35238bceSAndroid Build Coastguard Worker     , m_iterNdx(0)
988*35238bceSAndroid Build Coastguard Worker {
989*35238bceSAndroid Build Coastguard Worker }
990*35238bceSAndroid Build Coastguard Worker 
~TransformFeedbackCase(void)991*35238bceSAndroid Build Coastguard Worker TransformFeedbackCase::~TransformFeedbackCase(void)
992*35238bceSAndroid Build Coastguard Worker {
993*35238bceSAndroid Build Coastguard Worker     TransformFeedbackCase::deinit();
994*35238bceSAndroid Build Coastguard Worker }
995*35238bceSAndroid Build Coastguard Worker 
hasArraysInTFVaryings(const ProgramSpec & spec)996*35238bceSAndroid Build Coastguard Worker static bool hasArraysInTFVaryings(const ProgramSpec &spec)
997*35238bceSAndroid Build Coastguard Worker {
998*35238bceSAndroid Build Coastguard Worker     for (vector<string>::const_iterator tfVar = spec.getTransformFeedbackVaryings().begin();
999*35238bceSAndroid Build Coastguard Worker          tfVar != spec.getTransformFeedbackVaryings().end(); ++tfVar)
1000*35238bceSAndroid Build Coastguard Worker     {
1001*35238bceSAndroid Build Coastguard Worker         string varName = glu::parseVariableName(tfVar->c_str());
1002*35238bceSAndroid Build Coastguard Worker         vector<Varying>::const_iterator varIter =
1003*35238bceSAndroid Build Coastguard Worker             std::find_if(spec.getVaryings().begin(), spec.getVaryings().end(), VaryingNameEquals(varName));
1004*35238bceSAndroid Build Coastguard Worker 
1005*35238bceSAndroid Build Coastguard Worker         if (varName == "gl_Position" || varName == "gl_PointSize")
1006*35238bceSAndroid Build Coastguard Worker             continue;
1007*35238bceSAndroid Build Coastguard Worker 
1008*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(varIter != spec.getVaryings().end());
1009*35238bceSAndroid Build Coastguard Worker 
1010*35238bceSAndroid Build Coastguard Worker         if (varIter->type.isArrayType())
1011*35238bceSAndroid Build Coastguard Worker             return true;
1012*35238bceSAndroid Build Coastguard Worker     }
1013*35238bceSAndroid Build Coastguard Worker 
1014*35238bceSAndroid Build Coastguard Worker     return false;
1015*35238bceSAndroid Build Coastguard Worker }
1016*35238bceSAndroid Build Coastguard Worker 
init(void)1017*35238bceSAndroid Build Coastguard Worker void TransformFeedbackCase::init(void)
1018*35238bceSAndroid Build Coastguard Worker {
1019*35238bceSAndroid Build Coastguard Worker     TestLog &log             = m_testCtx.getLog();
1020*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1021*35238bceSAndroid Build Coastguard Worker 
1022*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!m_program);
1023*35238bceSAndroid Build Coastguard Worker     m_program = createVertexCaptureProgram(m_context.getRenderContext(), m_progSpec, m_bufferMode, m_primitiveType);
1024*35238bceSAndroid Build Coastguard Worker 
1025*35238bceSAndroid Build Coastguard Worker     log << *m_program;
1026*35238bceSAndroid Build Coastguard Worker     if (!m_program->isOk())
1027*35238bceSAndroid Build Coastguard Worker     {
1028*35238bceSAndroid Build Coastguard Worker         const bool linkFail = m_program->getShaderInfo(glu::SHADERTYPE_VERTEX).compileOk &&
1029*35238bceSAndroid Build Coastguard Worker                               m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk &&
1030*35238bceSAndroid Build Coastguard Worker                               !m_program->getProgramInfo().linkOk;
1031*35238bceSAndroid Build Coastguard Worker 
1032*35238bceSAndroid Build Coastguard Worker         if (linkFail)
1033*35238bceSAndroid Build Coastguard Worker         {
1034*35238bceSAndroid Build Coastguard Worker             if (!isProgramSupported(gl, m_progSpec, m_bufferMode))
1035*35238bceSAndroid Build Coastguard Worker                 throw tcu::NotSupportedError("Implementation limits execeeded", "", __FILE__, __LINE__);
1036*35238bceSAndroid Build Coastguard Worker             else if (hasArraysInTFVaryings(m_progSpec))
1037*35238bceSAndroid Build Coastguard Worker                 throw tcu::NotSupportedError("Capturing arrays is not supported (undefined in specification)", "",
1038*35238bceSAndroid Build Coastguard Worker                                              __FILE__, __LINE__);
1039*35238bceSAndroid Build Coastguard Worker             else
1040*35238bceSAndroid Build Coastguard Worker                 throw tcu::TestError("Link failed", "", __FILE__, __LINE__);
1041*35238bceSAndroid Build Coastguard Worker         }
1042*35238bceSAndroid Build Coastguard Worker         else
1043*35238bceSAndroid Build Coastguard Worker             throw tcu::TestError("Compile failed", "", __FILE__, __LINE__);
1044*35238bceSAndroid Build Coastguard Worker     }
1045*35238bceSAndroid Build Coastguard Worker 
1046*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "Transform feedback varyings: "
1047*35238bceSAndroid Build Coastguard Worker         << tcu::formatArray(m_progSpec.getTransformFeedbackVaryings().begin(),
1048*35238bceSAndroid Build Coastguard Worker                             m_progSpec.getTransformFeedbackVaryings().end())
1049*35238bceSAndroid Build Coastguard Worker         << TestLog::EndMessage;
1050*35238bceSAndroid Build Coastguard Worker 
1051*35238bceSAndroid Build Coastguard Worker     // Print out transform feedback points reported by GL.
1052*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "Transform feedback varyings reported by compiler:" << TestLog::EndMessage;
1053*35238bceSAndroid Build Coastguard Worker     logTransformFeedbackVaryings(log, gl, m_program->getProgram());
1054*35238bceSAndroid Build Coastguard Worker 
1055*35238bceSAndroid Build Coastguard Worker     // Compute input specification.
1056*35238bceSAndroid Build Coastguard Worker     computeInputLayout(m_attributes, m_inputStride, m_progSpec.getVaryings(), m_progSpec.isPointSizeUsed());
1057*35238bceSAndroid Build Coastguard Worker 
1058*35238bceSAndroid Build Coastguard Worker     // Build list of varyings used in transform feedback.
1059*35238bceSAndroid Build Coastguard Worker     computeTransformFeedbackOutputs(m_transformFeedbackOutputs, m_attributes, m_progSpec.getVaryings(),
1060*35238bceSAndroid Build Coastguard Worker                                     m_progSpec.getTransformFeedbackVaryings(), m_bufferMode);
1061*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!m_transformFeedbackOutputs.empty());
1062*35238bceSAndroid Build Coastguard Worker 
1063*35238bceSAndroid Build Coastguard Worker     // Buffer strides.
1064*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(m_bufferStrides.empty());
1065*35238bceSAndroid Build Coastguard Worker     if (m_bufferMode == GL_SEPARATE_ATTRIBS)
1066*35238bceSAndroid Build Coastguard Worker     {
1067*35238bceSAndroid Build Coastguard Worker         for (vector<Output>::const_iterator outIter = m_transformFeedbackOutputs.begin();
1068*35238bceSAndroid Build Coastguard Worker              outIter != m_transformFeedbackOutputs.end(); outIter++)
1069*35238bceSAndroid Build Coastguard Worker             m_bufferStrides.push_back(outIter->type.getScalarSize() * (int)sizeof(uint32_t));
1070*35238bceSAndroid Build Coastguard Worker     }
1071*35238bceSAndroid Build Coastguard Worker     else
1072*35238bceSAndroid Build Coastguard Worker     {
1073*35238bceSAndroid Build Coastguard Worker         int totalSize = 0;
1074*35238bceSAndroid Build Coastguard Worker         for (vector<Output>::const_iterator outIter = m_transformFeedbackOutputs.begin();
1075*35238bceSAndroid Build Coastguard Worker              outIter != m_transformFeedbackOutputs.end(); outIter++)
1076*35238bceSAndroid Build Coastguard Worker             totalSize += outIter->type.getScalarSize() * (int)sizeof(uint32_t);
1077*35238bceSAndroid Build Coastguard Worker 
1078*35238bceSAndroid Build Coastguard Worker         m_bufferStrides.push_back(totalSize);
1079*35238bceSAndroid Build Coastguard Worker     }
1080*35238bceSAndroid Build Coastguard Worker 
1081*35238bceSAndroid Build Coastguard Worker     // \note Actual storage is allocated in iterate().
1082*35238bceSAndroid Build Coastguard Worker     m_outputBuffers.resize(m_bufferStrides.size());
1083*35238bceSAndroid Build Coastguard Worker     gl.genBuffers((glw::GLsizei)m_outputBuffers.size(), &m_outputBuffers[0]);
1084*35238bceSAndroid Build Coastguard Worker 
1085*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!m_transformFeedback);
1086*35238bceSAndroid Build Coastguard Worker     m_transformFeedback = new glu::TransformFeedback(m_context.getRenderContext());
1087*35238bceSAndroid Build Coastguard Worker 
1088*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "init");
1089*35238bceSAndroid Build Coastguard Worker 
1090*35238bceSAndroid Build Coastguard Worker     m_iterNdx = 0;
1091*35238bceSAndroid Build Coastguard Worker     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1092*35238bceSAndroid Build Coastguard Worker }
1093*35238bceSAndroid Build Coastguard Worker 
deinit(void)1094*35238bceSAndroid Build Coastguard Worker void TransformFeedbackCase::deinit(void)
1095*35238bceSAndroid Build Coastguard Worker {
1096*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1097*35238bceSAndroid Build Coastguard Worker 
1098*35238bceSAndroid Build Coastguard Worker     if (!m_outputBuffers.empty())
1099*35238bceSAndroid Build Coastguard Worker     {
1100*35238bceSAndroid Build Coastguard Worker         gl.deleteBuffers((glw::GLsizei)m_outputBuffers.size(), &m_outputBuffers[0]);
1101*35238bceSAndroid Build Coastguard Worker         m_outputBuffers.clear();
1102*35238bceSAndroid Build Coastguard Worker     }
1103*35238bceSAndroid Build Coastguard Worker 
1104*35238bceSAndroid Build Coastguard Worker     delete m_transformFeedback;
1105*35238bceSAndroid Build Coastguard Worker     m_transformFeedback = DE_NULL;
1106*35238bceSAndroid Build Coastguard Worker 
1107*35238bceSAndroid Build Coastguard Worker     delete m_program;
1108*35238bceSAndroid Build Coastguard Worker     m_program = DE_NULL;
1109*35238bceSAndroid Build Coastguard Worker 
1110*35238bceSAndroid Build Coastguard Worker     // Clean up state.
1111*35238bceSAndroid Build Coastguard Worker     m_attributes.clear();
1112*35238bceSAndroid Build Coastguard Worker     m_transformFeedbackOutputs.clear();
1113*35238bceSAndroid Build Coastguard Worker     m_bufferStrides.clear();
1114*35238bceSAndroid Build Coastguard Worker     m_inputStride = 0;
1115*35238bceSAndroid Build Coastguard Worker }
1116*35238bceSAndroid Build Coastguard Worker 
iterate(void)1117*35238bceSAndroid Build Coastguard Worker TransformFeedbackCase::IterateResult TransformFeedbackCase::iterate(void)
1118*35238bceSAndroid Build Coastguard Worker {
1119*35238bceSAndroid Build Coastguard Worker     // Test cases.
1120*35238bceSAndroid Build Coastguard Worker     static const DrawCall s_elemCount1[]   = {DrawCall(1, true)};
1121*35238bceSAndroid Build Coastguard Worker     static const DrawCall s_elemCount2[]   = {DrawCall(2, true)};
1122*35238bceSAndroid Build Coastguard Worker     static const DrawCall s_elemCount3[]   = {DrawCall(3, true)};
1123*35238bceSAndroid Build Coastguard Worker     static const DrawCall s_elemCount4[]   = {DrawCall(4, true)};
1124*35238bceSAndroid Build Coastguard Worker     static const DrawCall s_elemCount123[] = {DrawCall(123, true)};
1125*35238bceSAndroid Build Coastguard Worker     static const DrawCall s_basicPause1[]  = {DrawCall(64, true), DrawCall(64, false), DrawCall(64, true)};
1126*35238bceSAndroid Build Coastguard Worker     static const DrawCall s_basicPause2[]  = {DrawCall(13, true), DrawCall(5, true), DrawCall(17, false),
1127*35238bceSAndroid Build Coastguard Worker                                               DrawCall(3, true), DrawCall(7, false)};
1128*35238bceSAndroid Build Coastguard Worker     static const DrawCall s_startPaused[]  = {DrawCall(123, false), DrawCall(123, true)};
1129*35238bceSAndroid Build Coastguard Worker     static const DrawCall s_random1[]      = {DrawCall(65, true),  DrawCall(135, false), DrawCall(74, true),
1130*35238bceSAndroid Build Coastguard Worker                                               DrawCall(16, false), DrawCall(226, false), DrawCall(9, true),
1131*35238bceSAndroid Build Coastguard Worker                                               DrawCall(174, false)};
1132*35238bceSAndroid Build Coastguard Worker     static const DrawCall s_random2[]      = {DrawCall(217, true), DrawCall(171, true), DrawCall(147, true),
1133*35238bceSAndroid Build Coastguard Worker                                               DrawCall(152, false), DrawCall(55, true)};
1134*35238bceSAndroid Build Coastguard Worker 
1135*35238bceSAndroid Build Coastguard Worker     static const struct
1136*35238bceSAndroid Build Coastguard Worker     {
1137*35238bceSAndroid Build Coastguard Worker         const DrawCall *calls;
1138*35238bceSAndroid Build Coastguard Worker         int numCalls;
1139*35238bceSAndroid Build Coastguard Worker     } s_iterations[] = {
1140*35238bceSAndroid Build Coastguard Worker #define ITER(ARR) {ARR, DE_LENGTH_OF_ARRAY(ARR)}
1141*35238bceSAndroid Build Coastguard Worker         ITER(s_elemCount1),   ITER(s_elemCount2),  ITER(s_elemCount3),  ITER(s_elemCount4),
1142*35238bceSAndroid Build Coastguard Worker         ITER(s_elemCount123), ITER(s_basicPause1), ITER(s_basicPause2), ITER(s_startPaused),
1143*35238bceSAndroid Build Coastguard Worker         ITER(s_random1),      ITER(s_random2)
1144*35238bceSAndroid Build Coastguard Worker #undef ITER
1145*35238bceSAndroid Build Coastguard Worker     };
1146*35238bceSAndroid Build Coastguard Worker 
1147*35238bceSAndroid Build Coastguard Worker     TestLog &log          = m_testCtx.getLog();
1148*35238bceSAndroid Build Coastguard Worker     bool isOk             = true;
1149*35238bceSAndroid Build Coastguard Worker     uint32_t seed         = deStringHash(getName()) ^ deInt32Hash(m_iterNdx);
1150*35238bceSAndroid Build Coastguard Worker     int numIterations     = DE_LENGTH_OF_ARRAY(s_iterations);
1151*35238bceSAndroid Build Coastguard Worker     const DrawCall *first = s_iterations[m_iterNdx].calls;
1152*35238bceSAndroid Build Coastguard Worker     const DrawCall *end   = s_iterations[m_iterNdx].calls + s_iterations[m_iterNdx].numCalls;
1153*35238bceSAndroid Build Coastguard Worker 
1154*35238bceSAndroid Build Coastguard Worker     std::string sectionName = std::string("Iteration") + de::toString(m_iterNdx + 1);
1155*35238bceSAndroid Build Coastguard Worker     std::string sectionDesc =
1156*35238bceSAndroid Build Coastguard Worker         std::string("Iteration ") + de::toString(m_iterNdx + 1) + " / " + de::toString(numIterations);
1157*35238bceSAndroid Build Coastguard Worker     tcu::ScopedLogSection section(log, sectionName, sectionDesc);
1158*35238bceSAndroid Build Coastguard Worker 
1159*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "Testing " << s_iterations[m_iterNdx].numCalls
1160*35238bceSAndroid Build Coastguard Worker         << " draw calls, (element count, TF state): " << tcu::formatArray(first, end) << TestLog::EndMessage;
1161*35238bceSAndroid Build Coastguard Worker 
1162*35238bceSAndroid Build Coastguard Worker     isOk = runTest(first, end, seed);
1163*35238bceSAndroid Build Coastguard Worker 
1164*35238bceSAndroid Build Coastguard Worker     if (!isOk)
1165*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result comparison failed");
1166*35238bceSAndroid Build Coastguard Worker 
1167*35238bceSAndroid Build Coastguard Worker     m_iterNdx += 1;
1168*35238bceSAndroid Build Coastguard Worker     return (isOk && m_iterNdx < numIterations) ? CONTINUE : STOP;
1169*35238bceSAndroid Build Coastguard Worker }
1170*35238bceSAndroid Build Coastguard Worker 
runTest(const DrawCall * first,const DrawCall * end,uint32_t seed)1171*35238bceSAndroid Build Coastguard Worker bool TransformFeedbackCase::runTest(const DrawCall *first, const DrawCall *end, uint32_t seed)
1172*35238bceSAndroid Build Coastguard Worker {
1173*35238bceSAndroid Build Coastguard Worker     TestLog &log             = m_testCtx.getLog();
1174*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1175*35238bceSAndroid Build Coastguard Worker     de::Random rnd(seed);
1176*35238bceSAndroid Build Coastguard Worker     int numInputs  = 0; //!< Sum of element counts in calls.
1177*35238bceSAndroid Build Coastguard Worker     int numOutputs = 0; //!< Sum of output counts for calls that have transform feedback enabled.
1178*35238bceSAndroid Build Coastguard Worker     int width      = m_context.getRenderContext().getRenderTarget().getWidth();
1179*35238bceSAndroid Build Coastguard Worker     int height     = m_context.getRenderContext().getRenderTarget().getHeight();
1180*35238bceSAndroid Build Coastguard Worker     int viewportW  = de::min((int)VIEWPORT_WIDTH, width);
1181*35238bceSAndroid Build Coastguard Worker     int viewportH  = de::min((int)VIEWPORT_HEIGHT, height);
1182*35238bceSAndroid Build Coastguard Worker     int viewportX  = rnd.getInt(0, width - viewportW);
1183*35238bceSAndroid Build Coastguard Worker     int viewportY  = rnd.getInt(0, height - viewportH);
1184*35238bceSAndroid Build Coastguard Worker     tcu::Surface frameWithTf(viewportW, viewportH);
1185*35238bceSAndroid Build Coastguard Worker     tcu::Surface frameWithoutTf(viewportW, viewportH);
1186*35238bceSAndroid Build Coastguard Worker     glu::Query primitiveQuery(m_context.getRenderContext());
1187*35238bceSAndroid Build Coastguard Worker     bool outputsOk = true;
1188*35238bceSAndroid Build Coastguard Worker     bool imagesOk  = true;
1189*35238bceSAndroid Build Coastguard Worker     bool queryOk   = true;
1190*35238bceSAndroid Build Coastguard Worker 
1191*35238bceSAndroid Build Coastguard Worker     // Compute totals.
1192*35238bceSAndroid Build Coastguard Worker     for (const DrawCall *call = first; call != end; call++)
1193*35238bceSAndroid Build Coastguard Worker     {
1194*35238bceSAndroid Build Coastguard Worker         numInputs += call->numElements;
1195*35238bceSAndroid Build Coastguard Worker         numOutputs +=
1196*35238bceSAndroid Build Coastguard Worker             call->transformFeedbackEnabled ? getTransformFeedbackOutputCount(m_primitiveType, call->numElements) : 0;
1197*35238bceSAndroid Build Coastguard Worker     }
1198*35238bceSAndroid Build Coastguard Worker 
1199*35238bceSAndroid Build Coastguard Worker     // Input data.
1200*35238bceSAndroid Build Coastguard Worker     vector<uint8_t> inputData(m_inputStride * numInputs);
1201*35238bceSAndroid Build Coastguard Worker     genInputData(m_attributes, numInputs, m_inputStride, &inputData[0], rnd);
1202*35238bceSAndroid Build Coastguard Worker 
1203*35238bceSAndroid Build Coastguard Worker     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transformFeedback->get());
1204*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback()");
1205*35238bceSAndroid Build Coastguard Worker 
1206*35238bceSAndroid Build Coastguard Worker     // Allocate storage for transform feedback output buffers and bind to targets.
1207*35238bceSAndroid Build Coastguard Worker     for (int bufNdx = 0; bufNdx < (int)m_outputBuffers.size(); bufNdx++)
1208*35238bceSAndroid Build Coastguard Worker     {
1209*35238bceSAndroid Build Coastguard Worker         uint32_t buffer      = m_outputBuffers[bufNdx];
1210*35238bceSAndroid Build Coastguard Worker         int stride           = m_bufferStrides[bufNdx];
1211*35238bceSAndroid Build Coastguard Worker         int target           = bufNdx;
1212*35238bceSAndroid Build Coastguard Worker         int size             = stride * numOutputs;
1213*35238bceSAndroid Build Coastguard Worker         int guardSize        = stride * BUFFER_GUARD_MULTIPLIER;
1214*35238bceSAndroid Build Coastguard Worker         const uint32_t usage = GL_DYNAMIC_READ;
1215*35238bceSAndroid Build Coastguard Worker 
1216*35238bceSAndroid Build Coastguard Worker         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
1217*35238bceSAndroid Build Coastguard Worker         gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, size + guardSize, DE_NULL, usage);
1218*35238bceSAndroid Build Coastguard Worker         writeBufferGuard(gl, GL_TRANSFORM_FEEDBACK_BUFFER, size, guardSize);
1219*35238bceSAndroid Build Coastguard Worker 
1220*35238bceSAndroid Build Coastguard Worker         // \todo [2012-07-30 pyry] glBindBufferRange()?
1221*35238bceSAndroid Build Coastguard Worker         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, target, buffer);
1222*35238bceSAndroid Build Coastguard Worker 
1223*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.getError(), "transform feedback buffer setup");
1224*35238bceSAndroid Build Coastguard Worker     }
1225*35238bceSAndroid Build Coastguard Worker 
1226*35238bceSAndroid Build Coastguard Worker     // Setup attributes.
1227*35238bceSAndroid Build Coastguard Worker     for (vector<Attribute>::const_iterator attrib = m_attributes.begin(); attrib != m_attributes.end(); attrib++)
1228*35238bceSAndroid Build Coastguard Worker     {
1229*35238bceSAndroid Build Coastguard Worker         int loc                  = gl.getAttribLocation(m_program->getProgram(), attrib->name.c_str());
1230*35238bceSAndroid Build Coastguard Worker         glu::DataType scalarType = glu::getDataTypeScalarType(attrib->type.getBasicType());
1231*35238bceSAndroid Build Coastguard Worker         int numComponents        = glu::getDataTypeScalarSize(attrib->type.getBasicType());
1232*35238bceSAndroid Build Coastguard Worker         const void *ptr          = &inputData[0] + attrib->offset;
1233*35238bceSAndroid Build Coastguard Worker 
1234*35238bceSAndroid Build Coastguard Worker         if (loc >= 0)
1235*35238bceSAndroid Build Coastguard Worker         {
1236*35238bceSAndroid Build Coastguard Worker             gl.enableVertexAttribArray(loc);
1237*35238bceSAndroid Build Coastguard Worker 
1238*35238bceSAndroid Build Coastguard Worker             if (scalarType == glu::TYPE_FLOAT)
1239*35238bceSAndroid Build Coastguard Worker                 gl.vertexAttribPointer(loc, numComponents, GL_FLOAT, GL_FALSE, m_inputStride, ptr);
1240*35238bceSAndroid Build Coastguard Worker             else if (scalarType == glu::TYPE_INT)
1241*35238bceSAndroid Build Coastguard Worker                 gl.vertexAttribIPointer(loc, numComponents, GL_INT, m_inputStride, ptr);
1242*35238bceSAndroid Build Coastguard Worker             else if (scalarType == glu::TYPE_UINT)
1243*35238bceSAndroid Build Coastguard Worker                 gl.vertexAttribIPointer(loc, numComponents, GL_UNSIGNED_INT, m_inputStride, ptr);
1244*35238bceSAndroid Build Coastguard Worker         }
1245*35238bceSAndroid Build Coastguard Worker     }
1246*35238bceSAndroid Build Coastguard Worker 
1247*35238bceSAndroid Build Coastguard Worker     // Setup viewport.
1248*35238bceSAndroid Build Coastguard Worker     gl.viewport(viewportX, viewportY, viewportW, viewportH);
1249*35238bceSAndroid Build Coastguard Worker 
1250*35238bceSAndroid Build Coastguard Worker     // Setup program.
1251*35238bceSAndroid Build Coastguard Worker     gl.useProgram(m_program->getProgram());
1252*35238bceSAndroid Build Coastguard Worker 
1253*35238bceSAndroid Build Coastguard Worker     gl.uniform4fv(gl.getUniformLocation(m_program->getProgram(), "u_scale"), 1, tcu::Vec4(0.01f).getPtr());
1254*35238bceSAndroid Build Coastguard Worker     gl.uniform4fv(gl.getUniformLocation(m_program->getProgram(), "u_bias"), 1, tcu::Vec4(0.5f).getPtr());
1255*35238bceSAndroid Build Coastguard Worker 
1256*35238bceSAndroid Build Coastguard Worker     // Enable query.
1257*35238bceSAndroid Build Coastguard Worker     gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, *primitiveQuery);
1258*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)");
1259*35238bceSAndroid Build Coastguard Worker 
1260*35238bceSAndroid Build Coastguard Worker     // Draw.
1261*35238bceSAndroid Build Coastguard Worker     {
1262*35238bceSAndroid Build Coastguard Worker         int offset     = 0;
1263*35238bceSAndroid Build Coastguard Worker         bool tfEnabled = true;
1264*35238bceSAndroid Build Coastguard Worker 
1265*35238bceSAndroid Build Coastguard Worker         gl.clear(GL_COLOR_BUFFER_BIT);
1266*35238bceSAndroid Build Coastguard Worker 
1267*35238bceSAndroid Build Coastguard Worker         gl.beginTransformFeedback(getTransformFeedbackPrimitiveMode(m_primitiveType));
1268*35238bceSAndroid Build Coastguard Worker 
1269*35238bceSAndroid Build Coastguard Worker         for (const DrawCall *call = first; call != end; call++)
1270*35238bceSAndroid Build Coastguard Worker         {
1271*35238bceSAndroid Build Coastguard Worker             // Pause or resume transform feedback if necessary.
1272*35238bceSAndroid Build Coastguard Worker             if (call->transformFeedbackEnabled != tfEnabled)
1273*35238bceSAndroid Build Coastguard Worker             {
1274*35238bceSAndroid Build Coastguard Worker                 if (call->transformFeedbackEnabled)
1275*35238bceSAndroid Build Coastguard Worker                     gl.resumeTransformFeedback();
1276*35238bceSAndroid Build Coastguard Worker                 else
1277*35238bceSAndroid Build Coastguard Worker                     gl.pauseTransformFeedback();
1278*35238bceSAndroid Build Coastguard Worker                 tfEnabled = call->transformFeedbackEnabled;
1279*35238bceSAndroid Build Coastguard Worker             }
1280*35238bceSAndroid Build Coastguard Worker 
1281*35238bceSAndroid Build Coastguard Worker             gl.drawArrays(m_primitiveType, offset, call->numElements);
1282*35238bceSAndroid Build Coastguard Worker             offset += call->numElements;
1283*35238bceSAndroid Build Coastguard Worker         }
1284*35238bceSAndroid Build Coastguard Worker 
1285*35238bceSAndroid Build Coastguard Worker         // Resume feedback before finishing it.
1286*35238bceSAndroid Build Coastguard Worker         if (!tfEnabled)
1287*35238bceSAndroid Build Coastguard Worker             gl.resumeTransformFeedback();
1288*35238bceSAndroid Build Coastguard Worker 
1289*35238bceSAndroid Build Coastguard Worker         gl.endTransformFeedback();
1290*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.getError(), "render");
1291*35238bceSAndroid Build Coastguard Worker     }
1292*35238bceSAndroid Build Coastguard Worker 
1293*35238bceSAndroid Build Coastguard Worker     gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
1294*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)");
1295*35238bceSAndroid Build Coastguard Worker 
1296*35238bceSAndroid Build Coastguard Worker     // Check and log query status right after submit
1297*35238bceSAndroid Build Coastguard Worker     {
1298*35238bceSAndroid Build Coastguard Worker         uint32_t available = GL_FALSE;
1299*35238bceSAndroid Build Coastguard Worker         gl.getQueryObjectuiv(*primitiveQuery, GL_QUERY_RESULT_AVAILABLE, &available);
1300*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv()");
1301*35238bceSAndroid Build Coastguard Worker 
1302*35238bceSAndroid Build Coastguard Worker         log << TestLog::Message << "GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN status after submit: "
1303*35238bceSAndroid Build Coastguard Worker             << (available != GL_FALSE ? "GL_TRUE" : "GL_FALSE") << TestLog::EndMessage;
1304*35238bceSAndroid Build Coastguard Worker     }
1305*35238bceSAndroid Build Coastguard Worker 
1306*35238bceSAndroid Build Coastguard Worker     // Compare result buffers.
1307*35238bceSAndroid Build Coastguard Worker     for (int bufferNdx = 0; bufferNdx < (int)m_outputBuffers.size(); bufferNdx++)
1308*35238bceSAndroid Build Coastguard Worker     {
1309*35238bceSAndroid Build Coastguard Worker         uint32_t buffer    = m_outputBuffers[bufferNdx];
1310*35238bceSAndroid Build Coastguard Worker         int stride         = m_bufferStrides[bufferNdx];
1311*35238bceSAndroid Build Coastguard Worker         int size           = stride * numOutputs;
1312*35238bceSAndroid Build Coastguard Worker         int guardSize      = stride * BUFFER_GUARD_MULTIPLIER;
1313*35238bceSAndroid Build Coastguard Worker         const void *bufPtr = DE_NULL;
1314*35238bceSAndroid Build Coastguard Worker 
1315*35238bceSAndroid Build Coastguard Worker         // Bind buffer for reading.
1316*35238bceSAndroid Build Coastguard Worker         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
1317*35238bceSAndroid Build Coastguard Worker         bufPtr = gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, size + guardSize, GL_MAP_READ_BIT);
1318*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.getError(), "mapping buffer");
1319*35238bceSAndroid Build Coastguard Worker 
1320*35238bceSAndroid Build Coastguard Worker         // Verify all output variables that are written to this buffer.
1321*35238bceSAndroid Build Coastguard Worker         for (vector<Output>::const_iterator out = m_transformFeedbackOutputs.begin();
1322*35238bceSAndroid Build Coastguard Worker              out != m_transformFeedbackOutputs.end(); out++)
1323*35238bceSAndroid Build Coastguard Worker         {
1324*35238bceSAndroid Build Coastguard Worker             if (out->bufferNdx != bufferNdx)
1325*35238bceSAndroid Build Coastguard Worker                 continue;
1326*35238bceSAndroid Build Coastguard Worker 
1327*35238bceSAndroid Build Coastguard Worker             int inputOffset  = 0;
1328*35238bceSAndroid Build Coastguard Worker             int outputOffset = 0;
1329*35238bceSAndroid Build Coastguard Worker 
1330*35238bceSAndroid Build Coastguard Worker             // Process all draw calls and check ones with transform feedback enabled.
1331*35238bceSAndroid Build Coastguard Worker             for (const DrawCall *call = first; call != end; call++)
1332*35238bceSAndroid Build Coastguard Worker             {
1333*35238bceSAndroid Build Coastguard Worker                 if (call->transformFeedbackEnabled)
1334*35238bceSAndroid Build Coastguard Worker                 {
1335*35238bceSAndroid Build Coastguard Worker                     const uint8_t *inputPtr  = &inputData[0] + inputOffset * m_inputStride;
1336*35238bceSAndroid Build Coastguard Worker                     const uint8_t *outputPtr = (const uint8_t *)bufPtr + outputOffset * stride;
1337*35238bceSAndroid Build Coastguard Worker 
1338*35238bceSAndroid Build Coastguard Worker                     if (!compareTransformFeedbackOutput(log, m_primitiveType, *out, call->numElements, inputPtr,
1339*35238bceSAndroid Build Coastguard Worker                                                         m_inputStride, outputPtr, stride))
1340*35238bceSAndroid Build Coastguard Worker                     {
1341*35238bceSAndroid Build Coastguard Worker                         outputsOk = false;
1342*35238bceSAndroid Build Coastguard Worker                         break;
1343*35238bceSAndroid Build Coastguard Worker                     }
1344*35238bceSAndroid Build Coastguard Worker                 }
1345*35238bceSAndroid Build Coastguard Worker 
1346*35238bceSAndroid Build Coastguard Worker                 inputOffset += call->numElements;
1347*35238bceSAndroid Build Coastguard Worker                 outputOffset += call->transformFeedbackEnabled ?
1348*35238bceSAndroid Build Coastguard Worker                                     getTransformFeedbackOutputCount(m_primitiveType, call->numElements) :
1349*35238bceSAndroid Build Coastguard Worker                                     0;
1350*35238bceSAndroid Build Coastguard Worker             }
1351*35238bceSAndroid Build Coastguard Worker         }
1352*35238bceSAndroid Build Coastguard Worker 
1353*35238bceSAndroid Build Coastguard Worker         // Verify guardband.
1354*35238bceSAndroid Build Coastguard Worker         if (!verifyGuard((const uint8_t *)bufPtr + size, guardSize))
1355*35238bceSAndroid Build Coastguard Worker         {
1356*35238bceSAndroid Build Coastguard Worker             log << TestLog::Message << "Error: Transform feedback buffer overrun detected" << TestLog::EndMessage;
1357*35238bceSAndroid Build Coastguard Worker             outputsOk = false;
1358*35238bceSAndroid Build Coastguard Worker         }
1359*35238bceSAndroid Build Coastguard Worker 
1360*35238bceSAndroid Build Coastguard Worker         gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1361*35238bceSAndroid Build Coastguard Worker     }
1362*35238bceSAndroid Build Coastguard Worker 
1363*35238bceSAndroid Build Coastguard Worker     // Check status after mapping buffers.
1364*35238bceSAndroid Build Coastguard Worker     {
1365*35238bceSAndroid Build Coastguard Worker         const bool mustBeReady  = !m_outputBuffers.empty(); // Mapping buffer forces synchronization.
1366*35238bceSAndroid Build Coastguard Worker         const int expectedCount = computeTransformFeedbackPrimitiveCount(m_primitiveType, first, end);
1367*35238bceSAndroid Build Coastguard Worker         uint32_t available      = GL_FALSE;
1368*35238bceSAndroid Build Coastguard Worker         uint32_t numPrimitives  = 0;
1369*35238bceSAndroid Build Coastguard Worker 
1370*35238bceSAndroid Build Coastguard Worker         gl.getQueryObjectuiv(*primitiveQuery, GL_QUERY_RESULT_AVAILABLE, &available);
1371*35238bceSAndroid Build Coastguard Worker         gl.getQueryObjectuiv(*primitiveQuery, GL_QUERY_RESULT, &numPrimitives);
1372*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv()");
1373*35238bceSAndroid Build Coastguard Worker 
1374*35238bceSAndroid Build Coastguard Worker         if (!mustBeReady && available == GL_FALSE)
1375*35238bceSAndroid Build Coastguard Worker         {
1376*35238bceSAndroid Build Coastguard Worker             log << TestLog::Message
1377*35238bceSAndroid Build Coastguard Worker                 << "ERROR: GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN result not available after mapping buffers!"
1378*35238bceSAndroid Build Coastguard Worker                 << TestLog::EndMessage;
1379*35238bceSAndroid Build Coastguard Worker             queryOk = false;
1380*35238bceSAndroid Build Coastguard Worker         }
1381*35238bceSAndroid Build Coastguard Worker 
1382*35238bceSAndroid Build Coastguard Worker         log << TestLog::Message << "GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN = " << numPrimitives
1383*35238bceSAndroid Build Coastguard Worker             << TestLog::EndMessage;
1384*35238bceSAndroid Build Coastguard Worker 
1385*35238bceSAndroid Build Coastguard Worker         if ((int)numPrimitives != expectedCount)
1386*35238bceSAndroid Build Coastguard Worker         {
1387*35238bceSAndroid Build Coastguard Worker             log << TestLog::Message << "ERROR: Expected " << expectedCount << " primitives!" << TestLog::EndMessage;
1388*35238bceSAndroid Build Coastguard Worker             queryOk = false;
1389*35238bceSAndroid Build Coastguard Worker         }
1390*35238bceSAndroid Build Coastguard Worker     }
1391*35238bceSAndroid Build Coastguard Worker 
1392*35238bceSAndroid Build Coastguard Worker     // Clear transform feedback state.
1393*35238bceSAndroid Build Coastguard Worker     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
1394*35238bceSAndroid Build Coastguard Worker     for (int bufNdx = 0; bufNdx < (int)m_outputBuffers.size(); bufNdx++)
1395*35238bceSAndroid Build Coastguard Worker     {
1396*35238bceSAndroid Build Coastguard Worker         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1397*35238bceSAndroid Build Coastguard Worker         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, bufNdx, 0);
1398*35238bceSAndroid Build Coastguard Worker     }
1399*35238bceSAndroid Build Coastguard Worker 
1400*35238bceSAndroid Build Coastguard Worker     // Read back rendered image.
1401*35238bceSAndroid Build Coastguard Worker     glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, frameWithTf.getAccess());
1402*35238bceSAndroid Build Coastguard Worker 
1403*35238bceSAndroid Build Coastguard Worker     // Render without transform feedback.
1404*35238bceSAndroid Build Coastguard Worker     {
1405*35238bceSAndroid Build Coastguard Worker         int offset = 0;
1406*35238bceSAndroid Build Coastguard Worker 
1407*35238bceSAndroid Build Coastguard Worker         gl.clear(GL_COLOR_BUFFER_BIT);
1408*35238bceSAndroid Build Coastguard Worker 
1409*35238bceSAndroid Build Coastguard Worker         for (const DrawCall *call = first; call != end; call++)
1410*35238bceSAndroid Build Coastguard Worker         {
1411*35238bceSAndroid Build Coastguard Worker             gl.drawArrays(m_primitiveType, offset, call->numElements);
1412*35238bceSAndroid Build Coastguard Worker             offset += call->numElements;
1413*35238bceSAndroid Build Coastguard Worker         }
1414*35238bceSAndroid Build Coastguard Worker 
1415*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.getError(), "render");
1416*35238bceSAndroid Build Coastguard Worker         glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, frameWithoutTf.getAccess());
1417*35238bceSAndroid Build Coastguard Worker     }
1418*35238bceSAndroid Build Coastguard Worker 
1419*35238bceSAndroid Build Coastguard Worker     // Compare images with and without transform feedback.
1420*35238bceSAndroid Build Coastguard Worker     imagesOk = tcu::pixelThresholdCompare(log, "Result", "Image comparison result", frameWithoutTf, frameWithTf,
1421*35238bceSAndroid Build Coastguard Worker                                           tcu::RGBA(1, 1, 1, 1), tcu::COMPARE_LOG_ON_ERROR);
1422*35238bceSAndroid Build Coastguard Worker 
1423*35238bceSAndroid Build Coastguard Worker     if (imagesOk)
1424*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << TestLog::Message
1425*35238bceSAndroid Build Coastguard Worker                            << "Rendering result comparison between TF enabled and TF disabled passed."
1426*35238bceSAndroid Build Coastguard Worker                            << TestLog::EndMessage;
1427*35238bceSAndroid Build Coastguard Worker     else
1428*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << TestLog::Message
1429*35238bceSAndroid Build Coastguard Worker                            << "ERROR: Rendering result comparison between TF enabled and TF disabled failed!"
1430*35238bceSAndroid Build Coastguard Worker                            << TestLog::EndMessage;
1431*35238bceSAndroid Build Coastguard Worker 
1432*35238bceSAndroid Build Coastguard Worker     return outputsOk && imagesOk && queryOk;
1433*35238bceSAndroid Build Coastguard Worker }
1434*35238bceSAndroid Build Coastguard Worker 
1435*35238bceSAndroid Build Coastguard Worker // Test cases.
1436*35238bceSAndroid Build Coastguard Worker 
1437*35238bceSAndroid Build Coastguard Worker class PositionCase : public TransformFeedbackCase
1438*35238bceSAndroid Build Coastguard Worker {
1439*35238bceSAndroid Build Coastguard Worker public:
PositionCase(Context & context,const char * name,const char * desc,uint32_t bufferType,uint32_t primitiveType)1440*35238bceSAndroid Build Coastguard Worker     PositionCase(Context &context, const char *name, const char *desc, uint32_t bufferType, uint32_t primitiveType)
1441*35238bceSAndroid Build Coastguard Worker         : TransformFeedbackCase(context, name, desc, bufferType, primitiveType)
1442*35238bceSAndroid Build Coastguard Worker     {
1443*35238bceSAndroid Build Coastguard Worker         m_progSpec.addTransformFeedbackVarying("gl_Position");
1444*35238bceSAndroid Build Coastguard Worker     }
1445*35238bceSAndroid Build Coastguard Worker };
1446*35238bceSAndroid Build Coastguard Worker 
1447*35238bceSAndroid Build Coastguard Worker class PointSizeCase : public TransformFeedbackCase
1448*35238bceSAndroid Build Coastguard Worker {
1449*35238bceSAndroid Build Coastguard Worker public:
PointSizeCase(Context & context,const char * name,const char * desc,uint32_t bufferType,uint32_t primitiveType)1450*35238bceSAndroid Build Coastguard Worker     PointSizeCase(Context &context, const char *name, const char *desc, uint32_t bufferType, uint32_t primitiveType)
1451*35238bceSAndroid Build Coastguard Worker         : TransformFeedbackCase(context, name, desc, bufferType, primitiveType)
1452*35238bceSAndroid Build Coastguard Worker     {
1453*35238bceSAndroid Build Coastguard Worker         m_progSpec.addTransformFeedbackVarying("gl_PointSize");
1454*35238bceSAndroid Build Coastguard Worker     }
1455*35238bceSAndroid Build Coastguard Worker };
1456*35238bceSAndroid Build Coastguard Worker 
1457*35238bceSAndroid Build Coastguard Worker class BasicTypeCase : public TransformFeedbackCase
1458*35238bceSAndroid Build Coastguard Worker {
1459*35238bceSAndroid Build Coastguard Worker public:
BasicTypeCase(Context & context,const char * name,const char * desc,uint32_t bufferType,uint32_t primitiveType,glu::DataType type,glu::Precision precision,Interpolation interpolation)1460*35238bceSAndroid Build Coastguard Worker     BasicTypeCase(Context &context, const char *name, const char *desc, uint32_t bufferType, uint32_t primitiveType,
1461*35238bceSAndroid Build Coastguard Worker                   glu::DataType type, glu::Precision precision, Interpolation interpolation)
1462*35238bceSAndroid Build Coastguard Worker         : TransformFeedbackCase(context, name, desc, bufferType, primitiveType)
1463*35238bceSAndroid Build Coastguard Worker     {
1464*35238bceSAndroid Build Coastguard Worker         m_progSpec.addVarying("v_varA", glu::VarType(type, precision), interpolation);
1465*35238bceSAndroid Build Coastguard Worker         m_progSpec.addVarying("v_varB", glu::VarType(type, precision), interpolation);
1466*35238bceSAndroid Build Coastguard Worker 
1467*35238bceSAndroid Build Coastguard Worker         m_progSpec.addTransformFeedbackVarying("v_varA");
1468*35238bceSAndroid Build Coastguard Worker         m_progSpec.addTransformFeedbackVarying("v_varB");
1469*35238bceSAndroid Build Coastguard Worker     }
1470*35238bceSAndroid Build Coastguard Worker };
1471*35238bceSAndroid Build Coastguard Worker 
1472*35238bceSAndroid Build Coastguard Worker class BasicArrayCase : public TransformFeedbackCase
1473*35238bceSAndroid Build Coastguard Worker {
1474*35238bceSAndroid Build Coastguard Worker public:
BasicArrayCase(Context & context,const char * name,const char * desc,uint32_t bufferType,uint32_t primitiveType,glu::DataType type,glu::Precision precision,Interpolation interpolation)1475*35238bceSAndroid Build Coastguard Worker     BasicArrayCase(Context &context, const char *name, const char *desc, uint32_t bufferType, uint32_t primitiveType,
1476*35238bceSAndroid Build Coastguard Worker                    glu::DataType type, glu::Precision precision, Interpolation interpolation)
1477*35238bceSAndroid Build Coastguard Worker         : TransformFeedbackCase(context, name, desc, bufferType, primitiveType)
1478*35238bceSAndroid Build Coastguard Worker     {
1479*35238bceSAndroid Build Coastguard Worker         if (glu::isDataTypeMatrix(type) || m_bufferMode == GL_SEPARATE_ATTRIBS)
1480*35238bceSAndroid Build Coastguard Worker         {
1481*35238bceSAndroid Build Coastguard Worker             // \note For matrix types we need to use reduced array sizes or otherwise we will exceed maximum attribute (16)
1482*35238bceSAndroid Build Coastguard Worker             //         or transform feedback component count (64).
1483*35238bceSAndroid Build Coastguard Worker             //         On separate attribs mode maximum component count per varying is 4.
1484*35238bceSAndroid Build Coastguard Worker             m_progSpec.addVarying("v_varA", glu::VarType(glu::VarType(type, precision), 1), interpolation);
1485*35238bceSAndroid Build Coastguard Worker             m_progSpec.addVarying("v_varB", glu::VarType(glu::VarType(type, precision), 2), interpolation);
1486*35238bceSAndroid Build Coastguard Worker         }
1487*35238bceSAndroid Build Coastguard Worker         else
1488*35238bceSAndroid Build Coastguard Worker         {
1489*35238bceSAndroid Build Coastguard Worker             m_progSpec.addVarying("v_varA", glu::VarType(glu::VarType(type, precision), 3), interpolation);
1490*35238bceSAndroid Build Coastguard Worker             m_progSpec.addVarying("v_varB", glu::VarType(glu::VarType(type, precision), 4), interpolation);
1491*35238bceSAndroid Build Coastguard Worker         }
1492*35238bceSAndroid Build Coastguard Worker 
1493*35238bceSAndroid Build Coastguard Worker         m_progSpec.addTransformFeedbackVarying("v_varA");
1494*35238bceSAndroid Build Coastguard Worker         m_progSpec.addTransformFeedbackVarying("v_varB");
1495*35238bceSAndroid Build Coastguard Worker     }
1496*35238bceSAndroid Build Coastguard Worker };
1497*35238bceSAndroid Build Coastguard Worker 
1498*35238bceSAndroid Build Coastguard Worker class ArrayElementCase : public TransformFeedbackCase
1499*35238bceSAndroid Build Coastguard Worker {
1500*35238bceSAndroid Build Coastguard Worker public:
ArrayElementCase(Context & context,const char * name,const char * desc,uint32_t bufferType,uint32_t primitiveType,glu::DataType type,glu::Precision precision,Interpolation interpolation)1501*35238bceSAndroid Build Coastguard Worker     ArrayElementCase(Context &context, const char *name, const char *desc, uint32_t bufferType, uint32_t primitiveType,
1502*35238bceSAndroid Build Coastguard Worker                      glu::DataType type, glu::Precision precision, Interpolation interpolation)
1503*35238bceSAndroid Build Coastguard Worker         : TransformFeedbackCase(context, name, desc, bufferType, primitiveType)
1504*35238bceSAndroid Build Coastguard Worker     {
1505*35238bceSAndroid Build Coastguard Worker         m_progSpec.addVarying("v_varA", glu::VarType(glu::VarType(type, precision), 3), interpolation);
1506*35238bceSAndroid Build Coastguard Worker         m_progSpec.addVarying("v_varB", glu::VarType(glu::VarType(type, precision), 4), interpolation);
1507*35238bceSAndroid Build Coastguard Worker 
1508*35238bceSAndroid Build Coastguard Worker         m_progSpec.addTransformFeedbackVarying("v_varA[1]");
1509*35238bceSAndroid Build Coastguard Worker         m_progSpec.addTransformFeedbackVarying("v_varB[0]");
1510*35238bceSAndroid Build Coastguard Worker         m_progSpec.addTransformFeedbackVarying("v_varB[3]");
1511*35238bceSAndroid Build Coastguard Worker     }
1512*35238bceSAndroid Build Coastguard Worker };
1513*35238bceSAndroid Build Coastguard Worker 
1514*35238bceSAndroid Build Coastguard Worker class RandomCase : public TransformFeedbackCase
1515*35238bceSAndroid Build Coastguard Worker {
1516*35238bceSAndroid Build Coastguard Worker public:
RandomCase(Context & context,const char * name,const char * desc,uint32_t bufferType,uint32_t primitiveType,uint32_t seed,bool elementCapture)1517*35238bceSAndroid Build Coastguard Worker     RandomCase(Context &context, const char *name, const char *desc, uint32_t bufferType, uint32_t primitiveType,
1518*35238bceSAndroid Build Coastguard Worker                uint32_t seed, bool elementCapture)
1519*35238bceSAndroid Build Coastguard Worker         : TransformFeedbackCase(context, name, desc, bufferType, primitiveType)
1520*35238bceSAndroid Build Coastguard Worker         , m_seed(seed)
1521*35238bceSAndroid Build Coastguard Worker         , m_elementCapture(elementCapture)
1522*35238bceSAndroid Build Coastguard Worker     {
1523*35238bceSAndroid Build Coastguard Worker     }
1524*35238bceSAndroid Build Coastguard Worker 
init(void)1525*35238bceSAndroid Build Coastguard Worker     void init(void)
1526*35238bceSAndroid Build Coastguard Worker     {
1527*35238bceSAndroid Build Coastguard Worker         // \note Hard-coded indices and hackery are used when indexing this, beware.
1528*35238bceSAndroid Build Coastguard Worker         static const glu::DataType typeCandidates[] = {
1529*35238bceSAndroid Build Coastguard Worker             glu::TYPE_FLOAT,        glu::TYPE_FLOAT_VEC2,   glu::TYPE_FLOAT_VEC3,   glu::TYPE_FLOAT_VEC4,
1530*35238bceSAndroid Build Coastguard Worker             glu::TYPE_INT,          glu::TYPE_INT_VEC2,     glu::TYPE_INT_VEC3,     glu::TYPE_INT_VEC4,
1531*35238bceSAndroid Build Coastguard Worker             glu::TYPE_UINT,         glu::TYPE_UINT_VEC2,    glu::TYPE_UINT_VEC3,    glu::TYPE_UINT_VEC4,
1532*35238bceSAndroid Build Coastguard Worker 
1533*35238bceSAndroid Build Coastguard Worker             glu::TYPE_FLOAT_MAT2,   glu::TYPE_FLOAT_MAT2X3, glu::TYPE_FLOAT_MAT2X4,
1534*35238bceSAndroid Build Coastguard Worker 
1535*35238bceSAndroid Build Coastguard Worker             glu::TYPE_FLOAT_MAT3X2, glu::TYPE_FLOAT_MAT3,   glu::TYPE_FLOAT_MAT3X4,
1536*35238bceSAndroid Build Coastguard Worker 
1537*35238bceSAndroid Build Coastguard Worker             glu::TYPE_FLOAT_MAT4X2, glu::TYPE_FLOAT_MAT4X3, glu::TYPE_FLOAT_MAT4};
1538*35238bceSAndroid Build Coastguard Worker 
1539*35238bceSAndroid Build Coastguard Worker         static const glu::Precision precisions[] = {glu::PRECISION_LOWP, glu::PRECISION_MEDIUMP, glu::PRECISION_HIGHP};
1540*35238bceSAndroid Build Coastguard Worker 
1541*35238bceSAndroid Build Coastguard Worker         static const Interpolation interpModes[] = {INTERPOLATION_FLAT, INTERPOLATION_SMOOTH, INTERPOLATION_CENTROID};
1542*35238bceSAndroid Build Coastguard Worker 
1543*35238bceSAndroid Build Coastguard Worker         const int maxAttributeVectors = 16;
1544*35238bceSAndroid Build Coastguard Worker         //        const int    maxTransformFeedbackComponents = 64; // \note It is enough to limit attribute set size.
1545*35238bceSAndroid Build Coastguard Worker         bool isSeparateMode                = m_bufferMode == GL_SEPARATE_ATTRIBS;
1546*35238bceSAndroid Build Coastguard Worker         int maxTransformFeedbackVars       = isSeparateMode ? 4 : maxAttributeVectors;
1547*35238bceSAndroid Build Coastguard Worker         const float arrayWeight            = 0.3f;
1548*35238bceSAndroid Build Coastguard Worker         const float positionWeight         = 0.7f;
1549*35238bceSAndroid Build Coastguard Worker         const float pointSizeWeight        = 0.1f;
1550*35238bceSAndroid Build Coastguard Worker         const float captureFullArrayWeight = 0.5f;
1551*35238bceSAndroid Build Coastguard Worker 
1552*35238bceSAndroid Build Coastguard Worker         de::Random rnd(m_seed);
1553*35238bceSAndroid Build Coastguard Worker         bool usePosition          = rnd.getFloat() < positionWeight;
1554*35238bceSAndroid Build Coastguard Worker         bool usePointSize         = rnd.getFloat() < pointSizeWeight;
1555*35238bceSAndroid Build Coastguard Worker         int numAttribVectorsToUse = rnd.getInt(1, maxAttributeVectors - 1 /*position*/ - (usePointSize ? 1 : 0));
1556*35238bceSAndroid Build Coastguard Worker 
1557*35238bceSAndroid Build Coastguard Worker         int numAttributeVectors = 0;
1558*35238bceSAndroid Build Coastguard Worker         int varNdx              = 0;
1559*35238bceSAndroid Build Coastguard Worker 
1560*35238bceSAndroid Build Coastguard Worker         // Generate varyings.
1561*35238bceSAndroid Build Coastguard Worker         while (numAttributeVectors < numAttribVectorsToUse)
1562*35238bceSAndroid Build Coastguard Worker         {
1563*35238bceSAndroid Build Coastguard Worker             int maxVecs = isSeparateMode ? de::min(2 /*at most 2*mat2*/, numAttribVectorsToUse - numAttributeVectors) :
1564*35238bceSAndroid Build Coastguard Worker                                            numAttribVectorsToUse - numAttributeVectors;
1565*35238bceSAndroid Build Coastguard Worker             const glu::DataType *begin = &typeCandidates[0];
1566*35238bceSAndroid Build Coastguard Worker             const glu::DataType *end   = begin + (maxVecs >= 4 ? 21 :
1567*35238bceSAndroid Build Coastguard Worker                                                   maxVecs >= 3 ? 18 :
1568*35238bceSAndroid Build Coastguard Worker                                                   maxVecs >= 2 ? (isSeparateMode ? 13 : 15) :
1569*35238bceSAndroid Build Coastguard Worker                                                                  12);
1570*35238bceSAndroid Build Coastguard Worker 
1571*35238bceSAndroid Build Coastguard Worker             glu::DataType type = rnd.choose<glu::DataType>(begin, end);
1572*35238bceSAndroid Build Coastguard Worker             glu::Precision precision =
1573*35238bceSAndroid Build Coastguard Worker                 rnd.choose<glu::Precision>(&precisions[0], &precisions[0] + DE_LENGTH_OF_ARRAY(precisions));
1574*35238bceSAndroid Build Coastguard Worker             Interpolation interp =
1575*35238bceSAndroid Build Coastguard Worker                 glu::getDataTypeScalarType(type) == glu::TYPE_FLOAT ?
1576*35238bceSAndroid Build Coastguard Worker                     rnd.choose<Interpolation>(&interpModes[0], &interpModes[0] + DE_LENGTH_OF_ARRAY(interpModes)) :
1577*35238bceSAndroid Build Coastguard Worker                     INTERPOLATION_FLAT;
1578*35238bceSAndroid Build Coastguard Worker             int numVecs      = glu::isDataTypeMatrix(type) ? glu::getDataTypeMatrixNumColumns(type) : 1;
1579*35238bceSAndroid Build Coastguard Worker             int numComps     = glu::getDataTypeScalarSize(type);
1580*35238bceSAndroid Build Coastguard Worker             int maxArrayLen  = de::max(1, isSeparateMode ? 4 / numComps : maxVecs / numVecs);
1581*35238bceSAndroid Build Coastguard Worker             bool useArray    = rnd.getFloat() < arrayWeight;
1582*35238bceSAndroid Build Coastguard Worker             int arrayLen     = useArray ? rnd.getInt(1, maxArrayLen) : 1;
1583*35238bceSAndroid Build Coastguard Worker             std::string name = "v_var" + de::toString(varNdx);
1584*35238bceSAndroid Build Coastguard Worker 
1585*35238bceSAndroid Build Coastguard Worker             if (useArray)
1586*35238bceSAndroid Build Coastguard Worker                 m_progSpec.addVarying(name.c_str(), glu::VarType(glu::VarType(type, precision), arrayLen), interp);
1587*35238bceSAndroid Build Coastguard Worker             else
1588*35238bceSAndroid Build Coastguard Worker                 m_progSpec.addVarying(name.c_str(), glu::VarType(type, precision), interp);
1589*35238bceSAndroid Build Coastguard Worker 
1590*35238bceSAndroid Build Coastguard Worker             numAttributeVectors += arrayLen * numVecs;
1591*35238bceSAndroid Build Coastguard Worker             varNdx += 1;
1592*35238bceSAndroid Build Coastguard Worker         }
1593*35238bceSAndroid Build Coastguard Worker 
1594*35238bceSAndroid Build Coastguard Worker         // Generate transform feedback candidate set.
1595*35238bceSAndroid Build Coastguard Worker         vector<string> tfCandidates;
1596*35238bceSAndroid Build Coastguard Worker 
1597*35238bceSAndroid Build Coastguard Worker         if (usePosition)
1598*35238bceSAndroid Build Coastguard Worker             tfCandidates.push_back("gl_Position");
1599*35238bceSAndroid Build Coastguard Worker         if (usePointSize)
1600*35238bceSAndroid Build Coastguard Worker             tfCandidates.push_back("gl_PointSize");
1601*35238bceSAndroid Build Coastguard Worker 
1602*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < varNdx /* num varyings */; ndx++)
1603*35238bceSAndroid Build Coastguard Worker         {
1604*35238bceSAndroid Build Coastguard Worker             const Varying &var = m_progSpec.getVaryings()[ndx];
1605*35238bceSAndroid Build Coastguard Worker 
1606*35238bceSAndroid Build Coastguard Worker             if (var.type.isArrayType())
1607*35238bceSAndroid Build Coastguard Worker             {
1608*35238bceSAndroid Build Coastguard Worker                 const bool captureFull = m_elementCapture ? (rnd.getFloat() < captureFullArrayWeight) : true;
1609*35238bceSAndroid Build Coastguard Worker 
1610*35238bceSAndroid Build Coastguard Worker                 if (captureFull)
1611*35238bceSAndroid Build Coastguard Worker                     tfCandidates.push_back(var.name);
1612*35238bceSAndroid Build Coastguard Worker                 else
1613*35238bceSAndroid Build Coastguard Worker                 {
1614*35238bceSAndroid Build Coastguard Worker                     const int numElem = var.type.getArraySize();
1615*35238bceSAndroid Build Coastguard Worker                     for (int elemNdx = 0; elemNdx < numElem; elemNdx++)
1616*35238bceSAndroid Build Coastguard Worker                         tfCandidates.push_back(var.name + "[" + de::toString(elemNdx) + "]");
1617*35238bceSAndroid Build Coastguard Worker                 }
1618*35238bceSAndroid Build Coastguard Worker             }
1619*35238bceSAndroid Build Coastguard Worker             else
1620*35238bceSAndroid Build Coastguard Worker                 tfCandidates.push_back(var.name);
1621*35238bceSAndroid Build Coastguard Worker         }
1622*35238bceSAndroid Build Coastguard Worker 
1623*35238bceSAndroid Build Coastguard Worker         // Pick random selection.
1624*35238bceSAndroid Build Coastguard Worker         vector<string> tfVaryings(de::min((int)tfCandidates.size(), maxTransformFeedbackVars));
1625*35238bceSAndroid Build Coastguard Worker         rnd.choose(tfCandidates.begin(), tfCandidates.end(), tfVaryings.begin(), (int)tfVaryings.size());
1626*35238bceSAndroid Build Coastguard Worker         rnd.shuffle(tfVaryings.begin(), tfVaryings.end());
1627*35238bceSAndroid Build Coastguard Worker 
1628*35238bceSAndroid Build Coastguard Worker         for (vector<string>::const_iterator var = tfVaryings.begin(); var != tfVaryings.end(); var++)
1629*35238bceSAndroid Build Coastguard Worker             m_progSpec.addTransformFeedbackVarying(var->c_str());
1630*35238bceSAndroid Build Coastguard Worker 
1631*35238bceSAndroid Build Coastguard Worker         TransformFeedbackCase::init();
1632*35238bceSAndroid Build Coastguard Worker     }
1633*35238bceSAndroid Build Coastguard Worker 
1634*35238bceSAndroid Build Coastguard Worker private:
1635*35238bceSAndroid Build Coastguard Worker     uint32_t m_seed;
1636*35238bceSAndroid Build Coastguard Worker     bool m_elementCapture;
1637*35238bceSAndroid Build Coastguard Worker };
1638*35238bceSAndroid Build Coastguard Worker 
1639*35238bceSAndroid Build Coastguard Worker } // namespace TransformFeedback
1640*35238bceSAndroid Build Coastguard Worker 
1641*35238bceSAndroid Build Coastguard Worker using namespace TransformFeedback;
1642*35238bceSAndroid Build Coastguard Worker 
TransformFeedbackTests(Context & context)1643*35238bceSAndroid Build Coastguard Worker TransformFeedbackTests::TransformFeedbackTests(Context &context)
1644*35238bceSAndroid Build Coastguard Worker     : TestCaseGroup(context, "transform_feedback", "Transform feedback tests")
1645*35238bceSAndroid Build Coastguard Worker {
1646*35238bceSAndroid Build Coastguard Worker }
1647*35238bceSAndroid Build Coastguard Worker 
~TransformFeedbackTests(void)1648*35238bceSAndroid Build Coastguard Worker TransformFeedbackTests::~TransformFeedbackTests(void)
1649*35238bceSAndroid Build Coastguard Worker {
1650*35238bceSAndroid Build Coastguard Worker }
1651*35238bceSAndroid Build Coastguard Worker 
init(void)1652*35238bceSAndroid Build Coastguard Worker void TransformFeedbackTests::init(void)
1653*35238bceSAndroid Build Coastguard Worker {
1654*35238bceSAndroid Build Coastguard Worker     static const struct
1655*35238bceSAndroid Build Coastguard Worker     {
1656*35238bceSAndroid Build Coastguard Worker         const char *name;
1657*35238bceSAndroid Build Coastguard Worker         uint32_t mode;
1658*35238bceSAndroid Build Coastguard Worker     } bufferModes[] = {{"separate", GL_SEPARATE_ATTRIBS}, {"interleaved", GL_INTERLEAVED_ATTRIBS}};
1659*35238bceSAndroid Build Coastguard Worker 
1660*35238bceSAndroid Build Coastguard Worker     static const struct
1661*35238bceSAndroid Build Coastguard Worker     {
1662*35238bceSAndroid Build Coastguard Worker         const char *name;
1663*35238bceSAndroid Build Coastguard Worker         uint32_t type;
1664*35238bceSAndroid Build Coastguard Worker     } primitiveTypes[] = {
1665*35238bceSAndroid Build Coastguard Worker         {"points", GL_POINTS}, {"lines", GL_LINES}, {"triangles", GL_TRIANGLES}
1666*35238bceSAndroid Build Coastguard Worker 
1667*35238bceSAndroid Build Coastguard Worker         // Not supported by GLES3.
1668*35238bceSAndroid Build Coastguard Worker         //        { "line_strip", GL_LINE_STRIP        },
1669*35238bceSAndroid Build Coastguard Worker         //        { "line_loop", GL_LINE_LOOP        },
1670*35238bceSAndroid Build Coastguard Worker         //        { "triangle_fan", GL_TRIANGLE_FAN        },
1671*35238bceSAndroid Build Coastguard Worker         //        { "triangle_strip", GL_TRIANGLE_STRIP    }
1672*35238bceSAndroid Build Coastguard Worker     };
1673*35238bceSAndroid Build Coastguard Worker 
1674*35238bceSAndroid Build Coastguard Worker     static const glu::DataType basicTypes[] = {glu::TYPE_FLOAT,        glu::TYPE_FLOAT_VEC2,   glu::TYPE_FLOAT_VEC3,
1675*35238bceSAndroid Build Coastguard Worker                                                glu::TYPE_FLOAT_VEC4,   glu::TYPE_FLOAT_MAT2,   glu::TYPE_FLOAT_MAT2X3,
1676*35238bceSAndroid Build Coastguard Worker                                                glu::TYPE_FLOAT_MAT2X4, glu::TYPE_FLOAT_MAT3X2, glu::TYPE_FLOAT_MAT3,
1677*35238bceSAndroid Build Coastguard Worker                                                glu::TYPE_FLOAT_MAT3X4, glu::TYPE_FLOAT_MAT4X2, glu::TYPE_FLOAT_MAT4X3,
1678*35238bceSAndroid Build Coastguard Worker                                                glu::TYPE_FLOAT_MAT4,   glu::TYPE_INT,          glu::TYPE_INT_VEC2,
1679*35238bceSAndroid Build Coastguard Worker                                                glu::TYPE_INT_VEC3,     glu::TYPE_INT_VEC4,     glu::TYPE_UINT,
1680*35238bceSAndroid Build Coastguard Worker                                                glu::TYPE_UINT_VEC2,    glu::TYPE_UINT_VEC3,    glu::TYPE_UINT_VEC4};
1681*35238bceSAndroid Build Coastguard Worker 
1682*35238bceSAndroid Build Coastguard Worker     static const glu::Precision precisions[] = {glu::PRECISION_LOWP, glu::PRECISION_MEDIUMP, glu::PRECISION_HIGHP};
1683*35238bceSAndroid Build Coastguard Worker 
1684*35238bceSAndroid Build Coastguard Worker     static const struct
1685*35238bceSAndroid Build Coastguard Worker     {
1686*35238bceSAndroid Build Coastguard Worker         const char *name;
1687*35238bceSAndroid Build Coastguard Worker         Interpolation interp;
1688*35238bceSAndroid Build Coastguard Worker     } interpModes[] = {
1689*35238bceSAndroid Build Coastguard Worker         {"smooth", INTERPOLATION_SMOOTH}, {"flat", INTERPOLATION_FLAT}, {"centroid", INTERPOLATION_CENTROID}};
1690*35238bceSAndroid Build Coastguard Worker 
1691*35238bceSAndroid Build Coastguard Worker     // .position
1692*35238bceSAndroid Build Coastguard Worker     {
1693*35238bceSAndroid Build Coastguard Worker         tcu::TestCaseGroup *positionGroup =
1694*35238bceSAndroid Build Coastguard Worker             new tcu::TestCaseGroup(m_testCtx, "position", "gl_Position capture using transform feedback");
1695*35238bceSAndroid Build Coastguard Worker         addChild(positionGroup);
1696*35238bceSAndroid Build Coastguard Worker 
1697*35238bceSAndroid Build Coastguard Worker         for (int primitiveType = 0; primitiveType < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveType++)
1698*35238bceSAndroid Build Coastguard Worker         {
1699*35238bceSAndroid Build Coastguard Worker             for (int bufferMode = 0; bufferMode < DE_LENGTH_OF_ARRAY(bufferModes); bufferMode++)
1700*35238bceSAndroid Build Coastguard Worker             {
1701*35238bceSAndroid Build Coastguard Worker                 string name = string(primitiveTypes[primitiveType].name) + "_" + bufferModes[bufferMode].name;
1702*35238bceSAndroid Build Coastguard Worker                 positionGroup->addChild(new PositionCase(m_context, name.c_str(), "", bufferModes[bufferMode].mode,
1703*35238bceSAndroid Build Coastguard Worker                                                          primitiveTypes[primitiveType].type));
1704*35238bceSAndroid Build Coastguard Worker             }
1705*35238bceSAndroid Build Coastguard Worker         }
1706*35238bceSAndroid Build Coastguard Worker     }
1707*35238bceSAndroid Build Coastguard Worker 
1708*35238bceSAndroid Build Coastguard Worker     // .point_size
1709*35238bceSAndroid Build Coastguard Worker     {
1710*35238bceSAndroid Build Coastguard Worker         tcu::TestCaseGroup *pointSizeGroup =
1711*35238bceSAndroid Build Coastguard Worker             new tcu::TestCaseGroup(m_testCtx, "point_size", "gl_PointSize capture using transform feedback");
1712*35238bceSAndroid Build Coastguard Worker         addChild(pointSizeGroup);
1713*35238bceSAndroid Build Coastguard Worker 
1714*35238bceSAndroid Build Coastguard Worker         for (int primitiveType = 0; primitiveType < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveType++)
1715*35238bceSAndroid Build Coastguard Worker         {
1716*35238bceSAndroid Build Coastguard Worker             for (int bufferMode = 0; bufferMode < DE_LENGTH_OF_ARRAY(bufferModes); bufferMode++)
1717*35238bceSAndroid Build Coastguard Worker             {
1718*35238bceSAndroid Build Coastguard Worker                 string name = string(primitiveTypes[primitiveType].name) + "_" + bufferModes[bufferMode].name;
1719*35238bceSAndroid Build Coastguard Worker                 pointSizeGroup->addChild(new PointSizeCase(m_context, name.c_str(), "", bufferModes[bufferMode].mode,
1720*35238bceSAndroid Build Coastguard Worker                                                            primitiveTypes[primitiveType].type));
1721*35238bceSAndroid Build Coastguard Worker             }
1722*35238bceSAndroid Build Coastguard Worker         }
1723*35238bceSAndroid Build Coastguard Worker     }
1724*35238bceSAndroid Build Coastguard Worker 
1725*35238bceSAndroid Build Coastguard Worker     // .basic_type
1726*35238bceSAndroid Build Coastguard Worker     {
1727*35238bceSAndroid Build Coastguard Worker         tcu::TestCaseGroup *basicTypeGroup =
1728*35238bceSAndroid Build Coastguard Worker             new tcu::TestCaseGroup(m_testCtx, "basic_types", "Basic types in transform feedback");
1729*35238bceSAndroid Build Coastguard Worker         addChild(basicTypeGroup);
1730*35238bceSAndroid Build Coastguard Worker 
1731*35238bceSAndroid Build Coastguard Worker         for (int bufferModeNdx = 0; bufferModeNdx < DE_LENGTH_OF_ARRAY(bufferModes); bufferModeNdx++)
1732*35238bceSAndroid Build Coastguard Worker         {
1733*35238bceSAndroid Build Coastguard Worker             tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[bufferModeNdx].name, "");
1734*35238bceSAndroid Build Coastguard Worker             uint32_t bufferMode           = bufferModes[bufferModeNdx].mode;
1735*35238bceSAndroid Build Coastguard Worker             basicTypeGroup->addChild(modeGroup);
1736*35238bceSAndroid Build Coastguard Worker 
1737*35238bceSAndroid Build Coastguard Worker             for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveTypeNdx++)
1738*35238bceSAndroid Build Coastguard Worker             {
1739*35238bceSAndroid Build Coastguard Worker                 tcu::TestCaseGroup *primitiveGroup =
1740*35238bceSAndroid Build Coastguard Worker                     new tcu::TestCaseGroup(m_testCtx, primitiveTypes[primitiveTypeNdx].name, "");
1741*35238bceSAndroid Build Coastguard Worker                 uint32_t primitiveType = primitiveTypes[primitiveTypeNdx].type;
1742*35238bceSAndroid Build Coastguard Worker                 modeGroup->addChild(primitiveGroup);
1743*35238bceSAndroid Build Coastguard Worker 
1744*35238bceSAndroid Build Coastguard Worker                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(basicTypes); typeNdx++)
1745*35238bceSAndroid Build Coastguard Worker                 {
1746*35238bceSAndroid Build Coastguard Worker                     glu::DataType type = basicTypes[typeNdx];
1747*35238bceSAndroid Build Coastguard Worker                     bool isFloat       = glu::getDataTypeScalarType(type) == glu::TYPE_FLOAT;
1748*35238bceSAndroid Build Coastguard Worker 
1749*35238bceSAndroid Build Coastguard Worker                     for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
1750*35238bceSAndroid Build Coastguard Worker                     {
1751*35238bceSAndroid Build Coastguard Worker                         glu::Precision precision = precisions[precNdx];
1752*35238bceSAndroid Build Coastguard Worker 
1753*35238bceSAndroid Build Coastguard Worker                         string name = string(glu::getPrecisionName(precision)) + "_" + glu::getDataTypeName(type);
1754*35238bceSAndroid Build Coastguard Worker                         primitiveGroup->addChild(
1755*35238bceSAndroid Build Coastguard Worker                             new BasicTypeCase(m_context, name.c_str(), "", bufferMode, primitiveType, type, precision,
1756*35238bceSAndroid Build Coastguard Worker                                               isFloat ? INTERPOLATION_SMOOTH : INTERPOLATION_FLAT));
1757*35238bceSAndroid Build Coastguard Worker                     }
1758*35238bceSAndroid Build Coastguard Worker                 }
1759*35238bceSAndroid Build Coastguard Worker             }
1760*35238bceSAndroid Build Coastguard Worker         }
1761*35238bceSAndroid Build Coastguard Worker     }
1762*35238bceSAndroid Build Coastguard Worker 
1763*35238bceSAndroid Build Coastguard Worker     // .array
1764*35238bceSAndroid Build Coastguard Worker     {
1765*35238bceSAndroid Build Coastguard Worker         tcu::TestCaseGroup *arrayGroup = new tcu::TestCaseGroup(m_testCtx, "array", "Capturing whole array in TF");
1766*35238bceSAndroid Build Coastguard Worker         addChild(arrayGroup);
1767*35238bceSAndroid Build Coastguard Worker 
1768*35238bceSAndroid Build Coastguard Worker         for (int bufferModeNdx = 0; bufferModeNdx < DE_LENGTH_OF_ARRAY(bufferModes); bufferModeNdx++)
1769*35238bceSAndroid Build Coastguard Worker         {
1770*35238bceSAndroid Build Coastguard Worker             tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[bufferModeNdx].name, "");
1771*35238bceSAndroid Build Coastguard Worker             uint32_t bufferMode           = bufferModes[bufferModeNdx].mode;
1772*35238bceSAndroid Build Coastguard Worker             arrayGroup->addChild(modeGroup);
1773*35238bceSAndroid Build Coastguard Worker 
1774*35238bceSAndroid Build Coastguard Worker             for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveTypeNdx++)
1775*35238bceSAndroid Build Coastguard Worker             {
1776*35238bceSAndroid Build Coastguard Worker                 tcu::TestCaseGroup *primitiveGroup =
1777*35238bceSAndroid Build Coastguard Worker                     new tcu::TestCaseGroup(m_testCtx, primitiveTypes[primitiveTypeNdx].name, "");
1778*35238bceSAndroid Build Coastguard Worker                 uint32_t primitiveType = primitiveTypes[primitiveTypeNdx].type;
1779*35238bceSAndroid Build Coastguard Worker                 modeGroup->addChild(primitiveGroup);
1780*35238bceSAndroid Build Coastguard Worker 
1781*35238bceSAndroid Build Coastguard Worker                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(basicTypes); typeNdx++)
1782*35238bceSAndroid Build Coastguard Worker                 {
1783*35238bceSAndroid Build Coastguard Worker                     glu::DataType type = basicTypes[typeNdx];
1784*35238bceSAndroid Build Coastguard Worker                     bool isFloat       = glu::getDataTypeScalarType(type) == glu::TYPE_FLOAT;
1785*35238bceSAndroid Build Coastguard Worker 
1786*35238bceSAndroid Build Coastguard Worker                     for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
1787*35238bceSAndroid Build Coastguard Worker                     {
1788*35238bceSAndroid Build Coastguard Worker                         glu::Precision precision = precisions[precNdx];
1789*35238bceSAndroid Build Coastguard Worker 
1790*35238bceSAndroid Build Coastguard Worker                         string name = string(glu::getPrecisionName(precision)) + "_" + glu::getDataTypeName(type);
1791*35238bceSAndroid Build Coastguard Worker                         primitiveGroup->addChild(
1792*35238bceSAndroid Build Coastguard Worker                             new BasicArrayCase(m_context, name.c_str(), "", bufferMode, primitiveType, type, precision,
1793*35238bceSAndroid Build Coastguard Worker                                                isFloat ? INTERPOLATION_SMOOTH : INTERPOLATION_FLAT));
1794*35238bceSAndroid Build Coastguard Worker                     }
1795*35238bceSAndroid Build Coastguard Worker                 }
1796*35238bceSAndroid Build Coastguard Worker             }
1797*35238bceSAndroid Build Coastguard Worker         }
1798*35238bceSAndroid Build Coastguard Worker     }
1799*35238bceSAndroid Build Coastguard Worker 
1800*35238bceSAndroid Build Coastguard Worker     // .array_element
1801*35238bceSAndroid Build Coastguard Worker     {
1802*35238bceSAndroid Build Coastguard Worker         tcu::TestCaseGroup *arrayElemGroup =
1803*35238bceSAndroid Build Coastguard Worker             new tcu::TestCaseGroup(m_testCtx, "array_element", "Capturing single array element in TF");
1804*35238bceSAndroid Build Coastguard Worker         addChild(arrayElemGroup);
1805*35238bceSAndroid Build Coastguard Worker 
1806*35238bceSAndroid Build Coastguard Worker         for (int bufferModeNdx = 0; bufferModeNdx < DE_LENGTH_OF_ARRAY(bufferModes); bufferModeNdx++)
1807*35238bceSAndroid Build Coastguard Worker         {
1808*35238bceSAndroid Build Coastguard Worker             tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[bufferModeNdx].name, "");
1809*35238bceSAndroid Build Coastguard Worker             uint32_t bufferMode           = bufferModes[bufferModeNdx].mode;
1810*35238bceSAndroid Build Coastguard Worker             arrayElemGroup->addChild(modeGroup);
1811*35238bceSAndroid Build Coastguard Worker 
1812*35238bceSAndroid Build Coastguard Worker             for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveTypeNdx++)
1813*35238bceSAndroid Build Coastguard Worker             {
1814*35238bceSAndroid Build Coastguard Worker                 tcu::TestCaseGroup *primitiveGroup =
1815*35238bceSAndroid Build Coastguard Worker                     new tcu::TestCaseGroup(m_testCtx, primitiveTypes[primitiveTypeNdx].name, "");
1816*35238bceSAndroid Build Coastguard Worker                 uint32_t primitiveType = primitiveTypes[primitiveTypeNdx].type;
1817*35238bceSAndroid Build Coastguard Worker                 modeGroup->addChild(primitiveGroup);
1818*35238bceSAndroid Build Coastguard Worker 
1819*35238bceSAndroid Build Coastguard Worker                 for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(basicTypes); typeNdx++)
1820*35238bceSAndroid Build Coastguard Worker                 {
1821*35238bceSAndroid Build Coastguard Worker                     glu::DataType type = basicTypes[typeNdx];
1822*35238bceSAndroid Build Coastguard Worker                     bool isFloat       = glu::getDataTypeScalarType(type) == glu::TYPE_FLOAT;
1823*35238bceSAndroid Build Coastguard Worker 
1824*35238bceSAndroid Build Coastguard Worker                     for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
1825*35238bceSAndroid Build Coastguard Worker                     {
1826*35238bceSAndroid Build Coastguard Worker                         glu::Precision precision = precisions[precNdx];
1827*35238bceSAndroid Build Coastguard Worker 
1828*35238bceSAndroid Build Coastguard Worker                         string name = string(glu::getPrecisionName(precision)) + "_" + glu::getDataTypeName(type);
1829*35238bceSAndroid Build Coastguard Worker                         primitiveGroup->addChild(
1830*35238bceSAndroid Build Coastguard Worker                             new ArrayElementCase(m_context, name.c_str(), "", bufferMode, primitiveType, type,
1831*35238bceSAndroid Build Coastguard Worker                                                  precision, isFloat ? INTERPOLATION_SMOOTH : INTERPOLATION_FLAT));
1832*35238bceSAndroid Build Coastguard Worker                     }
1833*35238bceSAndroid Build Coastguard Worker                 }
1834*35238bceSAndroid Build Coastguard Worker             }
1835*35238bceSAndroid Build Coastguard Worker         }
1836*35238bceSAndroid Build Coastguard Worker     }
1837*35238bceSAndroid Build Coastguard Worker 
1838*35238bceSAndroid Build Coastguard Worker     // .interpolation
1839*35238bceSAndroid Build Coastguard Worker     {
1840*35238bceSAndroid Build Coastguard Worker         tcu::TestCaseGroup *interpolationGroup = new tcu::TestCaseGroup(
1841*35238bceSAndroid Build Coastguard Worker             m_testCtx, "interpolation", "Different interpolation modes in transform feedback varyings");
1842*35238bceSAndroid Build Coastguard Worker         addChild(interpolationGroup);
1843*35238bceSAndroid Build Coastguard Worker 
1844*35238bceSAndroid Build Coastguard Worker         for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(interpModes); modeNdx++)
1845*35238bceSAndroid Build Coastguard Worker         {
1846*35238bceSAndroid Build Coastguard Worker             Interpolation interp          = interpModes[modeNdx].interp;
1847*35238bceSAndroid Build Coastguard Worker             tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, interpModes[modeNdx].name, "");
1848*35238bceSAndroid Build Coastguard Worker 
1849*35238bceSAndroid Build Coastguard Worker             interpolationGroup->addChild(modeGroup);
1850*35238bceSAndroid Build Coastguard Worker 
1851*35238bceSAndroid Build Coastguard Worker             for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisions); precNdx++)
1852*35238bceSAndroid Build Coastguard Worker             {
1853*35238bceSAndroid Build Coastguard Worker                 glu::Precision precision = precisions[precNdx];
1854*35238bceSAndroid Build Coastguard Worker 
1855*35238bceSAndroid Build Coastguard Worker                 for (int primitiveType = 0; primitiveType < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveType++)
1856*35238bceSAndroid Build Coastguard Worker                 {
1857*35238bceSAndroid Build Coastguard Worker                     for (int bufferMode = 0; bufferMode < DE_LENGTH_OF_ARRAY(bufferModes); bufferMode++)
1858*35238bceSAndroid Build Coastguard Worker                     {
1859*35238bceSAndroid Build Coastguard Worker                         string name = string(glu::getPrecisionName(precision)) + "_vec4_" +
1860*35238bceSAndroid Build Coastguard Worker                                       primitiveTypes[primitiveType].name + "_" + bufferModes[bufferMode].name;
1861*35238bceSAndroid Build Coastguard Worker                         modeGroup->addChild(new BasicTypeCase(m_context, name.c_str(), "", bufferModes[bufferMode].mode,
1862*35238bceSAndroid Build Coastguard Worker                                                               primitiveTypes[primitiveType].type, glu::TYPE_FLOAT_VEC4,
1863*35238bceSAndroid Build Coastguard Worker                                                               precision, interp));
1864*35238bceSAndroid Build Coastguard Worker                     }
1865*35238bceSAndroid Build Coastguard Worker                 }
1866*35238bceSAndroid Build Coastguard Worker             }
1867*35238bceSAndroid Build Coastguard Worker         }
1868*35238bceSAndroid Build Coastguard Worker     }
1869*35238bceSAndroid Build Coastguard Worker 
1870*35238bceSAndroid Build Coastguard Worker     // .random
1871*35238bceSAndroid Build Coastguard Worker     {
1872*35238bceSAndroid Build Coastguard Worker         tcu::TestCaseGroup *randomGroup =
1873*35238bceSAndroid Build Coastguard Worker             new tcu::TestCaseGroup(m_testCtx, "random", "Randomized transform feedback cases");
1874*35238bceSAndroid Build Coastguard Worker         addChild(randomGroup);
1875*35238bceSAndroid Build Coastguard Worker 
1876*35238bceSAndroid Build Coastguard Worker         for (int bufferModeNdx = 0; bufferModeNdx < DE_LENGTH_OF_ARRAY(bufferModes); bufferModeNdx++)
1877*35238bceSAndroid Build Coastguard Worker         {
1878*35238bceSAndroid Build Coastguard Worker             tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[bufferModeNdx].name, "");
1879*35238bceSAndroid Build Coastguard Worker             uint32_t bufferMode           = bufferModes[bufferModeNdx].mode;
1880*35238bceSAndroid Build Coastguard Worker             randomGroup->addChild(modeGroup);
1881*35238bceSAndroid Build Coastguard Worker 
1882*35238bceSAndroid Build Coastguard Worker             for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveTypeNdx++)
1883*35238bceSAndroid Build Coastguard Worker             {
1884*35238bceSAndroid Build Coastguard Worker                 tcu::TestCaseGroup *primitiveGroup =
1885*35238bceSAndroid Build Coastguard Worker                     new tcu::TestCaseGroup(m_testCtx, primitiveTypes[primitiveTypeNdx].name, "");
1886*35238bceSAndroid Build Coastguard Worker                 uint32_t primitiveType = primitiveTypes[primitiveTypeNdx].type;
1887*35238bceSAndroid Build Coastguard Worker                 modeGroup->addChild(primitiveGroup);
1888*35238bceSAndroid Build Coastguard Worker 
1889*35238bceSAndroid Build Coastguard Worker                 for (int ndx = 0; ndx < 10; ndx++)
1890*35238bceSAndroid Build Coastguard Worker                 {
1891*35238bceSAndroid Build Coastguard Worker                     uint32_t seed = deInt32Hash(bufferMode) ^ deInt32Hash(primitiveType) ^ deInt32Hash(ndx);
1892*35238bceSAndroid Build Coastguard Worker                     primitiveGroup->addChild(new RandomCase(m_context, de::toString(ndx + 1).c_str(), "", bufferMode,
1893*35238bceSAndroid Build Coastguard Worker                                                             primitiveType, seed, true));
1894*35238bceSAndroid Build Coastguard Worker                 }
1895*35238bceSAndroid Build Coastguard Worker             }
1896*35238bceSAndroid Build Coastguard Worker         }
1897*35238bceSAndroid Build Coastguard Worker     }
1898*35238bceSAndroid Build Coastguard Worker 
1899*35238bceSAndroid Build Coastguard Worker     // .random_full_array_capture
1900*35238bceSAndroid Build Coastguard Worker     {
1901*35238bceSAndroid Build Coastguard Worker         tcu::TestCaseGroup *randomNecGroup =
1902*35238bceSAndroid Build Coastguard Worker             new tcu::TestCaseGroup(m_testCtx, "random_full_array_capture",
1903*35238bceSAndroid Build Coastguard Worker                                    "Randomized transform feedback cases without array element capture");
1904*35238bceSAndroid Build Coastguard Worker         addChild(randomNecGroup);
1905*35238bceSAndroid Build Coastguard Worker 
1906*35238bceSAndroid Build Coastguard Worker         for (int bufferModeNdx = 0; bufferModeNdx < DE_LENGTH_OF_ARRAY(bufferModes); bufferModeNdx++)
1907*35238bceSAndroid Build Coastguard Worker         {
1908*35238bceSAndroid Build Coastguard Worker             tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[bufferModeNdx].name, "");
1909*35238bceSAndroid Build Coastguard Worker             uint32_t bufferMode           = bufferModes[bufferModeNdx].mode;
1910*35238bceSAndroid Build Coastguard Worker             randomNecGroup->addChild(modeGroup);
1911*35238bceSAndroid Build Coastguard Worker 
1912*35238bceSAndroid Build Coastguard Worker             for (int primitiveTypeNdx = 0; primitiveTypeNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); primitiveTypeNdx++)
1913*35238bceSAndroid Build Coastguard Worker             {
1914*35238bceSAndroid Build Coastguard Worker                 tcu::TestCaseGroup *primitiveGroup =
1915*35238bceSAndroid Build Coastguard Worker                     new tcu::TestCaseGroup(m_testCtx, primitiveTypes[primitiveTypeNdx].name, "");
1916*35238bceSAndroid Build Coastguard Worker                 uint32_t primitiveType = primitiveTypes[primitiveTypeNdx].type;
1917*35238bceSAndroid Build Coastguard Worker                 modeGroup->addChild(primitiveGroup);
1918*35238bceSAndroid Build Coastguard Worker 
1919*35238bceSAndroid Build Coastguard Worker                 for (int ndx = 0; ndx < 10; ndx++)
1920*35238bceSAndroid Build Coastguard Worker                 {
1921*35238bceSAndroid Build Coastguard Worker                     uint32_t seed = deInt32Hash(bufferMode) ^ deInt32Hash(primitiveType) ^ deInt32Hash(ndx);
1922*35238bceSAndroid Build Coastguard Worker                     primitiveGroup->addChild(new RandomCase(m_context, de::toString(ndx + 1).c_str(), "", bufferMode,
1923*35238bceSAndroid Build Coastguard Worker                                                             primitiveType, seed, false));
1924*35238bceSAndroid Build Coastguard Worker                 }
1925*35238bceSAndroid Build Coastguard Worker             }
1926*35238bceSAndroid Build Coastguard Worker         }
1927*35238bceSAndroid Build Coastguard Worker     }
1928*35238bceSAndroid Build Coastguard Worker }
1929*35238bceSAndroid Build Coastguard Worker 
1930*35238bceSAndroid Build Coastguard Worker } // namespace Functional
1931*35238bceSAndroid Build Coastguard Worker } // namespace gles3
1932*35238bceSAndroid Build Coastguard Worker } // namespace deqp
1933