xref: /aosp_15_r20/external/deqp/modules/gles31/stress/es31sVertexAttributeBindingTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program OpenGL ES 3.1 Module
3*35238bceSAndroid Build Coastguard Worker  * -------------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief Vertex attribute binding stress tests.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "es31sVertexAttributeBindingTests.hpp"
25*35238bceSAndroid Build Coastguard Worker #include "tcuVector.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "tcuTestLog.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "tcuRenderTarget.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "tcuSurface.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "gluCallLogWrapper.hpp"
30*35238bceSAndroid Build Coastguard Worker #include "gluObjectWrapper.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "gluPixelTransfer.hpp"
32*35238bceSAndroid Build Coastguard Worker #include "gluRenderContext.hpp"
33*35238bceSAndroid Build Coastguard Worker #include "gluShaderProgram.hpp"
34*35238bceSAndroid Build Coastguard Worker #include "gluStrUtil.hpp"
35*35238bceSAndroid Build Coastguard Worker #include "glwFunctions.hpp"
36*35238bceSAndroid Build Coastguard Worker #include "glwEnums.hpp"
37*35238bceSAndroid Build Coastguard Worker #include "deStringUtil.hpp"
38*35238bceSAndroid Build Coastguard Worker 
39*35238bceSAndroid Build Coastguard Worker namespace deqp
40*35238bceSAndroid Build Coastguard Worker {
41*35238bceSAndroid Build Coastguard Worker namespace gles31
42*35238bceSAndroid Build Coastguard Worker {
43*35238bceSAndroid Build Coastguard Worker namespace Stress
44*35238bceSAndroid Build Coastguard Worker {
45*35238bceSAndroid Build Coastguard Worker namespace
46*35238bceSAndroid Build Coastguard Worker {
47*35238bceSAndroid Build Coastguard Worker 
48*35238bceSAndroid Build Coastguard Worker static const char *const s_vertexSource = "#version 310 es\n"
49*35238bceSAndroid Build Coastguard Worker                                           "in highp vec4 a_position;\n"
50*35238bceSAndroid Build Coastguard Worker                                           "void main (void)\n"
51*35238bceSAndroid Build Coastguard Worker                                           "{\n"
52*35238bceSAndroid Build Coastguard Worker                                           "    gl_Position = a_position;\n"
53*35238bceSAndroid Build Coastguard Worker                                           "}\n";
54*35238bceSAndroid Build Coastguard Worker 
55*35238bceSAndroid Build Coastguard Worker static const char *const s_fragmentSource = "#version 310 es\n"
56*35238bceSAndroid Build Coastguard Worker                                             "layout(location = 0) out mediump vec4 fragColor;\n"
57*35238bceSAndroid Build Coastguard Worker                                             "void main (void)\n"
58*35238bceSAndroid Build Coastguard Worker                                             "{\n"
59*35238bceSAndroid Build Coastguard Worker                                             "    fragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
60*35238bceSAndroid Build Coastguard Worker                                             "}\n";
61*35238bceSAndroid Build Coastguard Worker 
62*35238bceSAndroid Build Coastguard Worker static const char *const s_colorFragmentShader = "#version 310 es\n"
63*35238bceSAndroid Build Coastguard Worker                                                  "in mediump vec4 v_color;\n"
64*35238bceSAndroid Build Coastguard Worker                                                  "layout(location = 0) out mediump vec4 fragColor;\n"
65*35238bceSAndroid Build Coastguard Worker                                                  "void main (void)\n"
66*35238bceSAndroid Build Coastguard Worker                                                  "{\n"
67*35238bceSAndroid Build Coastguard Worker                                                  "    fragColor = v_color;\n"
68*35238bceSAndroid Build Coastguard Worker                                                  "}\n";
69*35238bceSAndroid Build Coastguard Worker 
70*35238bceSAndroid Build Coastguard Worker // Verifies image contains only yellow or greeen, or a linear combination
71*35238bceSAndroid Build Coastguard Worker // of these colors.
verifyImageYellowGreen(const tcu::Surface & image,tcu::TestLog & log,bool logImageOnSuccess)72*35238bceSAndroid Build Coastguard Worker static bool verifyImageYellowGreen(const tcu::Surface &image, tcu::TestLog &log, bool logImageOnSuccess)
73*35238bceSAndroid Build Coastguard Worker {
74*35238bceSAndroid Build Coastguard Worker     using tcu::TestLog;
75*35238bceSAndroid Build Coastguard Worker 
76*35238bceSAndroid Build Coastguard Worker     const int colorThreshold = 20;
77*35238bceSAndroid Build Coastguard Worker 
78*35238bceSAndroid Build Coastguard Worker     tcu::Surface error(image.getWidth(), image.getHeight());
79*35238bceSAndroid Build Coastguard Worker     bool isOk = true;
80*35238bceSAndroid Build Coastguard Worker 
81*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "Verifying image contents." << TestLog::EndMessage;
82*35238bceSAndroid Build Coastguard Worker 
83*35238bceSAndroid Build Coastguard Worker     for (int y = 0; y < image.getHeight(); y++)
84*35238bceSAndroid Build Coastguard Worker         for (int x = 0; x < image.getWidth(); x++)
85*35238bceSAndroid Build Coastguard Worker         {
86*35238bceSAndroid Build Coastguard Worker             const tcu::RGBA pixel = image.getPixel(x, y);
87*35238bceSAndroid Build Coastguard Worker             bool pixelOk          = true;
88*35238bceSAndroid Build Coastguard Worker 
89*35238bceSAndroid Build Coastguard Worker             // Any pixel with !(G ~= 255) is faulty (not a linear combinations of green and yellow)
90*35238bceSAndroid Build Coastguard Worker             if (de::abs(pixel.getGreen() - 255) > colorThreshold)
91*35238bceSAndroid Build Coastguard Worker                 pixelOk = false;
92*35238bceSAndroid Build Coastguard Worker 
93*35238bceSAndroid Build Coastguard Worker             // Any pixel with !(B ~= 0) is faulty (not a linear combinations of green and yellow)
94*35238bceSAndroid Build Coastguard Worker             if (de::abs(pixel.getBlue() - 0) > colorThreshold)
95*35238bceSAndroid Build Coastguard Worker                 pixelOk = false;
96*35238bceSAndroid Build Coastguard Worker 
97*35238bceSAndroid Build Coastguard Worker             error.setPixel(x, y, (pixelOk) ? (tcu::RGBA(0, 255, 0, 255)) : (tcu::RGBA(255, 0, 0, 255)));
98*35238bceSAndroid Build Coastguard Worker             isOk = isOk && pixelOk;
99*35238bceSAndroid Build Coastguard Worker         }
100*35238bceSAndroid Build Coastguard Worker 
101*35238bceSAndroid Build Coastguard Worker     if (!isOk)
102*35238bceSAndroid Build Coastguard Worker     {
103*35238bceSAndroid Build Coastguard Worker         log << TestLog::Message << "Image verification failed." << TestLog::EndMessage;
104*35238bceSAndroid Build Coastguard Worker         log << TestLog::ImageSet("Verfication result", "Result of rendering")
105*35238bceSAndroid Build Coastguard Worker             << TestLog::Image("Result", "Result", image) << TestLog::Image("ErrorMask", "Error mask", error)
106*35238bceSAndroid Build Coastguard Worker             << TestLog::EndImageSet;
107*35238bceSAndroid Build Coastguard Worker     }
108*35238bceSAndroid Build Coastguard Worker     else
109*35238bceSAndroid Build Coastguard Worker     {
110*35238bceSAndroid Build Coastguard Worker         log << TestLog::Message << "Image verification passed." << TestLog::EndMessage;
111*35238bceSAndroid Build Coastguard Worker 
112*35238bceSAndroid Build Coastguard Worker         if (logImageOnSuccess)
113*35238bceSAndroid Build Coastguard Worker             log << TestLog::ImageSet("Verfication result", "Result of rendering")
114*35238bceSAndroid Build Coastguard Worker                 << TestLog::Image("Result", "Result", image) << TestLog::EndImageSet;
115*35238bceSAndroid Build Coastguard Worker     }
116*35238bceSAndroid Build Coastguard Worker 
117*35238bceSAndroid Build Coastguard Worker     return isOk;
118*35238bceSAndroid Build Coastguard Worker }
119*35238bceSAndroid Build Coastguard Worker 
120*35238bceSAndroid Build Coastguard Worker class BindingRenderCase : public TestCase
121*35238bceSAndroid Build Coastguard Worker {
122*35238bceSAndroid Build Coastguard Worker public:
123*35238bceSAndroid Build Coastguard Worker     enum
124*35238bceSAndroid Build Coastguard Worker     {
125*35238bceSAndroid Build Coastguard Worker         TEST_RENDER_SIZE = 64
126*35238bceSAndroid Build Coastguard Worker     };
127*35238bceSAndroid Build Coastguard Worker 
128*35238bceSAndroid Build Coastguard Worker     BindingRenderCase(Context &ctx, const char *name, const char *desc, bool unalignedData);
129*35238bceSAndroid Build Coastguard Worker     virtual ~BindingRenderCase(void);
130*35238bceSAndroid Build Coastguard Worker 
131*35238bceSAndroid Build Coastguard Worker     virtual void init(void);
132*35238bceSAndroid Build Coastguard Worker     virtual void deinit(void);
133*35238bceSAndroid Build Coastguard Worker     IterateResult iterate(void);
134*35238bceSAndroid Build Coastguard Worker 
135*35238bceSAndroid Build Coastguard Worker private:
136*35238bceSAndroid Build Coastguard Worker     virtual void renderTo(tcu::Surface &dst) = 0;
137*35238bceSAndroid Build Coastguard Worker     virtual void createBuffers(void)         = 0;
138*35238bceSAndroid Build Coastguard Worker     virtual void createShader(void)          = 0;
139*35238bceSAndroid Build Coastguard Worker 
140*35238bceSAndroid Build Coastguard Worker protected:
141*35238bceSAndroid Build Coastguard Worker     const bool m_unalignedData;
142*35238bceSAndroid Build Coastguard Worker     glw::GLuint m_vao;
143*35238bceSAndroid Build Coastguard Worker     glu::ShaderProgram *m_program;
144*35238bceSAndroid Build Coastguard Worker };
145*35238bceSAndroid Build Coastguard Worker 
BindingRenderCase(Context & ctx,const char * name,const char * desc,bool unalignedData)146*35238bceSAndroid Build Coastguard Worker BindingRenderCase::BindingRenderCase(Context &ctx, const char *name, const char *desc, bool unalignedData)
147*35238bceSAndroid Build Coastguard Worker     : TestCase(ctx, name, desc)
148*35238bceSAndroid Build Coastguard Worker     , m_unalignedData(unalignedData)
149*35238bceSAndroid Build Coastguard Worker     , m_vao(0)
150*35238bceSAndroid Build Coastguard Worker     , m_program(DE_NULL)
151*35238bceSAndroid Build Coastguard Worker {
152*35238bceSAndroid Build Coastguard Worker }
153*35238bceSAndroid Build Coastguard Worker 
~BindingRenderCase(void)154*35238bceSAndroid Build Coastguard Worker BindingRenderCase::~BindingRenderCase(void)
155*35238bceSAndroid Build Coastguard Worker {
156*35238bceSAndroid Build Coastguard Worker     deinit();
157*35238bceSAndroid Build Coastguard Worker }
158*35238bceSAndroid Build Coastguard Worker 
init(void)159*35238bceSAndroid Build Coastguard Worker void BindingRenderCase::init(void)
160*35238bceSAndroid Build Coastguard Worker {
161*35238bceSAndroid Build Coastguard Worker     // check requirements
162*35238bceSAndroid Build Coastguard Worker     if (m_context.getRenderTarget().getWidth() < TEST_RENDER_SIZE ||
163*35238bceSAndroid Build Coastguard Worker         m_context.getRenderTarget().getHeight() < TEST_RENDER_SIZE)
164*35238bceSAndroid Build Coastguard Worker         throw tcu::NotSupportedError("Test requires at least " + de::toString<int>(TEST_RENDER_SIZE) + "x" +
165*35238bceSAndroid Build Coastguard Worker                                      de::toString<int>(TEST_RENDER_SIZE) + " render target");
166*35238bceSAndroid Build Coastguard Worker 
167*35238bceSAndroid Build Coastguard Worker     // resources
168*35238bceSAndroid Build Coastguard Worker     m_context.getRenderContext().getFunctions().genVertexArrays(1, &m_vao);
169*35238bceSAndroid Build Coastguard Worker     if (m_context.getRenderContext().getFunctions().getError() != GL_NO_ERROR)
170*35238bceSAndroid Build Coastguard Worker         throw tcu::TestError("could not gen vao");
171*35238bceSAndroid Build Coastguard Worker 
172*35238bceSAndroid Build Coastguard Worker     createBuffers();
173*35238bceSAndroid Build Coastguard Worker     createShader();
174*35238bceSAndroid Build Coastguard Worker }
175*35238bceSAndroid Build Coastguard Worker 
deinit(void)176*35238bceSAndroid Build Coastguard Worker void BindingRenderCase::deinit(void)
177*35238bceSAndroid Build Coastguard Worker {
178*35238bceSAndroid Build Coastguard Worker     if (m_vao)
179*35238bceSAndroid Build Coastguard Worker     {
180*35238bceSAndroid Build Coastguard Worker         m_context.getRenderContext().getFunctions().deleteVertexArrays(1, &m_vao);
181*35238bceSAndroid Build Coastguard Worker         m_vao = 0;
182*35238bceSAndroid Build Coastguard Worker     }
183*35238bceSAndroid Build Coastguard Worker 
184*35238bceSAndroid Build Coastguard Worker     delete m_program;
185*35238bceSAndroid Build Coastguard Worker     m_program = DE_NULL;
186*35238bceSAndroid Build Coastguard Worker }
187*35238bceSAndroid Build Coastguard Worker 
iterate(void)188*35238bceSAndroid Build Coastguard Worker BindingRenderCase::IterateResult BindingRenderCase::iterate(void)
189*35238bceSAndroid Build Coastguard Worker {
190*35238bceSAndroid Build Coastguard Worker     tcu::Surface surface(TEST_RENDER_SIZE, TEST_RENDER_SIZE);
191*35238bceSAndroid Build Coastguard Worker 
192*35238bceSAndroid Build Coastguard Worker     // draw pattern
193*35238bceSAndroid Build Coastguard Worker 
194*35238bceSAndroid Build Coastguard Worker     renderTo(surface);
195*35238bceSAndroid Build Coastguard Worker 
196*35238bceSAndroid Build Coastguard Worker     // verify results
197*35238bceSAndroid Build Coastguard Worker 
198*35238bceSAndroid Build Coastguard Worker     if (verifyImageYellowGreen(surface, m_testCtx.getLog(), false))
199*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
200*35238bceSAndroid Build Coastguard Worker     else if (m_unalignedData)
201*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned data");
202*35238bceSAndroid Build Coastguard Worker     else
203*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
204*35238bceSAndroid Build Coastguard Worker 
205*35238bceSAndroid Build Coastguard Worker     return STOP;
206*35238bceSAndroid Build Coastguard Worker }
207*35238bceSAndroid Build Coastguard Worker 
208*35238bceSAndroid Build Coastguard Worker class SingleBindingCase : public BindingRenderCase
209*35238bceSAndroid Build Coastguard Worker {
210*35238bceSAndroid Build Coastguard Worker public:
211*35238bceSAndroid Build Coastguard Worker     enum CaseFlag
212*35238bceSAndroid Build Coastguard Worker     {
213*35238bceSAndroid Build Coastguard Worker         FLAG_ATTRIB_UNALIGNED = (1 << 0), // !< unalign attributes with relativeOffset
214*35238bceSAndroid Build Coastguard Worker         FLAG_ATTRIB_ALIGNED =
215*35238bceSAndroid Build Coastguard Worker             (1 << 1), // !< align attributes with relativeOffset to the buffer begin (and not buffer offset)
216*35238bceSAndroid Build Coastguard Worker         FLAG_ATTRIBS_MULTIPLE_ELEMS = (1 << 2), // !< use multiple attribute elements
217*35238bceSAndroid Build Coastguard Worker         FLAG_ATTRIBS_SHARED_ELEMS =
218*35238bceSAndroid Build Coastguard Worker             (1 << 3), // !< use multiple shared attribute elements. xyzw & rgba stored as (x, y, zr, wg, b, a)
219*35238bceSAndroid Build Coastguard Worker 
220*35238bceSAndroid Build Coastguard Worker         FLAG_BUF_ALIGNED_OFFSET   = (1 << 4), // !< use aligned offset to the buffer object
221*35238bceSAndroid Build Coastguard Worker         FLAG_BUF_UNALIGNED_OFFSET = (1 << 5), // !< use unaligned offset to the buffer object
222*35238bceSAndroid Build Coastguard Worker         FLAG_BUF_UNALIGNED_STRIDE = (1 << 6), // !< unalign buffer elements
223*35238bceSAndroid Build Coastguard Worker     };
224*35238bceSAndroid Build Coastguard Worker     SingleBindingCase(Context &ctx, const char *name, int flags);
225*35238bceSAndroid Build Coastguard Worker     ~SingleBindingCase(void);
226*35238bceSAndroid Build Coastguard Worker 
227*35238bceSAndroid Build Coastguard Worker     void init(void);
228*35238bceSAndroid Build Coastguard Worker     void deinit(void);
229*35238bceSAndroid Build Coastguard Worker 
230*35238bceSAndroid Build Coastguard Worker private:
231*35238bceSAndroid Build Coastguard Worker     struct TestSpec
232*35238bceSAndroid Build Coastguard Worker     {
233*35238bceSAndroid Build Coastguard Worker         int bufferOffset;
234*35238bceSAndroid Build Coastguard Worker         int bufferStride;
235*35238bceSAndroid Build Coastguard Worker         int positionAttrOffset;
236*35238bceSAndroid Build Coastguard Worker         int colorAttrOffset;
237*35238bceSAndroid Build Coastguard Worker         bool hasColorAttr;
238*35238bceSAndroid Build Coastguard Worker     };
239*35238bceSAndroid Build Coastguard Worker 
240*35238bceSAndroid Build Coastguard Worker     enum
241*35238bceSAndroid Build Coastguard Worker     {
242*35238bceSAndroid Build Coastguard Worker         GRID_SIZE = 20
243*35238bceSAndroid Build Coastguard Worker     };
244*35238bceSAndroid Build Coastguard Worker 
245*35238bceSAndroid Build Coastguard Worker     void renderTo(tcu::Surface &dst);
246*35238bceSAndroid Build Coastguard Worker 
247*35238bceSAndroid Build Coastguard Worker     static TestSpec genTestSpec(int flags);
248*35238bceSAndroid Build Coastguard Worker     static std::string genTestDescription(int flags);
249*35238bceSAndroid Build Coastguard Worker     static bool isDataUnaligned(int flags);
250*35238bceSAndroid Build Coastguard Worker 
251*35238bceSAndroid Build Coastguard Worker     void createBuffers(void);
252*35238bceSAndroid Build Coastguard Worker     void createShader(void);
253*35238bceSAndroid Build Coastguard Worker     std::string genVertexSource(void);
254*35238bceSAndroid Build Coastguard Worker 
255*35238bceSAndroid Build Coastguard Worker     const TestSpec m_spec;
256*35238bceSAndroid Build Coastguard Worker     glw::GLuint m_buf;
257*35238bceSAndroid Build Coastguard Worker };
258*35238bceSAndroid Build Coastguard Worker 
SingleBindingCase(Context & ctx,const char * name,int flags)259*35238bceSAndroid Build Coastguard Worker SingleBindingCase::SingleBindingCase(Context &ctx, const char *name, int flags)
260*35238bceSAndroid Build Coastguard Worker     : BindingRenderCase(ctx, name, genTestDescription(flags).c_str(), isDataUnaligned(flags))
261*35238bceSAndroid Build Coastguard Worker     , m_spec(genTestSpec(flags))
262*35238bceSAndroid Build Coastguard Worker     , m_buf(0)
263*35238bceSAndroid Build Coastguard Worker {
264*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!((flags & FLAG_ATTRIB_UNALIGNED) && (flags & FLAG_ATTRIB_ALIGNED)));
265*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!((flags & FLAG_ATTRIB_ALIGNED) && (flags & FLAG_BUF_UNALIGNED_STRIDE)));
266*35238bceSAndroid Build Coastguard Worker 
267*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(isDataUnaligned(flags));
268*35238bceSAndroid Build Coastguard Worker }
269*35238bceSAndroid Build Coastguard Worker 
~SingleBindingCase(void)270*35238bceSAndroid Build Coastguard Worker SingleBindingCase::~SingleBindingCase(void)
271*35238bceSAndroid Build Coastguard Worker {
272*35238bceSAndroid Build Coastguard Worker     deinit();
273*35238bceSAndroid Build Coastguard Worker }
274*35238bceSAndroid Build Coastguard Worker 
init(void)275*35238bceSAndroid Build Coastguard Worker void SingleBindingCase::init(void)
276*35238bceSAndroid Build Coastguard Worker {
277*35238bceSAndroid Build Coastguard Worker     // log what we are trying to do
278*35238bceSAndroid Build Coastguard Worker 
279*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << (int)GRID_SIZE << "x" << (int)GRID_SIZE << " grid.\n"
280*35238bceSAndroid Build Coastguard Worker                        << "Buffer format:\n"
281*35238bceSAndroid Build Coastguard Worker                        << "    bufferOffset: " << m_spec.bufferOffset << "\n"
282*35238bceSAndroid Build Coastguard Worker                        << "    bufferStride: " << m_spec.bufferStride << "\n"
283*35238bceSAndroid Build Coastguard Worker                        << "Vertex position format:\n"
284*35238bceSAndroid Build Coastguard Worker                        << "    type: float4\n"
285*35238bceSAndroid Build Coastguard Worker                        << "    offset: " << m_spec.positionAttrOffset << "\n"
286*35238bceSAndroid Build Coastguard Worker                        << "    total offset: " << m_spec.bufferOffset + m_spec.positionAttrOffset << "\n"
287*35238bceSAndroid Build Coastguard Worker                        << tcu::TestLog::EndMessage;
288*35238bceSAndroid Build Coastguard Worker 
289*35238bceSAndroid Build Coastguard Worker     if (m_spec.hasColorAttr)
290*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "Color:\n"
291*35238bceSAndroid Build Coastguard Worker                            << "    type: float4\n"
292*35238bceSAndroid Build Coastguard Worker                            << "    offset: " << m_spec.colorAttrOffset << "\n"
293*35238bceSAndroid Build Coastguard Worker                            << "    total offset: " << m_spec.bufferOffset + m_spec.colorAttrOffset << "\n"
294*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage;
295*35238bceSAndroid Build Coastguard Worker     // init
296*35238bceSAndroid Build Coastguard Worker 
297*35238bceSAndroid Build Coastguard Worker     BindingRenderCase::init();
298*35238bceSAndroid Build Coastguard Worker }
299*35238bceSAndroid Build Coastguard Worker 
deinit(void)300*35238bceSAndroid Build Coastguard Worker void SingleBindingCase::deinit(void)
301*35238bceSAndroid Build Coastguard Worker {
302*35238bceSAndroid Build Coastguard Worker     if (m_buf)
303*35238bceSAndroid Build Coastguard Worker     {
304*35238bceSAndroid Build Coastguard Worker         m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_buf);
305*35238bceSAndroid Build Coastguard Worker         m_buf = 0;
306*35238bceSAndroid Build Coastguard Worker     }
307*35238bceSAndroid Build Coastguard Worker 
308*35238bceSAndroid Build Coastguard Worker     BindingRenderCase::deinit();
309*35238bceSAndroid Build Coastguard Worker }
310*35238bceSAndroid Build Coastguard Worker 
renderTo(tcu::Surface & dst)311*35238bceSAndroid Build Coastguard Worker void SingleBindingCase::renderTo(tcu::Surface &dst)
312*35238bceSAndroid Build Coastguard Worker {
313*35238bceSAndroid Build Coastguard Worker     glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
314*35238bceSAndroid Build Coastguard Worker     const int positionLoc     = gl.glGetAttribLocation(m_program->getProgram(), "a_position");
315*35238bceSAndroid Build Coastguard Worker     const int colorLoc        = gl.glGetAttribLocation(m_program->getProgram(), "a_color");
316*35238bceSAndroid Build Coastguard Worker     const int colorUniformLoc = gl.glGetUniformLocation(m_program->getProgram(), "u_color");
317*35238bceSAndroid Build Coastguard Worker 
318*35238bceSAndroid Build Coastguard Worker     gl.enableLogging(true);
319*35238bceSAndroid Build Coastguard Worker 
320*35238bceSAndroid Build Coastguard Worker     gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
321*35238bceSAndroid Build Coastguard Worker     gl.glClear(GL_COLOR_BUFFER_BIT);
322*35238bceSAndroid Build Coastguard Worker     gl.glViewport(0, 0, dst.getWidth(), dst.getHeight());
323*35238bceSAndroid Build Coastguard Worker     gl.glBindVertexArray(m_vao);
324*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "set vao");
325*35238bceSAndroid Build Coastguard Worker 
326*35238bceSAndroid Build Coastguard Worker     gl.glUseProgram(m_program->getProgram());
327*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "use program");
328*35238bceSAndroid Build Coastguard Worker 
329*35238bceSAndroid Build Coastguard Worker     if (m_spec.hasColorAttr)
330*35238bceSAndroid Build Coastguard Worker     {
331*35238bceSAndroid Build Coastguard Worker         gl.glBindVertexBuffer(3, m_buf, m_spec.bufferOffset, m_spec.bufferStride);
332*35238bceSAndroid Build Coastguard Worker 
333*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribBinding(positionLoc, 3);
334*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribFormat(positionLoc, 4, GL_FLOAT, GL_FALSE, m_spec.positionAttrOffset);
335*35238bceSAndroid Build Coastguard Worker         gl.glEnableVertexAttribArray(positionLoc);
336*35238bceSAndroid Build Coastguard Worker 
337*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribBinding(colorLoc, 3);
338*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribFormat(colorLoc, 4, GL_FLOAT, GL_FALSE, m_spec.colorAttrOffset);
339*35238bceSAndroid Build Coastguard Worker         gl.glEnableVertexAttribArray(colorLoc);
340*35238bceSAndroid Build Coastguard Worker 
341*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "set va");
342*35238bceSAndroid Build Coastguard Worker 
343*35238bceSAndroid Build Coastguard Worker         gl.glDrawArrays(GL_TRIANGLES, 0, GRID_SIZE * GRID_SIZE * 6);
344*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "draw");
345*35238bceSAndroid Build Coastguard Worker     }
346*35238bceSAndroid Build Coastguard Worker     else
347*35238bceSAndroid Build Coastguard Worker     {
348*35238bceSAndroid Build Coastguard Worker         gl.glBindVertexBuffer(3, m_buf, m_spec.bufferOffset, m_spec.bufferStride);
349*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribBinding(positionLoc, 3);
350*35238bceSAndroid Build Coastguard Worker         gl.glVertexAttribFormat(positionLoc, 4, GL_FLOAT, GL_FALSE, m_spec.positionAttrOffset);
351*35238bceSAndroid Build Coastguard Worker         gl.glEnableVertexAttribArray(positionLoc);
352*35238bceSAndroid Build Coastguard Worker 
353*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "set va");
354*35238bceSAndroid Build Coastguard Worker         gl.glUniform4f(colorUniformLoc, 0.0f, 1.0f, 0.0f, 1.0f);
355*35238bceSAndroid Build Coastguard Worker 
356*35238bceSAndroid Build Coastguard Worker         gl.glDrawArrays(GL_TRIANGLES, 0, GRID_SIZE * GRID_SIZE * 6);
357*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.glGetError(), "draw");
358*35238bceSAndroid Build Coastguard Worker     }
359*35238bceSAndroid Build Coastguard Worker 
360*35238bceSAndroid Build Coastguard Worker     gl.glFinish();
361*35238bceSAndroid Build Coastguard Worker     gl.glBindVertexArray(0);
362*35238bceSAndroid Build Coastguard Worker     gl.glUseProgram(0);
363*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "clean");
364*35238bceSAndroid Build Coastguard Worker 
365*35238bceSAndroid Build Coastguard Worker     glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
366*35238bceSAndroid Build Coastguard Worker }
367*35238bceSAndroid Build Coastguard Worker 
genTestSpec(int flags)368*35238bceSAndroid Build Coastguard Worker SingleBindingCase::TestSpec SingleBindingCase::genTestSpec(int flags)
369*35238bceSAndroid Build Coastguard Worker {
370*35238bceSAndroid Build Coastguard Worker     const int datumSize          = 4;
371*35238bceSAndroid Build Coastguard Worker     const int bufferOffset       = (flags & FLAG_BUF_ALIGNED_OFFSET)   ? (32) :
372*35238bceSAndroid Build Coastguard Worker                                    (flags & FLAG_BUF_UNALIGNED_OFFSET) ? (19) :
373*35238bceSAndroid Build Coastguard Worker                                                                          (0);
374*35238bceSAndroid Build Coastguard Worker     const int attrBufAlignment   = ((bufferOffset % datumSize) == 0) ? (0) : (datumSize - (bufferOffset % datumSize));
375*35238bceSAndroid Build Coastguard Worker     const int positionAttrOffset = (flags & FLAG_ATTRIB_UNALIGNED) ? (3) :
376*35238bceSAndroid Build Coastguard Worker                                    (flags & FLAG_ATTRIB_ALIGNED)   ? (attrBufAlignment) :
377*35238bceSAndroid Build Coastguard Worker                                                                      (0);
378*35238bceSAndroid Build Coastguard Worker     const bool hasColorAttr      = (flags & FLAG_ATTRIBS_SHARED_ELEMS) || (flags & FLAG_ATTRIBS_MULTIPLE_ELEMS);
379*35238bceSAndroid Build Coastguard Worker     const int colorAttrOffset    = (flags & FLAG_ATTRIBS_SHARED_ELEMS)   ? (2 * datumSize) :
380*35238bceSAndroid Build Coastguard Worker                                    (flags & FLAG_ATTRIBS_MULTIPLE_ELEMS) ? (4 * datumSize) :
381*35238bceSAndroid Build Coastguard Worker                                                                            (-1);
382*35238bceSAndroid Build Coastguard Worker 
383*35238bceSAndroid Build Coastguard Worker     const int bufferStrideBase = de::max(positionAttrOffset + 4 * datumSize, colorAttrOffset + 4 * datumSize);
384*35238bceSAndroid Build Coastguard Worker     const int bufferStrideAlignment =
385*35238bceSAndroid Build Coastguard Worker         ((bufferStrideBase % datumSize) == 0) ? (0) : (datumSize - (bufferStrideBase % datumSize));
386*35238bceSAndroid Build Coastguard Worker     const int bufferStridePadding =
387*35238bceSAndroid Build Coastguard Worker         ((flags & FLAG_BUF_UNALIGNED_STRIDE) && deIsAligned32(bufferStrideBase, datumSize)) ? (13) :
388*35238bceSAndroid Build Coastguard Worker         (!(flags & FLAG_BUF_UNALIGNED_STRIDE) && !deIsAligned32(bufferStrideBase, datumSize)) ?
389*35238bceSAndroid Build Coastguard Worker                                                                                               (bufferStrideAlignment) :
390*35238bceSAndroid Build Coastguard Worker                                                                                               (0);
391*35238bceSAndroid Build Coastguard Worker 
392*35238bceSAndroid Build Coastguard Worker     TestSpec spec;
393*35238bceSAndroid Build Coastguard Worker 
394*35238bceSAndroid Build Coastguard Worker     spec.bufferOffset       = bufferOffset;
395*35238bceSAndroid Build Coastguard Worker     spec.bufferStride       = bufferStrideBase + bufferStridePadding;
396*35238bceSAndroid Build Coastguard Worker     spec.positionAttrOffset = positionAttrOffset;
397*35238bceSAndroid Build Coastguard Worker     spec.colorAttrOffset    = colorAttrOffset;
398*35238bceSAndroid Build Coastguard Worker     spec.hasColorAttr       = hasColorAttr;
399*35238bceSAndroid Build Coastguard Worker 
400*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_ATTRIB_UNALIGNED)
401*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(!deIsAligned32(spec.bufferOffset + spec.positionAttrOffset, datumSize));
402*35238bceSAndroid Build Coastguard Worker     else if (flags & FLAG_ATTRIB_ALIGNED)
403*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(deIsAligned32(spec.bufferOffset + spec.positionAttrOffset, datumSize));
404*35238bceSAndroid Build Coastguard Worker 
405*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_BUF_UNALIGNED_STRIDE)
406*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(!deIsAligned32(spec.bufferStride, datumSize));
407*35238bceSAndroid Build Coastguard Worker     else
408*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(deIsAligned32(spec.bufferStride, datumSize));
409*35238bceSAndroid Build Coastguard Worker 
410*35238bceSAndroid Build Coastguard Worker     return spec;
411*35238bceSAndroid Build Coastguard Worker }
412*35238bceSAndroid Build Coastguard Worker 
genTestDescription(int flags)413*35238bceSAndroid Build Coastguard Worker std::string SingleBindingCase::genTestDescription(int flags)
414*35238bceSAndroid Build Coastguard Worker {
415*35238bceSAndroid Build Coastguard Worker     std::ostringstream buf;
416*35238bceSAndroid Build Coastguard Worker     buf << "draw test pattern";
417*35238bceSAndroid Build Coastguard Worker 
418*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_ATTRIB_UNALIGNED)
419*35238bceSAndroid Build Coastguard Worker         buf << ", attribute offset (unaligned)";
420*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_ATTRIB_ALIGNED)
421*35238bceSAndroid Build Coastguard Worker         buf << ", attribute offset (aligned)";
422*35238bceSAndroid Build Coastguard Worker 
423*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_ATTRIBS_MULTIPLE_ELEMS)
424*35238bceSAndroid Build Coastguard Worker         buf << ", 2 attributes";
425*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_ATTRIBS_SHARED_ELEMS)
426*35238bceSAndroid Build Coastguard Worker         buf << ", 2 attributes (some components shared)";
427*35238bceSAndroid Build Coastguard Worker 
428*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_BUF_ALIGNED_OFFSET)
429*35238bceSAndroid Build Coastguard Worker         buf << ", buffer offset aligned";
430*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_BUF_UNALIGNED_OFFSET)
431*35238bceSAndroid Build Coastguard Worker         buf << ", buffer offset unaligned";
432*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_BUF_UNALIGNED_STRIDE)
433*35238bceSAndroid Build Coastguard Worker         buf << ", buffer stride unaligned";
434*35238bceSAndroid Build Coastguard Worker 
435*35238bceSAndroid Build Coastguard Worker     return buf.str();
436*35238bceSAndroid Build Coastguard Worker }
437*35238bceSAndroid Build Coastguard Worker 
isDataUnaligned(int flags)438*35238bceSAndroid Build Coastguard Worker bool SingleBindingCase::isDataUnaligned(int flags)
439*35238bceSAndroid Build Coastguard Worker {
440*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_ATTRIB_UNALIGNED)
441*35238bceSAndroid Build Coastguard Worker         return true;
442*35238bceSAndroid Build Coastguard Worker     if (flags & FLAG_ATTRIB_ALIGNED)
443*35238bceSAndroid Build Coastguard Worker         return false;
444*35238bceSAndroid Build Coastguard Worker 
445*35238bceSAndroid Build Coastguard Worker     return (flags & FLAG_BUF_UNALIGNED_OFFSET) || (flags & FLAG_BUF_UNALIGNED_STRIDE);
446*35238bceSAndroid Build Coastguard Worker }
447*35238bceSAndroid Build Coastguard Worker 
createBuffers(void)448*35238bceSAndroid Build Coastguard Worker void SingleBindingCase::createBuffers(void)
449*35238bceSAndroid Build Coastguard Worker {
450*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
451*35238bceSAndroid Build Coastguard Worker     std::vector<uint8_t> dataBuf(m_spec.bufferOffset + m_spec.bufferStride * GRID_SIZE * GRID_SIZE * 6);
452*35238bceSAndroid Build Coastguard Worker 
453*35238bceSAndroid Build Coastguard Worker     // In interleaved mode color rg and position zw are the same. Select "good" values for r and g
454*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 colorA(0.0f, 1.0f, 0.0f, 1.0f);
455*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 colorB(0.5f, 1.0f, 0.0f, 1.0f);
456*35238bceSAndroid Build Coastguard Worker 
457*35238bceSAndroid Build Coastguard Worker     for (int y = 0; y < GRID_SIZE; ++y)
458*35238bceSAndroid Build Coastguard Worker         for (int x = 0; x < GRID_SIZE; ++x)
459*35238bceSAndroid Build Coastguard Worker         {
460*35238bceSAndroid Build Coastguard Worker             const tcu::Vec4 &color       = ((x + y) % 2 == 0) ? (colorA) : (colorB);
461*35238bceSAndroid Build Coastguard Worker             const tcu::Vec4 positions[6] = {
462*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4(float(x + 0) / float(GRID_SIZE) * 2.0f - 1.0f, float(y + 0) / float(GRID_SIZE) * 2.0f - 1.0f,
463*35238bceSAndroid Build Coastguard Worker                           0.0f, 1.0f),
464*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4(float(x + 0) / float(GRID_SIZE) * 2.0f - 1.0f, float(y + 1) / float(GRID_SIZE) * 2.0f - 1.0f,
465*35238bceSAndroid Build Coastguard Worker                           0.0f, 1.0f),
466*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4(float(x + 1) / float(GRID_SIZE) * 2.0f - 1.0f, float(y + 1) / float(GRID_SIZE) * 2.0f - 1.0f,
467*35238bceSAndroid Build Coastguard Worker                           0.0f, 1.0f),
468*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4(float(x + 0) / float(GRID_SIZE) * 2.0f - 1.0f, float(y + 0) / float(GRID_SIZE) * 2.0f - 1.0f,
469*35238bceSAndroid Build Coastguard Worker                           0.0f, 1.0f),
470*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4(float(x + 1) / float(GRID_SIZE) * 2.0f - 1.0f, float(y + 1) / float(GRID_SIZE) * 2.0f - 1.0f,
471*35238bceSAndroid Build Coastguard Worker                           0.0f, 1.0f),
472*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4(float(x + 1) / float(GRID_SIZE) * 2.0f - 1.0f, float(y + 0) / float(GRID_SIZE) * 2.0f - 1.0f,
473*35238bceSAndroid Build Coastguard Worker                           0.0f, 1.0f),
474*35238bceSAndroid Build Coastguard Worker             };
475*35238bceSAndroid Build Coastguard Worker 
476*35238bceSAndroid Build Coastguard Worker             // copy cell vertices to the buffer.
477*35238bceSAndroid Build Coastguard Worker             for (int v = 0; v < 6; ++v)
478*35238bceSAndroid Build Coastguard Worker                 memcpy(&dataBuf[m_spec.bufferOffset + m_spec.positionAttrOffset +
479*35238bceSAndroid Build Coastguard Worker                                 m_spec.bufferStride * ((y * GRID_SIZE + x) * 6 + v)],
480*35238bceSAndroid Build Coastguard Worker                        positions[v].getPtr(), sizeof(positions[v]));
481*35238bceSAndroid Build Coastguard Worker 
482*35238bceSAndroid Build Coastguard Worker             // copy color to buffer
483*35238bceSAndroid Build Coastguard Worker             if (m_spec.hasColorAttr)
484*35238bceSAndroid Build Coastguard Worker                 for (int v = 0; v < 6; ++v)
485*35238bceSAndroid Build Coastguard Worker                     memcpy(&dataBuf[m_spec.bufferOffset + m_spec.colorAttrOffset +
486*35238bceSAndroid Build Coastguard Worker                                     m_spec.bufferStride * ((y * GRID_SIZE + x) * 6 + v)],
487*35238bceSAndroid Build Coastguard Worker                            color.getPtr(), sizeof(color));
488*35238bceSAndroid Build Coastguard Worker         }
489*35238bceSAndroid Build Coastguard Worker 
490*35238bceSAndroid Build Coastguard Worker     gl.genBuffers(1, &m_buf);
491*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_ARRAY_BUFFER, m_buf);
492*35238bceSAndroid Build Coastguard Worker     gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)dataBuf.size(), &dataBuf[0], GL_STATIC_DRAW);
493*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_ARRAY_BUFFER, 0);
494*35238bceSAndroid Build Coastguard Worker 
495*35238bceSAndroid Build Coastguard Worker     if (gl.getError() != GL_NO_ERROR)
496*35238bceSAndroid Build Coastguard Worker         throw tcu::TestError("could not init buffer");
497*35238bceSAndroid Build Coastguard Worker }
498*35238bceSAndroid Build Coastguard Worker 
createShader(void)499*35238bceSAndroid Build Coastguard Worker void SingleBindingCase::createShader(void)
500*35238bceSAndroid Build Coastguard Worker {
501*35238bceSAndroid Build Coastguard Worker     m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
502*35238bceSAndroid Build Coastguard Worker                                                                          << glu::VertexSource(genVertexSource())
503*35238bceSAndroid Build Coastguard Worker                                                                          << glu::FragmentSource(s_colorFragmentShader));
504*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << *m_program;
505*35238bceSAndroid Build Coastguard Worker 
506*35238bceSAndroid Build Coastguard Worker     if (!m_program->isOk())
507*35238bceSAndroid Build Coastguard Worker         throw tcu::TestError("could not build shader");
508*35238bceSAndroid Build Coastguard Worker }
509*35238bceSAndroid Build Coastguard Worker 
genVertexSource(void)510*35238bceSAndroid Build Coastguard Worker std::string SingleBindingCase::genVertexSource(void)
511*35238bceSAndroid Build Coastguard Worker {
512*35238bceSAndroid Build Coastguard Worker     const bool useUniformColor = !m_spec.hasColorAttr;
513*35238bceSAndroid Build Coastguard Worker     std::ostringstream buf;
514*35238bceSAndroid Build Coastguard Worker 
515*35238bceSAndroid Build Coastguard Worker     buf << "#version 310 es\n"
516*35238bceSAndroid Build Coastguard Worker            "in highp vec4 a_position;\n";
517*35238bceSAndroid Build Coastguard Worker 
518*35238bceSAndroid Build Coastguard Worker     if (!useUniformColor)
519*35238bceSAndroid Build Coastguard Worker         buf << "in highp vec4 a_color;\n";
520*35238bceSAndroid Build Coastguard Worker     else
521*35238bceSAndroid Build Coastguard Worker         buf << "uniform highp vec4 u_color;\n";
522*35238bceSAndroid Build Coastguard Worker 
523*35238bceSAndroid Build Coastguard Worker     buf << "out highp vec4 v_color;\n"
524*35238bceSAndroid Build Coastguard Worker            "void main (void)\n"
525*35238bceSAndroid Build Coastguard Worker            "{\n"
526*35238bceSAndroid Build Coastguard Worker            "    gl_Position = a_position;\n"
527*35238bceSAndroid Build Coastguard Worker            "    v_color = "
528*35238bceSAndroid Build Coastguard Worker         << ((useUniformColor) ? ("u_color") : ("a_color"))
529*35238bceSAndroid Build Coastguard Worker         << ";\n"
530*35238bceSAndroid Build Coastguard Worker            "}\n";
531*35238bceSAndroid Build Coastguard Worker 
532*35238bceSAndroid Build Coastguard Worker     return buf.str();
533*35238bceSAndroid Build Coastguard Worker }
534*35238bceSAndroid Build Coastguard Worker 
535*35238bceSAndroid Build Coastguard Worker class BindVertexBufferCase : public TestCase
536*35238bceSAndroid Build Coastguard Worker {
537*35238bceSAndroid Build Coastguard Worker public:
538*35238bceSAndroid Build Coastguard Worker     BindVertexBufferCase(Context &ctx, const char *name, const char *desc, int offset, int drawCount);
539*35238bceSAndroid Build Coastguard Worker     ~BindVertexBufferCase(void);
540*35238bceSAndroid Build Coastguard Worker 
541*35238bceSAndroid Build Coastguard Worker     void init(void);
542*35238bceSAndroid Build Coastguard Worker     void deinit(void);
543*35238bceSAndroid Build Coastguard Worker     IterateResult iterate(void);
544*35238bceSAndroid Build Coastguard Worker 
545*35238bceSAndroid Build Coastguard Worker private:
546*35238bceSAndroid Build Coastguard Worker     const int m_offset;
547*35238bceSAndroid Build Coastguard Worker     const int m_drawCount;
548*35238bceSAndroid Build Coastguard Worker     uint32_t m_buffer;
549*35238bceSAndroid Build Coastguard Worker     glu::ShaderProgram *m_program;
550*35238bceSAndroid Build Coastguard Worker };
551*35238bceSAndroid Build Coastguard Worker 
BindVertexBufferCase(Context & ctx,const char * name,const char * desc,int offset,int drawCount)552*35238bceSAndroid Build Coastguard Worker BindVertexBufferCase::BindVertexBufferCase(Context &ctx, const char *name, const char *desc, int offset, int drawCount)
553*35238bceSAndroid Build Coastguard Worker     : TestCase(ctx, name, desc)
554*35238bceSAndroid Build Coastguard Worker     , m_offset(offset)
555*35238bceSAndroid Build Coastguard Worker     , m_drawCount(drawCount)
556*35238bceSAndroid Build Coastguard Worker     , m_buffer(0)
557*35238bceSAndroid Build Coastguard Worker     , m_program(DE_NULL)
558*35238bceSAndroid Build Coastguard Worker {
559*35238bceSAndroid Build Coastguard Worker }
560*35238bceSAndroid Build Coastguard Worker 
~BindVertexBufferCase(void)561*35238bceSAndroid Build Coastguard Worker BindVertexBufferCase::~BindVertexBufferCase(void)
562*35238bceSAndroid Build Coastguard Worker {
563*35238bceSAndroid Build Coastguard Worker     deinit();
564*35238bceSAndroid Build Coastguard Worker }
565*35238bceSAndroid Build Coastguard Worker 
init(void)566*35238bceSAndroid Build Coastguard Worker void BindVertexBufferCase::init(void)
567*35238bceSAndroid Build Coastguard Worker {
568*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
569*35238bceSAndroid Build Coastguard Worker     std::vector<tcu::Vec4> data(m_drawCount); // !< some junk data to make sure buffer is really allocated
570*35238bceSAndroid Build Coastguard Worker 
571*35238bceSAndroid Build Coastguard Worker     gl.genBuffers(1, &m_buffer);
572*35238bceSAndroid Build Coastguard Worker     gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer);
573*35238bceSAndroid Build Coastguard Worker     gl.bufferData(GL_ARRAY_BUFFER, int(m_drawCount * sizeof(tcu::Vec4)), &data[0], GL_STATIC_DRAW);
574*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.getError(), "buffer gen");
575*35238bceSAndroid Build Coastguard Worker 
576*35238bceSAndroid Build Coastguard Worker     m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
577*35238bceSAndroid Build Coastguard Worker                                                                          << glu::VertexSource(s_vertexSource)
578*35238bceSAndroid Build Coastguard Worker                                                                          << glu::FragmentSource(s_fragmentSource));
579*35238bceSAndroid Build Coastguard Worker     if (!m_program->isOk())
580*35238bceSAndroid Build Coastguard Worker     {
581*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << *m_program;
582*35238bceSAndroid Build Coastguard Worker         throw tcu::TestError("could not build program");
583*35238bceSAndroid Build Coastguard Worker     }
584*35238bceSAndroid Build Coastguard Worker }
585*35238bceSAndroid Build Coastguard Worker 
deinit(void)586*35238bceSAndroid Build Coastguard Worker void BindVertexBufferCase::deinit(void)
587*35238bceSAndroid Build Coastguard Worker {
588*35238bceSAndroid Build Coastguard Worker     if (m_buffer)
589*35238bceSAndroid Build Coastguard Worker     {
590*35238bceSAndroid Build Coastguard Worker         m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_buffer);
591*35238bceSAndroid Build Coastguard Worker         m_buffer = 0;
592*35238bceSAndroid Build Coastguard Worker     }
593*35238bceSAndroid Build Coastguard Worker 
594*35238bceSAndroid Build Coastguard Worker     delete m_program;
595*35238bceSAndroid Build Coastguard Worker     m_program = DE_NULL;
596*35238bceSAndroid Build Coastguard Worker }
597*35238bceSAndroid Build Coastguard Worker 
iterate(void)598*35238bceSAndroid Build Coastguard Worker BindVertexBufferCase::IterateResult BindVertexBufferCase::iterate(void)
599*35238bceSAndroid Build Coastguard Worker {
600*35238bceSAndroid Build Coastguard Worker     glu::CallLogWrapper gl(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
601*35238bceSAndroid Build Coastguard Worker     const int32_t positionLoc = gl.glGetAttribLocation(m_program->getProgram(), "a_position");
602*35238bceSAndroid Build Coastguard Worker     tcu::Surface dst(m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight());
603*35238bceSAndroid Build Coastguard Worker     glu::VertexArray vao(m_context.getRenderContext());
604*35238bceSAndroid Build Coastguard Worker 
605*35238bceSAndroid Build Coastguard Worker     gl.enableLogging(true);
606*35238bceSAndroid Build Coastguard Worker 
607*35238bceSAndroid Build Coastguard Worker     gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
608*35238bceSAndroid Build Coastguard Worker     gl.glClear(GL_COLOR_BUFFER_BIT);
609*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "setup");
610*35238bceSAndroid Build Coastguard Worker 
611*35238bceSAndroid Build Coastguard Worker     gl.glUseProgram(m_program->getProgram());
612*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "use program");
613*35238bceSAndroid Build Coastguard Worker 
614*35238bceSAndroid Build Coastguard Worker     gl.glBindVertexArray(*vao);
615*35238bceSAndroid Build Coastguard Worker     gl.glEnableVertexAttribArray(positionLoc);
616*35238bceSAndroid Build Coastguard Worker     gl.glVertexAttribFormat(positionLoc, 4, GL_FLOAT, GL_FALSE, 0);
617*35238bceSAndroid Build Coastguard Worker     gl.glVertexAttribBinding(positionLoc, 0);
618*35238bceSAndroid Build Coastguard Worker     gl.glBindVertexBuffer(0, m_buffer, m_offset, int(sizeof(tcu::Vec4)));
619*35238bceSAndroid Build Coastguard Worker     GLU_EXPECT_NO_ERROR(gl.glGetError(), "set buffer");
620*35238bceSAndroid Build Coastguard Worker 
621*35238bceSAndroid Build Coastguard Worker     gl.glDrawArrays(GL_POINTS, 0, m_drawCount);
622*35238bceSAndroid Build Coastguard Worker 
623*35238bceSAndroid Build Coastguard Worker     // allow errors after attempted out-of-bounds memory access
624*35238bceSAndroid Build Coastguard Worker     {
625*35238bceSAndroid Build Coastguard Worker         const uint32_t error = gl.glGetError();
626*35238bceSAndroid Build Coastguard Worker 
627*35238bceSAndroid Build Coastguard Worker         if (error != GL_NO_ERROR)
628*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "Got error: " << glu::getErrorStr(error) << ", ignoring..."
629*35238bceSAndroid Build Coastguard Worker                                << tcu::TestLog::EndMessage;
630*35238bceSAndroid Build Coastguard Worker     }
631*35238bceSAndroid Build Coastguard Worker 
632*35238bceSAndroid Build Coastguard Worker     // read pixels to wait for rendering
633*35238bceSAndroid Build Coastguard Worker     gl.glFinish();
634*35238bceSAndroid Build Coastguard Worker     glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
635*35238bceSAndroid Build Coastguard Worker 
636*35238bceSAndroid Build Coastguard Worker     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
637*35238bceSAndroid Build Coastguard Worker     return STOP;
638*35238bceSAndroid Build Coastguard Worker }
639*35238bceSAndroid Build Coastguard Worker 
640*35238bceSAndroid Build Coastguard Worker } // namespace
641*35238bceSAndroid Build Coastguard Worker 
VertexAttributeBindingTests(Context & context)642*35238bceSAndroid Build Coastguard Worker VertexAttributeBindingTests::VertexAttributeBindingTests(Context &context)
643*35238bceSAndroid Build Coastguard Worker     : TestCaseGroup(context, "vertex_attribute_binding", "Test vertex attribute binding stress tests")
644*35238bceSAndroid Build Coastguard Worker {
645*35238bceSAndroid Build Coastguard Worker }
646*35238bceSAndroid Build Coastguard Worker 
~VertexAttributeBindingTests(void)647*35238bceSAndroid Build Coastguard Worker VertexAttributeBindingTests::~VertexAttributeBindingTests(void)
648*35238bceSAndroid Build Coastguard Worker {
649*35238bceSAndroid Build Coastguard Worker }
650*35238bceSAndroid Build Coastguard Worker 
init(void)651*35238bceSAndroid Build Coastguard Worker void VertexAttributeBindingTests::init(void)
652*35238bceSAndroid Build Coastguard Worker {
653*35238bceSAndroid Build Coastguard Worker     tcu::TestCaseGroup *const unalignedGroup = new tcu::TestCaseGroup(m_testCtx, "unaligned", "Unaligned access");
654*35238bceSAndroid Build Coastguard Worker     tcu::TestCaseGroup *const bufferRangeGroup =
655*35238bceSAndroid Build Coastguard Worker         new tcu::TestCaseGroup(m_testCtx, "buffer_bounds", "Source data over buffer bounds");
656*35238bceSAndroid Build Coastguard Worker 
657*35238bceSAndroid Build Coastguard Worker     addChild(unalignedGroup);
658*35238bceSAndroid Build Coastguard Worker     addChild(bufferRangeGroup);
659*35238bceSAndroid Build Coastguard Worker 
660*35238bceSAndroid Build Coastguard Worker     // .unaligned
661*35238bceSAndroid Build Coastguard Worker     {
662*35238bceSAndroid Build Coastguard Worker         unalignedGroup->addChild(
663*35238bceSAndroid Build Coastguard Worker             new SingleBindingCase(m_context, "elements_1_unaligned", SingleBindingCase::FLAG_ATTRIB_UNALIGNED));
664*35238bceSAndroid Build Coastguard Worker         unalignedGroup->addChild(new SingleBindingCase(m_context, "offset_elements_1_unaligned",
665*35238bceSAndroid Build Coastguard Worker                                                        SingleBindingCase::FLAG_BUF_ALIGNED_OFFSET |
666*35238bceSAndroid Build Coastguard Worker                                                            SingleBindingCase::FLAG_ATTRIB_UNALIGNED));
667*35238bceSAndroid Build Coastguard Worker 
668*35238bceSAndroid Build Coastguard Worker         unalignedGroup->addChild(new SingleBindingCase(m_context, "unaligned_offset_elements_1",
669*35238bceSAndroid Build Coastguard Worker                                                        SingleBindingCase::FLAG_BUF_UNALIGNED_OFFSET | 0));
670*35238bceSAndroid Build Coastguard Worker         unalignedGroup->addChild(new SingleBindingCase(m_context, "unaligned_offset_elements_1_unaligned",
671*35238bceSAndroid Build Coastguard Worker                                                        SingleBindingCase::FLAG_BUF_UNALIGNED_OFFSET |
672*35238bceSAndroid Build Coastguard Worker                                                            SingleBindingCase::FLAG_ATTRIB_UNALIGNED));
673*35238bceSAndroid Build Coastguard Worker         unalignedGroup->addChild(new SingleBindingCase(m_context, "unaligned_offset_elements_2",
674*35238bceSAndroid Build Coastguard Worker                                                        SingleBindingCase::FLAG_BUF_UNALIGNED_OFFSET |
675*35238bceSAndroid Build Coastguard Worker                                                            SingleBindingCase::FLAG_ATTRIBS_MULTIPLE_ELEMS));
676*35238bceSAndroid Build Coastguard Worker         unalignedGroup->addChild(new SingleBindingCase(m_context, "unaligned_offset_elements_2_share_elements",
677*35238bceSAndroid Build Coastguard Worker                                                        SingleBindingCase::FLAG_BUF_UNALIGNED_OFFSET |
678*35238bceSAndroid Build Coastguard Worker                                                            SingleBindingCase::FLAG_ATTRIBS_SHARED_ELEMS));
679*35238bceSAndroid Build Coastguard Worker 
680*35238bceSAndroid Build Coastguard Worker         unalignedGroup->addChild(new SingleBindingCase(m_context, "unaligned_stride_elements_1",
681*35238bceSAndroid Build Coastguard Worker                                                        SingleBindingCase::FLAG_BUF_UNALIGNED_STRIDE | 0));
682*35238bceSAndroid Build Coastguard Worker         unalignedGroup->addChild(new SingleBindingCase(m_context, "unaligned_stride_elements_2",
683*35238bceSAndroid Build Coastguard Worker                                                        SingleBindingCase::FLAG_BUF_UNALIGNED_STRIDE |
684*35238bceSAndroid Build Coastguard Worker                                                            SingleBindingCase::FLAG_ATTRIBS_MULTIPLE_ELEMS));
685*35238bceSAndroid Build Coastguard Worker         unalignedGroup->addChild(new SingleBindingCase(m_context, "unaligned_stride_elements_2_share_elements",
686*35238bceSAndroid Build Coastguard Worker                                                        SingleBindingCase::FLAG_BUF_UNALIGNED_STRIDE |
687*35238bceSAndroid Build Coastguard Worker                                                            SingleBindingCase::FLAG_ATTRIBS_SHARED_ELEMS));
688*35238bceSAndroid Build Coastguard Worker     }
689*35238bceSAndroid Build Coastguard Worker 
690*35238bceSAndroid Build Coastguard Worker     // .buffer_bounds
691*35238bceSAndroid Build Coastguard Worker     {
692*35238bceSAndroid Build Coastguard Worker         // bind buffer offset cases
693*35238bceSAndroid Build Coastguard Worker         bufferRangeGroup->addChild(new BindVertexBufferCase(m_context, "bind_vertex_buffer_offset_over_bounds_10",
694*35238bceSAndroid Build Coastguard Worker                                                             "Offset over buffer bounds", 0x00210000, 10));
695*35238bceSAndroid Build Coastguard Worker         bufferRangeGroup->addChild(new BindVertexBufferCase(m_context, "bind_vertex_buffer_offset_over_bounds_1000",
696*35238bceSAndroid Build Coastguard Worker                                                             "Offset over buffer bounds", 0x00210000, 1000));
697*35238bceSAndroid Build Coastguard Worker         bufferRangeGroup->addChild(new BindVertexBufferCase(m_context, "bind_vertex_buffer_offset_near_wrap_10",
698*35238bceSAndroid Build Coastguard Worker                                                             "Offset over buffer bounds, near wrapping", 0x7FFFFFF0,
699*35238bceSAndroid Build Coastguard Worker                                                             10));
700*35238bceSAndroid Build Coastguard Worker         bufferRangeGroup->addChild(new BindVertexBufferCase(m_context, "bind_vertex_buffer_offset_near_wrap_1000",
701*35238bceSAndroid Build Coastguard Worker                                                             "Offset over buffer bounds, near wrapping", 0x7FFFFFF0,
702*35238bceSAndroid Build Coastguard Worker                                                             1000));
703*35238bceSAndroid Build Coastguard Worker     }
704*35238bceSAndroid Build Coastguard Worker }
705*35238bceSAndroid Build Coastguard Worker 
706*35238bceSAndroid Build Coastguard Worker } // namespace Stress
707*35238bceSAndroid Build Coastguard Worker } // namespace gles31
708*35238bceSAndroid Build Coastguard Worker } // namespace deqp
709