xref: /aosp_15_r20/external/angle/src/tests/gl_tests/AttributeLayoutTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2018 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker // AttributeLayoutTest:
7*8975f5c5SAndroid Build Coastguard Worker //   Test various layouts of vertex attribute data:
8*8975f5c5SAndroid Build Coastguard Worker //   - in memory, in buffer object, or combination of both
9*8975f5c5SAndroid Build Coastguard Worker //   - sequential or interleaved
10*8975f5c5SAndroid Build Coastguard Worker //   - various combinations of data types
11*8975f5c5SAndroid Build Coastguard Worker 
12*8975f5c5SAndroid Build Coastguard Worker #include <vector>
13*8975f5c5SAndroid Build Coastguard Worker 
14*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/ANGLETest.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/gl_raii.h"
16*8975f5c5SAndroid Build Coastguard Worker 
17*8975f5c5SAndroid Build Coastguard Worker using namespace angle;
18*8975f5c5SAndroid Build Coastguard Worker 
19*8975f5c5SAndroid Build Coastguard Worker namespace
20*8975f5c5SAndroid Build Coastguard Worker {
21*8975f5c5SAndroid Build Coastguard Worker 
22*8975f5c5SAndroid Build Coastguard Worker // Test will draw these four triangles.
23*8975f5c5SAndroid Build Coastguard Worker // clang-format off
24*8975f5c5SAndroid Build Coastguard Worker constexpr double kTriangleData[] = {
25*8975f5c5SAndroid Build Coastguard Worker     // xy       rgb
26*8975f5c5SAndroid Build Coastguard Worker     0,0,        1,1,0,
27*8975f5c5SAndroid Build Coastguard Worker     -1,+1,      1,1,0,
28*8975f5c5SAndroid Build Coastguard Worker     +1,+1,      1,1,0,
29*8975f5c5SAndroid Build Coastguard Worker 
30*8975f5c5SAndroid Build Coastguard Worker     0,0,        0,1,0,
31*8975f5c5SAndroid Build Coastguard Worker     +1,+1,      0,1,0,
32*8975f5c5SAndroid Build Coastguard Worker     +1,-1,      0,1,0,
33*8975f5c5SAndroid Build Coastguard Worker 
34*8975f5c5SAndroid Build Coastguard Worker     0,0,        0,1,1,
35*8975f5c5SAndroid Build Coastguard Worker     +1,-1,      0,1,1,
36*8975f5c5SAndroid Build Coastguard Worker     -1,-1,      0,1,1,
37*8975f5c5SAndroid Build Coastguard Worker 
38*8975f5c5SAndroid Build Coastguard Worker     0,0,        1,0,1,
39*8975f5c5SAndroid Build Coastguard Worker     -1,-1,      1,0,1,
40*8975f5c5SAndroid Build Coastguard Worker     -1,+1,      1,0,1,
41*8975f5c5SAndroid Build Coastguard Worker };
42*8975f5c5SAndroid Build Coastguard Worker // clang-format on
43*8975f5c5SAndroid Build Coastguard Worker 
44*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kNumVertices = ArraySize(kTriangleData) / 5;
45*8975f5c5SAndroid Build Coastguard Worker 
46*8975f5c5SAndroid Build Coastguard Worker // Vertex data source description.
47*8975f5c5SAndroid Build Coastguard Worker class VertexData
48*8975f5c5SAndroid Build Coastguard Worker {
49*8975f5c5SAndroid Build Coastguard Worker   public:
VertexData(int dimension,const double * data,unsigned offset,unsigned stride,unsigned numVertices)50*8975f5c5SAndroid Build Coastguard Worker     VertexData(int dimension,
51*8975f5c5SAndroid Build Coastguard Worker                const double *data,
52*8975f5c5SAndroid Build Coastguard Worker                unsigned offset,
53*8975f5c5SAndroid Build Coastguard Worker                unsigned stride,
54*8975f5c5SAndroid Build Coastguard Worker                unsigned numVertices)
55*8975f5c5SAndroid Build Coastguard Worker         : mNumVertices(numVertices),
56*8975f5c5SAndroid Build Coastguard Worker           mDimension(dimension),
57*8975f5c5SAndroid Build Coastguard Worker           mData(data),
58*8975f5c5SAndroid Build Coastguard Worker           mOffset(offset),
59*8975f5c5SAndroid Build Coastguard Worker           mStride(stride)
60*8975f5c5SAndroid Build Coastguard Worker     {}
getDimension() const61*8975f5c5SAndroid Build Coastguard Worker     int getDimension() const { return mDimension; }
getNumVertices() const62*8975f5c5SAndroid Build Coastguard Worker     unsigned getNumVertices() const { return mNumVertices; }
getValue(unsigned vertexNumber,int component) const63*8975f5c5SAndroid Build Coastguard Worker     double getValue(unsigned vertexNumber, int component) const
64*8975f5c5SAndroid Build Coastguard Worker     {
65*8975f5c5SAndroid Build Coastguard Worker         return mData[mOffset + mStride * vertexNumber + component];
66*8975f5c5SAndroid Build Coastguard Worker     }
67*8975f5c5SAndroid Build Coastguard Worker 
68*8975f5c5SAndroid Build Coastguard Worker   private:
69*8975f5c5SAndroid Build Coastguard Worker     unsigned mNumVertices;
70*8975f5c5SAndroid Build Coastguard Worker     int mDimension;
71*8975f5c5SAndroid Build Coastguard Worker     const double *mData;
72*8975f5c5SAndroid Build Coastguard Worker     // offset and stride in doubles
73*8975f5c5SAndroid Build Coastguard Worker     unsigned mOffset;
74*8975f5c5SAndroid Build Coastguard Worker     unsigned mStride;
75*8975f5c5SAndroid Build Coastguard Worker };
76*8975f5c5SAndroid Build Coastguard Worker 
77*8975f5c5SAndroid Build Coastguard Worker // A container for one or more vertex attributes.
78*8975f5c5SAndroid Build Coastguard Worker class Container
79*8975f5c5SAndroid Build Coastguard Worker {
80*8975f5c5SAndroid Build Coastguard Worker   public:
81*8975f5c5SAndroid Build Coastguard Worker     static constexpr size_t kSize = 1024;
82*8975f5c5SAndroid Build Coastguard Worker 
open(void)83*8975f5c5SAndroid Build Coastguard Worker     void open(void) { memset(mMemory, 0xff, kSize); }
getDestination(size_t offset)84*8975f5c5SAndroid Build Coastguard Worker     void *getDestination(size_t offset) { return mMemory + offset; }
close(void)85*8975f5c5SAndroid Build Coastguard Worker     virtual void close(void) {}
~Container()86*8975f5c5SAndroid Build Coastguard Worker     virtual ~Container() {}
87*8975f5c5SAndroid Build Coastguard Worker     virtual const char *getAddress() = 0;
88*8975f5c5SAndroid Build Coastguard Worker     virtual GLuint getBuffer()       = 0;
89*8975f5c5SAndroid Build Coastguard Worker 
90*8975f5c5SAndroid Build Coastguard Worker   protected:
91*8975f5c5SAndroid Build Coastguard Worker     char mMemory[kSize];
92*8975f5c5SAndroid Build Coastguard Worker };
93*8975f5c5SAndroid Build Coastguard Worker 
94*8975f5c5SAndroid Build Coastguard Worker // Vertex attribute data in client memory.
95*8975f5c5SAndroid Build Coastguard Worker class Memory : public Container
96*8975f5c5SAndroid Build Coastguard Worker {
97*8975f5c5SAndroid Build Coastguard Worker   public:
getAddress()98*8975f5c5SAndroid Build Coastguard Worker     const char *getAddress() override { return mMemory; }
getBuffer()99*8975f5c5SAndroid Build Coastguard Worker     GLuint getBuffer() override { return 0; }
100*8975f5c5SAndroid Build Coastguard Worker };
101*8975f5c5SAndroid Build Coastguard Worker 
102*8975f5c5SAndroid Build Coastguard Worker // Vertex attribute data in buffer object.
103*8975f5c5SAndroid Build Coastguard Worker class Buffer : public Container
104*8975f5c5SAndroid Build Coastguard Worker {
105*8975f5c5SAndroid Build Coastguard Worker   public:
close(void)106*8975f5c5SAndroid Build Coastguard Worker     void close(void) override
107*8975f5c5SAndroid Build Coastguard Worker     {
108*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
109*8975f5c5SAndroid Build Coastguard Worker         glBufferData(GL_ARRAY_BUFFER, sizeof(mMemory), mMemory, GL_STATIC_DRAW);
110*8975f5c5SAndroid Build Coastguard Worker     }
111*8975f5c5SAndroid Build Coastguard Worker 
getAddress()112*8975f5c5SAndroid Build Coastguard Worker     const char *getAddress() override { return nullptr; }
getBuffer()113*8975f5c5SAndroid Build Coastguard Worker     GLuint getBuffer() override { return mBuffer; }
114*8975f5c5SAndroid Build Coastguard Worker 
115*8975f5c5SAndroid Build Coastguard Worker   protected:
116*8975f5c5SAndroid Build Coastguard Worker     GLBuffer mBuffer;
117*8975f5c5SAndroid Build Coastguard Worker };
118*8975f5c5SAndroid Build Coastguard Worker 
119*8975f5c5SAndroid Build Coastguard Worker // Encapsulate the storage, layout, format and data of a vertex attribute.
120*8975f5c5SAndroid Build Coastguard Worker struct Attrib
121*8975f5c5SAndroid Build Coastguard Worker {
openContainer__anon4c90fb2d0111::Attrib122*8975f5c5SAndroid Build Coastguard Worker     void openContainer(void) const { mContainer->open(); }
123*8975f5c5SAndroid Build Coastguard Worker 
fillContainer__anon4c90fb2d0111::Attrib124*8975f5c5SAndroid Build Coastguard Worker     void fillContainer(void) const
125*8975f5c5SAndroid Build Coastguard Worker     {
126*8975f5c5SAndroid Build Coastguard Worker         for (unsigned i = 0; i < mData.getNumVertices(); ++i)
127*8975f5c5SAndroid Build Coastguard Worker         {
128*8975f5c5SAndroid Build Coastguard Worker             for (int j = 0; j < mData.getDimension(); ++j)
129*8975f5c5SAndroid Build Coastguard Worker             {
130*8975f5c5SAndroid Build Coastguard Worker                 size_t destOffset = mOffset + mStride * i + mCTypeSize * j;
131*8975f5c5SAndroid Build Coastguard Worker                 if (destOffset + mCTypeSize > Container::kSize)
132*8975f5c5SAndroid Build Coastguard Worker                     FAIL() << "test case does not fit container";
133*8975f5c5SAndroid Build Coastguard Worker 
134*8975f5c5SAndroid Build Coastguard Worker                 double value = mData.getValue(i, j);
135*8975f5c5SAndroid Build Coastguard Worker                 if (mGLType == GL_FIXED)
136*8975f5c5SAndroid Build Coastguard Worker                     value *= 1 << 16;
137*8975f5c5SAndroid Build Coastguard Worker                 else if (mNormalized)
138*8975f5c5SAndroid Build Coastguard Worker                 {
139*8975f5c5SAndroid Build Coastguard Worker                     if (value < mMinIn || value > mMaxIn)
140*8975f5c5SAndroid Build Coastguard Worker                         FAIL() << "test data does not fit format";
141*8975f5c5SAndroid Build Coastguard Worker                     value = (value - mMinIn) * mScale + mMinOut;
142*8975f5c5SAndroid Build Coastguard Worker                 }
143*8975f5c5SAndroid Build Coastguard Worker 
144*8975f5c5SAndroid Build Coastguard Worker                 mStore(value, mContainer->getDestination(destOffset));
145*8975f5c5SAndroid Build Coastguard Worker             }
146*8975f5c5SAndroid Build Coastguard Worker         }
147*8975f5c5SAndroid Build Coastguard Worker     }
148*8975f5c5SAndroid Build Coastguard Worker 
closeContainer__anon4c90fb2d0111::Attrib149*8975f5c5SAndroid Build Coastguard Worker     void closeContainer(void) const { mContainer->close(); }
150*8975f5c5SAndroid Build Coastguard Worker 
enable__anon4c90fb2d0111::Attrib151*8975f5c5SAndroid Build Coastguard Worker     void enable(unsigned index) const
152*8975f5c5SAndroid Build Coastguard Worker     {
153*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ARRAY_BUFFER, mContainer->getBuffer());
154*8975f5c5SAndroid Build Coastguard Worker         if (mPureInteger)
155*8975f5c5SAndroid Build Coastguard Worker         {
156*8975f5c5SAndroid Build Coastguard Worker             glVertexAttribIPointer(index, mData.getDimension(), mGLType, mStride,
157*8975f5c5SAndroid Build Coastguard Worker                                    mContainer->getAddress() + mOffset);
158*8975f5c5SAndroid Build Coastguard Worker         }
159*8975f5c5SAndroid Build Coastguard Worker         else
160*8975f5c5SAndroid Build Coastguard Worker         {
161*8975f5c5SAndroid Build Coastguard Worker             glVertexAttribPointer(index, mData.getDimension(), mGLType, mNormalized, mStride,
162*8975f5c5SAndroid Build Coastguard Worker                                   mContainer->getAddress() + mOffset);
163*8975f5c5SAndroid Build Coastguard Worker         }
164*8975f5c5SAndroid Build Coastguard Worker         EXPECT_GL_NO_ERROR();
165*8975f5c5SAndroid Build Coastguard Worker         glEnableVertexAttribArray(index);
166*8975f5c5SAndroid Build Coastguard Worker     }
167*8975f5c5SAndroid Build Coastguard Worker 
inClientMemory__anon4c90fb2d0111::Attrib168*8975f5c5SAndroid Build Coastguard Worker     bool inClientMemory(void) const { return mContainer->getAddress() != nullptr; }
169*8975f5c5SAndroid Build Coastguard Worker 
170*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<Container> mContainer;
171*8975f5c5SAndroid Build Coastguard Worker     unsigned mOffset;
172*8975f5c5SAndroid Build Coastguard Worker     unsigned mStride;
173*8975f5c5SAndroid Build Coastguard Worker     const VertexData &mData;
174*8975f5c5SAndroid Build Coastguard Worker     void (*mStore)(double value, void *dest);
175*8975f5c5SAndroid Build Coastguard Worker     GLenum mGLType;
176*8975f5c5SAndroid Build Coastguard Worker     GLboolean mNormalized;
177*8975f5c5SAndroid Build Coastguard Worker     GLboolean mPureInteger = GL_FALSE;
178*8975f5c5SAndroid Build Coastguard Worker     size_t mCTypeSize;
179*8975f5c5SAndroid Build Coastguard Worker     double mMinIn;
180*8975f5c5SAndroid Build Coastguard Worker     double mMaxIn;
181*8975f5c5SAndroid Build Coastguard Worker     double mMinOut;
182*8975f5c5SAndroid Build Coastguard Worker     double mScale;
183*8975f5c5SAndroid Build Coastguard Worker };
184*8975f5c5SAndroid Build Coastguard Worker 
185*8975f5c5SAndroid Build Coastguard Worker // Change type and store.
186*8975f5c5SAndroid Build Coastguard Worker template <class T>
Store(double value,void * dest)187*8975f5c5SAndroid Build Coastguard Worker void Store(double value, void *dest)
188*8975f5c5SAndroid Build Coastguard Worker {
189*8975f5c5SAndroid Build Coastguard Worker     T v = static_cast<T>(value);
190*8975f5c5SAndroid Build Coastguard Worker     memcpy(dest, &v, sizeof(v));
191*8975f5c5SAndroid Build Coastguard Worker }
192*8975f5c5SAndroid Build Coastguard Worker 
193*8975f5c5SAndroid Build Coastguard Worker // Function object that makes Attrib structs according to a vertex format.
194*8975f5c5SAndroid Build Coastguard Worker template <class CType, GLenum GLType, bool Normalized, bool PureInteger = false>
195*8975f5c5SAndroid Build Coastguard Worker class Format
196*8975f5c5SAndroid Build Coastguard Worker {
197*8975f5c5SAndroid Build Coastguard Worker     static_assert(!(Normalized && GLType == GL_FLOAT), "Normalized float does not make sense.");
198*8975f5c5SAndroid Build Coastguard Worker 
199*8975f5c5SAndroid Build Coastguard Worker   public:
Format(bool es3)200*8975f5c5SAndroid Build Coastguard Worker     Format(bool es3) : mES3(es3) {}
201*8975f5c5SAndroid Build Coastguard Worker 
operator ()(std::shared_ptr<Container> container,unsigned offset,unsigned stride,const VertexData & data) const202*8975f5c5SAndroid Build Coastguard Worker     Attrib operator()(std::shared_ptr<Container> container,
203*8975f5c5SAndroid Build Coastguard Worker                       unsigned offset,
204*8975f5c5SAndroid Build Coastguard Worker                       unsigned stride,
205*8975f5c5SAndroid Build Coastguard Worker                       const VertexData &data) const
206*8975f5c5SAndroid Build Coastguard Worker     {
207*8975f5c5SAndroid Build Coastguard Worker         double minIn    = 0;
208*8975f5c5SAndroid Build Coastguard Worker         double maxIn    = 1;
209*8975f5c5SAndroid Build Coastguard Worker         double minOut   = std::numeric_limits<CType>::min();
210*8975f5c5SAndroid Build Coastguard Worker         double rangeOut = std::numeric_limits<CType>::max() - minOut;
211*8975f5c5SAndroid Build Coastguard Worker 
212*8975f5c5SAndroid Build Coastguard Worker         if (std::is_signed<CType>::value)
213*8975f5c5SAndroid Build Coastguard Worker         {
214*8975f5c5SAndroid Build Coastguard Worker             minIn = -1;
215*8975f5c5SAndroid Build Coastguard Worker             maxIn = +1;
216*8975f5c5SAndroid Build Coastguard Worker             if (mES3)
217*8975f5c5SAndroid Build Coastguard Worker             {
218*8975f5c5SAndroid Build Coastguard Worker                 minOut += 1;
219*8975f5c5SAndroid Build Coastguard Worker                 rangeOut -= 1;
220*8975f5c5SAndroid Build Coastguard Worker             }
221*8975f5c5SAndroid Build Coastguard Worker         }
222*8975f5c5SAndroid Build Coastguard Worker 
223*8975f5c5SAndroid Build Coastguard Worker         return {
224*8975f5c5SAndroid Build Coastguard Worker             container,
225*8975f5c5SAndroid Build Coastguard Worker             offset,
226*8975f5c5SAndroid Build Coastguard Worker             stride,
227*8975f5c5SAndroid Build Coastguard Worker             data,
228*8975f5c5SAndroid Build Coastguard Worker             Store<CType>,
229*8975f5c5SAndroid Build Coastguard Worker             GLType,
230*8975f5c5SAndroid Build Coastguard Worker             Normalized,
231*8975f5c5SAndroid Build Coastguard Worker             PureInteger,
232*8975f5c5SAndroid Build Coastguard Worker             sizeof(CType),
233*8975f5c5SAndroid Build Coastguard Worker             minIn,
234*8975f5c5SAndroid Build Coastguard Worker             maxIn,
235*8975f5c5SAndroid Build Coastguard Worker             minOut,
236*8975f5c5SAndroid Build Coastguard Worker             rangeOut / (maxIn - minIn),
237*8975f5c5SAndroid Build Coastguard Worker         };
238*8975f5c5SAndroid Build Coastguard Worker     }
239*8975f5c5SAndroid Build Coastguard Worker 
240*8975f5c5SAndroid Build Coastguard Worker   protected:
241*8975f5c5SAndroid Build Coastguard Worker     const bool mES3;
242*8975f5c5SAndroid Build Coastguard Worker };
243*8975f5c5SAndroid Build Coastguard Worker 
244*8975f5c5SAndroid Build Coastguard Worker typedef std::vector<Attrib> TestCase;
245*8975f5c5SAndroid Build Coastguard Worker 
PrepareTestCase(const TestCase & tc)246*8975f5c5SAndroid Build Coastguard Worker void PrepareTestCase(const TestCase &tc)
247*8975f5c5SAndroid Build Coastguard Worker {
248*8975f5c5SAndroid Build Coastguard Worker     for (const Attrib &a : tc)
249*8975f5c5SAndroid Build Coastguard Worker         a.openContainer();
250*8975f5c5SAndroid Build Coastguard Worker     for (const Attrib &a : tc)
251*8975f5c5SAndroid Build Coastguard Worker         a.fillContainer();
252*8975f5c5SAndroid Build Coastguard Worker     for (const Attrib &a : tc)
253*8975f5c5SAndroid Build Coastguard Worker         a.closeContainer();
254*8975f5c5SAndroid Build Coastguard Worker     unsigned i = 0;
255*8975f5c5SAndroid Build Coastguard Worker     for (const Attrib &a : tc)
256*8975f5c5SAndroid Build Coastguard Worker         a.enable(i++);
257*8975f5c5SAndroid Build Coastguard Worker }
258*8975f5c5SAndroid Build Coastguard Worker 
259*8975f5c5SAndroid Build Coastguard Worker class AttributeLayoutTest : public ANGLETest<>
260*8975f5c5SAndroid Build Coastguard Worker {
261*8975f5c5SAndroid Build Coastguard Worker   protected:
AttributeLayoutTest()262*8975f5c5SAndroid Build Coastguard Worker     AttributeLayoutTest()
263*8975f5c5SAndroid Build Coastguard Worker         : mProgram(0),
264*8975f5c5SAndroid Build Coastguard Worker           mCoord(2, kTriangleData, 0, 5, kNumVertices),
265*8975f5c5SAndroid Build Coastguard Worker           mColor(3, kTriangleData, 2, 5, kNumVertices)
266*8975f5c5SAndroid Build Coastguard Worker     {
267*8975f5c5SAndroid Build Coastguard Worker         setWindowWidth(128);
268*8975f5c5SAndroid Build Coastguard Worker         setWindowHeight(128);
269*8975f5c5SAndroid Build Coastguard Worker         setConfigRedBits(8);
270*8975f5c5SAndroid Build Coastguard Worker         setConfigGreenBits(8);
271*8975f5c5SAndroid Build Coastguard Worker         setConfigBlueBits(8);
272*8975f5c5SAndroid Build Coastguard Worker         setConfigAlphaBits(8);
273*8975f5c5SAndroid Build Coastguard Worker     }
274*8975f5c5SAndroid Build Coastguard Worker 
275*8975f5c5SAndroid Build Coastguard Worker     void GetTestCases(void);
276*8975f5c5SAndroid Build Coastguard Worker 
testSetUp()277*8975f5c5SAndroid Build Coastguard Worker     void testSetUp() override
278*8975f5c5SAndroid Build Coastguard Worker     {
279*8975f5c5SAndroid Build Coastguard Worker         glClearColor(.2f, .2f, .2f, .0f);
280*8975f5c5SAndroid Build Coastguard Worker         glClear(GL_COLOR_BUFFER_BIT);
281*8975f5c5SAndroid Build Coastguard Worker 
282*8975f5c5SAndroid Build Coastguard Worker         glDisable(GL_DEPTH_TEST);
283*8975f5c5SAndroid Build Coastguard Worker 
284*8975f5c5SAndroid Build Coastguard Worker         constexpr char kVS[] =
285*8975f5c5SAndroid Build Coastguard Worker             "attribute mediump vec2 coord;\n"
286*8975f5c5SAndroid Build Coastguard Worker             "attribute mediump vec3 color;\n"
287*8975f5c5SAndroid Build Coastguard Worker             "varying mediump vec3 vcolor;\n"
288*8975f5c5SAndroid Build Coastguard Worker             "void main(void)\n"
289*8975f5c5SAndroid Build Coastguard Worker             "{\n"
290*8975f5c5SAndroid Build Coastguard Worker             "    gl_Position = vec4(coord, 0, 1);\n"
291*8975f5c5SAndroid Build Coastguard Worker             "    vcolor = color;\n"
292*8975f5c5SAndroid Build Coastguard Worker             "}\n";
293*8975f5c5SAndroid Build Coastguard Worker 
294*8975f5c5SAndroid Build Coastguard Worker         constexpr char kFS[] =
295*8975f5c5SAndroid Build Coastguard Worker             "varying mediump vec3 vcolor;\n"
296*8975f5c5SAndroid Build Coastguard Worker             "void main(void)\n"
297*8975f5c5SAndroid Build Coastguard Worker             "{\n"
298*8975f5c5SAndroid Build Coastguard Worker             "    gl_FragColor = vec4(vcolor, 0);\n"
299*8975f5c5SAndroid Build Coastguard Worker             "}\n";
300*8975f5c5SAndroid Build Coastguard Worker 
301*8975f5c5SAndroid Build Coastguard Worker         mProgram = CompileProgram(kVS, kFS);
302*8975f5c5SAndroid Build Coastguard Worker         ASSERT_NE(0u, mProgram);
303*8975f5c5SAndroid Build Coastguard Worker         glUseProgram(mProgram);
304*8975f5c5SAndroid Build Coastguard Worker 
305*8975f5c5SAndroid Build Coastguard Worker         glGenBuffers(1, &mIndexBuffer);
306*8975f5c5SAndroid Build Coastguard Worker 
307*8975f5c5SAndroid Build Coastguard Worker         GetTestCases();
308*8975f5c5SAndroid Build Coastguard Worker     }
309*8975f5c5SAndroid Build Coastguard Worker 
testTearDown()310*8975f5c5SAndroid Build Coastguard Worker     void testTearDown() override
311*8975f5c5SAndroid Build Coastguard Worker     {
312*8975f5c5SAndroid Build Coastguard Worker         mTestCases.clear();
313*8975f5c5SAndroid Build Coastguard Worker         glDeleteProgram(mProgram);
314*8975f5c5SAndroid Build Coastguard Worker         glDeleteBuffers(1, &mIndexBuffer);
315*8975f5c5SAndroid Build Coastguard Worker     }
316*8975f5c5SAndroid Build Coastguard Worker 
Skip(const TestCase &)317*8975f5c5SAndroid Build Coastguard Worker     virtual bool Skip(const TestCase &) { return false; }
318*8975f5c5SAndroid Build Coastguard Worker     virtual void Draw(int firstVertex, unsigned vertexCount, const GLushort *indices) = 0;
319*8975f5c5SAndroid Build Coastguard Worker 
Run(bool drawFirstTriangle)320*8975f5c5SAndroid Build Coastguard Worker     void Run(bool drawFirstTriangle)
321*8975f5c5SAndroid Build Coastguard Worker     {
322*8975f5c5SAndroid Build Coastguard Worker         glViewport(0, 0, getWindowWidth(), getWindowHeight());
323*8975f5c5SAndroid Build Coastguard Worker         glUseProgram(mProgram);
324*8975f5c5SAndroid Build Coastguard Worker 
325*8975f5c5SAndroid Build Coastguard Worker         for (unsigned i = 0; i < mTestCases.size(); ++i)
326*8975f5c5SAndroid Build Coastguard Worker         {
327*8975f5c5SAndroid Build Coastguard Worker             if (mTestCases[i].size() == 0 || Skip(mTestCases[i]))
328*8975f5c5SAndroid Build Coastguard Worker                 continue;
329*8975f5c5SAndroid Build Coastguard Worker 
330*8975f5c5SAndroid Build Coastguard Worker             PrepareTestCase(mTestCases[i]);
331*8975f5c5SAndroid Build Coastguard Worker 
332*8975f5c5SAndroid Build Coastguard Worker             glClear(GL_COLOR_BUFFER_BIT);
333*8975f5c5SAndroid Build Coastguard Worker 
334*8975f5c5SAndroid Build Coastguard Worker             std::string testCase;
335*8975f5c5SAndroid Build Coastguard Worker             if (drawFirstTriangle)
336*8975f5c5SAndroid Build Coastguard Worker             {
337*8975f5c5SAndroid Build Coastguard Worker                 Draw(0, kNumVertices, mIndices);
338*8975f5c5SAndroid Build Coastguard Worker                 testCase = "draw";
339*8975f5c5SAndroid Build Coastguard Worker             }
340*8975f5c5SAndroid Build Coastguard Worker             else
341*8975f5c5SAndroid Build Coastguard Worker             {
342*8975f5c5SAndroid Build Coastguard Worker                 Draw(3, kNumVertices - 3, mIndices + 3);
343*8975f5c5SAndroid Build Coastguard Worker                 testCase = "skip";
344*8975f5c5SAndroid Build Coastguard Worker             }
345*8975f5c5SAndroid Build Coastguard Worker 
346*8975f5c5SAndroid Build Coastguard Worker             testCase += " first triangle case ";
347*8975f5c5SAndroid Build Coastguard Worker             int w = getWindowWidth() / 4;
348*8975f5c5SAndroid Build Coastguard Worker             int h = getWindowHeight() / 4;
349*8975f5c5SAndroid Build Coastguard Worker             if (drawFirstTriangle)
350*8975f5c5SAndroid Build Coastguard Worker             {
351*8975f5c5SAndroid Build Coastguard Worker                 EXPECT_PIXEL_EQ(w * 2, h * 3, 255, 255, 0, 0) << testCase << i;
352*8975f5c5SAndroid Build Coastguard Worker             }
353*8975f5c5SAndroid Build Coastguard Worker             else
354*8975f5c5SAndroid Build Coastguard Worker             {
355*8975f5c5SAndroid Build Coastguard Worker                 EXPECT_PIXEL_EQ(w * 2, h * 3, 51, 51, 51, 0) << testCase << i;
356*8975f5c5SAndroid Build Coastguard Worker             }
357*8975f5c5SAndroid Build Coastguard Worker             EXPECT_PIXEL_EQ(w * 3, h * 2, 0, 255, 0, 0) << testCase << i;
358*8975f5c5SAndroid Build Coastguard Worker             EXPECT_PIXEL_EQ(w * 2, h * 1, 0, 255, 255, 0) << testCase << i;
359*8975f5c5SAndroid Build Coastguard Worker             EXPECT_PIXEL_EQ(w * 1, h * 2, 255, 0, 255, 0) << testCase << i;
360*8975f5c5SAndroid Build Coastguard Worker         }
361*8975f5c5SAndroid Build Coastguard Worker     }
362*8975f5c5SAndroid Build Coastguard Worker 
363*8975f5c5SAndroid Build Coastguard Worker     static const GLushort mIndices[kNumVertices];
364*8975f5c5SAndroid Build Coastguard Worker 
365*8975f5c5SAndroid Build Coastguard Worker     GLuint mProgram;
366*8975f5c5SAndroid Build Coastguard Worker     GLuint mIndexBuffer;
367*8975f5c5SAndroid Build Coastguard Worker 
368*8975f5c5SAndroid Build Coastguard Worker     std::vector<TestCase> mTestCases;
369*8975f5c5SAndroid Build Coastguard Worker 
370*8975f5c5SAndroid Build Coastguard Worker     VertexData mCoord;
371*8975f5c5SAndroid Build Coastguard Worker     VertexData mColor;
372*8975f5c5SAndroid Build Coastguard Worker };
373*8975f5c5SAndroid Build Coastguard Worker const GLushort AttributeLayoutTest::mIndices[kNumVertices] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
374*8975f5c5SAndroid Build Coastguard Worker 
GetTestCases(void)375*8975f5c5SAndroid Build Coastguard Worker void AttributeLayoutTest::GetTestCases(void)
376*8975f5c5SAndroid Build Coastguard Worker {
377*8975f5c5SAndroid Build Coastguard Worker     const bool es3 = getClientMajorVersion() >= 3;
378*8975f5c5SAndroid Build Coastguard Worker 
379*8975f5c5SAndroid Build Coastguard Worker     Format<GLfloat, GL_FLOAT, false> Float(es3);
380*8975f5c5SAndroid Build Coastguard Worker     Format<GLint, GL_FIXED, false> Fixed(es3);
381*8975f5c5SAndroid Build Coastguard Worker 
382*8975f5c5SAndroid Build Coastguard Worker     Format<GLbyte, GL_BYTE, false> SByte(es3);
383*8975f5c5SAndroid Build Coastguard Worker     Format<GLubyte, GL_UNSIGNED_BYTE, false> UByte(es3);
384*8975f5c5SAndroid Build Coastguard Worker     Format<GLshort, GL_SHORT, false> SShort(es3);
385*8975f5c5SAndroid Build Coastguard Worker     Format<GLushort, GL_UNSIGNED_SHORT, false> UShort(es3);
386*8975f5c5SAndroid Build Coastguard Worker     Format<GLint, GL_INT, false> SInt(es3);
387*8975f5c5SAndroid Build Coastguard Worker     Format<GLuint, GL_UNSIGNED_INT, false> UInt(es3);
388*8975f5c5SAndroid Build Coastguard Worker 
389*8975f5c5SAndroid Build Coastguard Worker     Format<GLbyte, GL_BYTE, true> NormSByte(es3);
390*8975f5c5SAndroid Build Coastguard Worker     Format<GLubyte, GL_UNSIGNED_BYTE, true> NormUByte(es3);
391*8975f5c5SAndroid Build Coastguard Worker     Format<GLshort, GL_SHORT, true> NormSShort(es3);
392*8975f5c5SAndroid Build Coastguard Worker     Format<GLushort, GL_UNSIGNED_SHORT, true> NormUShort(es3);
393*8975f5c5SAndroid Build Coastguard Worker     Format<GLint, GL_INT, true> NormSInt(es3);
394*8975f5c5SAndroid Build Coastguard Worker     Format<GLuint, GL_UNSIGNED_INT, true> NormUInt(es3);
395*8975f5c5SAndroid Build Coastguard Worker 
396*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<Container> M0 = std::make_shared<Memory>();
397*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<Container> M1 = std::make_shared<Memory>();
398*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<Container> B0 = std::make_shared<Buffer>();
399*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<Container> B1 = std::make_shared<Buffer>();
400*8975f5c5SAndroid Build Coastguard Worker 
401*8975f5c5SAndroid Build Coastguard Worker     // 0. two buffers
402*8975f5c5SAndroid Build Coastguard Worker     mTestCases.push_back({Float(B0, 0, 8, mCoord), Float(B1, 0, 12, mColor)});
403*8975f5c5SAndroid Build Coastguard Worker 
404*8975f5c5SAndroid Build Coastguard Worker     // 1. two memory
405*8975f5c5SAndroid Build Coastguard Worker     mTestCases.push_back({Float(M0, 0, 8, mCoord), Float(M1, 0, 12, mColor)});
406*8975f5c5SAndroid Build Coastguard Worker 
407*8975f5c5SAndroid Build Coastguard Worker     // 2. one memory, sequential
408*8975f5c5SAndroid Build Coastguard Worker     mTestCases.push_back({Float(M0, 0, 8, mCoord), Float(M0, 96, 12, mColor)});
409*8975f5c5SAndroid Build Coastguard Worker 
410*8975f5c5SAndroid Build Coastguard Worker     // 3. one memory, interleaved
411*8975f5c5SAndroid Build Coastguard Worker     mTestCases.push_back({Float(M0, 0, 20, mCoord), Float(M0, 8, 20, mColor)});
412*8975f5c5SAndroid Build Coastguard Worker 
413*8975f5c5SAndroid Build Coastguard Worker     // 4. buffer and memory
414*8975f5c5SAndroid Build Coastguard Worker     mTestCases.push_back({Float(B0, 0, 8, mCoord), Float(M0, 0, 12, mColor)});
415*8975f5c5SAndroid Build Coastguard Worker 
416*8975f5c5SAndroid Build Coastguard Worker     // 5. stride != size
417*8975f5c5SAndroid Build Coastguard Worker     mTestCases.push_back({Float(B0, 0, 16, mCoord), Float(B1, 0, 12, mColor)});
418*8975f5c5SAndroid Build Coastguard Worker 
419*8975f5c5SAndroid Build Coastguard Worker     // 6-7. same stride and format, switching data between memory and buffer
420*8975f5c5SAndroid Build Coastguard Worker     mTestCases.push_back({Float(M0, 0, 16, mCoord), Float(M1, 0, 12, mColor)});
421*8975f5c5SAndroid Build Coastguard Worker     mTestCases.push_back({Float(B0, 0, 16, mCoord), Float(B1, 0, 12, mColor)});
422*8975f5c5SAndroid Build Coastguard Worker 
423*8975f5c5SAndroid Build Coastguard Worker     // 8-9. same stride and format, offset change
424*8975f5c5SAndroid Build Coastguard Worker     mTestCases.push_back({Float(B0, 0, 8, mCoord), Float(B1, 0, 12, mColor)});
425*8975f5c5SAndroid Build Coastguard Worker     mTestCases.push_back({Float(B0, 3, 8, mCoord), Float(B1, 4, 12, mColor)});
426*8975f5c5SAndroid Build Coastguard Worker 
427*8975f5c5SAndroid Build Coastguard Worker     // 10-11. unaligned buffer data
428*8975f5c5SAndroid Build Coastguard Worker     mTestCases.push_back({Float(M0, 0, 8, mCoord), Float(B0, 1, 13, mColor)});
429*8975f5c5SAndroid Build Coastguard Worker     mTestCases.push_back({Float(M0, 0, 8, mCoord), Float(B1, 1, 13, mColor)});
430*8975f5c5SAndroid Build Coastguard Worker 
431*8975f5c5SAndroid Build Coastguard Worker     // 12-15. byte/short
432*8975f5c5SAndroid Build Coastguard Worker     mTestCases.push_back({SByte(M0, 0, 20, mCoord), UByte(M0, 10, 20, mColor)});
433*8975f5c5SAndroid Build Coastguard Worker     mTestCases.push_back({SShort(M0, 0, 20, mCoord), UShort(M0, 8, 20, mColor)});
434*8975f5c5SAndroid Build Coastguard Worker     mTestCases.push_back({NormSByte(M0, 0, 8, mCoord), NormUByte(M0, 4, 8, mColor)});
435*8975f5c5SAndroid Build Coastguard Worker     mTestCases.push_back({NormSShort(M0, 0, 20, mCoord), NormUShort(M0, 8, 20, mColor)});
436*8975f5c5SAndroid Build Coastguard Worker 
437*8975f5c5SAndroid Build Coastguard Worker     // 16. one buffer, sequential
438*8975f5c5SAndroid Build Coastguard Worker     mTestCases.push_back({Fixed(B0, 0, 8, mCoord), Float(B0, 96, 12, mColor)});
439*8975f5c5SAndroid Build Coastguard Worker 
440*8975f5c5SAndroid Build Coastguard Worker     // 17. one buffer, interleaved
441*8975f5c5SAndroid Build Coastguard Worker     mTestCases.push_back({Fixed(B0, 0, 20, mCoord), Float(B0, 8, 20, mColor)});
442*8975f5c5SAndroid Build Coastguard Worker 
443*8975f5c5SAndroid Build Coastguard Worker     // 18. memory and buffer, float and integer
444*8975f5c5SAndroid Build Coastguard Worker     mTestCases.push_back({Float(M0, 0, 8, mCoord), SByte(B0, 0, 12, mColor)});
445*8975f5c5SAndroid Build Coastguard Worker 
446*8975f5c5SAndroid Build Coastguard Worker     // 19. buffer and memory, unusual offset and stride
447*8975f5c5SAndroid Build Coastguard Worker     mTestCases.push_back({Float(B0, 11, 13, mCoord), Float(M0, 23, 17, mColor)});
448*8975f5c5SAndroid Build Coastguard Worker 
449*8975f5c5SAndroid Build Coastguard Worker     // 20-21. remaining ES3 formats
450*8975f5c5SAndroid Build Coastguard Worker     if (es3)
451*8975f5c5SAndroid Build Coastguard Worker     {
452*8975f5c5SAndroid Build Coastguard Worker         mTestCases.push_back({SInt(M0, 0, 40, mCoord), UInt(M0, 16, 40, mColor)});
453*8975f5c5SAndroid Build Coastguard Worker         // Fails on Nexus devices (anglebug.com/42261348)
454*8975f5c5SAndroid Build Coastguard Worker         if (!IsNexus5X())
455*8975f5c5SAndroid Build Coastguard Worker             mTestCases.push_back({NormSInt(M0, 0, 40, mCoord), NormUInt(M0, 16, 40, mColor)});
456*8975f5c5SAndroid Build Coastguard Worker     }
457*8975f5c5SAndroid Build Coastguard Worker }
458*8975f5c5SAndroid Build Coastguard Worker 
459*8975f5c5SAndroid Build Coastguard Worker class AttributeLayoutNonIndexed : public AttributeLayoutTest
460*8975f5c5SAndroid Build Coastguard Worker {
Draw(int firstVertex,unsigned vertexCount,const GLushort * indices)461*8975f5c5SAndroid Build Coastguard Worker     void Draw(int firstVertex, unsigned vertexCount, const GLushort *indices) override
462*8975f5c5SAndroid Build Coastguard Worker     {
463*8975f5c5SAndroid Build Coastguard Worker         glDrawArrays(GL_TRIANGLES, firstVertex, vertexCount);
464*8975f5c5SAndroid Build Coastguard Worker     }
465*8975f5c5SAndroid Build Coastguard Worker };
466*8975f5c5SAndroid Build Coastguard Worker 
467*8975f5c5SAndroid Build Coastguard Worker class AttributeLayoutMemoryIndexed : public AttributeLayoutTest
468*8975f5c5SAndroid Build Coastguard Worker {
Draw(int firstVertex,unsigned vertexCount,const GLushort * indices)469*8975f5c5SAndroid Build Coastguard Worker     void Draw(int firstVertex, unsigned vertexCount, const GLushort *indices) override
470*8975f5c5SAndroid Build Coastguard Worker     {
471*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
472*8975f5c5SAndroid Build Coastguard Worker         glDrawElements(GL_TRIANGLES, vertexCount, GL_UNSIGNED_SHORT, indices);
473*8975f5c5SAndroid Build Coastguard Worker     }
474*8975f5c5SAndroid Build Coastguard Worker };
475*8975f5c5SAndroid Build Coastguard Worker 
476*8975f5c5SAndroid Build Coastguard Worker class AttributeLayoutBufferIndexed : public AttributeLayoutTest
477*8975f5c5SAndroid Build Coastguard Worker {
Draw(int firstVertex,unsigned vertexCount,const GLushort * indices)478*8975f5c5SAndroid Build Coastguard Worker     void Draw(int firstVertex, unsigned vertexCount, const GLushort *indices) override
479*8975f5c5SAndroid Build Coastguard Worker     {
480*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
481*8975f5c5SAndroid Build Coastguard Worker         glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(*mIndices) * vertexCount, indices,
482*8975f5c5SAndroid Build Coastguard Worker                      GL_STATIC_DRAW);
483*8975f5c5SAndroid Build Coastguard Worker         glDrawElements(GL_TRIANGLES, vertexCount, GL_UNSIGNED_SHORT, nullptr);
484*8975f5c5SAndroid Build Coastguard Worker     }
485*8975f5c5SAndroid Build Coastguard Worker };
486*8975f5c5SAndroid Build Coastguard Worker 
TEST_P(AttributeLayoutNonIndexed,Test)487*8975f5c5SAndroid Build Coastguard Worker TEST_P(AttributeLayoutNonIndexed, Test)
488*8975f5c5SAndroid Build Coastguard Worker {
489*8975f5c5SAndroid Build Coastguard Worker     Run(true);
490*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
491*8975f5c5SAndroid Build Coastguard Worker     Run(false);
492*8975f5c5SAndroid Build Coastguard Worker }
493*8975f5c5SAndroid Build Coastguard Worker 
TEST_P(AttributeLayoutMemoryIndexed,Test)494*8975f5c5SAndroid Build Coastguard Worker TEST_P(AttributeLayoutMemoryIndexed, Test)
495*8975f5c5SAndroid Build Coastguard Worker {
496*8975f5c5SAndroid Build Coastguard Worker     Run(true);
497*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
498*8975f5c5SAndroid Build Coastguard Worker     Run(false);
499*8975f5c5SAndroid Build Coastguard Worker }
500*8975f5c5SAndroid Build Coastguard Worker 
TEST_P(AttributeLayoutBufferIndexed,Test)501*8975f5c5SAndroid Build Coastguard Worker TEST_P(AttributeLayoutBufferIndexed, Test)
502*8975f5c5SAndroid Build Coastguard Worker {
503*8975f5c5SAndroid Build Coastguard Worker     Run(true);
504*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsOpenGL());
505*8975f5c5SAndroid Build Coastguard Worker     Run(false);
506*8975f5c5SAndroid Build Coastguard Worker }
507*8975f5c5SAndroid Build Coastguard Worker 
508*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(AttributeLayoutNonIndexed,
509*8975f5c5SAndroid Build Coastguard Worker                                        ES3_VULKAN()
510*8975f5c5SAndroid Build Coastguard Worker                                            .disable(Feature::SupportsExtendedDynamicState)
511*8975f5c5SAndroid Build Coastguard Worker                                            .disable(Feature::SupportsExtendedDynamicState2));
512*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(AttributeLayoutMemoryIndexed,
513*8975f5c5SAndroid Build Coastguard Worker                                        ES3_VULKAN()
514*8975f5c5SAndroid Build Coastguard Worker                                            .disable(Feature::SupportsExtendedDynamicState)
515*8975f5c5SAndroid Build Coastguard Worker                                            .disable(Feature::SupportsExtendedDynamicState2));
516*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(AttributeLayoutBufferIndexed,
517*8975f5c5SAndroid Build Coastguard Worker                                        ES3_VULKAN()
518*8975f5c5SAndroid Build Coastguard Worker                                            .disable(Feature::SupportsExtendedDynamicState)
519*8975f5c5SAndroid Build Coastguard Worker                                            .disable(Feature::SupportsExtendedDynamicState2));
520*8975f5c5SAndroid Build Coastguard Worker 
521*8975f5c5SAndroid Build Coastguard Worker #define STRINGIFY2(X) #X
522*8975f5c5SAndroid Build Coastguard Worker #define STRINGIFY(X) STRINGIFY2(X)
523*8975f5c5SAndroid Build Coastguard Worker 
524*8975f5c5SAndroid Build Coastguard Worker // clang-format off
525*8975f5c5SAndroid Build Coastguard Worker #define VS_SHADER(ColorDataType) \
526*8975f5c5SAndroid Build Coastguard Worker "#version 300 es\n"\
527*8975f5c5SAndroid Build Coastguard Worker "in highp vec2 coord;\n"\
528*8975f5c5SAndroid Build Coastguard Worker "in highp " STRINGIFY(ColorDataType) " color;\n"\
529*8975f5c5SAndroid Build Coastguard Worker "flat out highp " STRINGIFY(ColorDataType) " vcolor;\n"\
530*8975f5c5SAndroid Build Coastguard Worker "void main(void)\n"\
531*8975f5c5SAndroid Build Coastguard Worker "{\n"\
532*8975f5c5SAndroid Build Coastguard Worker "    gl_Position = vec4(coord, 0, 1);\n"\
533*8975f5c5SAndroid Build Coastguard Worker "    vcolor = color;\n"\
534*8975f5c5SAndroid Build Coastguard Worker "}\n"
535*8975f5c5SAndroid Build Coastguard Worker 
536*8975f5c5SAndroid Build Coastguard Worker #define PS_SHADER(ColorDataType) \
537*8975f5c5SAndroid Build Coastguard Worker "#version 300 es\n"\
538*8975f5c5SAndroid Build Coastguard Worker "flat in highp " STRINGIFY(ColorDataType) " vcolor;\n"\
539*8975f5c5SAndroid Build Coastguard Worker "out highp " STRINGIFY(ColorDataType) " outColor;\n"\
540*8975f5c5SAndroid Build Coastguard Worker "void main(void)\n"\
541*8975f5c5SAndroid Build Coastguard Worker "{\n"\
542*8975f5c5SAndroid Build Coastguard Worker "    outColor = vcolor;\n"\
543*8975f5c5SAndroid Build Coastguard Worker "}\n"
544*8975f5c5SAndroid Build Coastguard Worker 
545*8975f5c5SAndroid Build Coastguard Worker // clang-format on
546*8975f5c5SAndroid Build Coastguard Worker 
547*8975f5c5SAndroid Build Coastguard Worker // clang-format off
548*8975f5c5SAndroid Build Coastguard Worker constexpr double kVertexData[] = {
549*8975f5c5SAndroid Build Coastguard Worker    //x   y       rgba
550*8975f5c5SAndroid Build Coastguard Worker     -1, -1,      128, 128, 93, 255,
551*8975f5c5SAndroid Build Coastguard Worker     +1, -1,      128, 128, 93, 255,
552*8975f5c5SAndroid Build Coastguard Worker     -1, +1,      128, 128, 93, 255,
553*8975f5c5SAndroid Build Coastguard Worker     +1, +1,      128, 128, 93, 255,
554*8975f5c5SAndroid Build Coastguard Worker };
555*8975f5c5SAndroid Build Coastguard Worker // clang-format on
556*8975f5c5SAndroid Build Coastguard Worker 
557*8975f5c5SAndroid Build Coastguard Worker template <class ResType>
GetRefValue(const void * data,GLenum glType)558*8975f5c5SAndroid Build Coastguard Worker ResType GetRefValue(const void *data, GLenum glType)
559*8975f5c5SAndroid Build Coastguard Worker {
560*8975f5c5SAndroid Build Coastguard Worker     switch (glType)
561*8975f5c5SAndroid Build Coastguard Worker     {
562*8975f5c5SAndroid Build Coastguard Worker         case GL_BYTE:
563*8975f5c5SAndroid Build Coastguard Worker         {
564*8975f5c5SAndroid Build Coastguard Worker             const int8_t *p = reinterpret_cast<const int8_t *>(data);
565*8975f5c5SAndroid Build Coastguard Worker             return ResType(p[0], p[1], p[2], p[3]);
566*8975f5c5SAndroid Build Coastguard Worker         }
567*8975f5c5SAndroid Build Coastguard Worker         case GL_SHORT:
568*8975f5c5SAndroid Build Coastguard Worker         case GL_HALF_FLOAT:
569*8975f5c5SAndroid Build Coastguard Worker         {
570*8975f5c5SAndroid Build Coastguard Worker             const int16_t *p = reinterpret_cast<const int16_t *>(data);
571*8975f5c5SAndroid Build Coastguard Worker             return ResType(p[0], p[1], p[2], p[3]);
572*8975f5c5SAndroid Build Coastguard Worker         }
573*8975f5c5SAndroid Build Coastguard Worker         case GL_INT:
574*8975f5c5SAndroid Build Coastguard Worker         case GL_FIXED:
575*8975f5c5SAndroid Build Coastguard Worker         {
576*8975f5c5SAndroid Build Coastguard Worker             const int32_t *p = reinterpret_cast<const int32_t *>(data);
577*8975f5c5SAndroid Build Coastguard Worker             return ResType(p[0], p[1], p[2], p[3]);
578*8975f5c5SAndroid Build Coastguard Worker         }
579*8975f5c5SAndroid Build Coastguard Worker         case GL_UNSIGNED_BYTE:
580*8975f5c5SAndroid Build Coastguard Worker         {
581*8975f5c5SAndroid Build Coastguard Worker             const uint8_t *p = reinterpret_cast<const uint8_t *>(data);
582*8975f5c5SAndroid Build Coastguard Worker             return ResType(p[0], p[1], p[2], p[3]);
583*8975f5c5SAndroid Build Coastguard Worker         }
584*8975f5c5SAndroid Build Coastguard Worker         case GL_UNSIGNED_SHORT:
585*8975f5c5SAndroid Build Coastguard Worker         {
586*8975f5c5SAndroid Build Coastguard Worker             const uint16_t *p = reinterpret_cast<const uint16_t *>(data);
587*8975f5c5SAndroid Build Coastguard Worker             return ResType(p[0], p[1], p[2], p[3]);
588*8975f5c5SAndroid Build Coastguard Worker         }
589*8975f5c5SAndroid Build Coastguard Worker         case GL_FLOAT:
590*8975f5c5SAndroid Build Coastguard Worker         case GL_UNSIGNED_INT:
591*8975f5c5SAndroid Build Coastguard Worker         {
592*8975f5c5SAndroid Build Coastguard Worker             const uint32_t *p = reinterpret_cast<const uint32_t *>(data);
593*8975f5c5SAndroid Build Coastguard Worker             return ResType(p[0], p[1], p[2], p[3]);
594*8975f5c5SAndroid Build Coastguard Worker         }
595*8975f5c5SAndroid Build Coastguard Worker         default:
596*8975f5c5SAndroid Build Coastguard Worker         {
597*8975f5c5SAndroid Build Coastguard Worker             ASSERT(0);
598*8975f5c5SAndroid Build Coastguard Worker             const uint32_t *p = reinterpret_cast<const uint32_t *>(data);
599*8975f5c5SAndroid Build Coastguard Worker             return ResType(p[0], p[1], p[2], p[3]);
600*8975f5c5SAndroid Build Coastguard Worker         }
601*8975f5c5SAndroid Build Coastguard Worker     }
602*8975f5c5SAndroid Build Coastguard Worker }
603*8975f5c5SAndroid Build Coastguard Worker 
604*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kIndexCount = 6;
605*8975f5c5SAndroid Build Coastguard Worker constexpr int kRboSize       = 8;
606*8975f5c5SAndroid Build Coastguard Worker 
ConvertFloatToUnorm8(const GLColor32F & color32f)607*8975f5c5SAndroid Build Coastguard Worker GLColor ConvertFloatToUnorm8(const GLColor32F &color32f)
608*8975f5c5SAndroid Build Coastguard Worker {
609*8975f5c5SAndroid Build Coastguard Worker     float r = std::clamp(color32f.R, 0.0f, 1.0f);
610*8975f5c5SAndroid Build Coastguard Worker     float g = std::clamp(color32f.G, 0.0f, 1.0f);
611*8975f5c5SAndroid Build Coastguard Worker     float b = std::clamp(color32f.B, 0.0f, 1.0f);
612*8975f5c5SAndroid Build Coastguard Worker     float a = std::clamp(color32f.A, 0.0f, 1.0f);
613*8975f5c5SAndroid Build Coastguard Worker     return GLColor(std::round(r * 255), std::round(g * 255), std::round(b * 255),
614*8975f5c5SAndroid Build Coastguard Worker                    std::round(a * 255));
615*8975f5c5SAndroid Build Coastguard Worker }
616*8975f5c5SAndroid Build Coastguard Worker 
BindAttribLocation(GLuint program)617*8975f5c5SAndroid Build Coastguard Worker void BindAttribLocation(GLuint program)
618*8975f5c5SAndroid Build Coastguard Worker {
619*8975f5c5SAndroid Build Coastguard Worker     glBindAttribLocation(program, 0, "coord");
620*8975f5c5SAndroid Build Coastguard Worker     glBindAttribLocation(program, 1, "color");
621*8975f5c5SAndroid Build Coastguard Worker }
622*8975f5c5SAndroid Build Coastguard Worker 
623*8975f5c5SAndroid Build Coastguard Worker class AttributeDataTypeMismatchTest : public ANGLETest<>
624*8975f5c5SAndroid Build Coastguard Worker {
625*8975f5c5SAndroid Build Coastguard Worker   public:
626*8975f5c5SAndroid Build Coastguard Worker     enum VsInputDataType
627*8975f5c5SAndroid Build Coastguard Worker     {
628*8975f5c5SAndroid Build Coastguard Worker         FLOAT    = 0,
629*8975f5c5SAndroid Build Coastguard Worker         INT      = 1,
630*8975f5c5SAndroid Build Coastguard Worker         UNSIGNED = 2,
631*8975f5c5SAndroid Build Coastguard Worker         COUNT    = 3,
632*8975f5c5SAndroid Build Coastguard Worker     };
633*8975f5c5SAndroid Build Coastguard Worker 
634*8975f5c5SAndroid Build Coastguard Worker   protected:
AttributeDataTypeMismatchTest()635*8975f5c5SAndroid Build Coastguard Worker     AttributeDataTypeMismatchTest()
636*8975f5c5SAndroid Build Coastguard Worker         : mCoord(2, kVertexData, 0, 6, 4), mColor(4, kVertexData, 2, 6, 4)
637*8975f5c5SAndroid Build Coastguard Worker     {
638*8975f5c5SAndroid Build Coastguard Worker         setWindowWidth(128);
639*8975f5c5SAndroid Build Coastguard Worker         setWindowHeight(128);
640*8975f5c5SAndroid Build Coastguard Worker         setConfigRedBits(8);
641*8975f5c5SAndroid Build Coastguard Worker         setConfigGreenBits(8);
642*8975f5c5SAndroid Build Coastguard Worker         setConfigBlueBits(8);
643*8975f5c5SAndroid Build Coastguard Worker         setConfigAlphaBits(8);
644*8975f5c5SAndroid Build Coastguard Worker     }
645*8975f5c5SAndroid Build Coastguard Worker 
createFbo(GLuint rbo)646*8975f5c5SAndroid Build Coastguard Worker     GLuint createFbo(GLuint rbo)
647*8975f5c5SAndroid Build Coastguard Worker     {
648*8975f5c5SAndroid Build Coastguard Worker 
649*8975f5c5SAndroid Build Coastguard Worker         GLuint fbo = 0;
650*8975f5c5SAndroid Build Coastguard Worker         glGenFramebuffers(1, &fbo);
651*8975f5c5SAndroid Build Coastguard Worker         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
652*8975f5c5SAndroid Build Coastguard Worker         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
653*8975f5c5SAndroid Build Coastguard Worker         glBindFramebuffer(GL_FRAMEBUFFER, 0);
654*8975f5c5SAndroid Build Coastguard Worker         return fbo;
655*8975f5c5SAndroid Build Coastguard Worker     }
656*8975f5c5SAndroid Build Coastguard Worker 
createRbo(VsInputDataType inputDataType)657*8975f5c5SAndroid Build Coastguard Worker     GLuint createRbo(VsInputDataType inputDataType)
658*8975f5c5SAndroid Build Coastguard Worker     {
659*8975f5c5SAndroid Build Coastguard Worker         GLuint rbo = 0;
660*8975f5c5SAndroid Build Coastguard Worker         glGenRenderbuffers(1, &rbo);
661*8975f5c5SAndroid Build Coastguard Worker         GLenum format = GL_RGBA8;
662*8975f5c5SAndroid Build Coastguard Worker         if (inputDataType == VsInputDataType::INT)
663*8975f5c5SAndroid Build Coastguard Worker         {
664*8975f5c5SAndroid Build Coastguard Worker             format = GL_RGBA32I;
665*8975f5c5SAndroid Build Coastguard Worker         }
666*8975f5c5SAndroid Build Coastguard Worker         else if (inputDataType == VsInputDataType::UNSIGNED)
667*8975f5c5SAndroid Build Coastguard Worker         {
668*8975f5c5SAndroid Build Coastguard Worker             format = GL_RGBA32UI;
669*8975f5c5SAndroid Build Coastguard Worker         }
670*8975f5c5SAndroid Build Coastguard Worker         glBindRenderbuffer(GL_RENDERBUFFER, rbo);
671*8975f5c5SAndroid Build Coastguard Worker         glRenderbufferStorage(GL_RENDERBUFFER, format, kRboSize, kRboSize);
672*8975f5c5SAndroid Build Coastguard Worker         glBindRenderbuffer(GL_RENDERBUFFER, 0);
673*8975f5c5SAndroid Build Coastguard Worker         return rbo;
674*8975f5c5SAndroid Build Coastguard Worker     }
675*8975f5c5SAndroid Build Coastguard Worker 
testSetUp()676*8975f5c5SAndroid Build Coastguard Worker     void testSetUp() override
677*8975f5c5SAndroid Build Coastguard Worker     {
678*8975f5c5SAndroid Build Coastguard Worker         glClearColor(.2f, .2f, .2f, .0f);
679*8975f5c5SAndroid Build Coastguard Worker         glClear(GL_COLOR_BUFFER_BIT);
680*8975f5c5SAndroid Build Coastguard Worker 
681*8975f5c5SAndroid Build Coastguard Worker         glDisable(GL_DEPTH_TEST);
682*8975f5c5SAndroid Build Coastguard Worker 
683*8975f5c5SAndroid Build Coastguard Worker         constexpr const char *kVS[VsInputDataType::COUNT] = {
684*8975f5c5SAndroid Build Coastguard Worker             VS_SHADER(vec4),
685*8975f5c5SAndroid Build Coastguard Worker             VS_SHADER(ivec4),
686*8975f5c5SAndroid Build Coastguard Worker             VS_SHADER(uvec4),
687*8975f5c5SAndroid Build Coastguard Worker         };
688*8975f5c5SAndroid Build Coastguard Worker 
689*8975f5c5SAndroid Build Coastguard Worker         constexpr const char *kFS[VsInputDataType::COUNT] = {
690*8975f5c5SAndroid Build Coastguard Worker             PS_SHADER(vec4),
691*8975f5c5SAndroid Build Coastguard Worker             PS_SHADER(ivec4),
692*8975f5c5SAndroid Build Coastguard Worker             PS_SHADER(uvec4),
693*8975f5c5SAndroid Build Coastguard Worker         };
694*8975f5c5SAndroid Build Coastguard Worker 
695*8975f5c5SAndroid Build Coastguard Worker         for (int i = VsInputDataType::FLOAT; i < VsInputDataType::COUNT; ++i)
696*8975f5c5SAndroid Build Coastguard Worker         {
697*8975f5c5SAndroid Build Coastguard Worker             mProgram[i] = CompileProgram(kVS[i], kFS[i], BindAttribLocation);
698*8975f5c5SAndroid Build Coastguard Worker             ASSERT_NE(0u, mProgram[i]);
699*8975f5c5SAndroid Build Coastguard Worker             mRbo[i] = createRbo(static_cast<VsInputDataType>(i));
700*8975f5c5SAndroid Build Coastguard Worker             ASSERT_NE(0u, mRbo[i]);
701*8975f5c5SAndroid Build Coastguard Worker             mFbo[i] = createFbo(mRbo[i]);
702*8975f5c5SAndroid Build Coastguard Worker             ASSERT_NE(0u, mFbo[i]);
703*8975f5c5SAndroid Build Coastguard Worker         }
704*8975f5c5SAndroid Build Coastguard Worker 
705*8975f5c5SAndroid Build Coastguard Worker         glGenBuffers(1, &mIndexBuffer);
706*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
707*8975f5c5SAndroid Build Coastguard Worker         glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(mIndices), mIndices, GL_STATIC_DRAW);
708*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
709*8975f5c5SAndroid Build Coastguard Worker     }
710*8975f5c5SAndroid Build Coastguard Worker 
GetTestCases(VsInputDataType dataType)711*8975f5c5SAndroid Build Coastguard Worker     void GetTestCases(VsInputDataType dataType)
712*8975f5c5SAndroid Build Coastguard Worker     {
713*8975f5c5SAndroid Build Coastguard Worker         const bool es3 = getClientMajorVersion() >= 3;
714*8975f5c5SAndroid Build Coastguard Worker 
715*8975f5c5SAndroid Build Coastguard Worker         std::shared_ptr<Container> B0 = std::make_shared<Buffer>();
716*8975f5c5SAndroid Build Coastguard Worker         if (dataType != VsInputDataType::FLOAT)
717*8975f5c5SAndroid Build Coastguard Worker         {
718*8975f5c5SAndroid Build Coastguard Worker             // float and fixed.
719*8975f5c5SAndroid Build Coastguard Worker             Format<GLfloat, GL_FLOAT, false> Float(es3);
720*8975f5c5SAndroid Build Coastguard Worker             Format<GLint, GL_FIXED, false> Fixed(es3);
721*8975f5c5SAndroid Build Coastguard Worker             Format<GLshort, GL_HALF_FLOAT, false> halfFloat(es3);
722*8975f5c5SAndroid Build Coastguard Worker             // for UScale, SScale.
723*8975f5c5SAndroid Build Coastguard Worker             Format<GLbyte, GL_BYTE, false> SByte(es3);
724*8975f5c5SAndroid Build Coastguard Worker             Format<GLubyte, GL_UNSIGNED_BYTE, false> UByte(es3);
725*8975f5c5SAndroid Build Coastguard Worker             Format<GLshort, GL_SHORT, false> SShort(es3);
726*8975f5c5SAndroid Build Coastguard Worker             Format<GLushort, GL_UNSIGNED_SHORT, false> UShort(es3);
727*8975f5c5SAndroid Build Coastguard Worker             // UScale32, Scale32 may emulated. testing unsigned<-->int
728*8975f5c5SAndroid Build Coastguard Worker             Format<GLint, GL_INT, false, true> SInt(es3);
729*8975f5c5SAndroid Build Coastguard Worker             Format<GLuint, GL_UNSIGNED_INT, false, true> UInt(es3);
730*8975f5c5SAndroid Build Coastguard Worker             mTestCases.push_back({Float(B0, 0, 12, mCoord), SByte(B0, 8, 12, mColor)});
731*8975f5c5SAndroid Build Coastguard Worker             mTestCases.push_back({Float(B0, 0, 12, mCoord), UByte(B0, 8, 12, mColor)});
732*8975f5c5SAndroid Build Coastguard Worker             mTestCases.push_back({Float(B0, 0, 16, mCoord), SShort(B0, 8, 16, mColor)});
733*8975f5c5SAndroid Build Coastguard Worker             mTestCases.push_back({Float(B0, 0, 16, mCoord), UShort(B0, 8, 16, mColor)});
734*8975f5c5SAndroid Build Coastguard Worker             mTestCases.push_back({Float(B0, 0, 16, mCoord), halfFloat(B0, 8, 16, mColor)});
735*8975f5c5SAndroid Build Coastguard Worker             mTestCases.push_back({Float(B0, 0, 24, mCoord), SInt(B0, 8, 24, mColor)});
736*8975f5c5SAndroid Build Coastguard Worker             mTestCases.push_back({Float(B0, 0, 24, mCoord), UInt(B0, 8, 24, mColor)});
737*8975f5c5SAndroid Build Coastguard Worker             mTestCases.push_back({Float(B0, 0, 24, mCoord), Float(B0, 8, 24, mColor)});
738*8975f5c5SAndroid Build Coastguard Worker             // for GL_FIXED, angle may use GLfloat emulated.
739*8975f5c5SAndroid Build Coastguard Worker             // mTestCases.push_back({Float(B0, 0, 24, mCoord), Fixed(B0, 8, 24, mColor)});
740*8975f5c5SAndroid Build Coastguard Worker         }
741*8975f5c5SAndroid Build Coastguard Worker         else
742*8975f5c5SAndroid Build Coastguard Worker         {
743*8975f5c5SAndroid Build Coastguard Worker             Format<GLfloat, GL_FLOAT, false> Float(es3);
744*8975f5c5SAndroid Build Coastguard Worker             Format<GLbyte, GL_BYTE, false, true> SByte(es3);
745*8975f5c5SAndroid Build Coastguard Worker             Format<GLubyte, GL_UNSIGNED_BYTE, false, true> UByte(es3);
746*8975f5c5SAndroid Build Coastguard Worker             Format<GLshort, GL_SHORT, false, true> SShort(es3);
747*8975f5c5SAndroid Build Coastguard Worker             Format<GLushort, GL_UNSIGNED_SHORT, false, true> UShort(es3);
748*8975f5c5SAndroid Build Coastguard Worker             Format<GLint, GL_INT, false, true> SInt(es3);
749*8975f5c5SAndroid Build Coastguard Worker             Format<GLuint, GL_UNSIGNED_INT, false, true> UInt(es3);
750*8975f5c5SAndroid Build Coastguard Worker             mTestCases.push_back({Float(B0, 0, 12, mCoord), SByte(B0, 8, 12, mColor)});
751*8975f5c5SAndroid Build Coastguard Worker             mTestCases.push_back({Float(B0, 0, 12, mCoord), UByte(B0, 8, 12, mColor)});
752*8975f5c5SAndroid Build Coastguard Worker             mTestCases.push_back({Float(B0, 0, 16, mCoord), SShort(B0, 8, 16, mColor)});
753*8975f5c5SAndroid Build Coastguard Worker             mTestCases.push_back({Float(B0, 0, 16, mCoord), UShort(B0, 8, 16, mColor)});
754*8975f5c5SAndroid Build Coastguard Worker             // UScale32, Scale32 may emulated.
755*8975f5c5SAndroid Build Coastguard Worker             // mTestCases.push_back({Float(B0, 0, 24, mCoord), SInt(B0, 8, 24, mColor)});
756*8975f5c5SAndroid Build Coastguard Worker             // mTestCases.push_back({Float(B0, 0, 24, mCoord), UInt(B0, 8, 24, mColor)});
757*8975f5c5SAndroid Build Coastguard Worker         }
758*8975f5c5SAndroid Build Coastguard Worker     }
759*8975f5c5SAndroid Build Coastguard Worker 
testTearDown()760*8975f5c5SAndroid Build Coastguard Worker     void testTearDown() override
761*8975f5c5SAndroid Build Coastguard Worker     {
762*8975f5c5SAndroid Build Coastguard Worker         mTestCases.clear();
763*8975f5c5SAndroid Build Coastguard Worker         for (int i = 0; i < VsInputDataType::COUNT; ++i)
764*8975f5c5SAndroid Build Coastguard Worker         {
765*8975f5c5SAndroid Build Coastguard Worker             glDeleteProgram(mProgram[i]);
766*8975f5c5SAndroid Build Coastguard Worker             glDeleteFramebuffers(1, &mFbo[i]);
767*8975f5c5SAndroid Build Coastguard Worker             glDeleteRenderbuffers(1, &mRbo[i]);
768*8975f5c5SAndroid Build Coastguard Worker         }
769*8975f5c5SAndroid Build Coastguard Worker         glDeleteBuffers(1, &mIndexBuffer);
770*8975f5c5SAndroid Build Coastguard Worker     }
771*8975f5c5SAndroid Build Coastguard Worker 
GetMappedGLType(GLenum glType,VsInputDataType vsInputDataType)772*8975f5c5SAndroid Build Coastguard Worker     GLenum GetMappedGLType(GLenum glType, VsInputDataType vsInputDataType)
773*8975f5c5SAndroid Build Coastguard Worker     {
774*8975f5c5SAndroid Build Coastguard Worker         switch (glType)
775*8975f5c5SAndroid Build Coastguard Worker         {
776*8975f5c5SAndroid Build Coastguard Worker             case GL_BYTE:
777*8975f5c5SAndroid Build Coastguard Worker                 return vsInputDataType != VsInputDataType::UNSIGNED ? GL_BYTE : GL_UNSIGNED_BYTE;
778*8975f5c5SAndroid Build Coastguard Worker             case GL_SHORT:
779*8975f5c5SAndroid Build Coastguard Worker             case GL_HALF_FLOAT:
780*8975f5c5SAndroid Build Coastguard Worker                 return vsInputDataType != VsInputDataType::UNSIGNED ? GL_SHORT : GL_UNSIGNED_SHORT;
781*8975f5c5SAndroid Build Coastguard Worker             case GL_INT:
782*8975f5c5SAndroid Build Coastguard Worker             case GL_FIXED:
783*8975f5c5SAndroid Build Coastguard Worker                 return vsInputDataType != VsInputDataType::UNSIGNED ? GL_INT : GL_UNSIGNED_INT;
784*8975f5c5SAndroid Build Coastguard Worker             case GL_UNSIGNED_BYTE:
785*8975f5c5SAndroid Build Coastguard Worker                 return vsInputDataType != VsInputDataType::INT ? GL_UNSIGNED_BYTE : GL_BYTE;
786*8975f5c5SAndroid Build Coastguard Worker             case GL_UNSIGNED_SHORT:
787*8975f5c5SAndroid Build Coastguard Worker                 return vsInputDataType != VsInputDataType::INT ? GL_UNSIGNED_SHORT : GL_SHORT;
788*8975f5c5SAndroid Build Coastguard Worker             case GL_FLOAT:
789*8975f5c5SAndroid Build Coastguard Worker             case GL_UNSIGNED_INT:
790*8975f5c5SAndroid Build Coastguard Worker                 return vsInputDataType != VsInputDataType::INT ? GL_UNSIGNED_INT : GL_INT;
791*8975f5c5SAndroid Build Coastguard Worker             default:
792*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(0);
793*8975f5c5SAndroid Build Coastguard Worker                 return vsInputDataType != VsInputDataType::INT ? GL_UNSIGNED_INT : GL_INT;
794*8975f5c5SAndroid Build Coastguard Worker         }
795*8975f5c5SAndroid Build Coastguard Worker     }
796*8975f5c5SAndroid Build Coastguard Worker 
Run(VsInputDataType dataType)797*8975f5c5SAndroid Build Coastguard Worker     void Run(VsInputDataType dataType)
798*8975f5c5SAndroid Build Coastguard Worker     {
799*8975f5c5SAndroid Build Coastguard Worker         GetTestCases(dataType);
800*8975f5c5SAndroid Build Coastguard Worker         ASSERT(dataType < VsInputDataType::COUNT);
801*8975f5c5SAndroid Build Coastguard Worker         glBindFramebuffer(GL_FRAMEBUFFER, mFbo[dataType]);
802*8975f5c5SAndroid Build Coastguard Worker         glViewport(0, 0, kRboSize, kRboSize);
803*8975f5c5SAndroid Build Coastguard Worker         glUseProgram(mProgram[dataType]);
804*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
805*8975f5c5SAndroid Build Coastguard Worker         for (unsigned i = 0; i < mTestCases.size(); ++i)
806*8975f5c5SAndroid Build Coastguard Worker         {
807*8975f5c5SAndroid Build Coastguard Worker             if (mTestCases[i].size() == 0)
808*8975f5c5SAndroid Build Coastguard Worker                 continue;
809*8975f5c5SAndroid Build Coastguard Worker             ASSERT(mTestCases[i].size() == 2);
810*8975f5c5SAndroid Build Coastguard Worker             PrepareTestCase(mTestCases[i]);
811*8975f5c5SAndroid Build Coastguard Worker             EXPECT_GL_NO_ERROR();
812*8975f5c5SAndroid Build Coastguard Worker             GLint iClearValue[]   = {0, 0, 0, 1};
813*8975f5c5SAndroid Build Coastguard Worker             GLfloat fClearValue[] = {1.0f, 0.0f, 0.0f, 1.0f};
814*8975f5c5SAndroid Build Coastguard Worker             switch (dataType)
815*8975f5c5SAndroid Build Coastguard Worker             {
816*8975f5c5SAndroid Build Coastguard Worker                 case VsInputDataType::FLOAT:
817*8975f5c5SAndroid Build Coastguard Worker                     glClearBufferfv(GL_COLOR, 0, fClearValue);
818*8975f5c5SAndroid Build Coastguard Worker                     break;
819*8975f5c5SAndroid Build Coastguard Worker                 case VsInputDataType::INT:
820*8975f5c5SAndroid Build Coastguard Worker                     glClearBufferiv(GL_COLOR, 0, iClearValue);
821*8975f5c5SAndroid Build Coastguard Worker                     break;
822*8975f5c5SAndroid Build Coastguard Worker                 case VsInputDataType::UNSIGNED:
823*8975f5c5SAndroid Build Coastguard Worker                     glClearBufferuiv(GL_COLOR, 0, reinterpret_cast<const GLuint *>(iClearValue));
824*8975f5c5SAndroid Build Coastguard Worker                     break;
825*8975f5c5SAndroid Build Coastguard Worker                 default:
826*8975f5c5SAndroid Build Coastguard Worker                     ASSERT(0);
827*8975f5c5SAndroid Build Coastguard Worker             }
828*8975f5c5SAndroid Build Coastguard Worker             EXPECT_GL_NO_ERROR();
829*8975f5c5SAndroid Build Coastguard Worker             glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
830*8975f5c5SAndroid Build Coastguard Worker             EXPECT_GL_NO_ERROR();
831*8975f5c5SAndroid Build Coastguard Worker 
832*8975f5c5SAndroid Build Coastguard Worker             std::shared_ptr<Container> container = mTestCases[i][1].mContainer;
833*8975f5c5SAndroid Build Coastguard Worker             size_t offset                        = mTestCases[i][1].mOffset;
834*8975f5c5SAndroid Build Coastguard Worker             GLenum glType = GetMappedGLType(mTestCases[i][1].mGLType, dataType);
835*8975f5c5SAndroid Build Coastguard Worker             switch (dataType)
836*8975f5c5SAndroid Build Coastguard Worker             {
837*8975f5c5SAndroid Build Coastguard Worker                 case VsInputDataType::FLOAT:
838*8975f5c5SAndroid Build Coastguard Worker                     EXPECT_PIXEL_COLOR_EQ(0, 0,
839*8975f5c5SAndroid Build Coastguard Worker                                           ConvertFloatToUnorm8(GetRefValue<GLColor32F>(
840*8975f5c5SAndroid Build Coastguard Worker                                               container->getDestination(offset), glType)));
841*8975f5c5SAndroid Build Coastguard Worker                     break;
842*8975f5c5SAndroid Build Coastguard Worker                 case VsInputDataType::INT:
843*8975f5c5SAndroid Build Coastguard Worker                     EXPECT_PIXEL_RECT32I_EQ(
844*8975f5c5SAndroid Build Coastguard Worker                         0, 0, 1, 1,
845*8975f5c5SAndroid Build Coastguard Worker                         GetRefValue<GLColor32I>(container->getDestination(offset), glType));
846*8975f5c5SAndroid Build Coastguard Worker                     break;
847*8975f5c5SAndroid Build Coastguard Worker                 case VsInputDataType::UNSIGNED:
848*8975f5c5SAndroid Build Coastguard Worker                     EXPECT_PIXEL_RECT32UI_EQ(
849*8975f5c5SAndroid Build Coastguard Worker                         0, 0, 1, 1,
850*8975f5c5SAndroid Build Coastguard Worker                         GetRefValue<GLColor32UI>(container->getDestination(offset), glType));
851*8975f5c5SAndroid Build Coastguard Worker                     break;
852*8975f5c5SAndroid Build Coastguard Worker                 default:
853*8975f5c5SAndroid Build Coastguard Worker                     ASSERT(0);
854*8975f5c5SAndroid Build Coastguard Worker             }
855*8975f5c5SAndroid Build Coastguard Worker         }
856*8975f5c5SAndroid Build Coastguard Worker         mTestCases.clear();
857*8975f5c5SAndroid Build Coastguard Worker     }
858*8975f5c5SAndroid Build Coastguard Worker 
859*8975f5c5SAndroid Build Coastguard Worker     static const GLushort mIndices[kIndexCount];
860*8975f5c5SAndroid Build Coastguard Worker 
861*8975f5c5SAndroid Build Coastguard Worker     GLuint mProgram[VsInputDataType::COUNT];
862*8975f5c5SAndroid Build Coastguard Worker     GLuint mFbo[VsInputDataType::COUNT];
863*8975f5c5SAndroid Build Coastguard Worker     GLuint mRbo[VsInputDataType::COUNT];
864*8975f5c5SAndroid Build Coastguard Worker     GLuint mIndexBuffer;
865*8975f5c5SAndroid Build Coastguard Worker 
866*8975f5c5SAndroid Build Coastguard Worker     std::vector<TestCase> mTestCases;
867*8975f5c5SAndroid Build Coastguard Worker 
868*8975f5c5SAndroid Build Coastguard Worker     VertexData mCoord;
869*8975f5c5SAndroid Build Coastguard Worker     VertexData mColor;
870*8975f5c5SAndroid Build Coastguard Worker };
871*8975f5c5SAndroid Build Coastguard Worker 
872*8975f5c5SAndroid Build Coastguard Worker const GLushort AttributeDataTypeMismatchTest::mIndices[kIndexCount] = {0, 1, 2, 2, 1, 3};
873*8975f5c5SAndroid Build Coastguard Worker 
874*8975f5c5SAndroid Build Coastguard Worker // Test Attribute input data type mismatch with vertex shader input.
875*8975f5c5SAndroid Build Coastguard Worker // Change the attribute input data type to vertex shader input data type.
TEST_P(AttributeDataTypeMismatchTest,Test)876*8975f5c5SAndroid Build Coastguard Worker TEST_P(AttributeDataTypeMismatchTest, Test)
877*8975f5c5SAndroid Build Coastguard Worker {
878*8975f5c5SAndroid Build Coastguard Worker     // At some device. UScale and Scale are emulated.
879*8975f5c5SAndroid Build Coastguard Worker     // Restrict tests running at nvidia device only.
880*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan() || !IsNVIDIA());
881*8975f5c5SAndroid Build Coastguard Worker     Run(VsInputDataType::FLOAT);
882*8975f5c5SAndroid Build Coastguard Worker     Run(VsInputDataType::INT);
883*8975f5c5SAndroid Build Coastguard Worker     Run(VsInputDataType::UNSIGNED);
884*8975f5c5SAndroid Build Coastguard Worker }
885*8975f5c5SAndroid Build Coastguard Worker 
886*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES3(AttributeDataTypeMismatchTest);
887*8975f5c5SAndroid Build Coastguard Worker 
888*8975f5c5SAndroid Build Coastguard Worker }  // anonymous namespace
889