1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2015 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 #include "anglebase/numerics/safe_conversions.h"
7*8975f5c5SAndroid Build Coastguard Worker #include "common/mathutil.h"
8*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/ANGLETest.h"
9*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/gl_raii.h"
10*8975f5c5SAndroid Build Coastguard Worker #include "util/random_utils.h"
11*8975f5c5SAndroid Build Coastguard Worker
12*8975f5c5SAndroid Build Coastguard Worker using namespace angle;
13*8975f5c5SAndroid Build Coastguard Worker
14*8975f5c5SAndroid Build Coastguard Worker namespace
15*8975f5c5SAndroid Build Coastguard Worker {
16*8975f5c5SAndroid Build Coastguard Worker
TypeStride(GLenum attribType)17*8975f5c5SAndroid Build Coastguard Worker GLsizei TypeStride(GLenum attribType)
18*8975f5c5SAndroid Build Coastguard Worker {
19*8975f5c5SAndroid Build Coastguard Worker switch (attribType)
20*8975f5c5SAndroid Build Coastguard Worker {
21*8975f5c5SAndroid Build Coastguard Worker case GL_UNSIGNED_BYTE:
22*8975f5c5SAndroid Build Coastguard Worker case GL_BYTE:
23*8975f5c5SAndroid Build Coastguard Worker return 1;
24*8975f5c5SAndroid Build Coastguard Worker case GL_UNSIGNED_SHORT:
25*8975f5c5SAndroid Build Coastguard Worker case GL_SHORT:
26*8975f5c5SAndroid Build Coastguard Worker case GL_HALF_FLOAT:
27*8975f5c5SAndroid Build Coastguard Worker case GL_HALF_FLOAT_OES:
28*8975f5c5SAndroid Build Coastguard Worker return 2;
29*8975f5c5SAndroid Build Coastguard Worker case GL_UNSIGNED_INT:
30*8975f5c5SAndroid Build Coastguard Worker case GL_INT:
31*8975f5c5SAndroid Build Coastguard Worker case GL_FLOAT:
32*8975f5c5SAndroid Build Coastguard Worker case GL_UNSIGNED_INT_10_10_10_2_OES:
33*8975f5c5SAndroid Build Coastguard Worker case GL_INT_10_10_10_2_OES:
34*8975f5c5SAndroid Build Coastguard Worker return 4;
35*8975f5c5SAndroid Build Coastguard Worker default:
36*8975f5c5SAndroid Build Coastguard Worker EXPECT_TRUE(false);
37*8975f5c5SAndroid Build Coastguard Worker return 0;
38*8975f5c5SAndroid Build Coastguard Worker }
39*8975f5c5SAndroid Build Coastguard Worker }
40*8975f5c5SAndroid Build Coastguard Worker
41*8975f5c5SAndroid Build Coastguard Worker template <typename T>
Normalize(T value)42*8975f5c5SAndroid Build Coastguard Worker GLfloat Normalize(T value)
43*8975f5c5SAndroid Build Coastguard Worker {
44*8975f5c5SAndroid Build Coastguard Worker static_assert(std::is_integral<T>::value, "Integer required.");
45*8975f5c5SAndroid Build Coastguard Worker if (std::is_signed<T>::value)
46*8975f5c5SAndroid Build Coastguard Worker {
47*8975f5c5SAndroid Build Coastguard Worker typedef typename std::make_unsigned<T>::type unsigned_type;
48*8975f5c5SAndroid Build Coastguard Worker return (2.0f * static_cast<GLfloat>(value) + 1.0f) /
49*8975f5c5SAndroid Build Coastguard Worker static_cast<GLfloat>(std::numeric_limits<unsigned_type>::max());
50*8975f5c5SAndroid Build Coastguard Worker }
51*8975f5c5SAndroid Build Coastguard Worker else
52*8975f5c5SAndroid Build Coastguard Worker {
53*8975f5c5SAndroid Build Coastguard Worker return static_cast<GLfloat>(value) / static_cast<GLfloat>(std::numeric_limits<T>::max());
54*8975f5c5SAndroid Build Coastguard Worker }
55*8975f5c5SAndroid Build Coastguard Worker }
56*8975f5c5SAndroid Build Coastguard Worker
57*8975f5c5SAndroid Build Coastguard Worker // Normalization for each channel of signed/unsigned 10_10_10_2 types
58*8975f5c5SAndroid Build Coastguard Worker template <typename T>
Normalize10(T value)59*8975f5c5SAndroid Build Coastguard Worker GLfloat Normalize10(T value)
60*8975f5c5SAndroid Build Coastguard Worker {
61*8975f5c5SAndroid Build Coastguard Worker static_assert(std::is_integral<T>::value, "Integer required.");
62*8975f5c5SAndroid Build Coastguard Worker GLfloat floatOutput;
63*8975f5c5SAndroid Build Coastguard Worker if (std::is_signed<T>::value)
64*8975f5c5SAndroid Build Coastguard Worker {
65*8975f5c5SAndroid Build Coastguard Worker const uint32_t signMask = 0x200; // 1 set at the 9th bit
66*8975f5c5SAndroid Build Coastguard Worker const uint32_t negativeMask = 0xFFFFFC00; // All bits from 10 to 31 set to 1
67*8975f5c5SAndroid Build Coastguard Worker
68*8975f5c5SAndroid Build Coastguard Worker if (value & signMask)
69*8975f5c5SAndroid Build Coastguard Worker {
70*8975f5c5SAndroid Build Coastguard Worker int negativeNumber = value | negativeMask;
71*8975f5c5SAndroid Build Coastguard Worker floatOutput = static_cast<GLfloat>(negativeNumber);
72*8975f5c5SAndroid Build Coastguard Worker }
73*8975f5c5SAndroid Build Coastguard Worker else
74*8975f5c5SAndroid Build Coastguard Worker {
75*8975f5c5SAndroid Build Coastguard Worker floatOutput = static_cast<GLfloat>(value);
76*8975f5c5SAndroid Build Coastguard Worker }
77*8975f5c5SAndroid Build Coastguard Worker
78*8975f5c5SAndroid Build Coastguard Worker const int32_t maxValue = 0x1FF; // 1 set in bits 0 through 8
79*8975f5c5SAndroid Build Coastguard Worker const int32_t minValue = 0xFFFFFE01; // Inverse of maxValue
80*8975f5c5SAndroid Build Coastguard Worker
81*8975f5c5SAndroid Build Coastguard Worker // A 10-bit two's complement number has the possibility of being minValue - 1 but
82*8975f5c5SAndroid Build Coastguard Worker // OpenGL's normalization rules dictate that it should be clamped to minValue in
83*8975f5c5SAndroid Build Coastguard Worker // this case.
84*8975f5c5SAndroid Build Coastguard Worker if (floatOutput < minValue)
85*8975f5c5SAndroid Build Coastguard Worker floatOutput = minValue;
86*8975f5c5SAndroid Build Coastguard Worker
87*8975f5c5SAndroid Build Coastguard Worker const int32_t halfRange = (maxValue - minValue) >> 1;
88*8975f5c5SAndroid Build Coastguard Worker floatOutput = ((floatOutput - minValue) / halfRange) - 1.0f;
89*8975f5c5SAndroid Build Coastguard Worker }
90*8975f5c5SAndroid Build Coastguard Worker else
91*8975f5c5SAndroid Build Coastguard Worker {
92*8975f5c5SAndroid Build Coastguard Worker const GLfloat maxValue = 1023.0f; // 1 set in bits 0 through 9
93*8975f5c5SAndroid Build Coastguard Worker floatOutput = static_cast<GLfloat>(value) / maxValue;
94*8975f5c5SAndroid Build Coastguard Worker }
95*8975f5c5SAndroid Build Coastguard Worker return floatOutput;
96*8975f5c5SAndroid Build Coastguard Worker }
97*8975f5c5SAndroid Build Coastguard Worker
98*8975f5c5SAndroid Build Coastguard Worker template <typename T>
Normalize2(T value)99*8975f5c5SAndroid Build Coastguard Worker GLfloat Normalize2(T value)
100*8975f5c5SAndroid Build Coastguard Worker {
101*8975f5c5SAndroid Build Coastguard Worker static_assert(std::is_integral<T>::value, "Integer required.");
102*8975f5c5SAndroid Build Coastguard Worker if (std::is_signed<T>::value)
103*8975f5c5SAndroid Build Coastguard Worker {
104*8975f5c5SAndroid Build Coastguard Worker GLfloat outputValue = static_cast<float>(value) / 1.0f;
105*8975f5c5SAndroid Build Coastguard Worker outputValue = (outputValue >= -1.0f) ? (outputValue) : (-1.0f);
106*8975f5c5SAndroid Build Coastguard Worker return outputValue;
107*8975f5c5SAndroid Build Coastguard Worker }
108*8975f5c5SAndroid Build Coastguard Worker else
109*8975f5c5SAndroid Build Coastguard Worker {
110*8975f5c5SAndroid Build Coastguard Worker return static_cast<float>(value) / 3.0f;
111*8975f5c5SAndroid Build Coastguard Worker }
112*8975f5c5SAndroid Build Coastguard Worker }
113*8975f5c5SAndroid Build Coastguard Worker
114*8975f5c5SAndroid Build Coastguard Worker template <typename DestT, typename SrcT>
Pack1010102(std::array<SrcT,4> input)115*8975f5c5SAndroid Build Coastguard Worker DestT Pack1010102(std::array<SrcT, 4> input)
116*8975f5c5SAndroid Build Coastguard Worker {
117*8975f5c5SAndroid Build Coastguard Worker static_assert(std::is_integral<SrcT>::value, "Integer required.");
118*8975f5c5SAndroid Build Coastguard Worker static_assert(std::is_integral<DestT>::value, "Integer required.");
119*8975f5c5SAndroid Build Coastguard Worker static_assert(std::is_unsigned<SrcT>::value == std::is_unsigned<DestT>::value,
120*8975f5c5SAndroid Build Coastguard Worker "Signedness should be equal.");
121*8975f5c5SAndroid Build Coastguard Worker DestT rOut, gOut, bOut, aOut;
122*8975f5c5SAndroid Build Coastguard Worker rOut = static_cast<DestT>(input[0]);
123*8975f5c5SAndroid Build Coastguard Worker gOut = static_cast<DestT>(input[1]);
124*8975f5c5SAndroid Build Coastguard Worker bOut = static_cast<DestT>(input[2]);
125*8975f5c5SAndroid Build Coastguard Worker aOut = static_cast<DestT>(input[3]);
126*8975f5c5SAndroid Build Coastguard Worker
127*8975f5c5SAndroid Build Coastguard Worker if (std::is_unsigned<SrcT>::value)
128*8975f5c5SAndroid Build Coastguard Worker {
129*8975f5c5SAndroid Build Coastguard Worker return rOut << 22 | gOut << 12 | bOut << 2 | aOut;
130*8975f5c5SAndroid Build Coastguard Worker }
131*8975f5c5SAndroid Build Coastguard Worker else
132*8975f5c5SAndroid Build Coastguard Worker {
133*8975f5c5SAndroid Build Coastguard Worker // Need to apply bit mask to account for sign extension
134*8975f5c5SAndroid Build Coastguard Worker return (0xFFC00000u & rOut << 22) | (0x003FF000u & gOut << 12) | (0x00000FFCu & bOut << 2) |
135*8975f5c5SAndroid Build Coastguard Worker (0x00000003u & aOut);
136*8975f5c5SAndroid Build Coastguard Worker }
137*8975f5c5SAndroid Build Coastguard Worker }
138*8975f5c5SAndroid Build Coastguard Worker
139*8975f5c5SAndroid Build Coastguard Worker class VertexAttributeTest : public ANGLETest<>
140*8975f5c5SAndroid Build Coastguard Worker {
141*8975f5c5SAndroid Build Coastguard Worker protected:
VertexAttributeTest()142*8975f5c5SAndroid Build Coastguard Worker VertexAttributeTest() : mProgram(0), mTestAttrib(-1), mExpectedAttrib(-1), mBuffer(0)
143*8975f5c5SAndroid Build Coastguard Worker {
144*8975f5c5SAndroid Build Coastguard Worker setWindowWidth(128);
145*8975f5c5SAndroid Build Coastguard Worker setWindowHeight(128);
146*8975f5c5SAndroid Build Coastguard Worker setConfigRedBits(8);
147*8975f5c5SAndroid Build Coastguard Worker setConfigGreenBits(8);
148*8975f5c5SAndroid Build Coastguard Worker setConfigBlueBits(8);
149*8975f5c5SAndroid Build Coastguard Worker setConfigAlphaBits(8);
150*8975f5c5SAndroid Build Coastguard Worker setConfigDepthBits(24);
151*8975f5c5SAndroid Build Coastguard Worker }
152*8975f5c5SAndroid Build Coastguard Worker
153*8975f5c5SAndroid Build Coastguard Worker enum class Source
154*8975f5c5SAndroid Build Coastguard Worker {
155*8975f5c5SAndroid Build Coastguard Worker BUFFER,
156*8975f5c5SAndroid Build Coastguard Worker IMMEDIATE,
157*8975f5c5SAndroid Build Coastguard Worker };
158*8975f5c5SAndroid Build Coastguard Worker
159*8975f5c5SAndroid Build Coastguard Worker struct TestData final : private angle::NonCopyable
160*8975f5c5SAndroid Build Coastguard Worker {
TestData__anon8ff86acd0111::VertexAttributeTest::TestData161*8975f5c5SAndroid Build Coastguard Worker TestData(GLenum typeIn,
162*8975f5c5SAndroid Build Coastguard Worker GLboolean normalizedIn,
163*8975f5c5SAndroid Build Coastguard Worker Source sourceIn,
164*8975f5c5SAndroid Build Coastguard Worker const void *inputDataIn,
165*8975f5c5SAndroid Build Coastguard Worker const GLfloat *expectedDataIn)
166*8975f5c5SAndroid Build Coastguard Worker : type(typeIn),
167*8975f5c5SAndroid Build Coastguard Worker normalized(normalizedIn),
168*8975f5c5SAndroid Build Coastguard Worker bufferOffset(0),
169*8975f5c5SAndroid Build Coastguard Worker source(sourceIn),
170*8975f5c5SAndroid Build Coastguard Worker inputData(inputDataIn),
171*8975f5c5SAndroid Build Coastguard Worker expectedData(expectedDataIn),
172*8975f5c5SAndroid Build Coastguard Worker clearBeforeDraw(false)
173*8975f5c5SAndroid Build Coastguard Worker {}
174*8975f5c5SAndroid Build Coastguard Worker
175*8975f5c5SAndroid Build Coastguard Worker GLenum type;
176*8975f5c5SAndroid Build Coastguard Worker GLboolean normalized;
177*8975f5c5SAndroid Build Coastguard Worker size_t bufferOffset;
178*8975f5c5SAndroid Build Coastguard Worker Source source;
179*8975f5c5SAndroid Build Coastguard Worker
180*8975f5c5SAndroid Build Coastguard Worker const void *inputData;
181*8975f5c5SAndroid Build Coastguard Worker const GLfloat *expectedData;
182*8975f5c5SAndroid Build Coastguard Worker
183*8975f5c5SAndroid Build Coastguard Worker bool clearBeforeDraw;
184*8975f5c5SAndroid Build Coastguard Worker };
185*8975f5c5SAndroid Build Coastguard Worker
setupTest(const TestData & test,GLint typeSize)186*8975f5c5SAndroid Build Coastguard Worker void setupTest(const TestData &test, GLint typeSize)
187*8975f5c5SAndroid Build Coastguard Worker {
188*8975f5c5SAndroid Build Coastguard Worker if (mProgram == 0)
189*8975f5c5SAndroid Build Coastguard Worker {
190*8975f5c5SAndroid Build Coastguard Worker initBasicProgram();
191*8975f5c5SAndroid Build Coastguard Worker }
192*8975f5c5SAndroid Build Coastguard Worker
193*8975f5c5SAndroid Build Coastguard Worker if (test.source == Source::BUFFER)
194*8975f5c5SAndroid Build Coastguard Worker {
195*8975f5c5SAndroid Build Coastguard Worker GLsizei dataSize = kVertexCount * TypeStride(test.type);
196*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
197*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, dataSize, test.inputData, GL_STATIC_DRAW);
198*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, typeSize, test.type, test.normalized, 0,
199*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<void *>(test.bufferOffset));
200*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
201*8975f5c5SAndroid Build Coastguard Worker }
202*8975f5c5SAndroid Build Coastguard Worker else
203*8975f5c5SAndroid Build Coastguard Worker {
204*8975f5c5SAndroid Build Coastguard Worker ASSERT_EQ(Source::IMMEDIATE, test.source);
205*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
206*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, typeSize, test.type, test.normalized, 0,
207*8975f5c5SAndroid Build Coastguard Worker test.inputData);
208*8975f5c5SAndroid Build Coastguard Worker }
209*8975f5c5SAndroid Build Coastguard Worker
210*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, typeSize, GL_FLOAT, GL_FALSE, 0, test.expectedData);
211*8975f5c5SAndroid Build Coastguard Worker
212*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
213*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mExpectedAttrib);
214*8975f5c5SAndroid Build Coastguard Worker }
215*8975f5c5SAndroid Build Coastguard Worker
checkPixels()216*8975f5c5SAndroid Build Coastguard Worker void checkPixels()
217*8975f5c5SAndroid Build Coastguard Worker {
218*8975f5c5SAndroid Build Coastguard Worker GLint viewportSize[4];
219*8975f5c5SAndroid Build Coastguard Worker glGetIntegerv(GL_VIEWPORT, viewportSize);
220*8975f5c5SAndroid Build Coastguard Worker
221*8975f5c5SAndroid Build Coastguard Worker GLint midPixelX = (viewportSize[0] + viewportSize[2]) / 2;
222*8975f5c5SAndroid Build Coastguard Worker GLint midPixelY = (viewportSize[1] + viewportSize[3]) / 2;
223*8975f5c5SAndroid Build Coastguard Worker
224*8975f5c5SAndroid Build Coastguard Worker // We need to offset our checks from triangle edges to ensure we don't fall on a single tri
225*8975f5c5SAndroid Build Coastguard Worker // Avoid making assumptions of drawQuad with four checks to check the four possible tri
226*8975f5c5SAndroid Build Coastguard Worker // regions
227*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_EQ((midPixelX + viewportSize[0]) / 2, midPixelY, 255, 255, 255, 255);
228*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_EQ((midPixelX + viewportSize[2]) / 2, midPixelY, 255, 255, 255, 255);
229*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_EQ(midPixelX, (midPixelY + viewportSize[1]) / 2, 255, 255, 255, 255);
230*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_EQ(midPixelX, (midPixelY + viewportSize[3]) / 2, 255, 255, 255, 255);
231*8975f5c5SAndroid Build Coastguard Worker }
232*8975f5c5SAndroid Build Coastguard Worker
checkPixelsUnEqual()233*8975f5c5SAndroid Build Coastguard Worker void checkPixelsUnEqual()
234*8975f5c5SAndroid Build Coastguard Worker {
235*8975f5c5SAndroid Build Coastguard Worker GLint viewportSize[4];
236*8975f5c5SAndroid Build Coastguard Worker glGetIntegerv(GL_VIEWPORT, viewportSize);
237*8975f5c5SAndroid Build Coastguard Worker
238*8975f5c5SAndroid Build Coastguard Worker GLint midPixelX = (viewportSize[0] + viewportSize[2]) / 2;
239*8975f5c5SAndroid Build Coastguard Worker GLint midPixelY = (viewportSize[1] + viewportSize[3]) / 2;
240*8975f5c5SAndroid Build Coastguard Worker
241*8975f5c5SAndroid Build Coastguard Worker // We need to offset our checks from triangle edges to ensure we don't fall on a single tri
242*8975f5c5SAndroid Build Coastguard Worker // Avoid making assumptions of drawQuad with four checks to check the four possible tri
243*8975f5c5SAndroid Build Coastguard Worker // regions
244*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_NE((midPixelX + viewportSize[0]) / 2, midPixelY, 255, 255, 255, 255);
245*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_NE((midPixelX + viewportSize[2]) / 2, midPixelY, 255, 255, 255, 255);
246*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_NE(midPixelX, (midPixelY + viewportSize[1]) / 2, 255, 255, 255, 255);
247*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_NE(midPixelX, (midPixelY + viewportSize[3]) / 2, 255, 255, 255, 255);
248*8975f5c5SAndroid Build Coastguard Worker }
249*8975f5c5SAndroid Build Coastguard Worker
runTest(const TestData & test)250*8975f5c5SAndroid Build Coastguard Worker void runTest(const TestData &test) { runTest(test, true); }
251*8975f5c5SAndroid Build Coastguard Worker
runTest(const TestData & test,bool checkPixelEqual)252*8975f5c5SAndroid Build Coastguard Worker void runTest(const TestData &test, bool checkPixelEqual)
253*8975f5c5SAndroid Build Coastguard Worker {
254*8975f5c5SAndroid Build Coastguard Worker // TODO(geofflang): Figure out why this is broken on AMD OpenGL
255*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
256*8975f5c5SAndroid Build Coastguard Worker
257*8975f5c5SAndroid Build Coastguard Worker for (GLint i = 0; i < 4; i++)
258*8975f5c5SAndroid Build Coastguard Worker {
259*8975f5c5SAndroid Build Coastguard Worker GLint typeSize = i + 1;
260*8975f5c5SAndroid Build Coastguard Worker setupTest(test, typeSize);
261*8975f5c5SAndroid Build Coastguard Worker
262*8975f5c5SAndroid Build Coastguard Worker if (test.clearBeforeDraw)
263*8975f5c5SAndroid Build Coastguard Worker {
264*8975f5c5SAndroid Build Coastguard Worker glClear(GL_COLOR_BUFFER_BIT);
265*8975f5c5SAndroid Build Coastguard Worker }
266*8975f5c5SAndroid Build Coastguard Worker
267*8975f5c5SAndroid Build Coastguard Worker drawQuad(mProgram, "position", 0.5f);
268*8975f5c5SAndroid Build Coastguard Worker
269*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(mTestAttrib);
270*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(mExpectedAttrib);
271*8975f5c5SAndroid Build Coastguard Worker
272*8975f5c5SAndroid Build Coastguard Worker if (checkPixelEqual)
273*8975f5c5SAndroid Build Coastguard Worker {
274*8975f5c5SAndroid Build Coastguard Worker checkPixels();
275*8975f5c5SAndroid Build Coastguard Worker }
276*8975f5c5SAndroid Build Coastguard Worker else
277*8975f5c5SAndroid Build Coastguard Worker {
278*8975f5c5SAndroid Build Coastguard Worker checkPixelsUnEqual();
279*8975f5c5SAndroid Build Coastguard Worker }
280*8975f5c5SAndroid Build Coastguard Worker }
281*8975f5c5SAndroid Build Coastguard Worker }
282*8975f5c5SAndroid Build Coastguard Worker
testSetUp()283*8975f5c5SAndroid Build Coastguard Worker void testSetUp() override
284*8975f5c5SAndroid Build Coastguard Worker {
285*8975f5c5SAndroid Build Coastguard Worker glClearColor(0, 0, 0, 0);
286*8975f5c5SAndroid Build Coastguard Worker glClearDepthf(0.0);
287*8975f5c5SAndroid Build Coastguard Worker glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
288*8975f5c5SAndroid Build Coastguard Worker
289*8975f5c5SAndroid Build Coastguard Worker glDisable(GL_DEPTH_TEST);
290*8975f5c5SAndroid Build Coastguard Worker
291*8975f5c5SAndroid Build Coastguard Worker glGenBuffers(1, &mBuffer);
292*8975f5c5SAndroid Build Coastguard Worker }
293*8975f5c5SAndroid Build Coastguard Worker
testTearDown()294*8975f5c5SAndroid Build Coastguard Worker void testTearDown() override
295*8975f5c5SAndroid Build Coastguard Worker {
296*8975f5c5SAndroid Build Coastguard Worker glDeleteProgram(mProgram);
297*8975f5c5SAndroid Build Coastguard Worker glDeleteBuffers(1, &mBuffer);
298*8975f5c5SAndroid Build Coastguard Worker }
299*8975f5c5SAndroid Build Coastguard Worker
compileMultiAttribProgram(GLint attribCount)300*8975f5c5SAndroid Build Coastguard Worker GLuint compileMultiAttribProgram(GLint attribCount)
301*8975f5c5SAndroid Build Coastguard Worker {
302*8975f5c5SAndroid Build Coastguard Worker std::stringstream shaderStream;
303*8975f5c5SAndroid Build Coastguard Worker
304*8975f5c5SAndroid Build Coastguard Worker shaderStream << "attribute mediump vec4 position;" << std::endl;
305*8975f5c5SAndroid Build Coastguard Worker for (GLint attribIndex = 0; attribIndex < attribCount; ++attribIndex)
306*8975f5c5SAndroid Build Coastguard Worker {
307*8975f5c5SAndroid Build Coastguard Worker shaderStream << "attribute float a" << attribIndex << ";" << std::endl;
308*8975f5c5SAndroid Build Coastguard Worker }
309*8975f5c5SAndroid Build Coastguard Worker shaderStream << "varying mediump float color;" << std::endl
310*8975f5c5SAndroid Build Coastguard Worker << "void main() {" << std::endl
311*8975f5c5SAndroid Build Coastguard Worker << " gl_Position = position;" << std::endl
312*8975f5c5SAndroid Build Coastguard Worker << " color = 0.0;" << std::endl;
313*8975f5c5SAndroid Build Coastguard Worker for (GLint attribIndex = 0; attribIndex < attribCount; ++attribIndex)
314*8975f5c5SAndroid Build Coastguard Worker {
315*8975f5c5SAndroid Build Coastguard Worker shaderStream << " color += a" << attribIndex << ";" << std::endl;
316*8975f5c5SAndroid Build Coastguard Worker }
317*8975f5c5SAndroid Build Coastguard Worker shaderStream << "}" << std::endl;
318*8975f5c5SAndroid Build Coastguard Worker
319*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] =
320*8975f5c5SAndroid Build Coastguard Worker "varying mediump float color;\n"
321*8975f5c5SAndroid Build Coastguard Worker "void main(void)\n"
322*8975f5c5SAndroid Build Coastguard Worker "{\n"
323*8975f5c5SAndroid Build Coastguard Worker " gl_FragColor = vec4(color, 0.0, 0.0, 1.0);\n"
324*8975f5c5SAndroid Build Coastguard Worker "}\n";
325*8975f5c5SAndroid Build Coastguard Worker
326*8975f5c5SAndroid Build Coastguard Worker return CompileProgram(shaderStream.str().c_str(), kFS);
327*8975f5c5SAndroid Build Coastguard Worker }
328*8975f5c5SAndroid Build Coastguard Worker
setupMultiAttribs(GLuint program,GLint attribCount,GLfloat value)329*8975f5c5SAndroid Build Coastguard Worker void setupMultiAttribs(GLuint program, GLint attribCount, GLfloat value)
330*8975f5c5SAndroid Build Coastguard Worker {
331*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
332*8975f5c5SAndroid Build Coastguard Worker for (GLint attribIndex = 0; attribIndex < attribCount; ++attribIndex)
333*8975f5c5SAndroid Build Coastguard Worker {
334*8975f5c5SAndroid Build Coastguard Worker std::stringstream attribStream;
335*8975f5c5SAndroid Build Coastguard Worker attribStream << "a" << attribIndex;
336*8975f5c5SAndroid Build Coastguard Worker GLint location = glGetAttribLocation(program, attribStream.str().c_str());
337*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, location);
338*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib1f(location, value);
339*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(location);
340*8975f5c5SAndroid Build Coastguard Worker }
341*8975f5c5SAndroid Build Coastguard Worker }
342*8975f5c5SAndroid Build Coastguard Worker
initBasicProgram()343*8975f5c5SAndroid Build Coastguard Worker void initBasicProgram()
344*8975f5c5SAndroid Build Coastguard Worker {
345*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] =
346*8975f5c5SAndroid Build Coastguard Worker "attribute mediump vec4 position;\n"
347*8975f5c5SAndroid Build Coastguard Worker "attribute highp vec4 test;\n"
348*8975f5c5SAndroid Build Coastguard Worker "attribute highp vec4 expected;\n"
349*8975f5c5SAndroid Build Coastguard Worker "varying mediump vec4 color;\n"
350*8975f5c5SAndroid Build Coastguard Worker "void main(void)\n"
351*8975f5c5SAndroid Build Coastguard Worker "{\n"
352*8975f5c5SAndroid Build Coastguard Worker " gl_Position = position;\n"
353*8975f5c5SAndroid Build Coastguard Worker " vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);\n"
354*8975f5c5SAndroid Build Coastguard Worker " color = vec4(lessThanEqual(abs(test - expected), threshold));\n"
355*8975f5c5SAndroid Build Coastguard Worker "}\n";
356*8975f5c5SAndroid Build Coastguard Worker
357*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] =
358*8975f5c5SAndroid Build Coastguard Worker "varying mediump vec4 color;\n"
359*8975f5c5SAndroid Build Coastguard Worker "void main(void)\n"
360*8975f5c5SAndroid Build Coastguard Worker "{\n"
361*8975f5c5SAndroid Build Coastguard Worker " gl_FragColor = color;\n"
362*8975f5c5SAndroid Build Coastguard Worker "}\n";
363*8975f5c5SAndroid Build Coastguard Worker
364*8975f5c5SAndroid Build Coastguard Worker mProgram = CompileProgram(kVS, kFS);
365*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(0u, mProgram);
366*8975f5c5SAndroid Build Coastguard Worker
367*8975f5c5SAndroid Build Coastguard Worker mTestAttrib = glGetAttribLocation(mProgram, "test");
368*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, mTestAttrib);
369*8975f5c5SAndroid Build Coastguard Worker mExpectedAttrib = glGetAttribLocation(mProgram, "expected");
370*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, mExpectedAttrib);
371*8975f5c5SAndroid Build Coastguard Worker
372*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
373*8975f5c5SAndroid Build Coastguard Worker }
374*8975f5c5SAndroid Build Coastguard Worker
375*8975f5c5SAndroid Build Coastguard Worker static constexpr size_t kVertexCount = 24;
376*8975f5c5SAndroid Build Coastguard Worker
InitTestData(std::array<GLfloat,kVertexCount> & inputData,std::array<GLfloat,kVertexCount> & expectedData)377*8975f5c5SAndroid Build Coastguard Worker static void InitTestData(std::array<GLfloat, kVertexCount> &inputData,
378*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> &expectedData)
379*8975f5c5SAndroid Build Coastguard Worker {
380*8975f5c5SAndroid Build Coastguard Worker for (size_t count = 0; count < kVertexCount; ++count)
381*8975f5c5SAndroid Build Coastguard Worker {
382*8975f5c5SAndroid Build Coastguard Worker inputData[count] = static_cast<GLfloat>(count);
383*8975f5c5SAndroid Build Coastguard Worker expectedData[count] = inputData[count];
384*8975f5c5SAndroid Build Coastguard Worker }
385*8975f5c5SAndroid Build Coastguard Worker }
386*8975f5c5SAndroid Build Coastguard Worker
InitQuadVertexBuffer(GLBuffer * buffer)387*8975f5c5SAndroid Build Coastguard Worker static void InitQuadVertexBuffer(GLBuffer *buffer)
388*8975f5c5SAndroid Build Coastguard Worker {
389*8975f5c5SAndroid Build Coastguard Worker auto quadVertices = GetQuadVertices();
390*8975f5c5SAndroid Build Coastguard Worker GLsizei quadVerticesSize =
391*8975f5c5SAndroid Build Coastguard Worker static_cast<GLsizei>(quadVertices.size() * sizeof(quadVertices[0]));
392*8975f5c5SAndroid Build Coastguard Worker
393*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, *buffer);
394*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, quadVerticesSize, nullptr, GL_STATIC_DRAW);
395*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ARRAY_BUFFER, 0, quadVerticesSize, quadVertices.data());
396*8975f5c5SAndroid Build Coastguard Worker }
397*8975f5c5SAndroid Build Coastguard Worker
InitQuadPlusOneVertexBuffer(GLBuffer * buffer)398*8975f5c5SAndroid Build Coastguard Worker static void InitQuadPlusOneVertexBuffer(GLBuffer *buffer)
399*8975f5c5SAndroid Build Coastguard Worker {
400*8975f5c5SAndroid Build Coastguard Worker auto quadVertices = GetQuadVertices();
401*8975f5c5SAndroid Build Coastguard Worker GLsizei quadVerticesSize =
402*8975f5c5SAndroid Build Coastguard Worker static_cast<GLsizei>(quadVertices.size() * sizeof(quadVertices[0]));
403*8975f5c5SAndroid Build Coastguard Worker
404*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, *buffer);
405*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, quadVerticesSize + sizeof(Vector3), nullptr, GL_STATIC_DRAW);
406*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ARRAY_BUFFER, 0, quadVerticesSize, quadVertices.data());
407*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ARRAY_BUFFER, quadVerticesSize, sizeof(Vector3), &quadVertices[0]);
408*8975f5c5SAndroid Build Coastguard Worker }
409*8975f5c5SAndroid Build Coastguard Worker
410*8975f5c5SAndroid Build Coastguard Worker GLuint mProgram;
411*8975f5c5SAndroid Build Coastguard Worker GLint mTestAttrib;
412*8975f5c5SAndroid Build Coastguard Worker GLint mExpectedAttrib;
413*8975f5c5SAndroid Build Coastguard Worker GLuint mBuffer;
414*8975f5c5SAndroid Build Coastguard Worker };
415*8975f5c5SAndroid Build Coastguard Worker
TEST_P(VertexAttributeTest,UnsignedByteUnnormalized)416*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, UnsignedByteUnnormalized)
417*8975f5c5SAndroid Build Coastguard Worker {
418*8975f5c5SAndroid Build Coastguard Worker std::array<GLubyte, kVertexCount> inputData = {
419*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, 4, 5, 6, 7, 125, 126, 127, 128, 129, 250, 251, 252, 253, 254, 255}};
420*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
421*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
422*8975f5c5SAndroid Build Coastguard Worker {
423*8975f5c5SAndroid Build Coastguard Worker expectedData[i] = inputData[i];
424*8975f5c5SAndroid Build Coastguard Worker }
425*8975f5c5SAndroid Build Coastguard Worker
426*8975f5c5SAndroid Build Coastguard Worker TestData data(GL_UNSIGNED_BYTE, GL_FALSE, Source::IMMEDIATE, inputData.data(),
427*8975f5c5SAndroid Build Coastguard Worker expectedData.data());
428*8975f5c5SAndroid Build Coastguard Worker runTest(data);
429*8975f5c5SAndroid Build Coastguard Worker }
430*8975f5c5SAndroid Build Coastguard Worker
TEST_P(VertexAttributeTest,UnsignedByteNormalized)431*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, UnsignedByteNormalized)
432*8975f5c5SAndroid Build Coastguard Worker {
433*8975f5c5SAndroid Build Coastguard Worker std::array<GLubyte, kVertexCount> inputData = {
434*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, 4, 5, 6, 7, 125, 126, 127, 128, 129, 250, 251, 252, 253, 254, 255}};
435*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
436*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
437*8975f5c5SAndroid Build Coastguard Worker {
438*8975f5c5SAndroid Build Coastguard Worker expectedData[i] = Normalize(inputData[i]);
439*8975f5c5SAndroid Build Coastguard Worker }
440*8975f5c5SAndroid Build Coastguard Worker
441*8975f5c5SAndroid Build Coastguard Worker TestData data(GL_UNSIGNED_BYTE, GL_TRUE, Source::IMMEDIATE, inputData.data(),
442*8975f5c5SAndroid Build Coastguard Worker expectedData.data());
443*8975f5c5SAndroid Build Coastguard Worker runTest(data);
444*8975f5c5SAndroid Build Coastguard Worker }
445*8975f5c5SAndroid Build Coastguard Worker
TEST_P(VertexAttributeTest,ByteUnnormalized)446*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, ByteUnnormalized)
447*8975f5c5SAndroid Build Coastguard Worker {
448*8975f5c5SAndroid Build Coastguard Worker std::array<GLbyte, kVertexCount> inputData = {
449*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, 4, -1, -2, -3, -4, 125, 126, 127, -128, -127, -126}};
450*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
451*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
452*8975f5c5SAndroid Build Coastguard Worker {
453*8975f5c5SAndroid Build Coastguard Worker expectedData[i] = inputData[i];
454*8975f5c5SAndroid Build Coastguard Worker }
455*8975f5c5SAndroid Build Coastguard Worker
456*8975f5c5SAndroid Build Coastguard Worker TestData data(GL_BYTE, GL_FALSE, Source::IMMEDIATE, inputData.data(), expectedData.data());
457*8975f5c5SAndroid Build Coastguard Worker runTest(data);
458*8975f5c5SAndroid Build Coastguard Worker }
459*8975f5c5SAndroid Build Coastguard Worker
TEST_P(VertexAttributeTest,ByteNormalized)460*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, ByteNormalized)
461*8975f5c5SAndroid Build Coastguard Worker {
462*8975f5c5SAndroid Build Coastguard Worker std::array<GLbyte, kVertexCount> inputData = {
463*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, 4, -1, -2, -3, -4, 125, 126, 127, -128, -127, -126}};
464*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
465*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
466*8975f5c5SAndroid Build Coastguard Worker {
467*8975f5c5SAndroid Build Coastguard Worker expectedData[i] = Normalize(inputData[i]);
468*8975f5c5SAndroid Build Coastguard Worker }
469*8975f5c5SAndroid Build Coastguard Worker
470*8975f5c5SAndroid Build Coastguard Worker TestData data(GL_BYTE, GL_TRUE, Source::IMMEDIATE, inputData.data(), expectedData.data());
471*8975f5c5SAndroid Build Coastguard Worker runTest(data);
472*8975f5c5SAndroid Build Coastguard Worker }
473*8975f5c5SAndroid Build Coastguard Worker
TEST_P(VertexAttributeTest,UnsignedShortUnnormalized)474*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, UnsignedShortUnnormalized)
475*8975f5c5SAndroid Build Coastguard Worker {
476*8975f5c5SAndroid Build Coastguard Worker std::array<GLushort, kVertexCount> inputData = {
477*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, 254, 255, 256, 32766, 32767, 32768, 65533, 65534, 65535}};
478*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
479*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
480*8975f5c5SAndroid Build Coastguard Worker {
481*8975f5c5SAndroid Build Coastguard Worker expectedData[i] = inputData[i];
482*8975f5c5SAndroid Build Coastguard Worker }
483*8975f5c5SAndroid Build Coastguard Worker
484*8975f5c5SAndroid Build Coastguard Worker TestData data(GL_UNSIGNED_SHORT, GL_FALSE, Source::IMMEDIATE, inputData.data(),
485*8975f5c5SAndroid Build Coastguard Worker expectedData.data());
486*8975f5c5SAndroid Build Coastguard Worker runTest(data);
487*8975f5c5SAndroid Build Coastguard Worker }
488*8975f5c5SAndroid Build Coastguard Worker
TEST_P(VertexAttributeTest,UnsignedShortNormalized)489*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, UnsignedShortNormalized)
490*8975f5c5SAndroid Build Coastguard Worker {
491*8975f5c5SAndroid Build Coastguard Worker std::array<GLushort, kVertexCount> inputData = {
492*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, 254, 255, 256, 32766, 32767, 32768, 65533, 65534, 65535}};
493*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
494*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
495*8975f5c5SAndroid Build Coastguard Worker {
496*8975f5c5SAndroid Build Coastguard Worker expectedData[i] = Normalize(inputData[i]);
497*8975f5c5SAndroid Build Coastguard Worker }
498*8975f5c5SAndroid Build Coastguard Worker
499*8975f5c5SAndroid Build Coastguard Worker TestData data(GL_UNSIGNED_SHORT, GL_TRUE, Source::IMMEDIATE, inputData.data(),
500*8975f5c5SAndroid Build Coastguard Worker expectedData.data());
501*8975f5c5SAndroid Build Coastguard Worker runTest(data);
502*8975f5c5SAndroid Build Coastguard Worker }
503*8975f5c5SAndroid Build Coastguard Worker
TEST_P(VertexAttributeTest,ShortUnnormalized)504*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, ShortUnnormalized)
505*8975f5c5SAndroid Build Coastguard Worker {
506*8975f5c5SAndroid Build Coastguard Worker std::array<GLshort, kVertexCount> inputData = {
507*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, -1, -2, -3, -4, 32766, 32767, -32768, -32767, -32766}};
508*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
509*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
510*8975f5c5SAndroid Build Coastguard Worker {
511*8975f5c5SAndroid Build Coastguard Worker expectedData[i] = inputData[i];
512*8975f5c5SAndroid Build Coastguard Worker }
513*8975f5c5SAndroid Build Coastguard Worker
514*8975f5c5SAndroid Build Coastguard Worker TestData data(GL_SHORT, GL_FALSE, Source::IMMEDIATE, inputData.data(), expectedData.data());
515*8975f5c5SAndroid Build Coastguard Worker runTest(data);
516*8975f5c5SAndroid Build Coastguard Worker }
517*8975f5c5SAndroid Build Coastguard Worker
TEST_P(VertexAttributeTest,ShortNormalized)518*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, ShortNormalized)
519*8975f5c5SAndroid Build Coastguard Worker {
520*8975f5c5SAndroid Build Coastguard Worker std::array<GLshort, kVertexCount> inputData = {
521*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, -1, -2, -3, -4, 32766, 32767, -32768, -32767, -32766}};
522*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
523*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
524*8975f5c5SAndroid Build Coastguard Worker {
525*8975f5c5SAndroid Build Coastguard Worker expectedData[i] = Normalize(inputData[i]);
526*8975f5c5SAndroid Build Coastguard Worker }
527*8975f5c5SAndroid Build Coastguard Worker
528*8975f5c5SAndroid Build Coastguard Worker TestData data(GL_SHORT, GL_TRUE, Source::IMMEDIATE, inputData.data(), expectedData.data());
529*8975f5c5SAndroid Build Coastguard Worker runTest(data);
530*8975f5c5SAndroid Build Coastguard Worker }
531*8975f5c5SAndroid Build Coastguard Worker
532*8975f5c5SAndroid Build Coastguard Worker // Verify that vertex data is updated correctly when using a float/half-float client memory pointer.
TEST_P(VertexAttributeTest,HalfFloatClientMemoryPointer)533*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, HalfFloatClientMemoryPointer)
534*8975f5c5SAndroid Build Coastguard Worker {
535*8975f5c5SAndroid Build Coastguard Worker std::array<GLhalf, kVertexCount> inputData;
536*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData = {
537*8975f5c5SAndroid Build Coastguard Worker {0.f, 1.5f, 2.3f, 3.2f, -1.8f, -2.2f, -3.9f, -4.f, 34.5f, 32.2f, -78.8f, -77.4f, -76.1f}};
538*8975f5c5SAndroid Build Coastguard Worker
539*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
540*8975f5c5SAndroid Build Coastguard Worker {
541*8975f5c5SAndroid Build Coastguard Worker inputData[i] = gl::float32ToFloat16(expectedData[i]);
542*8975f5c5SAndroid Build Coastguard Worker }
543*8975f5c5SAndroid Build Coastguard Worker
544*8975f5c5SAndroid Build Coastguard Worker // If the extension is enabled run the test on all contexts
545*8975f5c5SAndroid Build Coastguard Worker if (IsGLExtensionEnabled("GL_OES_vertex_half_float"))
546*8975f5c5SAndroid Build Coastguard Worker {
547*8975f5c5SAndroid Build Coastguard Worker TestData imediateData(GL_HALF_FLOAT_OES, GL_FALSE, Source::IMMEDIATE, inputData.data(),
548*8975f5c5SAndroid Build Coastguard Worker expectedData.data());
549*8975f5c5SAndroid Build Coastguard Worker runTest(imediateData);
550*8975f5c5SAndroid Build Coastguard Worker }
551*8975f5c5SAndroid Build Coastguard Worker // Otherwise run the test only if it is an ES3 context
552*8975f5c5SAndroid Build Coastguard Worker else if (getClientMajorVersion() >= 3)
553*8975f5c5SAndroid Build Coastguard Worker {
554*8975f5c5SAndroid Build Coastguard Worker TestData imediateData(GL_HALF_FLOAT, GL_FALSE, Source::IMMEDIATE, inputData.data(),
555*8975f5c5SAndroid Build Coastguard Worker expectedData.data());
556*8975f5c5SAndroid Build Coastguard Worker runTest(imediateData);
557*8975f5c5SAndroid Build Coastguard Worker }
558*8975f5c5SAndroid Build Coastguard Worker }
559*8975f5c5SAndroid Build Coastguard Worker
560*8975f5c5SAndroid Build Coastguard Worker // Verify that vertex data is updated correctly when using a float/half-float buffer.
TEST_P(VertexAttributeTest,HalfFloatBuffer)561*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, HalfFloatBuffer)
562*8975f5c5SAndroid Build Coastguard Worker {
563*8975f5c5SAndroid Build Coastguard Worker std::array<GLhalf, kVertexCount> inputData;
564*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData = {
565*8975f5c5SAndroid Build Coastguard Worker {0.f, 1.5f, 2.3f, 3.2f, -1.8f, -2.2f, -3.9f, -4.f, 34.5f, 32.2f, -78.8f, -77.4f, -76.1f}};
566*8975f5c5SAndroid Build Coastguard Worker
567*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
568*8975f5c5SAndroid Build Coastguard Worker {
569*8975f5c5SAndroid Build Coastguard Worker inputData[i] = gl::float32ToFloat16(expectedData[i]);
570*8975f5c5SAndroid Build Coastguard Worker }
571*8975f5c5SAndroid Build Coastguard Worker
572*8975f5c5SAndroid Build Coastguard Worker // If the extension is enabled run the test on all contexts
573*8975f5c5SAndroid Build Coastguard Worker if (IsGLExtensionEnabled("GL_OES_vertex_half_float"))
574*8975f5c5SAndroid Build Coastguard Worker {
575*8975f5c5SAndroid Build Coastguard Worker TestData bufferData(GL_HALF_FLOAT_OES, GL_FALSE, Source::BUFFER, inputData.data(),
576*8975f5c5SAndroid Build Coastguard Worker expectedData.data());
577*8975f5c5SAndroid Build Coastguard Worker runTest(bufferData);
578*8975f5c5SAndroid Build Coastguard Worker }
579*8975f5c5SAndroid Build Coastguard Worker // Otherwise run the test only if it is an ES3 context
580*8975f5c5SAndroid Build Coastguard Worker else if (getClientMajorVersion() >= 3)
581*8975f5c5SAndroid Build Coastguard Worker {
582*8975f5c5SAndroid Build Coastguard Worker TestData bufferData(GL_HALF_FLOAT, GL_FALSE, Source::BUFFER, inputData.data(),
583*8975f5c5SAndroid Build Coastguard Worker expectedData.data());
584*8975f5c5SAndroid Build Coastguard Worker runTest(bufferData);
585*8975f5c5SAndroid Build Coastguard Worker }
586*8975f5c5SAndroid Build Coastguard Worker }
587*8975f5c5SAndroid Build Coastguard Worker
588*8975f5c5SAndroid Build Coastguard Worker // Verify that using the same client memory pointer in different format won't mess up the draw.
TEST_P(VertexAttributeTest,UsingDifferentFormatAndSameClientMemoryPointer)589*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, UsingDifferentFormatAndSameClientMemoryPointer)
590*8975f5c5SAndroid Build Coastguard Worker {
591*8975f5c5SAndroid Build Coastguard Worker std::array<GLshort, kVertexCount> inputData = {
592*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, -1, -2, -3, -4, 32766, 32767, -32768, -32767, -32766}};
593*8975f5c5SAndroid Build Coastguard Worker
594*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> unnormalizedExpectedData;
595*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
596*8975f5c5SAndroid Build Coastguard Worker {
597*8975f5c5SAndroid Build Coastguard Worker unnormalizedExpectedData[i] = inputData[i];
598*8975f5c5SAndroid Build Coastguard Worker }
599*8975f5c5SAndroid Build Coastguard Worker
600*8975f5c5SAndroid Build Coastguard Worker TestData unnormalizedData(GL_SHORT, GL_FALSE, Source::IMMEDIATE, inputData.data(),
601*8975f5c5SAndroid Build Coastguard Worker unnormalizedExpectedData.data());
602*8975f5c5SAndroid Build Coastguard Worker runTest(unnormalizedData);
603*8975f5c5SAndroid Build Coastguard Worker
604*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> normalizedExpectedData;
605*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
606*8975f5c5SAndroid Build Coastguard Worker {
607*8975f5c5SAndroid Build Coastguard Worker inputData[i] = -inputData[i];
608*8975f5c5SAndroid Build Coastguard Worker normalizedExpectedData[i] = Normalize(inputData[i]);
609*8975f5c5SAndroid Build Coastguard Worker }
610*8975f5c5SAndroid Build Coastguard Worker
611*8975f5c5SAndroid Build Coastguard Worker TestData normalizedData(GL_SHORT, GL_TRUE, Source::IMMEDIATE, inputData.data(),
612*8975f5c5SAndroid Build Coastguard Worker normalizedExpectedData.data());
613*8975f5c5SAndroid Build Coastguard Worker runTest(normalizedData);
614*8975f5c5SAndroid Build Coastguard Worker }
615*8975f5c5SAndroid Build Coastguard Worker
616*8975f5c5SAndroid Build Coastguard Worker // Verify that vertex format is updated correctly when the client memory pointer is same.
TEST_P(VertexAttributeTest,NegativeUsingDifferentFormatAndSameClientMemoryPointer)617*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, NegativeUsingDifferentFormatAndSameClientMemoryPointer)
618*8975f5c5SAndroid Build Coastguard Worker {
619*8975f5c5SAndroid Build Coastguard Worker std::array<GLshort, kVertexCount> inputData = {
620*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, -1, -2, -3, -4, 32766, 32767, -32768, -32767, -32766}};
621*8975f5c5SAndroid Build Coastguard Worker
622*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> unnormalizedExpectedData;
623*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
624*8975f5c5SAndroid Build Coastguard Worker {
625*8975f5c5SAndroid Build Coastguard Worker unnormalizedExpectedData[i] = inputData[i];
626*8975f5c5SAndroid Build Coastguard Worker }
627*8975f5c5SAndroid Build Coastguard Worker
628*8975f5c5SAndroid Build Coastguard Worker // Use unnormalized short as the format of the data in client memory pointer in the first draw.
629*8975f5c5SAndroid Build Coastguard Worker TestData unnormalizedData(GL_SHORT, GL_FALSE, Source::IMMEDIATE, inputData.data(),
630*8975f5c5SAndroid Build Coastguard Worker unnormalizedExpectedData.data());
631*8975f5c5SAndroid Build Coastguard Worker runTest(unnormalizedData);
632*8975f5c5SAndroid Build Coastguard Worker
633*8975f5c5SAndroid Build Coastguard Worker // Use normalized short as the format of the data in client memory pointer in the second draw,
634*8975f5c5SAndroid Build Coastguard Worker // but mExpectedAttrib is the same as the first draw.
635*8975f5c5SAndroid Build Coastguard Worker TestData normalizedData(GL_SHORT, GL_TRUE, Source::IMMEDIATE, inputData.data(),
636*8975f5c5SAndroid Build Coastguard Worker unnormalizedExpectedData.data());
637*8975f5c5SAndroid Build Coastguard Worker runTest(normalizedData, false);
638*8975f5c5SAndroid Build Coastguard Worker }
639*8975f5c5SAndroid Build Coastguard Worker
640*8975f5c5SAndroid Build Coastguard Worker // Verify that using different vertex format and same buffer won't mess up the draw.
TEST_P(VertexAttributeTest,UsingDifferentFormatAndSameBuffer)641*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, UsingDifferentFormatAndSameBuffer)
642*8975f5c5SAndroid Build Coastguard Worker {
643*8975f5c5SAndroid Build Coastguard Worker std::array<GLshort, kVertexCount> inputData = {
644*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, -1, -2, -3, -4, 32766, 32767, -32768, -32767, -32766}};
645*8975f5c5SAndroid Build Coastguard Worker
646*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> unnormalizedExpectedData;
647*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> normalizedExpectedData;
648*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
649*8975f5c5SAndroid Build Coastguard Worker {
650*8975f5c5SAndroid Build Coastguard Worker unnormalizedExpectedData[i] = inputData[i];
651*8975f5c5SAndroid Build Coastguard Worker normalizedExpectedData[i] = Normalize(inputData[i]);
652*8975f5c5SAndroid Build Coastguard Worker }
653*8975f5c5SAndroid Build Coastguard Worker
654*8975f5c5SAndroid Build Coastguard Worker // Use unnormalized short as the format of the data in mBuffer in the first draw.
655*8975f5c5SAndroid Build Coastguard Worker TestData unnormalizedData(GL_SHORT, GL_FALSE, Source::BUFFER, inputData.data(),
656*8975f5c5SAndroid Build Coastguard Worker unnormalizedExpectedData.data());
657*8975f5c5SAndroid Build Coastguard Worker runTest(unnormalizedData);
658*8975f5c5SAndroid Build Coastguard Worker
659*8975f5c5SAndroid Build Coastguard Worker // Use normalized short as the format of the data in mBuffer in the second draw.
660*8975f5c5SAndroid Build Coastguard Worker TestData normalizedData(GL_SHORT, GL_TRUE, Source::BUFFER, inputData.data(),
661*8975f5c5SAndroid Build Coastguard Worker normalizedExpectedData.data());
662*8975f5c5SAndroid Build Coastguard Worker runTest(normalizedData);
663*8975f5c5SAndroid Build Coastguard Worker }
664*8975f5c5SAndroid Build Coastguard Worker
665*8975f5c5SAndroid Build Coastguard Worker // Verify that vertex format is updated correctly when the buffer is same.
TEST_P(VertexAttributeTest,NegativeUsingDifferentFormatAndSameBuffer)666*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, NegativeUsingDifferentFormatAndSameBuffer)
667*8975f5c5SAndroid Build Coastguard Worker {
668*8975f5c5SAndroid Build Coastguard Worker std::array<GLshort, kVertexCount> inputData = {
669*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, -1, -2, -3, -4, 32766, 32767, -32768, -32767, -32766}};
670*8975f5c5SAndroid Build Coastguard Worker
671*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> unnormalizedExpectedData;
672*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
673*8975f5c5SAndroid Build Coastguard Worker {
674*8975f5c5SAndroid Build Coastguard Worker unnormalizedExpectedData[i] = inputData[i];
675*8975f5c5SAndroid Build Coastguard Worker }
676*8975f5c5SAndroid Build Coastguard Worker
677*8975f5c5SAndroid Build Coastguard Worker // Use unnormalized short as the format of the data in mBuffer in the first draw.
678*8975f5c5SAndroid Build Coastguard Worker TestData unnormalizedData(GL_SHORT, GL_FALSE, Source::BUFFER, inputData.data(),
679*8975f5c5SAndroid Build Coastguard Worker unnormalizedExpectedData.data());
680*8975f5c5SAndroid Build Coastguard Worker runTest(unnormalizedData);
681*8975f5c5SAndroid Build Coastguard Worker
682*8975f5c5SAndroid Build Coastguard Worker // Use normalized short as the format of the data in mBuffer in the second draw, but
683*8975f5c5SAndroid Build Coastguard Worker // mExpectedAttrib is the same as the first draw.
684*8975f5c5SAndroid Build Coastguard Worker TestData normalizedData(GL_SHORT, GL_TRUE, Source::BUFFER, inputData.data(),
685*8975f5c5SAndroid Build Coastguard Worker unnormalizedExpectedData.data());
686*8975f5c5SAndroid Build Coastguard Worker
687*8975f5c5SAndroid Build Coastguard Worker // The check should fail because the test data is changed while the expected data is the same.
688*8975f5c5SAndroid Build Coastguard Worker runTest(normalizedData, false);
689*8975f5c5SAndroid Build Coastguard Worker }
690*8975f5c5SAndroid Build Coastguard Worker
691*8975f5c5SAndroid Build Coastguard Worker // Verify that mixed using buffer and client memory pointer won't mess up the draw.
TEST_P(VertexAttributeTest,MixedUsingBufferAndClientMemoryPointer)692*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, MixedUsingBufferAndClientMemoryPointer)
693*8975f5c5SAndroid Build Coastguard Worker {
694*8975f5c5SAndroid Build Coastguard Worker std::array<GLshort, kVertexCount> inputData = {
695*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, -1, -2, -3, -4, 32766, 32767, -32768, -32767, -32766}};
696*8975f5c5SAndroid Build Coastguard Worker
697*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> unnormalizedExpectedData;
698*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> normalizedExpectedData;
699*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
700*8975f5c5SAndroid Build Coastguard Worker {
701*8975f5c5SAndroid Build Coastguard Worker unnormalizedExpectedData[i] = inputData[i];
702*8975f5c5SAndroid Build Coastguard Worker normalizedExpectedData[i] = Normalize(inputData[i]);
703*8975f5c5SAndroid Build Coastguard Worker }
704*8975f5c5SAndroid Build Coastguard Worker
705*8975f5c5SAndroid Build Coastguard Worker TestData unnormalizedData(GL_SHORT, GL_FALSE, Source::IMMEDIATE, inputData.data(),
706*8975f5c5SAndroid Build Coastguard Worker unnormalizedExpectedData.data());
707*8975f5c5SAndroid Build Coastguard Worker runTest(unnormalizedData);
708*8975f5c5SAndroid Build Coastguard Worker
709*8975f5c5SAndroid Build Coastguard Worker TestData unnormalizedBufferData(GL_SHORT, GL_FALSE, Source::BUFFER, inputData.data(),
710*8975f5c5SAndroid Build Coastguard Worker unnormalizedExpectedData.data());
711*8975f5c5SAndroid Build Coastguard Worker runTest(unnormalizedBufferData);
712*8975f5c5SAndroid Build Coastguard Worker
713*8975f5c5SAndroid Build Coastguard Worker TestData normalizedData(GL_SHORT, GL_TRUE, Source::IMMEDIATE, inputData.data(),
714*8975f5c5SAndroid Build Coastguard Worker normalizedExpectedData.data());
715*8975f5c5SAndroid Build Coastguard Worker runTest(normalizedData);
716*8975f5c5SAndroid Build Coastguard Worker }
717*8975f5c5SAndroid Build Coastguard Worker
718*8975f5c5SAndroid Build Coastguard Worker // Verify signed unnormalized INT_10_10_10_2 vertex type
TEST_P(VertexAttributeTest,SignedPacked1010102ExtensionUnnormalized)719*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, SignedPacked1010102ExtensionUnnormalized)
720*8975f5c5SAndroid Build Coastguard Worker {
721*8975f5c5SAndroid Build Coastguard Worker std::string extensionList(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
722*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF((extensionList.find("OES_vertex_type_10_10_10_2") == std::string::npos));
723*8975f5c5SAndroid Build Coastguard Worker
724*8975f5c5SAndroid Build Coastguard Worker // RGB channels are 10-bits, alpha is 2-bits
725*8975f5c5SAndroid Build Coastguard Worker std::array<std::array<GLshort, 4>, kVertexCount / 4> unpackedInput = {{{0, 1, 2, 0},
726*8975f5c5SAndroid Build Coastguard Worker {254, 255, 256, 1},
727*8975f5c5SAndroid Build Coastguard Worker {256, 255, 254, -2},
728*8975f5c5SAndroid Build Coastguard Worker {511, 510, 509, -1},
729*8975f5c5SAndroid Build Coastguard Worker {-512, -511, -500, -2},
730*8975f5c5SAndroid Build Coastguard Worker {-1, -2, -3, 1}}};
731*8975f5c5SAndroid Build Coastguard Worker
732*8975f5c5SAndroid Build Coastguard Worker std::array<GLint, kVertexCount> packedInput;
733*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedTypeSize4;
734*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedTypeSize3;
735*8975f5c5SAndroid Build Coastguard Worker
736*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount / 4; i++)
737*8975f5c5SAndroid Build Coastguard Worker {
738*8975f5c5SAndroid Build Coastguard Worker packedInput[i] = Pack1010102<GLint, GLshort>(unpackedInput[i]);
739*8975f5c5SAndroid Build Coastguard Worker
740*8975f5c5SAndroid Build Coastguard Worker expectedTypeSize3[i * 3 + 0] = expectedTypeSize4[i * 4 + 0] = unpackedInput[i][0];
741*8975f5c5SAndroid Build Coastguard Worker expectedTypeSize3[i * 3 + 1] = expectedTypeSize4[i * 4 + 1] = unpackedInput[i][1];
742*8975f5c5SAndroid Build Coastguard Worker expectedTypeSize3[i * 3 + 2] = expectedTypeSize4[i * 4 + 2] = unpackedInput[i][2];
743*8975f5c5SAndroid Build Coastguard Worker
744*8975f5c5SAndroid Build Coastguard Worker // when the type size is 3, alpha will be 1.0f by GLES driver
745*8975f5c5SAndroid Build Coastguard Worker expectedTypeSize4[i * 4 + 3] = unpackedInput[i][3];
746*8975f5c5SAndroid Build Coastguard Worker }
747*8975f5c5SAndroid Build Coastguard Worker
748*8975f5c5SAndroid Build Coastguard Worker TestData data4(GL_INT_10_10_10_2_OES, GL_FALSE, Source::IMMEDIATE, packedInput.data(),
749*8975f5c5SAndroid Build Coastguard Worker expectedTypeSize4.data());
750*8975f5c5SAndroid Build Coastguard Worker TestData bufferedData4(GL_INT_10_10_10_2_OES, GL_FALSE, Source::BUFFER, packedInput.data(),
751*8975f5c5SAndroid Build Coastguard Worker expectedTypeSize4.data());
752*8975f5c5SAndroid Build Coastguard Worker TestData data3(GL_INT_10_10_10_2_OES, GL_FALSE, Source::IMMEDIATE, packedInput.data(),
753*8975f5c5SAndroid Build Coastguard Worker expectedTypeSize3.data());
754*8975f5c5SAndroid Build Coastguard Worker TestData bufferedData3(GL_INT_10_10_10_2_OES, GL_FALSE, Source::BUFFER, packedInput.data(),
755*8975f5c5SAndroid Build Coastguard Worker expectedTypeSize3.data());
756*8975f5c5SAndroid Build Coastguard Worker
757*8975f5c5SAndroid Build Coastguard Worker std::array<std::pair<const TestData &, GLint>, 4> dataSet = {
758*8975f5c5SAndroid Build Coastguard Worker {{data4, 4}, {bufferedData4, 4}, {data3, 3}, {bufferedData3, 3}}};
759*8975f5c5SAndroid Build Coastguard Worker
760*8975f5c5SAndroid Build Coastguard Worker for (auto data : dataSet)
761*8975f5c5SAndroid Build Coastguard Worker {
762*8975f5c5SAndroid Build Coastguard Worker setupTest(data.first, data.second);
763*8975f5c5SAndroid Build Coastguard Worker drawQuad(mProgram, "position", 0.5f);
764*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(mTestAttrib);
765*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(mExpectedAttrib);
766*8975f5c5SAndroid Build Coastguard Worker checkPixels();
767*8975f5c5SAndroid Build Coastguard Worker }
768*8975f5c5SAndroid Build Coastguard Worker }
769*8975f5c5SAndroid Build Coastguard Worker
770*8975f5c5SAndroid Build Coastguard Worker // Verify signed normalized INT_10_10_10_2 vertex type
TEST_P(VertexAttributeTest,SignedPacked1010102ExtensionNormalized)771*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, SignedPacked1010102ExtensionNormalized)
772*8975f5c5SAndroid Build Coastguard Worker {
773*8975f5c5SAndroid Build Coastguard Worker std::string extensionList(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
774*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF((extensionList.find("OES_vertex_type_10_10_10_2") == std::string::npos));
775*8975f5c5SAndroid Build Coastguard Worker
776*8975f5c5SAndroid Build Coastguard Worker // RGB channels are 10-bits, alpha is 2-bits
777*8975f5c5SAndroid Build Coastguard Worker std::array<std::array<GLshort, 4>, kVertexCount / 4> unpackedInput = {{{0, 1, 2, 0},
778*8975f5c5SAndroid Build Coastguard Worker {254, 255, 256, 1},
779*8975f5c5SAndroid Build Coastguard Worker {256, 255, 254, -2},
780*8975f5c5SAndroid Build Coastguard Worker {511, 510, 509, -1},
781*8975f5c5SAndroid Build Coastguard Worker {-512, -511, -500, -2},
782*8975f5c5SAndroid Build Coastguard Worker {-1, -2, -3, 1}}};
783*8975f5c5SAndroid Build Coastguard Worker std::array<GLint, kVertexCount> packedInput;
784*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedNormalizedTypeSize4;
785*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedNormalizedTypeSize3;
786*8975f5c5SAndroid Build Coastguard Worker
787*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount / 4; i++)
788*8975f5c5SAndroid Build Coastguard Worker {
789*8975f5c5SAndroid Build Coastguard Worker packedInput[i] = Pack1010102<GLint, GLshort>(unpackedInput[i]);
790*8975f5c5SAndroid Build Coastguard Worker
791*8975f5c5SAndroid Build Coastguard Worker expectedNormalizedTypeSize3[i * 3 + 0] = expectedNormalizedTypeSize4[i * 4 + 0] =
792*8975f5c5SAndroid Build Coastguard Worker Normalize10<GLshort>(unpackedInput[i][0]);
793*8975f5c5SAndroid Build Coastguard Worker expectedNormalizedTypeSize3[i * 3 + 1] = expectedNormalizedTypeSize4[i * 4 + 1] =
794*8975f5c5SAndroid Build Coastguard Worker Normalize10<GLshort>(unpackedInput[i][1]);
795*8975f5c5SAndroid Build Coastguard Worker expectedNormalizedTypeSize3[i * 3 + 2] = expectedNormalizedTypeSize4[i * 4 + 2] =
796*8975f5c5SAndroid Build Coastguard Worker Normalize10<GLshort>(unpackedInput[i][2]);
797*8975f5c5SAndroid Build Coastguard Worker
798*8975f5c5SAndroid Build Coastguard Worker // when the type size is 3, alpha will be 1.0f by GLES driver
799*8975f5c5SAndroid Build Coastguard Worker expectedNormalizedTypeSize4[i * 4 + 3] = Normalize2<GLshort>(unpackedInput[i][3]);
800*8975f5c5SAndroid Build Coastguard Worker }
801*8975f5c5SAndroid Build Coastguard Worker
802*8975f5c5SAndroid Build Coastguard Worker TestData data4(GL_INT_10_10_10_2_OES, GL_TRUE, Source::IMMEDIATE, packedInput.data(),
803*8975f5c5SAndroid Build Coastguard Worker expectedNormalizedTypeSize4.data());
804*8975f5c5SAndroid Build Coastguard Worker TestData bufferedData4(GL_INT_10_10_10_2_OES, GL_TRUE, Source::BUFFER, packedInput.data(),
805*8975f5c5SAndroid Build Coastguard Worker expectedNormalizedTypeSize4.data());
806*8975f5c5SAndroid Build Coastguard Worker TestData data3(GL_INT_10_10_10_2_OES, GL_TRUE, Source::IMMEDIATE, packedInput.data(),
807*8975f5c5SAndroid Build Coastguard Worker expectedNormalizedTypeSize3.data());
808*8975f5c5SAndroid Build Coastguard Worker TestData bufferedData3(GL_INT_10_10_10_2_OES, GL_TRUE, Source::BUFFER, packedInput.data(),
809*8975f5c5SAndroid Build Coastguard Worker expectedNormalizedTypeSize3.data());
810*8975f5c5SAndroid Build Coastguard Worker
811*8975f5c5SAndroid Build Coastguard Worker std::array<std::pair<const TestData &, GLint>, 4> dataSet = {
812*8975f5c5SAndroid Build Coastguard Worker {{data4, 4}, {bufferedData4, 4}, {data3, 3}, {bufferedData3, 3}}};
813*8975f5c5SAndroid Build Coastguard Worker
814*8975f5c5SAndroid Build Coastguard Worker for (auto data : dataSet)
815*8975f5c5SAndroid Build Coastguard Worker {
816*8975f5c5SAndroid Build Coastguard Worker setupTest(data.first, data.second);
817*8975f5c5SAndroid Build Coastguard Worker drawQuad(mProgram, "position", 0.5f);
818*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(mTestAttrib);
819*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(mExpectedAttrib);
820*8975f5c5SAndroid Build Coastguard Worker checkPixels();
821*8975f5c5SAndroid Build Coastguard Worker }
822*8975f5c5SAndroid Build Coastguard Worker }
823*8975f5c5SAndroid Build Coastguard Worker
824*8975f5c5SAndroid Build Coastguard Worker // Verify unsigned unnormalized INT_10_10_10_2 vertex type
TEST_P(VertexAttributeTest,UnsignedPacked1010102ExtensionUnnormalized)825*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, UnsignedPacked1010102ExtensionUnnormalized)
826*8975f5c5SAndroid Build Coastguard Worker {
827*8975f5c5SAndroid Build Coastguard Worker std::string extensionList(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
828*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF((extensionList.find("OES_vertex_type_10_10_10_2") == std::string::npos));
829*8975f5c5SAndroid Build Coastguard Worker
830*8975f5c5SAndroid Build Coastguard Worker // RGB channels are 10-bits, alpha is 2-bits
831*8975f5c5SAndroid Build Coastguard Worker std::array<std::array<GLushort, 4>, kVertexCount / 4> unpackedInput = {{{0, 1, 2, 0},
832*8975f5c5SAndroid Build Coastguard Worker {511, 512, 513, 1},
833*8975f5c5SAndroid Build Coastguard Worker {1023, 1022, 1021, 3},
834*8975f5c5SAndroid Build Coastguard Worker {513, 512, 511, 2},
835*8975f5c5SAndroid Build Coastguard Worker {2, 1, 0, 3},
836*8975f5c5SAndroid Build Coastguard Worker {1023, 1022, 1022, 0}}};
837*8975f5c5SAndroid Build Coastguard Worker
838*8975f5c5SAndroid Build Coastguard Worker std::array<GLuint, kVertexCount> packedInput;
839*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedTypeSize3;
840*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedTypeSize4;
841*8975f5c5SAndroid Build Coastguard Worker
842*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount / 4; i++)
843*8975f5c5SAndroid Build Coastguard Worker {
844*8975f5c5SAndroid Build Coastguard Worker packedInput[i] = Pack1010102<GLuint, GLushort>(unpackedInput[i]);
845*8975f5c5SAndroid Build Coastguard Worker
846*8975f5c5SAndroid Build Coastguard Worker expectedTypeSize3[i * 3 + 0] = expectedTypeSize4[i * 4 + 0] = unpackedInput[i][0];
847*8975f5c5SAndroid Build Coastguard Worker expectedTypeSize3[i * 3 + 1] = expectedTypeSize4[i * 4 + 1] = unpackedInput[i][1];
848*8975f5c5SAndroid Build Coastguard Worker expectedTypeSize3[i * 3 + 2] = expectedTypeSize4[i * 4 + 2] = unpackedInput[i][2];
849*8975f5c5SAndroid Build Coastguard Worker
850*8975f5c5SAndroid Build Coastguard Worker // when the type size is 3, alpha will be 1.0f by GLES driver
851*8975f5c5SAndroid Build Coastguard Worker expectedTypeSize4[i * 4 + 3] = unpackedInput[i][3];
852*8975f5c5SAndroid Build Coastguard Worker }
853*8975f5c5SAndroid Build Coastguard Worker
854*8975f5c5SAndroid Build Coastguard Worker TestData data4(GL_UNSIGNED_INT_10_10_10_2_OES, GL_FALSE, Source::IMMEDIATE, packedInput.data(),
855*8975f5c5SAndroid Build Coastguard Worker expectedTypeSize4.data());
856*8975f5c5SAndroid Build Coastguard Worker TestData bufferedData4(GL_UNSIGNED_INT_10_10_10_2_OES, GL_FALSE, Source::BUFFER,
857*8975f5c5SAndroid Build Coastguard Worker packedInput.data(), expectedTypeSize4.data());
858*8975f5c5SAndroid Build Coastguard Worker TestData data3(GL_UNSIGNED_INT_10_10_10_2_OES, GL_FALSE, Source::BUFFER, packedInput.data(),
859*8975f5c5SAndroid Build Coastguard Worker expectedTypeSize3.data());
860*8975f5c5SAndroid Build Coastguard Worker TestData bufferedData3(GL_UNSIGNED_INT_10_10_10_2_OES, GL_FALSE, Source::BUFFER,
861*8975f5c5SAndroid Build Coastguard Worker packedInput.data(), expectedTypeSize3.data());
862*8975f5c5SAndroid Build Coastguard Worker
863*8975f5c5SAndroid Build Coastguard Worker std::array<std::pair<const TestData &, GLint>, 4> dataSet = {
864*8975f5c5SAndroid Build Coastguard Worker {{data4, 4}, {bufferedData4, 4}, {data3, 3}, {bufferedData3, 3}}};
865*8975f5c5SAndroid Build Coastguard Worker
866*8975f5c5SAndroid Build Coastguard Worker for (auto data : dataSet)
867*8975f5c5SAndroid Build Coastguard Worker {
868*8975f5c5SAndroid Build Coastguard Worker setupTest(data.first, data.second);
869*8975f5c5SAndroid Build Coastguard Worker drawQuad(mProgram, "position", 0.5f);
870*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(mTestAttrib);
871*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(mExpectedAttrib);
872*8975f5c5SAndroid Build Coastguard Worker checkPixels();
873*8975f5c5SAndroid Build Coastguard Worker }
874*8975f5c5SAndroid Build Coastguard Worker }
875*8975f5c5SAndroid Build Coastguard Worker
876*8975f5c5SAndroid Build Coastguard Worker // Verify unsigned normalized INT_10_10_10_2 vertex type
TEST_P(VertexAttributeTest,UnsignedPacked1010102ExtensionNormalized)877*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, UnsignedPacked1010102ExtensionNormalized)
878*8975f5c5SAndroid Build Coastguard Worker {
879*8975f5c5SAndroid Build Coastguard Worker std::string extensionList(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
880*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF((extensionList.find("OES_vertex_type_10_10_10_2") == std::string::npos));
881*8975f5c5SAndroid Build Coastguard Worker
882*8975f5c5SAndroid Build Coastguard Worker // RGB channels are 10-bits, alpha is 2-bits
883*8975f5c5SAndroid Build Coastguard Worker std::array<std::array<GLushort, 4>, kVertexCount / 4> unpackedInput = {{{0, 1, 2, 0},
884*8975f5c5SAndroid Build Coastguard Worker {511, 512, 513, 1},
885*8975f5c5SAndroid Build Coastguard Worker {1023, 1022, 1021, 3},
886*8975f5c5SAndroid Build Coastguard Worker {513, 512, 511, 2},
887*8975f5c5SAndroid Build Coastguard Worker {2, 1, 0, 3},
888*8975f5c5SAndroid Build Coastguard Worker {1023, 1022, 1022, 0}}};
889*8975f5c5SAndroid Build Coastguard Worker
890*8975f5c5SAndroid Build Coastguard Worker std::array<GLuint, kVertexCount> packedInput;
891*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedTypeSize4;
892*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedTypeSize3;
893*8975f5c5SAndroid Build Coastguard Worker
894*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount / 4; i++)
895*8975f5c5SAndroid Build Coastguard Worker {
896*8975f5c5SAndroid Build Coastguard Worker packedInput[i] = Pack1010102<GLuint, GLushort>(unpackedInput[i]);
897*8975f5c5SAndroid Build Coastguard Worker
898*8975f5c5SAndroid Build Coastguard Worker expectedTypeSize3[i * 3 + 0] = expectedTypeSize4[i * 4 + 0] =
899*8975f5c5SAndroid Build Coastguard Worker Normalize10<GLushort>(unpackedInput[i][0]);
900*8975f5c5SAndroid Build Coastguard Worker expectedTypeSize3[i * 3 + 1] = expectedTypeSize4[i * 4 + 1] =
901*8975f5c5SAndroid Build Coastguard Worker Normalize10<GLushort>(unpackedInput[i][1]);
902*8975f5c5SAndroid Build Coastguard Worker expectedTypeSize3[i * 3 + 2] = expectedTypeSize4[i * 4 + 2] =
903*8975f5c5SAndroid Build Coastguard Worker Normalize10<GLushort>(unpackedInput[i][2]);
904*8975f5c5SAndroid Build Coastguard Worker
905*8975f5c5SAndroid Build Coastguard Worker // when the type size is 3, alpha will be 1.0f by GLES driver
906*8975f5c5SAndroid Build Coastguard Worker expectedTypeSize4[i * 4 + 3] = Normalize2<GLushort>(unpackedInput[i][3]);
907*8975f5c5SAndroid Build Coastguard Worker }
908*8975f5c5SAndroid Build Coastguard Worker
909*8975f5c5SAndroid Build Coastguard Worker TestData data4(GL_UNSIGNED_INT_10_10_10_2_OES, GL_TRUE, Source::IMMEDIATE, packedInput.data(),
910*8975f5c5SAndroid Build Coastguard Worker expectedTypeSize4.data());
911*8975f5c5SAndroid Build Coastguard Worker TestData bufferedData4(GL_UNSIGNED_INT_10_10_10_2_OES, GL_TRUE, Source::BUFFER,
912*8975f5c5SAndroid Build Coastguard Worker packedInput.data(), expectedTypeSize4.data());
913*8975f5c5SAndroid Build Coastguard Worker TestData data3(GL_UNSIGNED_INT_10_10_10_2_OES, GL_TRUE, Source::IMMEDIATE, packedInput.data(),
914*8975f5c5SAndroid Build Coastguard Worker expectedTypeSize3.data());
915*8975f5c5SAndroid Build Coastguard Worker TestData bufferedData3(GL_UNSIGNED_INT_10_10_10_2_OES, GL_TRUE, Source::BUFFER,
916*8975f5c5SAndroid Build Coastguard Worker packedInput.data(), expectedTypeSize3.data());
917*8975f5c5SAndroid Build Coastguard Worker
918*8975f5c5SAndroid Build Coastguard Worker std::array<std::pair<const TestData &, GLint>, 4> dataSet = {
919*8975f5c5SAndroid Build Coastguard Worker {{data4, 4}, {bufferedData4, 4}, {data3, 3}, {bufferedData3, 3}}};
920*8975f5c5SAndroid Build Coastguard Worker
921*8975f5c5SAndroid Build Coastguard Worker for (auto data : dataSet)
922*8975f5c5SAndroid Build Coastguard Worker {
923*8975f5c5SAndroid Build Coastguard Worker setupTest(data.first, data.second);
924*8975f5c5SAndroid Build Coastguard Worker drawQuad(mProgram, "position", 0.5f);
925*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(mTestAttrib);
926*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(mExpectedAttrib);
927*8975f5c5SAndroid Build Coastguard Worker checkPixels();
928*8975f5c5SAndroid Build Coastguard Worker };
929*8975f5c5SAndroid Build Coastguard Worker }
930*8975f5c5SAndroid Build Coastguard Worker
931*8975f5c5SAndroid Build Coastguard Worker // Test that mixing array and current vertex attribute values works with the same matrix input
TEST_P(VertexAttributeTest,MixedMatrixSources)932*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, MixedMatrixSources)
933*8975f5c5SAndroid Build Coastguard Worker {
934*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] = R"(
935*8975f5c5SAndroid Build Coastguard Worker attribute vec4 a_position;
936*8975f5c5SAndroid Build Coastguard Worker attribute mat4 a_matrix;
937*8975f5c5SAndroid Build Coastguard Worker varying vec4 v_color;
938*8975f5c5SAndroid Build Coastguard Worker void main() {
939*8975f5c5SAndroid Build Coastguard Worker v_color = vec4(0.5, 0.25, 0.125, 0.0625) * a_matrix;
940*8975f5c5SAndroid Build Coastguard Worker gl_Position = a_position;
941*8975f5c5SAndroid Build Coastguard Worker })";
942*8975f5c5SAndroid Build Coastguard Worker
943*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] = R"(
944*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
945*8975f5c5SAndroid Build Coastguard Worker varying vec4 v_color;
946*8975f5c5SAndroid Build Coastguard Worker void main() {
947*8975f5c5SAndroid Build Coastguard Worker gl_FragColor = v_color;
948*8975f5c5SAndroid Build Coastguard Worker })";
949*8975f5c5SAndroid Build Coastguard Worker
950*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(program, kVS, kFS);
951*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 0, "a_position");
952*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 1, "a_matrix");
953*8975f5c5SAndroid Build Coastguard Worker glLinkProgram(program);
954*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
955*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
956*8975f5c5SAndroid Build Coastguard Worker
957*8975f5c5SAndroid Build Coastguard Worker GLBuffer buffer;
958*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < 4; ++i)
959*8975f5c5SAndroid Build Coastguard Worker {
960*8975f5c5SAndroid Build Coastguard Worker // Setup current attributes for all columns except one
961*8975f5c5SAndroid Build Coastguard Worker for (size_t col = 0; col < 4; ++col)
962*8975f5c5SAndroid Build Coastguard Worker {
963*8975f5c5SAndroid Build Coastguard Worker GLfloat v[4] = {0.0, 0.0, 0.0, 0.0};
964*8975f5c5SAndroid Build Coastguard Worker v[col] = col == i ? 0.0 : 1.0;
965*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib4fv(1 + col, v);
966*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(1 + col);
967*8975f5c5SAndroid Build Coastguard Worker }
968*8975f5c5SAndroid Build Coastguard Worker
969*8975f5c5SAndroid Build Coastguard Worker // Setup vertex array data for the i-th column
970*8975f5c5SAndroid Build Coastguard Worker GLfloat data[16]{};
971*8975f5c5SAndroid Build Coastguard Worker data[0 * 4 + i] = 1.0;
972*8975f5c5SAndroid Build Coastguard Worker data[1 * 4 + i] = 1.0;
973*8975f5c5SAndroid Build Coastguard Worker data[2 * 4 + i] = 1.0;
974*8975f5c5SAndroid Build Coastguard Worker data[3 * 4 + i] = 1.0;
975*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, buffer);
976*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
977*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(1 + i, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(0));
978*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(1 + i);
979*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
980*8975f5c5SAndroid Build Coastguard Worker
981*8975f5c5SAndroid Build Coastguard Worker glClear(GL_COLOR_BUFFER_BIT);
982*8975f5c5SAndroid Build Coastguard Worker drawIndexedQuad(program, "a_position", 0.0f, 1.0f, true);
983*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(128, 64, 32, 16), 1);
984*8975f5c5SAndroid Build Coastguard Worker }
985*8975f5c5SAndroid Build Coastguard Worker }
986*8975f5c5SAndroid Build Coastguard Worker
987*8975f5c5SAndroid Build Coastguard Worker // Test that interleaved layout works for drawing one vertex
TEST_P(VertexAttributeTest,InterleavedOneVertex)988*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, InterleavedOneVertex)
989*8975f5c5SAndroid Build Coastguard Worker {
990*8975f5c5SAndroid Build Coastguard Worker float pointSizeRange[2] = {};
991*8975f5c5SAndroid Build Coastguard Worker glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, pointSizeRange);
992*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(pointSizeRange[1] < 8);
993*8975f5c5SAndroid Build Coastguard Worker
994*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] = R"(
995*8975f5c5SAndroid Build Coastguard Worker attribute vec4 a_pos;
996*8975f5c5SAndroid Build Coastguard Worker attribute vec4 a_col;
997*8975f5c5SAndroid Build Coastguard Worker varying mediump vec4 v_col;
998*8975f5c5SAndroid Build Coastguard Worker void main() {
999*8975f5c5SAndroid Build Coastguard Worker gl_PointSize = 8.0;
1000*8975f5c5SAndroid Build Coastguard Worker gl_Position = a_pos;
1001*8975f5c5SAndroid Build Coastguard Worker v_col = a_col;
1002*8975f5c5SAndroid Build Coastguard Worker })";
1003*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] = R"(
1004*8975f5c5SAndroid Build Coastguard Worker varying mediump vec4 v_col;
1005*8975f5c5SAndroid Build Coastguard Worker void main() {
1006*8975f5c5SAndroid Build Coastguard Worker gl_FragColor = v_col;
1007*8975f5c5SAndroid Build Coastguard Worker })";
1008*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(program, kVS, kFS);
1009*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 0, "a_pos");
1010*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 1, "a_col");
1011*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
1012*8975f5c5SAndroid Build Coastguard Worker
1013*8975f5c5SAndroid Build Coastguard Worker GLBuffer buf;
1014*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, buf);
1015*8975f5c5SAndroid Build Coastguard Worker
1016*8975f5c5SAndroid Build Coastguard Worker // One vertex, magenta
1017*8975f5c5SAndroid Build Coastguard Worker const GLfloat data1[8] = {
1018*8975f5c5SAndroid Build Coastguard Worker 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
1019*8975f5c5SAndroid Build Coastguard Worker };
1020*8975f5c5SAndroid Build Coastguard Worker
1021*8975f5c5SAndroid Build Coastguard Worker // Two vertices, red and blue
1022*8975f5c5SAndroid Build Coastguard Worker const GLfloat data2[16] = {
1023*8975f5c5SAndroid Build Coastguard Worker -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1024*8975f5c5SAndroid Build Coastguard Worker +0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
1025*8975f5c5SAndroid Build Coastguard Worker };
1026*8975f5c5SAndroid Build Coastguard Worker
1027*8975f5c5SAndroid Build Coastguard Worker // One vertex, green
1028*8975f5c5SAndroid Build Coastguard Worker const GLfloat data3[8] = {
1029*8975f5c5SAndroid Build Coastguard Worker 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
1030*8975f5c5SAndroid Build Coastguard Worker };
1031*8975f5c5SAndroid Build Coastguard Worker
1032*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(0);
1033*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(1);
1034*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 32, reinterpret_cast<void *>(0));
1035*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 32, reinterpret_cast<void *>(16));
1036*8975f5c5SAndroid Build Coastguard Worker
1037*8975f5c5SAndroid Build Coastguard Worker // The second attribute stride is reaching beyond the buffer's length.
1038*8975f5c5SAndroid Build Coastguard Worker // It must not cause any errors as there only one vertex to draw.
1039*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, 32, data1, GL_STATIC_DRAW);
1040*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_POINTS, 0, 1);
1041*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
1042*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(64, 64, GLColor::magenta);
1043*8975f5c5SAndroid Build Coastguard Worker
1044*8975f5c5SAndroid Build Coastguard Worker // Replace data and draw two vertices to ensure that stride has been applied correctly.
1045*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, 64, data2, GL_STATIC_DRAW);
1046*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_POINTS, 0, 2);
1047*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
1048*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(32, 64, GLColor::red);
1049*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(96, 64, GLColor::blue);
1050*8975f5c5SAndroid Build Coastguard Worker
1051*8975f5c5SAndroid Build Coastguard Worker // Replace data reducing the buffer size back to one vertex
1052*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, 32, data3, GL_STATIC_DRAW);
1053*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_POINTS, 0, 1);
1054*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
1055*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(64, 64, GLColor::green);
1056*8975f5c5SAndroid Build Coastguard Worker }
1057*8975f5c5SAndroid Build Coastguard Worker
1058*8975f5c5SAndroid Build Coastguard Worker class VertexAttributeTestES3 : public VertexAttributeTest
1059*8975f5c5SAndroid Build Coastguard Worker {
1060*8975f5c5SAndroid Build Coastguard Worker protected:
VertexAttributeTestES3()1061*8975f5c5SAndroid Build Coastguard Worker VertexAttributeTestES3() {}
1062*8975f5c5SAndroid Build Coastguard Worker };
1063*8975f5c5SAndroid Build Coastguard Worker
TEST_P(VertexAttributeTestES3,IntUnnormalized)1064*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, IntUnnormalized)
1065*8975f5c5SAndroid Build Coastguard Worker {
1066*8975f5c5SAndroid Build Coastguard Worker GLint lo = std::numeric_limits<GLint>::min();
1067*8975f5c5SAndroid Build Coastguard Worker GLint hi = std::numeric_limits<GLint>::max();
1068*8975f5c5SAndroid Build Coastguard Worker std::array<GLint, kVertexCount> inputData = {
1069*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, -1, -2, -3, -4, -1, hi, hi - 1, lo, lo + 1}};
1070*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
1071*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
1072*8975f5c5SAndroid Build Coastguard Worker {
1073*8975f5c5SAndroid Build Coastguard Worker expectedData[i] = static_cast<GLfloat>(inputData[i]);
1074*8975f5c5SAndroid Build Coastguard Worker }
1075*8975f5c5SAndroid Build Coastguard Worker
1076*8975f5c5SAndroid Build Coastguard Worker TestData data(GL_INT, GL_FALSE, Source::BUFFER, inputData.data(), expectedData.data());
1077*8975f5c5SAndroid Build Coastguard Worker runTest(data);
1078*8975f5c5SAndroid Build Coastguard Worker }
1079*8975f5c5SAndroid Build Coastguard Worker
TEST_P(VertexAttributeTestES3,IntNormalized)1080*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, IntNormalized)
1081*8975f5c5SAndroid Build Coastguard Worker {
1082*8975f5c5SAndroid Build Coastguard Worker GLint lo = std::numeric_limits<GLint>::min();
1083*8975f5c5SAndroid Build Coastguard Worker GLint hi = std::numeric_limits<GLint>::max();
1084*8975f5c5SAndroid Build Coastguard Worker std::array<GLint, kVertexCount> inputData = {
1085*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, -1, -2, -3, -4, -1, hi, hi - 1, lo, lo + 1}};
1086*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
1087*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
1088*8975f5c5SAndroid Build Coastguard Worker {
1089*8975f5c5SAndroid Build Coastguard Worker expectedData[i] = Normalize(inputData[i]);
1090*8975f5c5SAndroid Build Coastguard Worker }
1091*8975f5c5SAndroid Build Coastguard Worker
1092*8975f5c5SAndroid Build Coastguard Worker TestData data(GL_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
1093*8975f5c5SAndroid Build Coastguard Worker runTest(data);
1094*8975f5c5SAndroid Build Coastguard Worker }
1095*8975f5c5SAndroid Build Coastguard Worker
1096*8975f5c5SAndroid Build Coastguard Worker // Same as IntUnnormalized but with glClear() before running the test to force
1097*8975f5c5SAndroid Build Coastguard Worker // starting a render pass. This to verify that buffer format conversion within
1098*8975f5c5SAndroid Build Coastguard Worker // an active render pass works as expected in Metal back-end.
TEST_P(VertexAttributeTestES3,IntUnnormalizedWithClear)1099*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, IntUnnormalizedWithClear)
1100*8975f5c5SAndroid Build Coastguard Worker {
1101*8975f5c5SAndroid Build Coastguard Worker GLint lo = std::numeric_limits<GLint>::min();
1102*8975f5c5SAndroid Build Coastguard Worker GLint hi = std::numeric_limits<GLint>::max();
1103*8975f5c5SAndroid Build Coastguard Worker std::array<GLint, kVertexCount> inputData = {
1104*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, -1, -2, -3, -4, -1, hi, hi - 1, lo, lo + 1}};
1105*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
1106*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
1107*8975f5c5SAndroid Build Coastguard Worker {
1108*8975f5c5SAndroid Build Coastguard Worker expectedData[i] = static_cast<GLfloat>(inputData[i]);
1109*8975f5c5SAndroid Build Coastguard Worker }
1110*8975f5c5SAndroid Build Coastguard Worker
1111*8975f5c5SAndroid Build Coastguard Worker TestData data(GL_INT, GL_FALSE, Source::BUFFER, inputData.data(), expectedData.data());
1112*8975f5c5SAndroid Build Coastguard Worker data.clearBeforeDraw = true;
1113*8975f5c5SAndroid Build Coastguard Worker
1114*8975f5c5SAndroid Build Coastguard Worker runTest(data);
1115*8975f5c5SAndroid Build Coastguard Worker }
1116*8975f5c5SAndroid Build Coastguard Worker
1117*8975f5c5SAndroid Build Coastguard Worker // Same as IntNormalized but with glClear() before running the test to force
1118*8975f5c5SAndroid Build Coastguard Worker // starting a render pass. This to verify that buffer format conversion within
1119*8975f5c5SAndroid Build Coastguard Worker // an active render pass works as expected in Metal back-end.
TEST_P(VertexAttributeTestES3,IntNormalizedWithClear)1120*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, IntNormalizedWithClear)
1121*8975f5c5SAndroid Build Coastguard Worker {
1122*8975f5c5SAndroid Build Coastguard Worker GLint lo = std::numeric_limits<GLint>::min();
1123*8975f5c5SAndroid Build Coastguard Worker GLint hi = std::numeric_limits<GLint>::max();
1124*8975f5c5SAndroid Build Coastguard Worker std::array<GLint, kVertexCount> inputData = {
1125*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, -1, -2, -3, -4, -1, hi, hi - 1, lo, lo + 1}};
1126*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
1127*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
1128*8975f5c5SAndroid Build Coastguard Worker {
1129*8975f5c5SAndroid Build Coastguard Worker expectedData[i] = Normalize(inputData[i]);
1130*8975f5c5SAndroid Build Coastguard Worker }
1131*8975f5c5SAndroid Build Coastguard Worker
1132*8975f5c5SAndroid Build Coastguard Worker TestData data(GL_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
1133*8975f5c5SAndroid Build Coastguard Worker data.clearBeforeDraw = true;
1134*8975f5c5SAndroid Build Coastguard Worker
1135*8975f5c5SAndroid Build Coastguard Worker runTest(data);
1136*8975f5c5SAndroid Build Coastguard Worker }
1137*8975f5c5SAndroid Build Coastguard Worker
TEST_P(VertexAttributeTestES3,UnsignedIntUnnormalized)1138*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, UnsignedIntUnnormalized)
1139*8975f5c5SAndroid Build Coastguard Worker {
1140*8975f5c5SAndroid Build Coastguard Worker GLuint mid = std::numeric_limits<GLuint>::max() >> 1;
1141*8975f5c5SAndroid Build Coastguard Worker GLuint hi = std::numeric_limits<GLuint>::max();
1142*8975f5c5SAndroid Build Coastguard Worker std::array<GLuint, kVertexCount> inputData = {
1143*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
1144*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
1145*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
1146*8975f5c5SAndroid Build Coastguard Worker {
1147*8975f5c5SAndroid Build Coastguard Worker expectedData[i] = static_cast<GLfloat>(inputData[i]);
1148*8975f5c5SAndroid Build Coastguard Worker }
1149*8975f5c5SAndroid Build Coastguard Worker
1150*8975f5c5SAndroid Build Coastguard Worker TestData data(GL_UNSIGNED_INT, GL_FALSE, Source::BUFFER, inputData.data(), expectedData.data());
1151*8975f5c5SAndroid Build Coastguard Worker runTest(data);
1152*8975f5c5SAndroid Build Coastguard Worker }
1153*8975f5c5SAndroid Build Coastguard Worker
TEST_P(VertexAttributeTestES3,UnsignedIntNormalized)1154*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, UnsignedIntNormalized)
1155*8975f5c5SAndroid Build Coastguard Worker {
1156*8975f5c5SAndroid Build Coastguard Worker GLuint mid = std::numeric_limits<GLuint>::max() >> 1;
1157*8975f5c5SAndroid Build Coastguard Worker GLuint hi = std::numeric_limits<GLuint>::max();
1158*8975f5c5SAndroid Build Coastguard Worker std::array<GLuint, kVertexCount> inputData = {
1159*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
1160*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
1161*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
1162*8975f5c5SAndroid Build Coastguard Worker {
1163*8975f5c5SAndroid Build Coastguard Worker expectedData[i] = Normalize(inputData[i]);
1164*8975f5c5SAndroid Build Coastguard Worker }
1165*8975f5c5SAndroid Build Coastguard Worker
1166*8975f5c5SAndroid Build Coastguard Worker TestData data(GL_UNSIGNED_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
1167*8975f5c5SAndroid Build Coastguard Worker runTest(data);
1168*8975f5c5SAndroid Build Coastguard Worker }
1169*8975f5c5SAndroid Build Coastguard Worker
1170*8975f5c5SAndroid Build Coastguard Worker // Same as UnsignedIntNormalized but with glClear() before running the test to force
1171*8975f5c5SAndroid Build Coastguard Worker // starting a render pass. This to verify that buffer format conversion within
1172*8975f5c5SAndroid Build Coastguard Worker // an active render pass works as expected in Metal back-end.
TEST_P(VertexAttributeTestES3,UnsignedIntNormalizedWithClear)1173*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, UnsignedIntNormalizedWithClear)
1174*8975f5c5SAndroid Build Coastguard Worker {
1175*8975f5c5SAndroid Build Coastguard Worker GLuint mid = std::numeric_limits<GLuint>::max() >> 1;
1176*8975f5c5SAndroid Build Coastguard Worker GLuint hi = std::numeric_limits<GLuint>::max();
1177*8975f5c5SAndroid Build Coastguard Worker std::array<GLuint, kVertexCount> inputData = {
1178*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
1179*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
1180*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
1181*8975f5c5SAndroid Build Coastguard Worker {
1182*8975f5c5SAndroid Build Coastguard Worker expectedData[i] = Normalize(inputData[i]);
1183*8975f5c5SAndroid Build Coastguard Worker }
1184*8975f5c5SAndroid Build Coastguard Worker
1185*8975f5c5SAndroid Build Coastguard Worker TestData data(GL_UNSIGNED_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
1186*8975f5c5SAndroid Build Coastguard Worker data.clearBeforeDraw = true;
1187*8975f5c5SAndroid Build Coastguard Worker runTest(data);
1188*8975f5c5SAndroid Build Coastguard Worker }
1189*8975f5c5SAndroid Build Coastguard Worker
SetupColorsForUnitQuad(GLint location,const GLColor32F & color,GLenum usage,GLBuffer * vbo)1190*8975f5c5SAndroid Build Coastguard Worker void SetupColorsForUnitQuad(GLint location, const GLColor32F &color, GLenum usage, GLBuffer *vbo)
1191*8975f5c5SAndroid Build Coastguard Worker {
1192*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, *vbo);
1193*8975f5c5SAndroid Build Coastguard Worker std::vector<GLColor32F> vertices(6, color);
1194*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLColor32F), vertices.data(), usage);
1195*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(location);
1196*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE, 0, 0);
1197*8975f5c5SAndroid Build Coastguard Worker }
1198*8975f5c5SAndroid Build Coastguard Worker
1199*8975f5c5SAndroid Build Coastguard Worker // Tests that rendering works as expected with VAOs.
TEST_P(VertexAttributeTestES3,VertexArrayObjectRendering)1200*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, VertexArrayObjectRendering)
1201*8975f5c5SAndroid Build Coastguard Worker {
1202*8975f5c5SAndroid Build Coastguard Worker constexpr char kVertexShader[] =
1203*8975f5c5SAndroid Build Coastguard Worker "attribute vec4 a_position;\n"
1204*8975f5c5SAndroid Build Coastguard Worker "attribute vec4 a_color;\n"
1205*8975f5c5SAndroid Build Coastguard Worker "varying vec4 v_color;\n"
1206*8975f5c5SAndroid Build Coastguard Worker "void main()\n"
1207*8975f5c5SAndroid Build Coastguard Worker "{\n"
1208*8975f5c5SAndroid Build Coastguard Worker " gl_Position = a_position;\n"
1209*8975f5c5SAndroid Build Coastguard Worker " v_color = a_color;\n"
1210*8975f5c5SAndroid Build Coastguard Worker "}";
1211*8975f5c5SAndroid Build Coastguard Worker
1212*8975f5c5SAndroid Build Coastguard Worker constexpr char kFragmentShader[] =
1213*8975f5c5SAndroid Build Coastguard Worker "precision mediump float;\n"
1214*8975f5c5SAndroid Build Coastguard Worker "varying vec4 v_color;\n"
1215*8975f5c5SAndroid Build Coastguard Worker "void main()\n"
1216*8975f5c5SAndroid Build Coastguard Worker "{\n"
1217*8975f5c5SAndroid Build Coastguard Worker " gl_FragColor = v_color;\n"
1218*8975f5c5SAndroid Build Coastguard Worker "}";
1219*8975f5c5SAndroid Build Coastguard Worker
1220*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
1221*8975f5c5SAndroid Build Coastguard Worker
1222*8975f5c5SAndroid Build Coastguard Worker GLint positionLoc = glGetAttribLocation(program, "a_position");
1223*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, positionLoc);
1224*8975f5c5SAndroid Build Coastguard Worker GLint colorLoc = glGetAttribLocation(program, "a_color");
1225*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, colorLoc);
1226*8975f5c5SAndroid Build Coastguard Worker
1227*8975f5c5SAndroid Build Coastguard Worker GLVertexArray vaos[2];
1228*8975f5c5SAndroid Build Coastguard Worker GLBuffer positionBuffer;
1229*8975f5c5SAndroid Build Coastguard Worker GLBuffer colorBuffers[2];
1230*8975f5c5SAndroid Build Coastguard Worker
1231*8975f5c5SAndroid Build Coastguard Worker const auto &quadVertices = GetQuadVertices();
1232*8975f5c5SAndroid Build Coastguard Worker
1233*8975f5c5SAndroid Build Coastguard Worker glBindVertexArray(vaos[0]);
1234*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
1235*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, quadVertices.size() * sizeof(Vector3), quadVertices.data(),
1236*8975f5c5SAndroid Build Coastguard Worker GL_STATIC_DRAW);
1237*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(positionLoc);
1238*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
1239*8975f5c5SAndroid Build Coastguard Worker SetupColorsForUnitQuad(colorLoc, kFloatRed, GL_STREAM_DRAW, &colorBuffers[0]);
1240*8975f5c5SAndroid Build Coastguard Worker
1241*8975f5c5SAndroid Build Coastguard Worker glBindVertexArray(vaos[1]);
1242*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
1243*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(positionLoc);
1244*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
1245*8975f5c5SAndroid Build Coastguard Worker SetupColorsForUnitQuad(colorLoc, kFloatGreen, GL_STATIC_DRAW, &colorBuffers[1]);
1246*8975f5c5SAndroid Build Coastguard Worker
1247*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
1248*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
1249*8975f5c5SAndroid Build Coastguard Worker
1250*8975f5c5SAndroid Build Coastguard Worker for (int ii = 0; ii < 2; ++ii)
1251*8975f5c5SAndroid Build Coastguard Worker {
1252*8975f5c5SAndroid Build Coastguard Worker glBindVertexArray(vaos[0]);
1253*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
1254*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1255*8975f5c5SAndroid Build Coastguard Worker
1256*8975f5c5SAndroid Build Coastguard Worker glBindVertexArray(vaos[1]);
1257*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
1258*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
1259*8975f5c5SAndroid Build Coastguard Worker }
1260*8975f5c5SAndroid Build Coastguard Worker
1261*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
1262*8975f5c5SAndroid Build Coastguard Worker }
1263*8975f5c5SAndroid Build Coastguard Worker
1264*8975f5c5SAndroid Build Coastguard Worker // Validate that we can support GL_MAX_ATTRIBS attribs
TEST_P(VertexAttributeTest,MaxAttribs)1265*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, MaxAttribs)
1266*8975f5c5SAndroid Build Coastguard Worker {
1267*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadill): Figure out why we get this error on AMD/OpenGL.
1268*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
1269*8975f5c5SAndroid Build Coastguard Worker
1270*8975f5c5SAndroid Build Coastguard Worker GLint maxAttribs;
1271*8975f5c5SAndroid Build Coastguard Worker glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs);
1272*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
1273*8975f5c5SAndroid Build Coastguard Worker
1274*8975f5c5SAndroid Build Coastguard Worker // Reserve one attrib for position
1275*8975f5c5SAndroid Build Coastguard Worker GLint drawAttribs = maxAttribs - 1;
1276*8975f5c5SAndroid Build Coastguard Worker
1277*8975f5c5SAndroid Build Coastguard Worker GLuint program = compileMultiAttribProgram(drawAttribs);
1278*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(0u, program);
1279*8975f5c5SAndroid Build Coastguard Worker
1280*8975f5c5SAndroid Build Coastguard Worker setupMultiAttribs(program, drawAttribs, 0.5f / static_cast<float>(drawAttribs));
1281*8975f5c5SAndroid Build Coastguard Worker drawQuad(program, "position", 0.5f);
1282*8975f5c5SAndroid Build Coastguard Worker
1283*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
1284*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_NEAR(0, 0, 128, 0, 0, 255, 1);
1285*8975f5c5SAndroid Build Coastguard Worker }
1286*8975f5c5SAndroid Build Coastguard Worker
1287*8975f5c5SAndroid Build Coastguard Worker // Validate that we cannot support GL_MAX_ATTRIBS+1 attribs
TEST_P(VertexAttributeTest,MaxAttribsPlusOne)1288*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, MaxAttribsPlusOne)
1289*8975f5c5SAndroid Build Coastguard Worker {
1290*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadill): Figure out why we get this error on AMD/ES2/OpenGL
1291*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsAMD() && GetParam() == ES2_OPENGL());
1292*8975f5c5SAndroid Build Coastguard Worker
1293*8975f5c5SAndroid Build Coastguard Worker GLint maxAttribs;
1294*8975f5c5SAndroid Build Coastguard Worker glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs);
1295*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
1296*8975f5c5SAndroid Build Coastguard Worker
1297*8975f5c5SAndroid Build Coastguard Worker // Exceed attrib count by one (counting position)
1298*8975f5c5SAndroid Build Coastguard Worker GLint drawAttribs = maxAttribs;
1299*8975f5c5SAndroid Build Coastguard Worker
1300*8975f5c5SAndroid Build Coastguard Worker GLuint program = compileMultiAttribProgram(drawAttribs);
1301*8975f5c5SAndroid Build Coastguard Worker ASSERT_EQ(0u, program);
1302*8975f5c5SAndroid Build Coastguard Worker }
1303*8975f5c5SAndroid Build Coastguard Worker
1304*8975f5c5SAndroid Build Coastguard Worker // Simple test for when we use glBindAttribLocation
TEST_P(VertexAttributeTest,SimpleBindAttribLocation)1305*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, SimpleBindAttribLocation)
1306*8975f5c5SAndroid Build Coastguard Worker {
1307*8975f5c5SAndroid Build Coastguard Worker // Re-use the multi-attrib program, binding attribute 0
1308*8975f5c5SAndroid Build Coastguard Worker GLuint program = compileMultiAttribProgram(1);
1309*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 2, "position");
1310*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 3, "a0");
1311*8975f5c5SAndroid Build Coastguard Worker glLinkProgram(program);
1312*8975f5c5SAndroid Build Coastguard Worker
1313*8975f5c5SAndroid Build Coastguard Worker // Setup and draw the quad
1314*8975f5c5SAndroid Build Coastguard Worker setupMultiAttribs(program, 1, 0.5f);
1315*8975f5c5SAndroid Build Coastguard Worker drawQuad(program, "position", 0.5f);
1316*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
1317*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_NEAR(0, 0, 128, 0, 0, 255, 1);
1318*8975f5c5SAndroid Build Coastguard Worker }
1319*8975f5c5SAndroid Build Coastguard Worker
1320*8975f5c5SAndroid Build Coastguard Worker class VertexAttributeOORTest : public VertexAttributeTest
1321*8975f5c5SAndroid Build Coastguard Worker {
1322*8975f5c5SAndroid Build Coastguard Worker public:
VertexAttributeOORTest()1323*8975f5c5SAndroid Build Coastguard Worker VertexAttributeOORTest()
1324*8975f5c5SAndroid Build Coastguard Worker {
1325*8975f5c5SAndroid Build Coastguard Worker setWebGLCompatibilityEnabled(true);
1326*8975f5c5SAndroid Build Coastguard Worker setRobustAccess(false);
1327*8975f5c5SAndroid Build Coastguard Worker }
1328*8975f5c5SAndroid Build Coastguard Worker };
1329*8975f5c5SAndroid Build Coastguard Worker
1330*8975f5c5SAndroid Build Coastguard Worker class RobustVertexAttributeTest : public VertexAttributeTest
1331*8975f5c5SAndroid Build Coastguard Worker {
1332*8975f5c5SAndroid Build Coastguard Worker public:
RobustVertexAttributeTest()1333*8975f5c5SAndroid Build Coastguard Worker RobustVertexAttributeTest()
1334*8975f5c5SAndroid Build Coastguard Worker {
1335*8975f5c5SAndroid Build Coastguard Worker // mac GL and metal do not support robustness.
1336*8975f5c5SAndroid Build Coastguard Worker if (!IsMac() && !IsIOS())
1337*8975f5c5SAndroid Build Coastguard Worker {
1338*8975f5c5SAndroid Build Coastguard Worker setRobustAccess(true);
1339*8975f5c5SAndroid Build Coastguard Worker }
1340*8975f5c5SAndroid Build Coastguard Worker }
1341*8975f5c5SAndroid Build Coastguard Worker };
1342*8975f5c5SAndroid Build Coastguard Worker
1343*8975f5c5SAndroid Build Coastguard Worker // Verify that drawing with a large out-of-range offset generates INVALID_OPERATION.
1344*8975f5c5SAndroid Build Coastguard Worker // Requires WebGL compatibility with robust access behaviour disabled.
TEST_P(VertexAttributeOORTest,ANGLEDrawArraysBufferTooSmall)1345*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeOORTest, ANGLEDrawArraysBufferTooSmall)
1346*8975f5c5SAndroid Build Coastguard Worker {
1347*8975f5c5SAndroid Build Coastguard Worker // Test skipped due to supporting GL_KHR_robust_buffer_access_behavior
1348*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_KHR_robust_buffer_access_behavior"));
1349*8975f5c5SAndroid Build Coastguard Worker
1350*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> inputData;
1351*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
1352*8975f5c5SAndroid Build Coastguard Worker InitTestData(inputData, expectedData);
1353*8975f5c5SAndroid Build Coastguard Worker
1354*8975f5c5SAndroid Build Coastguard Worker TestData data(GL_FLOAT, GL_FALSE, Source::BUFFER, inputData.data(), expectedData.data());
1355*8975f5c5SAndroid Build Coastguard Worker data.bufferOffset = kVertexCount * TypeStride(GL_FLOAT);
1356*8975f5c5SAndroid Build Coastguard Worker
1357*8975f5c5SAndroid Build Coastguard Worker setupTest(data, 1);
1358*8975f5c5SAndroid Build Coastguard Worker drawQuad(mProgram, "position", 0.5f);
1359*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1360*8975f5c5SAndroid Build Coastguard Worker }
1361*8975f5c5SAndroid Build Coastguard Worker
1362*8975f5c5SAndroid Build Coastguard Worker // Verify that index draw with an out-of-range offset generates INVALID_OPERATION.
1363*8975f5c5SAndroid Build Coastguard Worker // Requires WebGL compatibility with robust access behaviour disabled.
TEST_P(VertexAttributeOORTest,ANGLEDrawElementsBufferTooSmall)1364*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeOORTest, ANGLEDrawElementsBufferTooSmall)
1365*8975f5c5SAndroid Build Coastguard Worker {
1366*8975f5c5SAndroid Build Coastguard Worker // Test skipped due to supporting GL_KHR_robust_buffer_access_behavior
1367*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_KHR_robust_buffer_access_behavior"));
1368*8975f5c5SAndroid Build Coastguard Worker
1369*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> inputData;
1370*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
1371*8975f5c5SAndroid Build Coastguard Worker InitTestData(inputData, expectedData);
1372*8975f5c5SAndroid Build Coastguard Worker
1373*8975f5c5SAndroid Build Coastguard Worker TestData data(GL_FLOAT, GL_FALSE, Source::BUFFER, inputData.data(), expectedData.data());
1374*8975f5c5SAndroid Build Coastguard Worker data.bufferOffset = (kVertexCount - 3) * TypeStride(GL_FLOAT);
1375*8975f5c5SAndroid Build Coastguard Worker
1376*8975f5c5SAndroid Build Coastguard Worker setupTest(data, 1);
1377*8975f5c5SAndroid Build Coastguard Worker drawIndexedQuad(mProgram, "position", 0.5f, 1.0f, true);
1378*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1379*8975f5c5SAndroid Build Coastguard Worker }
1380*8975f5c5SAndroid Build Coastguard Worker
1381*8975f5c5SAndroid Build Coastguard Worker // Verify that DrawArarys with an out-of-range offset generates INVALID_OPERATION.
1382*8975f5c5SAndroid Build Coastguard Worker // Requires WebGL compatibility with robust access behaviour disabled.
TEST_P(VertexAttributeOORTest,ANGLEDrawArraysOutOfBoundsCases)1383*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeOORTest, ANGLEDrawArraysOutOfBoundsCases)
1384*8975f5c5SAndroid Build Coastguard Worker {
1385*8975f5c5SAndroid Build Coastguard Worker // Test skipped due to supporting GL_KHR_robust_buffer_access_behavior
1386*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_KHR_robust_buffer_access_behavior"));
1387*8975f5c5SAndroid Build Coastguard Worker
1388*8975f5c5SAndroid Build Coastguard Worker initBasicProgram();
1389*8975f5c5SAndroid Build Coastguard Worker
1390*8975f5c5SAndroid Build Coastguard Worker GLfloat singleFloat = 1.0f;
1391*8975f5c5SAndroid Build Coastguard Worker GLsizei dataSize = TypeStride(GL_FLOAT);
1392*8975f5c5SAndroid Build Coastguard Worker
1393*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1394*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, dataSize, &singleFloat, GL_STATIC_DRAW);
1395*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, 2, GL_FLOAT, GL_FALSE, 8, 0);
1396*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
1397*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
1398*8975f5c5SAndroid Build Coastguard Worker
1399*8975f5c5SAndroid Build Coastguard Worker drawIndexedQuad(mProgram, "position", 0.5f, 1.0f, true);
1400*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1401*8975f5c5SAndroid Build Coastguard Worker }
1402*8975f5c5SAndroid Build Coastguard Worker
1403*8975f5c5SAndroid Build Coastguard Worker // Test that enabling a buffer in an unused attribute doesn't crash. There should be an active
1404*8975f5c5SAndroid Build Coastguard Worker // attribute after that.
TEST_P(RobustVertexAttributeTest,BoundButUnusedBuffer)1405*8975f5c5SAndroid Build Coastguard Worker TEST_P(RobustVertexAttributeTest, BoundButUnusedBuffer)
1406*8975f5c5SAndroid Build Coastguard Worker {
1407*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] = R"(attribute vec2 offset;
1408*8975f5c5SAndroid Build Coastguard Worker void main()
1409*8975f5c5SAndroid Build Coastguard Worker {
1410*8975f5c5SAndroid Build Coastguard Worker gl_Position = vec4(offset.xy, 0, 1);
1411*8975f5c5SAndroid Build Coastguard Worker gl_PointSize = 1.0;
1412*8975f5c5SAndroid Build Coastguard Worker })";
1413*8975f5c5SAndroid Build Coastguard Worker
1414*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] = R"(precision mediump float;
1415*8975f5c5SAndroid Build Coastguard Worker void main()
1416*8975f5c5SAndroid Build Coastguard Worker {
1417*8975f5c5SAndroid Build Coastguard Worker gl_FragColor = vec4(1.0, 0, 0, 1.0);
1418*8975f5c5SAndroid Build Coastguard Worker })";
1419*8975f5c5SAndroid Build Coastguard Worker
1420*8975f5c5SAndroid Build Coastguard Worker const GLuint vs = CompileShader(GL_VERTEX_SHADER, kVS);
1421*8975f5c5SAndroid Build Coastguard Worker const GLuint fs = CompileShader(GL_FRAGMENT_SHADER, kFS);
1422*8975f5c5SAndroid Build Coastguard Worker
1423*8975f5c5SAndroid Build Coastguard Worker GLuint program = glCreateProgram();
1424*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 1, "offset");
1425*8975f5c5SAndroid Build Coastguard Worker glAttachShader(program, vs);
1426*8975f5c5SAndroid Build Coastguard Worker glAttachShader(program, fs);
1427*8975f5c5SAndroid Build Coastguard Worker glLinkProgram(program);
1428*8975f5c5SAndroid Build Coastguard Worker
1429*8975f5c5SAndroid Build Coastguard Worker GLBuffer buffer;
1430*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, buffer);
1431*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, 100, nullptr, GL_STATIC_DRAW);
1432*8975f5c5SAndroid Build Coastguard Worker
1433*8975f5c5SAndroid Build Coastguard Worker // Enable an unused attribute that is within the range of active attributes (not beyond it)
1434*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(0);
1435*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, 0);
1436*8975f5c5SAndroid Build Coastguard Worker
1437*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
1438*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
1439*8975f5c5SAndroid Build Coastguard Worker
1440*8975f5c5SAndroid Build Coastguard Worker // Destroy the buffer. Regression test for a tracking bug where the buffer was used by
1441*8975f5c5SAndroid Build Coastguard Worker // SwiftShader (even though location 1 is inactive), but not marked as used by ANGLE.
1442*8975f5c5SAndroid Build Coastguard Worker buffer.reset();
1443*8975f5c5SAndroid Build Coastguard Worker }
1444*8975f5c5SAndroid Build Coastguard Worker
1445*8975f5c5SAndroid Build Coastguard Worker // Verify that using a different start vertex doesn't mess up the draw.
TEST_P(VertexAttributeTest,DrawArraysWithBufferOffset)1446*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, DrawArraysWithBufferOffset)
1447*8975f5c5SAndroid Build Coastguard Worker {
1448*8975f5c5SAndroid Build Coastguard Worker initBasicProgram();
1449*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
1450*8975f5c5SAndroid Build Coastguard Worker
1451*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> inputData;
1452*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
1453*8975f5c5SAndroid Build Coastguard Worker InitTestData(inputData, expectedData);
1454*8975f5c5SAndroid Build Coastguard Worker
1455*8975f5c5SAndroid Build Coastguard Worker GLBuffer quadBuffer;
1456*8975f5c5SAndroid Build Coastguard Worker InitQuadPlusOneVertexBuffer(&quadBuffer);
1457*8975f5c5SAndroid Build Coastguard Worker
1458*8975f5c5SAndroid Build Coastguard Worker GLint positionLocation = glGetAttribLocation(mProgram, "position");
1459*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, positionLocation);
1460*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1461*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(positionLocation);
1462*8975f5c5SAndroid Build Coastguard Worker
1463*8975f5c5SAndroid Build Coastguard Worker GLsizei dataSize = kVertexCount * TypeStride(GL_FLOAT);
1464*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1465*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, dataSize + TypeStride(GL_FLOAT), nullptr, GL_STATIC_DRAW);
1466*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ARRAY_BUFFER, 0, dataSize, inputData.data());
1467*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1468*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
1469*8975f5c5SAndroid Build Coastguard Worker
1470*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
1471*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1472*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mExpectedAttrib);
1473*8975f5c5SAndroid Build Coastguard Worker
1474*8975f5c5SAndroid Build Coastguard Worker // Vertex draw with no start vertex offset (second argument is zero).
1475*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
1476*8975f5c5SAndroid Build Coastguard Worker checkPixels();
1477*8975f5c5SAndroid Build Coastguard Worker
1478*8975f5c5SAndroid Build Coastguard Worker // Draw offset by one vertex.
1479*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 1, 6);
1480*8975f5c5SAndroid Build Coastguard Worker checkPixels();
1481*8975f5c5SAndroid Build Coastguard Worker
1482*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
1483*8975f5c5SAndroid Build Coastguard Worker }
1484*8975f5c5SAndroid Build Coastguard Worker
1485*8975f5c5SAndroid Build Coastguard Worker // Verify that using an unaligned offset doesn't mess up the draw.
TEST_P(VertexAttributeTest,DrawArraysWithUnalignedBufferOffset)1486*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, DrawArraysWithUnalignedBufferOffset)
1487*8975f5c5SAndroid Build Coastguard Worker {
1488*8975f5c5SAndroid Build Coastguard Worker initBasicProgram();
1489*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
1490*8975f5c5SAndroid Build Coastguard Worker
1491*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> inputData;
1492*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
1493*8975f5c5SAndroid Build Coastguard Worker InitTestData(inputData, expectedData);
1494*8975f5c5SAndroid Build Coastguard Worker
1495*8975f5c5SAndroid Build Coastguard Worker GLBuffer quadBuffer;
1496*8975f5c5SAndroid Build Coastguard Worker InitQuadPlusOneVertexBuffer(&quadBuffer);
1497*8975f5c5SAndroid Build Coastguard Worker
1498*8975f5c5SAndroid Build Coastguard Worker GLint positionLocation = glGetAttribLocation(mProgram, "position");
1499*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, positionLocation);
1500*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1501*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(positionLocation);
1502*8975f5c5SAndroid Build Coastguard Worker
1503*8975f5c5SAndroid Build Coastguard Worker // Unaligned buffer offset (3)
1504*8975f5c5SAndroid Build Coastguard Worker GLsizei dataSize = kVertexCount * TypeStride(GL_FLOAT) + 3;
1505*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1506*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, dataSize, nullptr, GL_STATIC_DRAW);
1507*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ARRAY_BUFFER, 3, dataSize - 3, inputData.data());
1508*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(3));
1509*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
1510*8975f5c5SAndroid Build Coastguard Worker
1511*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
1512*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1513*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mExpectedAttrib);
1514*8975f5c5SAndroid Build Coastguard Worker
1515*8975f5c5SAndroid Build Coastguard Worker // Vertex draw with no start vertex offset (second argument is zero).
1516*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
1517*8975f5c5SAndroid Build Coastguard Worker checkPixels();
1518*8975f5c5SAndroid Build Coastguard Worker
1519*8975f5c5SAndroid Build Coastguard Worker // Draw offset by one vertex.
1520*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 1, 6);
1521*8975f5c5SAndroid Build Coastguard Worker checkPixels();
1522*8975f5c5SAndroid Build Coastguard Worker
1523*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
1524*8975f5c5SAndroid Build Coastguard Worker }
1525*8975f5c5SAndroid Build Coastguard Worker
1526*8975f5c5SAndroid Build Coastguard Worker // Verify that using an unaligned offset & GL_SHORT vertex attribute doesn't mess up the draw.
1527*8975f5c5SAndroid Build Coastguard Worker // In Metal backend, GL_SHORTx3 is coverted to GL_SHORTx4 if offset is unaligned.
TEST_P(VertexAttributeTest,DrawArraysWithUnalignedShortBufferOffset)1528*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, DrawArraysWithUnalignedShortBufferOffset)
1529*8975f5c5SAndroid Build Coastguard Worker {
1530*8975f5c5SAndroid Build Coastguard Worker initBasicProgram();
1531*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
1532*8975f5c5SAndroid Build Coastguard Worker
1533*8975f5c5SAndroid Build Coastguard Worker // input data is GL_SHORTx3 (6 bytes) but stride=8
1534*8975f5c5SAndroid Build Coastguard Worker std::array<GLshort, 4 * kVertexCount> inputData;
1535*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, 3 * kVertexCount> expectedData;
1536*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; ++i)
1537*8975f5c5SAndroid Build Coastguard Worker {
1538*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i] = 3 * i;
1539*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 1] = 3 * i + 1;
1540*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 2] = 3 * i + 2;
1541*8975f5c5SAndroid Build Coastguard Worker
1542*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i] = 3 * i;
1543*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i + 1] = 3 * i + 1;
1544*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i + 2] = 3 * i + 2;
1545*8975f5c5SAndroid Build Coastguard Worker }
1546*8975f5c5SAndroid Build Coastguard Worker
1547*8975f5c5SAndroid Build Coastguard Worker GLBuffer quadBuffer;
1548*8975f5c5SAndroid Build Coastguard Worker InitQuadPlusOneVertexBuffer(&quadBuffer);
1549*8975f5c5SAndroid Build Coastguard Worker
1550*8975f5c5SAndroid Build Coastguard Worker GLint positionLocation = glGetAttribLocation(mProgram, "position");
1551*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, positionLocation);
1552*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1553*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(positionLocation);
1554*8975f5c5SAndroid Build Coastguard Worker
1555*8975f5c5SAndroid Build Coastguard Worker // Unaligned buffer offset (8)
1556*8975f5c5SAndroid Build Coastguard Worker GLsizei dataSize = 3 * kVertexCount * TypeStride(GL_SHORT) + 8;
1557*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1558*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, dataSize, nullptr, GL_STATIC_DRAW);
1559*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ARRAY_BUFFER, 8, dataSize - 8, inputData.data());
1560*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, 3, GL_SHORT, GL_FALSE, /* stride */ 8,
1561*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<void *>(8));
1562*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
1563*8975f5c5SAndroid Build Coastguard Worker
1564*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
1565*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1566*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mExpectedAttrib);
1567*8975f5c5SAndroid Build Coastguard Worker
1568*8975f5c5SAndroid Build Coastguard Worker // Vertex draw with no start vertex offset (second argument is zero).
1569*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
1570*8975f5c5SAndroid Build Coastguard Worker checkPixels();
1571*8975f5c5SAndroid Build Coastguard Worker
1572*8975f5c5SAndroid Build Coastguard Worker // Draw offset by one vertex.
1573*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 1, 6);
1574*8975f5c5SAndroid Build Coastguard Worker checkPixels();
1575*8975f5c5SAndroid Build Coastguard Worker
1576*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
1577*8975f5c5SAndroid Build Coastguard Worker }
1578*8975f5c5SAndroid Build Coastguard Worker
1579*8975f5c5SAndroid Build Coastguard Worker // Verify that using a GL_FLOATx2 attribute with offset not divisible by 8 works.
TEST_P(VertexAttributeTest,DrawArraysWith2FloatAtOffsetNotDivisbleBy8)1580*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, DrawArraysWith2FloatAtOffsetNotDivisbleBy8)
1581*8975f5c5SAndroid Build Coastguard Worker {
1582*8975f5c5SAndroid Build Coastguard Worker initBasicProgram();
1583*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
1584*8975f5c5SAndroid Build Coastguard Worker
1585*8975f5c5SAndroid Build Coastguard Worker // input data is GL_FLOATx2 (8 bytes) and stride=36
1586*8975f5c5SAndroid Build Coastguard Worker std::array<GLubyte, 36 * kVertexCount> inputData;
1587*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, 2 * kVertexCount> expectedData;
1588*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; ++i)
1589*8975f5c5SAndroid Build Coastguard Worker {
1590*8975f5c5SAndroid Build Coastguard Worker expectedData[2 * i] = 2 * i;
1591*8975f5c5SAndroid Build Coastguard Worker expectedData[2 * i + 1] = 2 * i + 1;
1592*8975f5c5SAndroid Build Coastguard Worker
1593*8975f5c5SAndroid Build Coastguard Worker GLubyte *input = inputData.data() + 36 * i;
1594*8975f5c5SAndroid Build Coastguard Worker memcpy(input, &expectedData[2 * i], sizeof(float));
1595*8975f5c5SAndroid Build Coastguard Worker memcpy(input + sizeof(float), &expectedData[2 * i + 1], sizeof(float));
1596*8975f5c5SAndroid Build Coastguard Worker }
1597*8975f5c5SAndroid Build Coastguard Worker
1598*8975f5c5SAndroid Build Coastguard Worker GLBuffer quadBuffer;
1599*8975f5c5SAndroid Build Coastguard Worker InitQuadPlusOneVertexBuffer(&quadBuffer);
1600*8975f5c5SAndroid Build Coastguard Worker
1601*8975f5c5SAndroid Build Coastguard Worker GLint positionLocation = glGetAttribLocation(mProgram, "position");
1602*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, positionLocation);
1603*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1604*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(positionLocation);
1605*8975f5c5SAndroid Build Coastguard Worker
1606*8975f5c5SAndroid Build Coastguard Worker // offset is not float2 aligned (28)
1607*8975f5c5SAndroid Build Coastguard Worker GLsizei dataSize = 36 * kVertexCount + 28;
1608*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1609*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, dataSize, nullptr, GL_STATIC_DRAW);
1610*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ARRAY_BUFFER, 28, dataSize - 28, inputData.data());
1611*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, 2, GL_FLOAT, GL_FALSE, /* stride */ 36,
1612*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<void *>(28));
1613*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
1614*8975f5c5SAndroid Build Coastguard Worker
1615*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
1616*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, 2, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1617*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mExpectedAttrib);
1618*8975f5c5SAndroid Build Coastguard Worker
1619*8975f5c5SAndroid Build Coastguard Worker // Vertex draw with no start vertex offset (second argument is zero).
1620*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
1621*8975f5c5SAndroid Build Coastguard Worker checkPixels();
1622*8975f5c5SAndroid Build Coastguard Worker
1623*8975f5c5SAndroid Build Coastguard Worker // Draw offset by one vertex.
1624*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 1, 6);
1625*8975f5c5SAndroid Build Coastguard Worker checkPixels();
1626*8975f5c5SAndroid Build Coastguard Worker
1627*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
1628*8975f5c5SAndroid Build Coastguard Worker }
1629*8975f5c5SAndroid Build Coastguard Worker
1630*8975f5c5SAndroid Build Coastguard Worker // Verify that using offset=1 for GL_BYTE vertex attribute doesn't mess up the draw.
1631*8975f5c5SAndroid Build Coastguard Worker // Depending on backend, offset=1 for GL_BYTE could be natively supported or not.
1632*8975f5c5SAndroid Build Coastguard Worker // In the latter case, a vertex data conversion will have to be performed.
TEST_P(VertexAttributeTest,DrawArraysWithByteAtOffset1)1633*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, DrawArraysWithByteAtOffset1)
1634*8975f5c5SAndroid Build Coastguard Worker {
1635*8975f5c5SAndroid Build Coastguard Worker initBasicProgram();
1636*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
1637*8975f5c5SAndroid Build Coastguard Worker
1638*8975f5c5SAndroid Build Coastguard Worker // input data is GL_BYTEx3 (3 bytes) but stride=4
1639*8975f5c5SAndroid Build Coastguard Worker std::array<GLbyte, 4 * kVertexCount> inputData;
1640*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, 3 * kVertexCount> expectedData;
1641*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; ++i)
1642*8975f5c5SAndroid Build Coastguard Worker {
1643*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i] = 3 * i;
1644*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 1] = 3 * i + 1;
1645*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 2] = 3 * i + 2;
1646*8975f5c5SAndroid Build Coastguard Worker
1647*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i] = 3 * i;
1648*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i + 1] = 3 * i + 1;
1649*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i + 2] = 3 * i + 2;
1650*8975f5c5SAndroid Build Coastguard Worker }
1651*8975f5c5SAndroid Build Coastguard Worker
1652*8975f5c5SAndroid Build Coastguard Worker GLBuffer quadBuffer;
1653*8975f5c5SAndroid Build Coastguard Worker InitQuadPlusOneVertexBuffer(&quadBuffer);
1654*8975f5c5SAndroid Build Coastguard Worker
1655*8975f5c5SAndroid Build Coastguard Worker GLint positionLocation = glGetAttribLocation(mProgram, "position");
1656*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, positionLocation);
1657*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1658*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(positionLocation);
1659*8975f5c5SAndroid Build Coastguard Worker
1660*8975f5c5SAndroid Build Coastguard Worker // Buffer offset (1)
1661*8975f5c5SAndroid Build Coastguard Worker GLsizei dataSize = 4 * kVertexCount + 1;
1662*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1663*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, dataSize, nullptr, GL_STATIC_DRAW);
1664*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ARRAY_BUFFER, 1, dataSize - 1, inputData.data());
1665*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, 3, GL_BYTE, GL_FALSE, /* stride */ 4,
1666*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<void *>(1));
1667*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
1668*8975f5c5SAndroid Build Coastguard Worker
1669*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
1670*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1671*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mExpectedAttrib);
1672*8975f5c5SAndroid Build Coastguard Worker
1673*8975f5c5SAndroid Build Coastguard Worker // Vertex draw with no start vertex offset (second argument is zero).
1674*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
1675*8975f5c5SAndroid Build Coastguard Worker checkPixels();
1676*8975f5c5SAndroid Build Coastguard Worker
1677*8975f5c5SAndroid Build Coastguard Worker // Draw offset by one vertex.
1678*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 1, 6);
1679*8975f5c5SAndroid Build Coastguard Worker checkPixels();
1680*8975f5c5SAndroid Build Coastguard Worker
1681*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
1682*8975f5c5SAndroid Build Coastguard Worker }
1683*8975f5c5SAndroid Build Coastguard Worker
1684*8975f5c5SAndroid Build Coastguard Worker // Verify that using an aligned but non-multiples of 4 offset vertex attribute doesn't mess up the
1685*8975f5c5SAndroid Build Coastguard Worker // draw.
TEST_P(VertexAttributeTest,DrawArraysWithShortBufferOffsetNotMultipleOf4)1686*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, DrawArraysWithShortBufferOffsetNotMultipleOf4)
1687*8975f5c5SAndroid Build Coastguard Worker {
1688*8975f5c5SAndroid Build Coastguard Worker // http://anglebug.com/42263937
1689*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
1690*8975f5c5SAndroid Build Coastguard Worker
1691*8975f5c5SAndroid Build Coastguard Worker initBasicProgram();
1692*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
1693*8975f5c5SAndroid Build Coastguard Worker
1694*8975f5c5SAndroid Build Coastguard Worker // input data is GL_SHORTx3 (6 bytes) but stride=8
1695*8975f5c5SAndroid Build Coastguard Worker std::array<GLshort, 4 * kVertexCount> inputData;
1696*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, 3 * kVertexCount> expectedData;
1697*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; ++i)
1698*8975f5c5SAndroid Build Coastguard Worker {
1699*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i] = 3 * i;
1700*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 1] = 3 * i + 1;
1701*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 2] = 3 * i + 2;
1702*8975f5c5SAndroid Build Coastguard Worker
1703*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i] = 3 * i;
1704*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i + 1] = 3 * i + 1;
1705*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i + 2] = 3 * i + 2;
1706*8975f5c5SAndroid Build Coastguard Worker }
1707*8975f5c5SAndroid Build Coastguard Worker
1708*8975f5c5SAndroid Build Coastguard Worker GLBuffer quadBuffer;
1709*8975f5c5SAndroid Build Coastguard Worker InitQuadPlusOneVertexBuffer(&quadBuffer);
1710*8975f5c5SAndroid Build Coastguard Worker
1711*8975f5c5SAndroid Build Coastguard Worker GLint positionLocation = glGetAttribLocation(mProgram, "position");
1712*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, positionLocation);
1713*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1714*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(positionLocation);
1715*8975f5c5SAndroid Build Coastguard Worker
1716*8975f5c5SAndroid Build Coastguard Worker // Aligned but not multiples of 4 buffer offset (18)
1717*8975f5c5SAndroid Build Coastguard Worker GLsizei dataSize = 4 * kVertexCount * TypeStride(GL_SHORT) + 8;
1718*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1719*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, dataSize, nullptr, GL_STATIC_DRAW);
1720*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ARRAY_BUFFER, 18, dataSize - 18, inputData.data());
1721*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, 3, GL_SHORT, GL_FALSE, /* stride */ 8,
1722*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<void *>(18));
1723*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
1724*8975f5c5SAndroid Build Coastguard Worker
1725*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
1726*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1727*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mExpectedAttrib);
1728*8975f5c5SAndroid Build Coastguard Worker
1729*8975f5c5SAndroid Build Coastguard Worker // Vertex draw with no start vertex offset (second argument is zero).
1730*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
1731*8975f5c5SAndroid Build Coastguard Worker checkPixels();
1732*8975f5c5SAndroid Build Coastguard Worker
1733*8975f5c5SAndroid Build Coastguard Worker // Draw offset by one vertex.
1734*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 1, 6);
1735*8975f5c5SAndroid Build Coastguard Worker checkPixels();
1736*8975f5c5SAndroid Build Coastguard Worker
1737*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
1738*8975f5c5SAndroid Build Coastguard Worker }
1739*8975f5c5SAndroid Build Coastguard Worker
1740*8975f5c5SAndroid Build Coastguard Worker // Verify that using both aligned and unaligned offsets doesn't mess up the draw.
TEST_P(VertexAttributeTest,DrawArraysWithAlignedAndUnalignedBufferOffset)1741*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, DrawArraysWithAlignedAndUnalignedBufferOffset)
1742*8975f5c5SAndroid Build Coastguard Worker {
1743*8975f5c5SAndroid Build Coastguard Worker initBasicProgram();
1744*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
1745*8975f5c5SAndroid Build Coastguard Worker
1746*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> inputData;
1747*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
1748*8975f5c5SAndroid Build Coastguard Worker InitTestData(inputData, expectedData);
1749*8975f5c5SAndroid Build Coastguard Worker
1750*8975f5c5SAndroid Build Coastguard Worker GLBuffer quadBuffer;
1751*8975f5c5SAndroid Build Coastguard Worker InitQuadPlusOneVertexBuffer(&quadBuffer);
1752*8975f5c5SAndroid Build Coastguard Worker
1753*8975f5c5SAndroid Build Coastguard Worker GLint positionLocation = glGetAttribLocation(mProgram, "position");
1754*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, positionLocation);
1755*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1756*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(positionLocation);
1757*8975f5c5SAndroid Build Coastguard Worker
1758*8975f5c5SAndroid Build Coastguard Worker // ----------- Aligned buffer offset (4) -------------
1759*8975f5c5SAndroid Build Coastguard Worker GLsizei dataSize = kVertexCount * TypeStride(GL_FLOAT) + 4;
1760*8975f5c5SAndroid Build Coastguard Worker GLBuffer alignedBufer;
1761*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, alignedBufer);
1762*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, dataSize, nullptr, GL_STATIC_DRAW);
1763*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ARRAY_BUFFER, 4, dataSize - 4, inputData.data());
1764*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(4));
1765*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
1766*8975f5c5SAndroid Build Coastguard Worker
1767*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
1768*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1769*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mExpectedAttrib);
1770*8975f5c5SAndroid Build Coastguard Worker
1771*8975f5c5SAndroid Build Coastguard Worker // Vertex draw with no start vertex offset (second argument is zero).
1772*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
1773*8975f5c5SAndroid Build Coastguard Worker checkPixels();
1774*8975f5c5SAndroid Build Coastguard Worker
1775*8975f5c5SAndroid Build Coastguard Worker // Draw offset by one vertex.
1776*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 1, 6);
1777*8975f5c5SAndroid Build Coastguard Worker checkPixels();
1778*8975f5c5SAndroid Build Coastguard Worker
1779*8975f5c5SAndroid Build Coastguard Worker // ----------- Unaligned buffer offset (3) -------------
1780*8975f5c5SAndroid Build Coastguard Worker glClear(GL_COLOR_BUFFER_BIT);
1781*8975f5c5SAndroid Build Coastguard Worker
1782*8975f5c5SAndroid Build Coastguard Worker dataSize = kVertexCount * TypeStride(GL_FLOAT) + 3;
1783*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1784*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, dataSize, nullptr, GL_STATIC_DRAW);
1785*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ARRAY_BUFFER, 3, dataSize - 3, inputData.data());
1786*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0, reinterpret_cast<void *>(3));
1787*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
1788*8975f5c5SAndroid Build Coastguard Worker
1789*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
1790*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1791*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mExpectedAttrib);
1792*8975f5c5SAndroid Build Coastguard Worker
1793*8975f5c5SAndroid Build Coastguard Worker // Vertex draw with no start vertex offset (second argument is zero).
1794*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
1795*8975f5c5SAndroid Build Coastguard Worker checkPixels();
1796*8975f5c5SAndroid Build Coastguard Worker
1797*8975f5c5SAndroid Build Coastguard Worker // Draw offset by one vertex.
1798*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 1, 6);
1799*8975f5c5SAndroid Build Coastguard Worker checkPixels();
1800*8975f5c5SAndroid Build Coastguard Worker
1801*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
1802*8975f5c5SAndroid Build Coastguard Worker }
1803*8975f5c5SAndroid Build Coastguard Worker
1804*8975f5c5SAndroid Build Coastguard Worker // Verify that when we pass a client memory pointer to a disabled attribute the draw is still
1805*8975f5c5SAndroid Build Coastguard Worker // correct.
TEST_P(VertexAttributeTest,DrawArraysWithDisabledAttribute)1806*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, DrawArraysWithDisabledAttribute)
1807*8975f5c5SAndroid Build Coastguard Worker {
1808*8975f5c5SAndroid Build Coastguard Worker initBasicProgram();
1809*8975f5c5SAndroid Build Coastguard Worker
1810*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> inputData;
1811*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
1812*8975f5c5SAndroid Build Coastguard Worker InitTestData(inputData, expectedData);
1813*8975f5c5SAndroid Build Coastguard Worker
1814*8975f5c5SAndroid Build Coastguard Worker GLBuffer buffer;
1815*8975f5c5SAndroid Build Coastguard Worker InitQuadVertexBuffer(&buffer);
1816*8975f5c5SAndroid Build Coastguard Worker
1817*8975f5c5SAndroid Build Coastguard Worker GLint positionLocation = glGetAttribLocation(mProgram, "position");
1818*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, positionLocation);
1819*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1820*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(positionLocation);
1821*8975f5c5SAndroid Build Coastguard Worker
1822*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1823*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, sizeof(inputData), inputData.data(), GL_STATIC_DRAW);
1824*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1825*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
1826*8975f5c5SAndroid Build Coastguard Worker
1827*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
1828*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1829*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mExpectedAttrib);
1830*8975f5c5SAndroid Build Coastguard Worker
1831*8975f5c5SAndroid Build Coastguard Worker // mProgram2 adds an attribute 'disabled' on the basis of mProgram.
1832*8975f5c5SAndroid Build Coastguard Worker constexpr char testVertexShaderSource2[] =
1833*8975f5c5SAndroid Build Coastguard Worker "attribute mediump vec4 position;\n"
1834*8975f5c5SAndroid Build Coastguard Worker "attribute mediump vec4 test;\n"
1835*8975f5c5SAndroid Build Coastguard Worker "attribute mediump vec4 expected;\n"
1836*8975f5c5SAndroid Build Coastguard Worker "attribute mediump vec4 disabled;\n"
1837*8975f5c5SAndroid Build Coastguard Worker "varying mediump vec4 color;\n"
1838*8975f5c5SAndroid Build Coastguard Worker "void main(void)\n"
1839*8975f5c5SAndroid Build Coastguard Worker "{\n"
1840*8975f5c5SAndroid Build Coastguard Worker " gl_Position = position;\n"
1841*8975f5c5SAndroid Build Coastguard Worker " vec4 threshold = max(abs(expected + disabled) * 0.005, 1.0 / 64.0);\n"
1842*8975f5c5SAndroid Build Coastguard Worker " color = vec4(lessThanEqual(abs(test - expected), threshold));\n"
1843*8975f5c5SAndroid Build Coastguard Worker "}\n";
1844*8975f5c5SAndroid Build Coastguard Worker
1845*8975f5c5SAndroid Build Coastguard Worker constexpr char testFragmentShaderSource[] =
1846*8975f5c5SAndroid Build Coastguard Worker "varying mediump vec4 color;\n"
1847*8975f5c5SAndroid Build Coastguard Worker "void main(void)\n"
1848*8975f5c5SAndroid Build Coastguard Worker "{\n"
1849*8975f5c5SAndroid Build Coastguard Worker " gl_FragColor = color;\n"
1850*8975f5c5SAndroid Build Coastguard Worker "}\n";
1851*8975f5c5SAndroid Build Coastguard Worker
1852*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(program, testVertexShaderSource2, testFragmentShaderSource);
1853*8975f5c5SAndroid Build Coastguard Worker GLuint mProgram2 = program;
1854*8975f5c5SAndroid Build Coastguard Worker
1855*8975f5c5SAndroid Build Coastguard Worker ASSERT_EQ(positionLocation, glGetAttribLocation(mProgram2, "position"));
1856*8975f5c5SAndroid Build Coastguard Worker ASSERT_EQ(mTestAttrib, glGetAttribLocation(mProgram2, "test"));
1857*8975f5c5SAndroid Build Coastguard Worker ASSERT_EQ(mExpectedAttrib, glGetAttribLocation(mProgram2, "expected"));
1858*8975f5c5SAndroid Build Coastguard Worker
1859*8975f5c5SAndroid Build Coastguard Worker // Pass a client memory pointer to disabledAttribute and disable it.
1860*8975f5c5SAndroid Build Coastguard Worker GLint disabledAttribute = glGetAttribLocation(mProgram2, "disabled");
1861*8975f5c5SAndroid Build Coastguard Worker ASSERT_EQ(-1, glGetAttribLocation(mProgram, "disabled"));
1862*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(disabledAttribute, 1, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1863*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(disabledAttribute);
1864*8975f5c5SAndroid Build Coastguard Worker
1865*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
1866*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
1867*8975f5c5SAndroid Build Coastguard Worker checkPixels();
1868*8975f5c5SAndroid Build Coastguard Worker
1869*8975f5c5SAndroid Build Coastguard Worker // Now enable disabledAttribute which should be used in mProgram2.
1870*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(disabledAttribute);
1871*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram2);
1872*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
1873*8975f5c5SAndroid Build Coastguard Worker checkPixels();
1874*8975f5c5SAndroid Build Coastguard Worker
1875*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
1876*8975f5c5SAndroid Build Coastguard Worker }
1877*8975f5c5SAndroid Build Coastguard Worker
1878*8975f5c5SAndroid Build Coastguard Worker // Test based on WebGL Test attribs/gl-disabled-vertex-attrib.html
TEST_P(VertexAttributeTest,DisabledAttribArrays)1879*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, DisabledAttribArrays)
1880*8975f5c5SAndroid Build Coastguard Worker {
1881*8975f5c5SAndroid Build Coastguard Worker // Known failure on Retina MBP: http://crbug.com/635081
1882*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsMac() && IsNVIDIA());
1883*8975f5c5SAndroid Build Coastguard Worker
1884*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] =
1885*8975f5c5SAndroid Build Coastguard Worker "attribute vec4 a_position;\n"
1886*8975f5c5SAndroid Build Coastguard Worker "attribute vec4 a_color;\n"
1887*8975f5c5SAndroid Build Coastguard Worker "varying vec4 v_color;\n"
1888*8975f5c5SAndroid Build Coastguard Worker "bool isCorrectColor(vec4 v) {\n"
1889*8975f5c5SAndroid Build Coastguard Worker " return v.x == 0.0 && v.y == 0.0 && v.z == 0.0 && v.w == 1.0;\n"
1890*8975f5c5SAndroid Build Coastguard Worker "}"
1891*8975f5c5SAndroid Build Coastguard Worker "void main() {\n"
1892*8975f5c5SAndroid Build Coastguard Worker " gl_Position = a_position;\n"
1893*8975f5c5SAndroid Build Coastguard Worker " v_color = isCorrectColor(a_color) ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);\n"
1894*8975f5c5SAndroid Build Coastguard Worker "}";
1895*8975f5c5SAndroid Build Coastguard Worker
1896*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] =
1897*8975f5c5SAndroid Build Coastguard Worker "varying mediump vec4 v_color;\n"
1898*8975f5c5SAndroid Build Coastguard Worker "void main() {\n"
1899*8975f5c5SAndroid Build Coastguard Worker " gl_FragColor = v_color;\n"
1900*8975f5c5SAndroid Build Coastguard Worker "}";
1901*8975f5c5SAndroid Build Coastguard Worker
1902*8975f5c5SAndroid Build Coastguard Worker GLint maxVertexAttribs = 0;
1903*8975f5c5SAndroid Build Coastguard Worker glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
1904*8975f5c5SAndroid Build Coastguard Worker
1905*8975f5c5SAndroid Build Coastguard Worker for (GLint colorIndex = 0; colorIndex < maxVertexAttribs; ++colorIndex)
1906*8975f5c5SAndroid Build Coastguard Worker {
1907*8975f5c5SAndroid Build Coastguard Worker GLuint program = CompileProgram(kVS, kFS, [&](GLuint program) {
1908*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, colorIndex, "a_color");
1909*8975f5c5SAndroid Build Coastguard Worker });
1910*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(0u, program);
1911*8975f5c5SAndroid Build Coastguard Worker
1912*8975f5c5SAndroid Build Coastguard Worker drawQuad(program, "a_position", 0.5f);
1913*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
1914*8975f5c5SAndroid Build Coastguard Worker
1915*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green) << "color index " << colorIndex;
1916*8975f5c5SAndroid Build Coastguard Worker
1917*8975f5c5SAndroid Build Coastguard Worker glDeleteProgram(program);
1918*8975f5c5SAndroid Build Coastguard Worker }
1919*8975f5c5SAndroid Build Coastguard Worker }
1920*8975f5c5SAndroid Build Coastguard Worker
1921*8975f5c5SAndroid Build Coastguard Worker // Test that draw with offset larger than vertex attribute's stride can work
TEST_P(VertexAttributeTest,DrawWithLargeBufferOffset)1922*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, DrawWithLargeBufferOffset)
1923*8975f5c5SAndroid Build Coastguard Worker {
1924*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kBufferOffset = 10000;
1925*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kQuadVertexCount = 4;
1926*8975f5c5SAndroid Build Coastguard Worker
1927*8975f5c5SAndroid Build Coastguard Worker std::array<GLbyte, kQuadVertexCount> validInputData = {{0, 1, 2, 3}};
1928*8975f5c5SAndroid Build Coastguard Worker
1929*8975f5c5SAndroid Build Coastguard Worker // 4 components
1930*8975f5c5SAndroid Build Coastguard Worker std::array<GLbyte, 4 * kQuadVertexCount + kBufferOffset> inputData = {};
1931*8975f5c5SAndroid Build Coastguard Worker
1932*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, 4 * kQuadVertexCount> expectedData;
1933*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kQuadVertexCount; i++)
1934*8975f5c5SAndroid Build Coastguard Worker {
1935*8975f5c5SAndroid Build Coastguard Worker for (int j = 0; j < 4; ++j)
1936*8975f5c5SAndroid Build Coastguard Worker {
1937*8975f5c5SAndroid Build Coastguard Worker inputData[kBufferOffset + 4 * i + j] = validInputData[i];
1938*8975f5c5SAndroid Build Coastguard Worker expectedData[4 * i + j] = validInputData[i];
1939*8975f5c5SAndroid Build Coastguard Worker }
1940*8975f5c5SAndroid Build Coastguard Worker }
1941*8975f5c5SAndroid Build Coastguard Worker
1942*8975f5c5SAndroid Build Coastguard Worker initBasicProgram();
1943*8975f5c5SAndroid Build Coastguard Worker
1944*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1945*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, inputData.size(), inputData.data(), GL_STATIC_DRAW);
1946*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, 4, GL_BYTE, GL_FALSE, 0,
1947*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<const void *>(kBufferOffset));
1948*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
1949*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
1950*8975f5c5SAndroid Build Coastguard Worker
1951*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, 4, GL_FLOAT, GL_FALSE, 0, expectedData.data());
1952*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mExpectedAttrib);
1953*8975f5c5SAndroid Build Coastguard Worker
1954*8975f5c5SAndroid Build Coastguard Worker drawIndexedQuad(mProgram, "position", 0.5f);
1955*8975f5c5SAndroid Build Coastguard Worker
1956*8975f5c5SAndroid Build Coastguard Worker checkPixels();
1957*8975f5c5SAndroid Build Coastguard Worker }
1958*8975f5c5SAndroid Build Coastguard Worker
1959*8975f5c5SAndroid Build Coastguard Worker // Test that drawing with large vertex attribute pointer offset and less components than
1960*8975f5c5SAndroid Build Coastguard Worker // shader expects is OK
TEST_P(VertexAttributeTest,DrawWithLargeBufferOffsetAndLessComponents)1961*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, DrawWithLargeBufferOffsetAndLessComponents)
1962*8975f5c5SAndroid Build Coastguard Worker {
1963*8975f5c5SAndroid Build Coastguard Worker // Shader expects vec4 but glVertexAttribPointer only provides 2 components
1964*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] = R"(attribute vec4 a_position;
1965*8975f5c5SAndroid Build Coastguard Worker attribute vec4 a_attrib;
1966*8975f5c5SAndroid Build Coastguard Worker varying vec4 v_attrib;
1967*8975f5c5SAndroid Build Coastguard Worker void main()
1968*8975f5c5SAndroid Build Coastguard Worker {
1969*8975f5c5SAndroid Build Coastguard Worker v_attrib = a_attrib;
1970*8975f5c5SAndroid Build Coastguard Worker gl_Position = a_position;
1971*8975f5c5SAndroid Build Coastguard Worker })";
1972*8975f5c5SAndroid Build Coastguard Worker
1973*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] = R"(precision mediump float;
1974*8975f5c5SAndroid Build Coastguard Worker varying vec4 v_attrib;
1975*8975f5c5SAndroid Build Coastguard Worker void main()
1976*8975f5c5SAndroid Build Coastguard Worker {
1977*8975f5c5SAndroid Build Coastguard Worker gl_FragColor = v_attrib;
1978*8975f5c5SAndroid Build Coastguard Worker })";
1979*8975f5c5SAndroid Build Coastguard Worker
1980*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(program, kVS, kFS);
1981*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 0, "a_position");
1982*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 1, "a_attrib");
1983*8975f5c5SAndroid Build Coastguard Worker glLinkProgram(program);
1984*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
1985*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
1986*8975f5c5SAndroid Build Coastguard Worker
1987*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kBufferOffset = 4998;
1988*8975f5c5SAndroid Build Coastguard Worker
1989*8975f5c5SAndroid Build Coastguard Worker // Set up color data so yellow is drawn (only R, G components are provided)
1990*8975f5c5SAndroid Build Coastguard Worker std::vector<GLushort> data(kBufferOffset + 12);
1991*8975f5c5SAndroid Build Coastguard Worker for (int i = 0; i < 12; ++i)
1992*8975f5c5SAndroid Build Coastguard Worker {
1993*8975f5c5SAndroid Build Coastguard Worker data[kBufferOffset + i] = 0xffff;
1994*8975f5c5SAndroid Build Coastguard Worker }
1995*8975f5c5SAndroid Build Coastguard Worker
1996*8975f5c5SAndroid Build Coastguard Worker GLBuffer buffer;
1997*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, buffer);
1998*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, sizeof(GLushort) * data.size(), data.data(), GL_STATIC_DRAW);
1999*8975f5c5SAndroid Build Coastguard Worker // Provide only 2 components for the vec4 in the shader
2000*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(1, 2, GL_UNSIGNED_SHORT, GL_TRUE, 0,
2001*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<const void *>(sizeof(GLushort) * kBufferOffset));
2002*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
2003*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(1);
2004*8975f5c5SAndroid Build Coastguard Worker
2005*8975f5c5SAndroid Build Coastguard Worker drawQuad(program, "a_position", 0.5f);
2006*8975f5c5SAndroid Build Coastguard Worker // Verify yellow was drawn
2007*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
2008*8975f5c5SAndroid Build Coastguard Worker }
2009*8975f5c5SAndroid Build Coastguard Worker
2010*8975f5c5SAndroid Build Coastguard Worker // Test that drawing with vertex attribute pointer with two non-overlapping BufferSubData calls
2011*8975f5c5SAndroid Build Coastguard Worker // works correctly, especially when vertex conversion is involved.
TEST_P(VertexAttributeTest,DrawArraysWithNonOverlapBufferSubData)2012*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, DrawArraysWithNonOverlapBufferSubData)
2013*8975f5c5SAndroid Build Coastguard Worker {
2014*8975f5c5SAndroid Build Coastguard Worker constexpr size_t vertexCount = 6;
2015*8975f5c5SAndroid Build Coastguard Worker initBasicProgram();
2016*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
2017*8975f5c5SAndroid Build Coastguard Worker
2018*8975f5c5SAndroid Build Coastguard Worker // input data is GL_BYTEx3 (3 bytes) but stride=4
2019*8975f5c5SAndroid Build Coastguard Worker std::array<GLbyte, 4 * vertexCount> inputData;
2020*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, 3 * vertexCount> expectedData;
2021*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < vertexCount; ++i)
2022*8975f5c5SAndroid Build Coastguard Worker {
2023*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i] = 3 * i;
2024*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 1] = 3 * i + 1;
2025*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 2] = 3 * i + 2;
2026*8975f5c5SAndroid Build Coastguard Worker
2027*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i] = 3 * i;
2028*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i + 1] = 3 * i + 1;
2029*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i + 2] = 3 * i + 2;
2030*8975f5c5SAndroid Build Coastguard Worker }
2031*8975f5c5SAndroid Build Coastguard Worker
2032*8975f5c5SAndroid Build Coastguard Worker GLBuffer quadBuffer;
2033*8975f5c5SAndroid Build Coastguard Worker InitQuadVertexBuffer(&quadBuffer);
2034*8975f5c5SAndroid Build Coastguard Worker GLint positionLocation = glGetAttribLocation(mProgram, "position");
2035*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, positionLocation);
2036*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2037*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(positionLocation);
2038*8975f5c5SAndroid Build Coastguard Worker
2039*8975f5c5SAndroid Build Coastguard Worker GLsizei fullDataSize = 4 * vertexCount;
2040*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2041*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, fullDataSize, nullptr, GL_STATIC_DRAW);
2042*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ARRAY_BUFFER, 0, fullDataSize, inputData.data());
2043*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, 3, GL_BYTE, GL_FALSE, /* stride */ 4, nullptr);
2044*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
2045*8975f5c5SAndroid Build Coastguard Worker
2046*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
2047*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0, expectedData.data());
2048*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mExpectedAttrib);
2049*8975f5c5SAndroid Build Coastguard Worker
2050*8975f5c5SAndroid Build Coastguard Worker // Draw quad and verify data
2051*8975f5c5SAndroid Build Coastguard Worker glClearColor(0, 0, 0, 0);
2052*8975f5c5SAndroid Build Coastguard Worker glClear(GL_COLOR_BUFFER_BIT);
2053*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, vertexCount);
2054*8975f5c5SAndroid Build Coastguard Worker checkPixels();
2055*8975f5c5SAndroid Build Coastguard Worker
2056*8975f5c5SAndroid Build Coastguard Worker // Update data with two non-overlapping BufferSubData calls with different set of data
2057*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < vertexCount; ++i)
2058*8975f5c5SAndroid Build Coastguard Worker {
2059*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i] = 3 * (i + vertexCount);
2060*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 1] = 3 * (i + vertexCount) + 1;
2061*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 2] = 3 * (i + vertexCount) + 2;
2062*8975f5c5SAndroid Build Coastguard Worker
2063*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i] = 3 * (i + vertexCount);
2064*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i + 1] = 3 * (i + vertexCount) + 1;
2065*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i + 2] = 3 * (i + vertexCount) + 2;
2066*8975f5c5SAndroid Build Coastguard Worker }
2067*8975f5c5SAndroid Build Coastguard Worker size_t halfDataSize = fullDataSize / 2;
2068*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2069*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ARRAY_BUFFER, 0, halfDataSize, inputData.data());
2070*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ARRAY_BUFFER, halfDataSize, fullDataSize - halfDataSize,
2071*8975f5c5SAndroid Build Coastguard Worker inputData.data() + halfDataSize);
2072*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
2073*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0, expectedData.data());
2074*8975f5c5SAndroid Build Coastguard Worker
2075*8975f5c5SAndroid Build Coastguard Worker // Draw quad and verify data
2076*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
2077*8975f5c5SAndroid Build Coastguard Worker checkPixels();
2078*8975f5c5SAndroid Build Coastguard Worker
2079*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
2080*8975f5c5SAndroid Build Coastguard Worker }
2081*8975f5c5SAndroid Build Coastguard Worker
2082*8975f5c5SAndroid Build Coastguard Worker // Test that drawing with vertex attribute pointer with two overlapping BufferSubData calls works
2083*8975f5c5SAndroid Build Coastguard Worker // correctly, especially when vertex conversion is involved.
TEST_P(VertexAttributeTest,DrawArraysWithOverlapBufferSubData)2084*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, DrawArraysWithOverlapBufferSubData)
2085*8975f5c5SAndroid Build Coastguard Worker {
2086*8975f5c5SAndroid Build Coastguard Worker constexpr size_t vertexCount = 6;
2087*8975f5c5SAndroid Build Coastguard Worker initBasicProgram();
2088*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
2089*8975f5c5SAndroid Build Coastguard Worker
2090*8975f5c5SAndroid Build Coastguard Worker // input data is GL_BYTEx3 (3 bytes) but stride=4
2091*8975f5c5SAndroid Build Coastguard Worker std::array<GLbyte, 4 * vertexCount> inputData;
2092*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, 3 * vertexCount> expectedData;
2093*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < vertexCount; ++i)
2094*8975f5c5SAndroid Build Coastguard Worker {
2095*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i] = 3 * i;
2096*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 1] = 3 * i + 1;
2097*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 2] = 3 * i + 2;
2098*8975f5c5SAndroid Build Coastguard Worker
2099*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i] = 3 * i;
2100*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i + 1] = 3 * i + 1;
2101*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i + 2] = 3 * i + 2;
2102*8975f5c5SAndroid Build Coastguard Worker }
2103*8975f5c5SAndroid Build Coastguard Worker
2104*8975f5c5SAndroid Build Coastguard Worker GLBuffer quadBuffer;
2105*8975f5c5SAndroid Build Coastguard Worker InitQuadVertexBuffer(&quadBuffer);
2106*8975f5c5SAndroid Build Coastguard Worker GLint positionLocation = glGetAttribLocation(mProgram, "position");
2107*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, positionLocation);
2108*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2109*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(positionLocation);
2110*8975f5c5SAndroid Build Coastguard Worker
2111*8975f5c5SAndroid Build Coastguard Worker GLsizei fullDataSize = 4 * vertexCount;
2112*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2113*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, fullDataSize, nullptr, GL_STATIC_DRAW);
2114*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ARRAY_BUFFER, 0, fullDataSize, inputData.data());
2115*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, 3, GL_BYTE, GL_FALSE, /* stride */ 4, nullptr);
2116*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
2117*8975f5c5SAndroid Build Coastguard Worker
2118*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
2119*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0, expectedData.data());
2120*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mExpectedAttrib);
2121*8975f5c5SAndroid Build Coastguard Worker
2122*8975f5c5SAndroid Build Coastguard Worker // Draw quad and verify data
2123*8975f5c5SAndroid Build Coastguard Worker glClearColor(0, 0, 0, 0);
2124*8975f5c5SAndroid Build Coastguard Worker glClear(GL_COLOR_BUFFER_BIT);
2125*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, vertexCount);
2126*8975f5c5SAndroid Build Coastguard Worker checkPixels();
2127*8975f5c5SAndroid Build Coastguard Worker
2128*8975f5c5SAndroid Build Coastguard Worker // Update data with two overlapping BufferSubData calls with different set of data.
2129*8975f5c5SAndroid Build Coastguard Worker size_t halfVertexCount = vertexCount / 2;
2130*8975f5c5SAndroid Build Coastguard Worker size_t quadDataSize = fullDataSize / 4;
2131*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2132*8975f5c5SAndroid Build Coastguard Worker // First subData is for the first 3 quarter of buffer, but only first half contains valid data.
2133*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < vertexCount; ++i)
2134*8975f5c5SAndroid Build Coastguard Worker {
2135*8975f5c5SAndroid Build Coastguard Worker if (i < halfVertexCount)
2136*8975f5c5SAndroid Build Coastguard Worker {
2137*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i] = 3 * (i + vertexCount);
2138*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 1] = 3 * (i + vertexCount) + 1;
2139*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 2] = 3 * (i + vertexCount) + 2;
2140*8975f5c5SAndroid Build Coastguard Worker }
2141*8975f5c5SAndroid Build Coastguard Worker else
2142*8975f5c5SAndroid Build Coastguard Worker {
2143*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i] = 0;
2144*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 1] = 0;
2145*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 2] = 0;
2146*8975f5c5SAndroid Build Coastguard Worker }
2147*8975f5c5SAndroid Build Coastguard Worker
2148*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i] = 3 * (i + vertexCount);
2149*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i + 1] = 3 * (i + vertexCount) + 1;
2150*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i + 2] = 3 * (i + vertexCount) + 2;
2151*8975f5c5SAndroid Build Coastguard Worker }
2152*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ARRAY_BUFFER, 0, 3 * quadDataSize, inputData.data());
2153*8975f5c5SAndroid Build Coastguard Worker // Second subData call is for the last half buffer, which overlaps with previous subData range.
2154*8975f5c5SAndroid Build Coastguard Worker size_t halfDataSize = fullDataSize / 2;
2155*8975f5c5SAndroid Build Coastguard Worker for (size_t i = halfVertexCount; i < vertexCount; ++i)
2156*8975f5c5SAndroid Build Coastguard Worker {
2157*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i] = 3 * (i + vertexCount);
2158*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 1] = 3 * (i + vertexCount) + 1;
2159*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 2] = 3 * (i + vertexCount) + 2;
2160*8975f5c5SAndroid Build Coastguard Worker }
2161*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ARRAY_BUFFER, halfDataSize, fullDataSize - halfDataSize,
2162*8975f5c5SAndroid Build Coastguard Worker inputData.data() + halfDataSize);
2163*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
2164*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0, expectedData.data());
2165*8975f5c5SAndroid Build Coastguard Worker
2166*8975f5c5SAndroid Build Coastguard Worker // Draw quad and verify data
2167*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
2168*8975f5c5SAndroid Build Coastguard Worker checkPixels();
2169*8975f5c5SAndroid Build Coastguard Worker
2170*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
2171*8975f5c5SAndroid Build Coastguard Worker }
2172*8975f5c5SAndroid Build Coastguard Worker
2173*8975f5c5SAndroid Build Coastguard Worker // Test that drawing with vertex attribute pointer with different offset. The second offset is
2174*8975f5c5SAndroid Build Coastguard Worker // multiple stride after first offset.
TEST_P(VertexAttributeTest,DrawArraysWithLargerBindingOffset)2175*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, DrawArraysWithLargerBindingOffset)
2176*8975f5c5SAndroid Build Coastguard Worker {
2177*8975f5c5SAndroid Build Coastguard Worker constexpr size_t vertexCount = 6;
2178*8975f5c5SAndroid Build Coastguard Worker initBasicProgram();
2179*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
2180*8975f5c5SAndroid Build Coastguard Worker
2181*8975f5c5SAndroid Build Coastguard Worker // input data is GL_BYTEx3 (3 bytes) but stride=4
2182*8975f5c5SAndroid Build Coastguard Worker std::array<GLbyte, 4 * vertexCount * 2> inputData;
2183*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, 3 * vertexCount * 2> expectedData;
2184*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < vertexCount * 2; ++i)
2185*8975f5c5SAndroid Build Coastguard Worker {
2186*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i] = 3 * i;
2187*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 1] = 3 * i + 1;
2188*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 2] = 3 * i + 2;
2189*8975f5c5SAndroid Build Coastguard Worker
2190*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i] = 3 * i;
2191*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i + 1] = 3 * i + 1;
2192*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i + 2] = 3 * i + 2;
2193*8975f5c5SAndroid Build Coastguard Worker }
2194*8975f5c5SAndroid Build Coastguard Worker
2195*8975f5c5SAndroid Build Coastguard Worker GLBuffer quadBuffer;
2196*8975f5c5SAndroid Build Coastguard Worker InitQuadVertexBuffer(&quadBuffer);
2197*8975f5c5SAndroid Build Coastguard Worker GLint positionLocation = glGetAttribLocation(mProgram, "position");
2198*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, positionLocation);
2199*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2200*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(positionLocation);
2201*8975f5c5SAndroid Build Coastguard Worker
2202*8975f5c5SAndroid Build Coastguard Worker GLsizei fullDataSize = 4 * vertexCount * 2;
2203*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2204*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, fullDataSize, nullptr, GL_STATIC_DRAW);
2205*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ARRAY_BUFFER, 0, fullDataSize, inputData.data());
2206*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, 3, GL_BYTE, GL_FALSE, /* stride */ 4, /*offset*/ nullptr);
2207*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
2208*8975f5c5SAndroid Build Coastguard Worker
2209*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
2210*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0, /*data*/ expectedData.data());
2211*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mExpectedAttrib);
2212*8975f5c5SAndroid Build Coastguard Worker
2213*8975f5c5SAndroid Build Coastguard Worker // Draw quad and verify data
2214*8975f5c5SAndroid Build Coastguard Worker glClearColor(0, 0, 0, 0);
2215*8975f5c5SAndroid Build Coastguard Worker glClear(GL_COLOR_BUFFER_BIT);
2216*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, vertexCount);
2217*8975f5c5SAndroid Build Coastguard Worker checkPixels();
2218*8975f5c5SAndroid Build Coastguard Worker
2219*8975f5c5SAndroid Build Coastguard Worker // Now bind to a larger offset and then draw and verify
2220*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2221*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, 3, GL_BYTE, GL_FALSE, /* stride */ 4,
2222*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<const void *>(4 * vertexCount));
2223*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
2224*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0,
2225*8975f5c5SAndroid Build Coastguard Worker expectedData.data() + 3 * vertexCount);
2226*8975f5c5SAndroid Build Coastguard Worker // Draw quad and verify data
2227*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, vertexCount);
2228*8975f5c5SAndroid Build Coastguard Worker checkPixels();
2229*8975f5c5SAndroid Build Coastguard Worker
2230*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
2231*8975f5c5SAndroid Build Coastguard Worker }
2232*8975f5c5SAndroid Build Coastguard Worker
2233*8975f5c5SAndroid Build Coastguard Worker // Test that drawing with vertex attribute pointer with different offset. The second offset is
2234*8975f5c5SAndroid Build Coastguard Worker // multiple stride before first offset.
TEST_P(VertexAttributeTest,DrawArraysWithSmallerBindingOffset)2235*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, DrawArraysWithSmallerBindingOffset)
2236*8975f5c5SAndroid Build Coastguard Worker {
2237*8975f5c5SAndroid Build Coastguard Worker constexpr size_t vertexCount = 6;
2238*8975f5c5SAndroid Build Coastguard Worker initBasicProgram();
2239*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
2240*8975f5c5SAndroid Build Coastguard Worker
2241*8975f5c5SAndroid Build Coastguard Worker // input data is GL_BYTEx3 (3 bytes) but stride=4
2242*8975f5c5SAndroid Build Coastguard Worker std::array<GLbyte, 4 * vertexCount * 2> inputData;
2243*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, 3 * vertexCount * 2> expectedData;
2244*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < vertexCount * 2; ++i)
2245*8975f5c5SAndroid Build Coastguard Worker {
2246*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i] = 3 * i;
2247*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 1] = 3 * i + 1;
2248*8975f5c5SAndroid Build Coastguard Worker inputData[4 * i + 2] = 3 * i + 2;
2249*8975f5c5SAndroid Build Coastguard Worker
2250*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i] = 3 * i;
2251*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i + 1] = 3 * i + 1;
2252*8975f5c5SAndroid Build Coastguard Worker expectedData[3 * i + 2] = 3 * i + 2;
2253*8975f5c5SAndroid Build Coastguard Worker }
2254*8975f5c5SAndroid Build Coastguard Worker
2255*8975f5c5SAndroid Build Coastguard Worker GLBuffer quadBuffer;
2256*8975f5c5SAndroid Build Coastguard Worker InitQuadVertexBuffer(&quadBuffer);
2257*8975f5c5SAndroid Build Coastguard Worker GLint positionLocation = glGetAttribLocation(mProgram, "position");
2258*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, positionLocation);
2259*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2260*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(positionLocation);
2261*8975f5c5SAndroid Build Coastguard Worker
2262*8975f5c5SAndroid Build Coastguard Worker GLsizei fullDataSize = 4 * vertexCount * 2;
2263*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2264*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, fullDataSize, nullptr, GL_STATIC_DRAW);
2265*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ARRAY_BUFFER, 0, fullDataSize, inputData.data());
2266*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, 3, GL_BYTE, GL_FALSE, /* stride */ 4,
2267*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<const void *>(4 * vertexCount));
2268*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
2269*8975f5c5SAndroid Build Coastguard Worker
2270*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
2271*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0,
2272*8975f5c5SAndroid Build Coastguard Worker expectedData.data() + 3 * vertexCount);
2273*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mExpectedAttrib);
2274*8975f5c5SAndroid Build Coastguard Worker
2275*8975f5c5SAndroid Build Coastguard Worker // Draw quad and verify data
2276*8975f5c5SAndroid Build Coastguard Worker glClearColor(0, 0, 0, 0);
2277*8975f5c5SAndroid Build Coastguard Worker glClear(GL_COLOR_BUFFER_BIT);
2278*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, vertexCount);
2279*8975f5c5SAndroid Build Coastguard Worker checkPixels();
2280*8975f5c5SAndroid Build Coastguard Worker
2281*8975f5c5SAndroid Build Coastguard Worker // Now bind to a smaller offset and draw and verify.
2282*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2283*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, 3, GL_BYTE, GL_FALSE, /* stride */ 4, /*offset*/ nullptr);
2284*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
2285*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, 3, GL_FLOAT, GL_FALSE, 0, /*data*/ expectedData.data());
2286*8975f5c5SAndroid Build Coastguard Worker // Draw quad and verify data
2287*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, vertexCount);
2288*8975f5c5SAndroid Build Coastguard Worker checkPixels();
2289*8975f5c5SAndroid Build Coastguard Worker
2290*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
2291*8975f5c5SAndroid Build Coastguard Worker }
2292*8975f5c5SAndroid Build Coastguard Worker
2293*8975f5c5SAndroid Build Coastguard Worker // Tests that we do not generate a SIGBUS error on arm when translating unaligned data.
2294*8975f5c5SAndroid Build Coastguard Worker // GL_RG32_SNORM_ANGLEX is used when using glVertexAttribPointer with certain parameters.
TEST_P(VertexAttributeTestES3,DrawWithUnalignedData)2295*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, DrawWithUnalignedData)
2296*8975f5c5SAndroid Build Coastguard Worker {
2297*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] = R"(#version 300 es
2298*8975f5c5SAndroid Build Coastguard Worker precision highp float;
2299*8975f5c5SAndroid Build Coastguard Worker in highp vec4 a_position;
2300*8975f5c5SAndroid Build Coastguard Worker in highp vec2 a_ColorTest;
2301*8975f5c5SAndroid Build Coastguard Worker out highp vec2 v_colorTest;
2302*8975f5c5SAndroid Build Coastguard Worker
2303*8975f5c5SAndroid Build Coastguard Worker void main() {
2304*8975f5c5SAndroid Build Coastguard Worker v_colorTest = a_ColorTest;
2305*8975f5c5SAndroid Build Coastguard Worker gl_Position = a_position;
2306*8975f5c5SAndroid Build Coastguard Worker })";
2307*8975f5c5SAndroid Build Coastguard Worker
2308*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] = R"(#version 300 es
2309*8975f5c5SAndroid Build Coastguard Worker precision highp float;
2310*8975f5c5SAndroid Build Coastguard Worker in highp vec2 v_colorTest;
2311*8975f5c5SAndroid Build Coastguard Worker out vec4 fragColor;
2312*8975f5c5SAndroid Build Coastguard Worker
2313*8975f5c5SAndroid Build Coastguard Worker void main() {
2314*8975f5c5SAndroid Build Coastguard Worker // The input value is 0x01000000 / 0x7FFFFFFF
2315*8975f5c5SAndroid Build Coastguard Worker if(abs(v_colorTest.x - 0.0078125) < 0.001) {
2316*8975f5c5SAndroid Build Coastguard Worker fragColor = vec4(0.0, 1.0, 0.0, 1.0);
2317*8975f5c5SAndroid Build Coastguard Worker } else {
2318*8975f5c5SAndroid Build Coastguard Worker fragColor = vec4(1.0, 0.0, 0.0, 1.0);
2319*8975f5c5SAndroid Build Coastguard Worker }
2320*8975f5c5SAndroid Build Coastguard Worker })";
2321*8975f5c5SAndroid Build Coastguard Worker
2322*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(program, kVS, kFS);
2323*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 0, "a_position");
2324*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 1, "a_ColorTest");
2325*8975f5c5SAndroid Build Coastguard Worker glLinkProgram(program);
2326*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
2327*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
2328*8975f5c5SAndroid Build Coastguard Worker
2329*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kDataSize = 12;
2330*8975f5c5SAndroid Build Coastguard Worker
2331*8975f5c5SAndroid Build Coastguard Worker // Initialize vertex attribute data with 1u32s, but shifted right by a variable number of bytes
2332*8975f5c5SAndroid Build Coastguard Worker GLubyte colorTestData[(kDataSize + 1) * sizeof(GLuint)];
2333*8975f5c5SAndroid Build Coastguard Worker
2334*8975f5c5SAndroid Build Coastguard Worker for (size_t offset = 0; offset < sizeof(GLuint); offset++)
2335*8975f5c5SAndroid Build Coastguard Worker {
2336*8975f5c5SAndroid Build Coastguard Worker for (size_t dataIndex = 0; dataIndex < kDataSize * sizeof(GLuint); dataIndex++)
2337*8975f5c5SAndroid Build Coastguard Worker {
2338*8975f5c5SAndroid Build Coastguard Worker if (dataIndex % sizeof(GLuint) == sizeof(GLuint) - 1)
2339*8975f5c5SAndroid Build Coastguard Worker {
2340*8975f5c5SAndroid Build Coastguard Worker colorTestData[dataIndex + offset] = 1;
2341*8975f5c5SAndroid Build Coastguard Worker }
2342*8975f5c5SAndroid Build Coastguard Worker else
2343*8975f5c5SAndroid Build Coastguard Worker {
2344*8975f5c5SAndroid Build Coastguard Worker
2345*8975f5c5SAndroid Build Coastguard Worker colorTestData[dataIndex + offset] = 0;
2346*8975f5c5SAndroid Build Coastguard Worker }
2347*8975f5c5SAndroid Build Coastguard Worker }
2348*8975f5c5SAndroid Build Coastguard Worker
2349*8975f5c5SAndroid Build Coastguard Worker GLubyte *offsetPtr = &colorTestData[offset];
2350*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(1, 2, GL_INT, GL_TRUE, sizeof(GLuint), offsetPtr);
2351*8975f5c5SAndroid Build Coastguard Worker
2352*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
2353*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(1);
2354*8975f5c5SAndroid Build Coastguard Worker
2355*8975f5c5SAndroid Build Coastguard Worker drawIndexedQuad(program, "a_position", 0.5f, 1.0f, false, true);
2356*8975f5c5SAndroid Build Coastguard Worker
2357*8975f5c5SAndroid Build Coastguard Worker // Verify green was drawn.
2358*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
2359*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
2360*8975f5c5SAndroid Build Coastguard Worker }
2361*8975f5c5SAndroid Build Coastguard Worker }
2362*8975f5c5SAndroid Build Coastguard Worker
2363*8975f5c5SAndroid Build Coastguard Worker // Tests that rendering is fine if GL_ANGLE_relaxed_vertex_attribute_type is enabled
2364*8975f5c5SAndroid Build Coastguard Worker // and mismatched integer signedness between the program's attribute type and the
2365*8975f5c5SAndroid Build Coastguard Worker // attribute type specified by VertexAttribIPointer are used.
TEST_P(VertexAttributeTestES3,DrawWithRelaxedVertexAttributeType)2366*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, DrawWithRelaxedVertexAttributeType)
2367*8975f5c5SAndroid Build Coastguard Worker {
2368*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_relaxed_vertex_attribute_type"));
2369*8975f5c5SAndroid Build Coastguard Worker
2370*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] = R"(#version 300 es
2371*8975f5c5SAndroid Build Coastguard Worker precision highp float;
2372*8975f5c5SAndroid Build Coastguard Worker in highp vec4 a_position;
2373*8975f5c5SAndroid Build Coastguard Worker in highp ivec4 a_ColorTest;
2374*8975f5c5SAndroid Build Coastguard Worker out highp vec4 v_colorTest;
2375*8975f5c5SAndroid Build Coastguard Worker
2376*8975f5c5SAndroid Build Coastguard Worker void main() {
2377*8975f5c5SAndroid Build Coastguard Worker v_colorTest = vec4(a_ColorTest);
2378*8975f5c5SAndroid Build Coastguard Worker gl_Position = a_position;
2379*8975f5c5SAndroid Build Coastguard Worker })";
2380*8975f5c5SAndroid Build Coastguard Worker
2381*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] = R"(#version 300 es
2382*8975f5c5SAndroid Build Coastguard Worker precision highp float;
2383*8975f5c5SAndroid Build Coastguard Worker in highp vec4 v_colorTest;
2384*8975f5c5SAndroid Build Coastguard Worker out vec4 fragColor;
2385*8975f5c5SAndroid Build Coastguard Worker
2386*8975f5c5SAndroid Build Coastguard Worker void main() {
2387*8975f5c5SAndroid Build Coastguard Worker if(v_colorTest.x > 0.5) {
2388*8975f5c5SAndroid Build Coastguard Worker fragColor = vec4(0.0, 1.0, 0.0, 1.0);
2389*8975f5c5SAndroid Build Coastguard Worker } else {
2390*8975f5c5SAndroid Build Coastguard Worker fragColor = vec4(1.0, 0.0, 0.0, 1.0);
2391*8975f5c5SAndroid Build Coastguard Worker }
2392*8975f5c5SAndroid Build Coastguard Worker })";
2393*8975f5c5SAndroid Build Coastguard Worker
2394*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(program, kVS, kFS);
2395*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 0, "a_position");
2396*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 1, "a_ColorTest");
2397*8975f5c5SAndroid Build Coastguard Worker glLinkProgram(program);
2398*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
2399*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
2400*8975f5c5SAndroid Build Coastguard Worker
2401*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kDataSize = 48;
2402*8975f5c5SAndroid Build Coastguard Worker
2403*8975f5c5SAndroid Build Coastguard Worker // Interleave test data with 0's.
2404*8975f5c5SAndroid Build Coastguard Worker // This guards against a future code change that adjusts stride to 0
2405*8975f5c5SAndroid Build Coastguard Worker
2406*8975f5c5SAndroid Build Coastguard Worker // clang-format off
2407*8975f5c5SAndroid Build Coastguard Worker constexpr GLuint kColorTestData[kDataSize] = {
2408*8975f5c5SAndroid Build Coastguard Worker // Vertex attribute data Unused data
2409*8975f5c5SAndroid Build Coastguard Worker 0u, 0u, 0u, 0u, /*red*/ 0u, 0u, 0u, 0u,
2410*8975f5c5SAndroid Build Coastguard Worker 1u, 1u, 1u, 1u, 0u, 0u, 0u, 0u,
2411*8975f5c5SAndroid Build Coastguard Worker 1u, 1u, 1u, 1u, 0u, 0u, 0u, 0u,
2412*8975f5c5SAndroid Build Coastguard Worker 1u, 1u, 1u, 1u, 0u, 0u, 0u, 0u,
2413*8975f5c5SAndroid Build Coastguard Worker 1u, 1u, 1u, 1u, 0u, 0u, 0u, 0u,
2414*8975f5c5SAndroid Build Coastguard Worker 1u, 1u, 1u, 1u, 0u, 0u, 0u, 0u
2415*8975f5c5SAndroid Build Coastguard Worker };
2416*8975f5c5SAndroid Build Coastguard Worker // clang-format on
2417*8975f5c5SAndroid Build Coastguard Worker
2418*8975f5c5SAndroid Build Coastguard Worker GLBuffer buffer;
2419*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, buffer);
2420*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, sizeof(GLuint) * kDataSize, kColorTestData, GL_STATIC_DRAW);
2421*8975f5c5SAndroid Build Coastguard Worker
2422*8975f5c5SAndroid Build Coastguard Worker glVertexAttribIPointer(1, 4, GL_UNSIGNED_INT, 8 * sizeof(GLuint),
2423*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<const void *>(0));
2424*8975f5c5SAndroid Build Coastguard Worker
2425*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
2426*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(1);
2427*8975f5c5SAndroid Build Coastguard Worker
2428*8975f5c5SAndroid Build Coastguard Worker drawQuad(program, "a_position", 0.5f);
2429*8975f5c5SAndroid Build Coastguard Worker
2430*8975f5c5SAndroid Build Coastguard Worker // Verify green was drawn. If the stride isn't adjusted to 0 this corner will be green. If it is
2431*8975f5c5SAndroid Build Coastguard Worker // adjusted to 0, the whole image will be red
2432*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
2433*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
2434*8975f5c5SAndroid Build Coastguard Worker }
2435*8975f5c5SAndroid Build Coastguard Worker
2436*8975f5c5SAndroid Build Coastguard Worker // Test that ensures we do not send data for components not specified by glVertexAttribPointer when
2437*8975f5c5SAndroid Build Coastguard Worker // component types and sizes are mismatched
TEST_P(VertexAttributeTestES3,DrawWithMismatchedComponentCount)2438*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, DrawWithMismatchedComponentCount)
2439*8975f5c5SAndroid Build Coastguard Worker {
2440*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_relaxed_vertex_attribute_type"));
2441*8975f5c5SAndroid Build Coastguard Worker
2442*8975f5c5SAndroid Build Coastguard Worker // To ensure the test results are valid when we don't send data for every component, the
2443*8975f5c5SAndroid Build Coastguard Worker // shader's values must be defined by the backend.
2444*8975f5c5SAndroid Build Coastguard Worker // Vulkan Spec 22.3. Vertex Attribute Divisor in Instanced Rendering
2445*8975f5c5SAndroid Build Coastguard Worker // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#_vertex_attribute_divisor_in_instanced_rendering
2446*8975f5c5SAndroid Build Coastguard Worker // If the format does not include G, B, or A components, then those are filled with (0,0,1) as
2447*8975f5c5SAndroid Build Coastguard Worker // needed (using either 1.0f or integer 1 based on the format) for attributes that are not
2448*8975f5c5SAndroid Build Coastguard Worker // 64-bit data types.
2449*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!IsVulkan());
2450*8975f5c5SAndroid Build Coastguard Worker
2451*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] = R"(#version 300 es
2452*8975f5c5SAndroid Build Coastguard Worker precision highp float;
2453*8975f5c5SAndroid Build Coastguard Worker in highp vec4 a_position;
2454*8975f5c5SAndroid Build Coastguard Worker in highp ivec2 a_ColorTest;
2455*8975f5c5SAndroid Build Coastguard Worker out highp vec2 v_colorTest;
2456*8975f5c5SAndroid Build Coastguard Worker
2457*8975f5c5SAndroid Build Coastguard Worker void main() {
2458*8975f5c5SAndroid Build Coastguard Worker v_colorTest = vec2(a_ColorTest);
2459*8975f5c5SAndroid Build Coastguard Worker gl_Position = a_position;
2460*8975f5c5SAndroid Build Coastguard Worker })";
2461*8975f5c5SAndroid Build Coastguard Worker
2462*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] = R"(#version 300 es
2463*8975f5c5SAndroid Build Coastguard Worker precision highp float;
2464*8975f5c5SAndroid Build Coastguard Worker in highp vec2 v_colorTest;
2465*8975f5c5SAndroid Build Coastguard Worker out vec4 fragColor;
2466*8975f5c5SAndroid Build Coastguard Worker
2467*8975f5c5SAndroid Build Coastguard Worker void main() {
2468*8975f5c5SAndroid Build Coastguard Worker if(v_colorTest.y < 0.5) {
2469*8975f5c5SAndroid Build Coastguard Worker fragColor = vec4(0.0, 1.0, 0.0, 1.0);
2470*8975f5c5SAndroid Build Coastguard Worker } else {
2471*8975f5c5SAndroid Build Coastguard Worker fragColor = vec4(1.0, 0.0, 0.0, 1.0);
2472*8975f5c5SAndroid Build Coastguard Worker }
2473*8975f5c5SAndroid Build Coastguard Worker })";
2474*8975f5c5SAndroid Build Coastguard Worker
2475*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(program, kVS, kFS);
2476*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 0, "a_position");
2477*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 1, "a_ColorTest");
2478*8975f5c5SAndroid Build Coastguard Worker glLinkProgram(program);
2479*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
2480*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
2481*8975f5c5SAndroid Build Coastguard Worker
2482*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kDataSize = 24;
2483*8975f5c5SAndroid Build Coastguard Worker
2484*8975f5c5SAndroid Build Coastguard Worker // Initialize vertex attribute data with 1s.
2485*8975f5c5SAndroid Build Coastguard Worker GLuint kColorTestData[kDataSize];
2486*8975f5c5SAndroid Build Coastguard Worker for (size_t dataIndex = 0; dataIndex < kDataSize; dataIndex++)
2487*8975f5c5SAndroid Build Coastguard Worker {
2488*8975f5c5SAndroid Build Coastguard Worker kColorTestData[dataIndex] = 1u;
2489*8975f5c5SAndroid Build Coastguard Worker }
2490*8975f5c5SAndroid Build Coastguard Worker
2491*8975f5c5SAndroid Build Coastguard Worker GLBuffer buffer;
2492*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, buffer);
2493*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, sizeof(GLuint) * kDataSize, kColorTestData, GL_STATIC_DRAW);
2494*8975f5c5SAndroid Build Coastguard Worker
2495*8975f5c5SAndroid Build Coastguard Worker glVertexAttribIPointer(1, 1, GL_UNSIGNED_INT, 4 * sizeof(GLuint),
2496*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<const void *>(0));
2497*8975f5c5SAndroid Build Coastguard Worker
2498*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
2499*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(1);
2500*8975f5c5SAndroid Build Coastguard Worker
2501*8975f5c5SAndroid Build Coastguard Worker drawQuad(program, "a_position", 0.5f);
2502*8975f5c5SAndroid Build Coastguard Worker
2503*8975f5c5SAndroid Build Coastguard Worker // Verify green was drawn.
2504*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green);
2505*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
2506*8975f5c5SAndroid Build Coastguard Worker }
2507*8975f5c5SAndroid Build Coastguard Worker
2508*8975f5c5SAndroid Build Coastguard Worker // Test that ensures we do not send data for components not specified by glVertexAttribPointer when
2509*8975f5c5SAndroid Build Coastguard Worker // component types and sizes are mismatched. Also guard against out of bound errors when atttribute
2510*8975f5c5SAndroid Build Coastguard Worker // locations are specified.
TEST_P(VertexAttributeTestES3,DrawWithMismatchedComponentCountLocationSpecified)2511*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, DrawWithMismatchedComponentCountLocationSpecified)
2512*8975f5c5SAndroid Build Coastguard Worker {
2513*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_relaxed_vertex_attribute_type"));
2514*8975f5c5SAndroid Build Coastguard Worker
2515*8975f5c5SAndroid Build Coastguard Worker // To ensure the test results are valid when we don't send data for every component, the
2516*8975f5c5SAndroid Build Coastguard Worker // shader's values must be defined by the backend.
2517*8975f5c5SAndroid Build Coastguard Worker // Vulkan Spec 22.3. Vertex Attribute Divisor in Instanced Rendering
2518*8975f5c5SAndroid Build Coastguard Worker // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#_vertex_attribute_divisor_in_instanced_rendering
2519*8975f5c5SAndroid Build Coastguard Worker // If the format does not include G, B, or A components, then those are filled with (0,0,1) as
2520*8975f5c5SAndroid Build Coastguard Worker // needed (using either 1.0f or integer 1 based on the format) for attributes that are not
2521*8975f5c5SAndroid Build Coastguard Worker // 64-bit data types.
2522*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!IsVulkan());
2523*8975f5c5SAndroid Build Coastguard Worker
2524*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] = R"(#version 300 es
2525*8975f5c5SAndroid Build Coastguard Worker precision highp float;
2526*8975f5c5SAndroid Build Coastguard Worker layout(location = 2) in highp vec4 a_position;
2527*8975f5c5SAndroid Build Coastguard Worker layout(location = 0) in highp ivec2 a_ColorTest;
2528*8975f5c5SAndroid Build Coastguard Worker out highp vec2 v_colorTest;
2529*8975f5c5SAndroid Build Coastguard Worker
2530*8975f5c5SAndroid Build Coastguard Worker void main() {
2531*8975f5c5SAndroid Build Coastguard Worker v_colorTest = vec2(a_ColorTest);
2532*8975f5c5SAndroid Build Coastguard Worker gl_Position = a_position;
2533*8975f5c5SAndroid Build Coastguard Worker })";
2534*8975f5c5SAndroid Build Coastguard Worker
2535*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] = R"(#version 300 es
2536*8975f5c5SAndroid Build Coastguard Worker precision highp float;
2537*8975f5c5SAndroid Build Coastguard Worker in highp vec2 v_colorTest;
2538*8975f5c5SAndroid Build Coastguard Worker out vec4 fragColor;
2539*8975f5c5SAndroid Build Coastguard Worker
2540*8975f5c5SAndroid Build Coastguard Worker void main() {
2541*8975f5c5SAndroid Build Coastguard Worker if(v_colorTest.y < 0.5) {
2542*8975f5c5SAndroid Build Coastguard Worker fragColor = vec4(0.0, 1.0, 0.0, 1.0);
2543*8975f5c5SAndroid Build Coastguard Worker } else {
2544*8975f5c5SAndroid Build Coastguard Worker fragColor = vec4(1.0, 0.0, 0.0, 1.0);
2545*8975f5c5SAndroid Build Coastguard Worker }
2546*8975f5c5SAndroid Build Coastguard Worker })";
2547*8975f5c5SAndroid Build Coastguard Worker
2548*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(program, kVS, kFS);
2549*8975f5c5SAndroid Build Coastguard Worker glLinkProgram(program);
2550*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
2551*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
2552*8975f5c5SAndroid Build Coastguard Worker
2553*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kDataSize = 24;
2554*8975f5c5SAndroid Build Coastguard Worker
2555*8975f5c5SAndroid Build Coastguard Worker // Initialize vertex attribute data with 1s.
2556*8975f5c5SAndroid Build Coastguard Worker GLuint kColorTestData[kDataSize];
2557*8975f5c5SAndroid Build Coastguard Worker for (size_t dataIndex = 0; dataIndex < kDataSize; dataIndex++)
2558*8975f5c5SAndroid Build Coastguard Worker {
2559*8975f5c5SAndroid Build Coastguard Worker kColorTestData[dataIndex] = 1u;
2560*8975f5c5SAndroid Build Coastguard Worker }
2561*8975f5c5SAndroid Build Coastguard Worker
2562*8975f5c5SAndroid Build Coastguard Worker GLBuffer buffer;
2563*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, buffer);
2564*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, sizeof(GLuint) * kDataSize, kColorTestData, GL_STATIC_DRAW);
2565*8975f5c5SAndroid Build Coastguard Worker
2566*8975f5c5SAndroid Build Coastguard Worker GLint colorLocation = glGetAttribLocation(program, "a_ColorTest");
2567*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(colorLocation, -1);
2568*8975f5c5SAndroid Build Coastguard Worker glVertexAttribIPointer(colorLocation, 1, GL_UNSIGNED_INT, 4 * sizeof(GLuint),
2569*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<const void *>(0));
2570*8975f5c5SAndroid Build Coastguard Worker
2571*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
2572*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(1);
2573*8975f5c5SAndroid Build Coastguard Worker
2574*8975f5c5SAndroid Build Coastguard Worker drawQuad(program, "a_position", 0.5f);
2575*8975f5c5SAndroid Build Coastguard Worker
2576*8975f5c5SAndroid Build Coastguard Worker // Verify green was drawn.
2577*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green);
2578*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
2579*8975f5c5SAndroid Build Coastguard Worker }
2580*8975f5c5SAndroid Build Coastguard Worker
2581*8975f5c5SAndroid Build Coastguard Worker class VertexAttributeTestES31 : public VertexAttributeTestES3
2582*8975f5c5SAndroid Build Coastguard Worker {
2583*8975f5c5SAndroid Build Coastguard Worker protected:
VertexAttributeTestES31()2584*8975f5c5SAndroid Build Coastguard Worker VertexAttributeTestES31() {}
2585*8975f5c5SAndroid Build Coastguard Worker
initTest()2586*8975f5c5SAndroid Build Coastguard Worker void initTest()
2587*8975f5c5SAndroid Build Coastguard Worker {
2588*8975f5c5SAndroid Build Coastguard Worker initBasicProgram();
2589*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
2590*8975f5c5SAndroid Build Coastguard Worker
2591*8975f5c5SAndroid Build Coastguard Worker glGenVertexArrays(1, &mVAO);
2592*8975f5c5SAndroid Build Coastguard Worker glBindVertexArray(mVAO);
2593*8975f5c5SAndroid Build Coastguard Worker
2594*8975f5c5SAndroid Build Coastguard Worker auto quadVertices = GetQuadVertices();
2595*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr quadVerticesSize =
2596*8975f5c5SAndroid Build Coastguard Worker static_cast<GLsizeiptr>(quadVertices.size() * sizeof(quadVertices[0]));
2597*8975f5c5SAndroid Build Coastguard Worker glGenBuffers(1, &mQuadBuffer);
2598*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mQuadBuffer);
2599*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, quadVerticesSize, quadVertices.data(), GL_STATIC_DRAW);
2600*8975f5c5SAndroid Build Coastguard Worker
2601*8975f5c5SAndroid Build Coastguard Worker GLint positionLocation = glGetAttribLocation(mProgram, "position");
2602*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, positionLocation);
2603*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2604*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(positionLocation);
2605*8975f5c5SAndroid Build Coastguard Worker
2606*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
2607*8975f5c5SAndroid Build Coastguard Worker for (size_t count = 0; count < kVertexCount; ++count)
2608*8975f5c5SAndroid Build Coastguard Worker {
2609*8975f5c5SAndroid Build Coastguard Worker expectedData[count] = static_cast<GLfloat>(count);
2610*8975f5c5SAndroid Build Coastguard Worker }
2611*8975f5c5SAndroid Build Coastguard Worker
2612*8975f5c5SAndroid Build Coastguard Worker const GLsizei kExpectedDataSize = kVertexCount * kFloatStride;
2613*8975f5c5SAndroid Build Coastguard Worker glGenBuffers(1, &mExpectedBuffer);
2614*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mExpectedBuffer);
2615*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, kExpectedDataSize, expectedData.data(), GL_STATIC_DRAW);
2616*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
2617*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mExpectedAttrib);
2618*8975f5c5SAndroid Build Coastguard Worker }
2619*8975f5c5SAndroid Build Coastguard Worker
testTearDown()2620*8975f5c5SAndroid Build Coastguard Worker void testTearDown() override
2621*8975f5c5SAndroid Build Coastguard Worker {
2622*8975f5c5SAndroid Build Coastguard Worker VertexAttributeTestES3::testTearDown();
2623*8975f5c5SAndroid Build Coastguard Worker
2624*8975f5c5SAndroid Build Coastguard Worker glDeleteBuffers(1, &mQuadBuffer);
2625*8975f5c5SAndroid Build Coastguard Worker glDeleteBuffers(1, &mExpectedBuffer);
2626*8975f5c5SAndroid Build Coastguard Worker glDeleteVertexArrays(1, &mVAO);
2627*8975f5c5SAndroid Build Coastguard Worker }
2628*8975f5c5SAndroid Build Coastguard Worker
drawArraysWithStrideAndRelativeOffset(GLint stride,GLuint relativeOffset)2629*8975f5c5SAndroid Build Coastguard Worker void drawArraysWithStrideAndRelativeOffset(GLint stride, GLuint relativeOffset)
2630*8975f5c5SAndroid Build Coastguard Worker {
2631*8975f5c5SAndroid Build Coastguard Worker initTest();
2632*8975f5c5SAndroid Build Coastguard Worker
2633*8975f5c5SAndroid Build Coastguard Worker GLint floatStride = std::max(stride / kFloatStride, 1);
2634*8975f5c5SAndroid Build Coastguard Worker GLuint floatRelativeOffset = relativeOffset / kFloatStride;
2635*8975f5c5SAndroid Build Coastguard Worker size_t floatCount = static_cast<size_t>(floatRelativeOffset) + kVertexCount * floatStride;
2636*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr inputSize = static_cast<GLsizeiptr>(floatCount) * kFloatStride;
2637*8975f5c5SAndroid Build Coastguard Worker
2638*8975f5c5SAndroid Build Coastguard Worker std::vector<GLfloat> inputData(floatCount);
2639*8975f5c5SAndroid Build Coastguard Worker for (size_t count = 0; count < kVertexCount; ++count)
2640*8975f5c5SAndroid Build Coastguard Worker {
2641*8975f5c5SAndroid Build Coastguard Worker inputData[floatRelativeOffset + count * floatStride] = static_cast<GLfloat>(count);
2642*8975f5c5SAndroid Build Coastguard Worker }
2643*8975f5c5SAndroid Build Coastguard Worker
2644*8975f5c5SAndroid Build Coastguard Worker // Ensure inputSize, inputStride and inputOffset are multiples of TypeStride(GL_FLOAT).
2645*8975f5c5SAndroid Build Coastguard Worker GLsizei inputStride = floatStride * kFloatStride;
2646*8975f5c5SAndroid Build Coastguard Worker GLsizeiptr inputRelativeOffset = floatRelativeOffset * kFloatStride;
2647*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
2648*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, inputSize, nullptr, GL_STATIC_DRAW);
2649*8975f5c5SAndroid Build Coastguard Worker glBufferSubData(GL_ARRAY_BUFFER, 0, inputSize, inputData.data());
2650*8975f5c5SAndroid Build Coastguard Worker glVertexAttribFormat(mTestAttrib, 1, GL_FLOAT, GL_FALSE,
2651*8975f5c5SAndroid Build Coastguard Worker base::checked_cast<GLuint>(inputRelativeOffset));
2652*8975f5c5SAndroid Build Coastguard Worker glBindVertexBuffer(mTestAttrib, mBuffer, 0, inputStride);
2653*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
2654*8975f5c5SAndroid Build Coastguard Worker
2655*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
2656*8975f5c5SAndroid Build Coastguard Worker checkPixels();
2657*8975f5c5SAndroid Build Coastguard Worker
2658*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
2659*8975f5c5SAndroid Build Coastguard Worker }
2660*8975f5c5SAndroid Build Coastguard Worker
initOnlyUpdateBindingTest(GLint bindingToUpdate)2661*8975f5c5SAndroid Build Coastguard Worker void initOnlyUpdateBindingTest(GLint bindingToUpdate)
2662*8975f5c5SAndroid Build Coastguard Worker {
2663*8975f5c5SAndroid Build Coastguard Worker initTest();
2664*8975f5c5SAndroid Build Coastguard Worker
2665*8975f5c5SAndroid Build Coastguard Worker constexpr GLuint kTestFloatOffset1 = kVertexCount;
2666*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kTestFloatOffset1 + kVertexCount> inputData1 = {};
2667*8975f5c5SAndroid Build Coastguard Worker for (size_t count = 0; count < kVertexCount; ++count)
2668*8975f5c5SAndroid Build Coastguard Worker {
2669*8975f5c5SAndroid Build Coastguard Worker GLfloat value = static_cast<GLfloat>(count);
2670*8975f5c5SAndroid Build Coastguard Worker inputData1[kTestFloatOffset1 + count] = value;
2671*8975f5c5SAndroid Build Coastguard Worker }
2672*8975f5c5SAndroid Build Coastguard Worker
2673*8975f5c5SAndroid Build Coastguard Worker GLBuffer testBuffer1;
2674*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, testBuffer1);
2675*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, inputData1.size() * kFloatStride, inputData1.data(),
2676*8975f5c5SAndroid Build Coastguard Worker GL_STATIC_DRAW);
2677*8975f5c5SAndroid Build Coastguard Worker
2678*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(bindingToUpdate, mTestAttrib);
2679*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(bindingToUpdate, mExpectedAttrib);
2680*8975f5c5SAndroid Build Coastguard Worker
2681*8975f5c5SAndroid Build Coastguard Worker // Set mTestAttrib using the binding bindingToUpdate.
2682*8975f5c5SAndroid Build Coastguard Worker glVertexAttribFormat(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0);
2683*8975f5c5SAndroid Build Coastguard Worker glBindVertexBuffer(bindingToUpdate, testBuffer1, kTestFloatOffset1 * kFloatStride,
2684*8975f5c5SAndroid Build Coastguard Worker kFloatStride);
2685*8975f5c5SAndroid Build Coastguard Worker glVertexAttribBinding(mTestAttrib, bindingToUpdate);
2686*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
2687*8975f5c5SAndroid Build Coastguard Worker
2688*8975f5c5SAndroid Build Coastguard Worker // In the first draw the current VAO states are set to driver.
2689*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
2690*8975f5c5SAndroid Build Coastguard Worker checkPixels();
2691*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
2692*8975f5c5SAndroid Build Coastguard Worker
2693*8975f5c5SAndroid Build Coastguard Worker // We need the second draw to ensure all VAO dirty bits are reset.
2694*8975f5c5SAndroid Build Coastguard Worker // e.g. On D3D11 back-ends, Buffer11::resize is called in the first draw, where the related
2695*8975f5c5SAndroid Build Coastguard Worker // binding is set to dirty again.
2696*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
2697*8975f5c5SAndroid Build Coastguard Worker checkPixels();
2698*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
2699*8975f5c5SAndroid Build Coastguard Worker }
2700*8975f5c5SAndroid Build Coastguard Worker
2701*8975f5c5SAndroid Build Coastguard Worker std::string makeMismatchingSignsTestVS(uint32_t attribCount, uint16_t signedMask);
2702*8975f5c5SAndroid Build Coastguard Worker std::string makeMismatchingSignsTestFS(uint32_t attribCount);
2703*8975f5c5SAndroid Build Coastguard Worker uint16_t setupVertexAttribPointersForMismatchSignsTest(uint16_t currentSignedMask,
2704*8975f5c5SAndroid Build Coastguard Worker uint16_t toggleMask);
2705*8975f5c5SAndroid Build Coastguard Worker
2706*8975f5c5SAndroid Build Coastguard Worker GLuint mVAO = 0;
2707*8975f5c5SAndroid Build Coastguard Worker GLuint mExpectedBuffer = 0;
2708*8975f5c5SAndroid Build Coastguard Worker GLuint mQuadBuffer = 0;
2709*8975f5c5SAndroid Build Coastguard Worker
2710*8975f5c5SAndroid Build Coastguard Worker const GLsizei kFloatStride = TypeStride(GL_FLOAT);
2711*8975f5c5SAndroid Build Coastguard Worker
2712*8975f5c5SAndroid Build Coastguard Worker // Set the maximum value for stride and relativeOffset in case they are too large.
2713*8975f5c5SAndroid Build Coastguard Worker const GLint MAX_STRIDE_FOR_TEST = 4095;
2714*8975f5c5SAndroid Build Coastguard Worker const GLint MAX_RELATIVE_OFFSET_FOR_TEST = 4095;
2715*8975f5c5SAndroid Build Coastguard Worker };
2716*8975f5c5SAndroid Build Coastguard Worker
2717*8975f5c5SAndroid Build Coastguard Worker // Verify that MAX_VERTEX_ATTRIB_STRIDE is no less than the minimum required value (2048) in ES3.1.
TEST_P(VertexAttributeTestES31,MaxVertexAttribStride)2718*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES31, MaxVertexAttribStride)
2719*8975f5c5SAndroid Build Coastguard Worker {
2720*8975f5c5SAndroid Build Coastguard Worker GLint maxStride;
2721*8975f5c5SAndroid Build Coastguard Worker glGetIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
2722*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
2723*8975f5c5SAndroid Build Coastguard Worker
2724*8975f5c5SAndroid Build Coastguard Worker EXPECT_GE(maxStride, 2048);
2725*8975f5c5SAndroid Build Coastguard Worker }
2726*8975f5c5SAndroid Build Coastguard Worker
2727*8975f5c5SAndroid Build Coastguard Worker // Verify that GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET is no less than the minimum required value
2728*8975f5c5SAndroid Build Coastguard Worker // (2047) in ES3.1.
TEST_P(VertexAttributeTestES31,MaxVertexAttribRelativeOffset)2729*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES31, MaxVertexAttribRelativeOffset)
2730*8975f5c5SAndroid Build Coastguard Worker {
2731*8975f5c5SAndroid Build Coastguard Worker GLint maxRelativeOffset;
2732*8975f5c5SAndroid Build Coastguard Worker glGetIntegerv(GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET, &maxRelativeOffset);
2733*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
2734*8975f5c5SAndroid Build Coastguard Worker
2735*8975f5c5SAndroid Build Coastguard Worker EXPECT_GE(maxRelativeOffset, 2047);
2736*8975f5c5SAndroid Build Coastguard Worker }
2737*8975f5c5SAndroid Build Coastguard Worker
2738*8975f5c5SAndroid Build Coastguard Worker // Verify using MAX_VERTEX_ATTRIB_STRIDE as stride doesn't mess up the draw.
2739*8975f5c5SAndroid Build Coastguard Worker // Use default value if the value of MAX_VERTEX_ATTRIB_STRIDE is too large for this test.
TEST_P(VertexAttributeTestES31,DrawArraysWithLargeStride)2740*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES31, DrawArraysWithLargeStride)
2741*8975f5c5SAndroid Build Coastguard Worker {
2742*8975f5c5SAndroid Build Coastguard Worker GLint maxStride;
2743*8975f5c5SAndroid Build Coastguard Worker glGetIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
2744*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
2745*8975f5c5SAndroid Build Coastguard Worker
2746*8975f5c5SAndroid Build Coastguard Worker GLint largeStride = std::min(maxStride, MAX_STRIDE_FOR_TEST);
2747*8975f5c5SAndroid Build Coastguard Worker drawArraysWithStrideAndRelativeOffset(largeStride, 0);
2748*8975f5c5SAndroid Build Coastguard Worker }
2749*8975f5c5SAndroid Build Coastguard Worker
2750*8975f5c5SAndroid Build Coastguard Worker // Verify using MAX_VERTEX_ATTRIB_RELATIVE_OFFSET as relativeOffset doesn't mess up the draw.
2751*8975f5c5SAndroid Build Coastguard Worker // Use default value if the value of MAX_VERTEX_ATTRIB_RELATIVE_OFFSSET is too large for this test.
TEST_P(VertexAttributeTestES31,DrawArraysWithLargeRelativeOffset)2752*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES31, DrawArraysWithLargeRelativeOffset)
2753*8975f5c5SAndroid Build Coastguard Worker {
2754*8975f5c5SAndroid Build Coastguard Worker GLint maxRelativeOffset;
2755*8975f5c5SAndroid Build Coastguard Worker glGetIntegerv(GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET, &maxRelativeOffset);
2756*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
2757*8975f5c5SAndroid Build Coastguard Worker
2758*8975f5c5SAndroid Build Coastguard Worker GLint largeRelativeOffset = std::min(maxRelativeOffset, MAX_RELATIVE_OFFSET_FOR_TEST);
2759*8975f5c5SAndroid Build Coastguard Worker drawArraysWithStrideAndRelativeOffset(0, largeRelativeOffset);
2760*8975f5c5SAndroid Build Coastguard Worker }
2761*8975f5c5SAndroid Build Coastguard Worker
2762*8975f5c5SAndroid Build Coastguard Worker // Test that vertex array object works correctly when render pipeline and compute pipeline are
2763*8975f5c5SAndroid Build Coastguard Worker // crossly executed.
TEST_P(VertexAttributeTestES31,MixedComputeAndRenderPipelines)2764*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES31, MixedComputeAndRenderPipelines)
2765*8975f5c5SAndroid Build Coastguard Worker {
2766*8975f5c5SAndroid Build Coastguard Worker constexpr char kComputeShader[] =
2767*8975f5c5SAndroid Build Coastguard Worker R"(#version 310 es
2768*8975f5c5SAndroid Build Coastguard Worker layout(local_size_x=1) in;
2769*8975f5c5SAndroid Build Coastguard Worker void main()
2770*8975f5c5SAndroid Build Coastguard Worker {
2771*8975f5c5SAndroid Build Coastguard Worker })";
2772*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_COMPUTE_PROGRAM(computeProgram, kComputeShader);
2773*8975f5c5SAndroid Build Coastguard Worker
2774*8975f5c5SAndroid Build Coastguard Worker glViewport(0, 0, getWindowWidth(), getWindowHeight());
2775*8975f5c5SAndroid Build Coastguard Worker glClearColor(0, 0, 0, 0);
2776*8975f5c5SAndroid Build Coastguard Worker
2777*8975f5c5SAndroid Build Coastguard Worker constexpr char kVertexShader[] =
2778*8975f5c5SAndroid Build Coastguard Worker R"(#version 310 es
2779*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
2780*8975f5c5SAndroid Build Coastguard Worker layout(location = 0) in vec4 position;
2781*8975f5c5SAndroid Build Coastguard Worker layout(location = 2) in vec2 aOffset;
2782*8975f5c5SAndroid Build Coastguard Worker layout(location = 3) in vec4 aColor;
2783*8975f5c5SAndroid Build Coastguard Worker out vec4 vColor;
2784*8975f5c5SAndroid Build Coastguard Worker void main() {
2785*8975f5c5SAndroid Build Coastguard Worker vColor = aColor;
2786*8975f5c5SAndroid Build Coastguard Worker gl_Position = position + vec4(aOffset, 0.0, 0.0);
2787*8975f5c5SAndroid Build Coastguard Worker })";
2788*8975f5c5SAndroid Build Coastguard Worker
2789*8975f5c5SAndroid Build Coastguard Worker constexpr char kFragmentShader[] =
2790*8975f5c5SAndroid Build Coastguard Worker R"(#version 310 es
2791*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
2792*8975f5c5SAndroid Build Coastguard Worker in vec4 vColor;
2793*8975f5c5SAndroid Build Coastguard Worker out vec4 color;
2794*8975f5c5SAndroid Build Coastguard Worker void main() {
2795*8975f5c5SAndroid Build Coastguard Worker color = vColor;
2796*8975f5c5SAndroid Build Coastguard Worker })";
2797*8975f5c5SAndroid Build Coastguard Worker
2798*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(renderProgram, kVertexShader, kFragmentShader);
2799*8975f5c5SAndroid Build Coastguard Worker
2800*8975f5c5SAndroid Build Coastguard Worker constexpr char kVertexShader1[] =
2801*8975f5c5SAndroid Build Coastguard Worker R"(#version 310 es
2802*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
2803*8975f5c5SAndroid Build Coastguard Worker layout(location = 1) in vec4 position;
2804*8975f5c5SAndroid Build Coastguard Worker layout(location = 2) in vec2 aOffset;
2805*8975f5c5SAndroid Build Coastguard Worker layout(location = 3) in vec4 aColor;
2806*8975f5c5SAndroid Build Coastguard Worker out vec4 vColor;
2807*8975f5c5SAndroid Build Coastguard Worker void main() {
2808*8975f5c5SAndroid Build Coastguard Worker vColor = aColor;
2809*8975f5c5SAndroid Build Coastguard Worker gl_Position = position + vec4(aOffset, 0.0, 0.0);
2810*8975f5c5SAndroid Build Coastguard Worker })";
2811*8975f5c5SAndroid Build Coastguard Worker
2812*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(renderProgram1, kVertexShader1, kFragmentShader);
2813*8975f5c5SAndroid Build Coastguard Worker
2814*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, 8> offsets = {
2815*8975f5c5SAndroid Build Coastguard Worker -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0,
2816*8975f5c5SAndroid Build Coastguard Worker };
2817*8975f5c5SAndroid Build Coastguard Worker GLBuffer offsetBuffer;
2818*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, offsetBuffer);
2819*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, offsets.size() * sizeof(GLfloat), offsets.data(), GL_STATIC_DRAW);
2820*8975f5c5SAndroid Build Coastguard Worker
2821*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, 16> colors0 = {
2822*8975f5c5SAndroid Build Coastguard Worker 1.0, 0.0, 0.0, 1.0, // Red
2823*8975f5c5SAndroid Build Coastguard Worker 0.0, 1.0, 0.0, 1.0, // Green
2824*8975f5c5SAndroid Build Coastguard Worker 0.0, 0.0, 1.0, 1.0, // Blue
2825*8975f5c5SAndroid Build Coastguard Worker 1.0, 1.0, 0.0, 1.0, // Yellow
2826*8975f5c5SAndroid Build Coastguard Worker };
2827*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, 16> colors1 = {
2828*8975f5c5SAndroid Build Coastguard Worker 1.0, 1.0, 0.0, 1.0, // Yellow
2829*8975f5c5SAndroid Build Coastguard Worker 0.0, 0.0, 1.0, 1.0, // Blue
2830*8975f5c5SAndroid Build Coastguard Worker 0.0, 1.0, 0.0, 1.0, // Green
2831*8975f5c5SAndroid Build Coastguard Worker 1.0, 0.0, 0.0, 1.0, // Red
2832*8975f5c5SAndroid Build Coastguard Worker };
2833*8975f5c5SAndroid Build Coastguard Worker GLBuffer colorBuffers[2];
2834*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[0]);
2835*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, colors0.size() * sizeof(GLfloat), colors0.data(), GL_STATIC_DRAW);
2836*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[1]);
2837*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, colors1.size() * sizeof(GLfloat), colors1.data(), GL_STATIC_DRAW);
2838*8975f5c5SAndroid Build Coastguard Worker
2839*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, 16> positions = {1.0, 1.0, -1.0, 1.0, -1.0, -1.0,
2840*8975f5c5SAndroid Build Coastguard Worker 1.0, 1.0, -1.0, -1.0, 1.0, -1.0};
2841*8975f5c5SAndroid Build Coastguard Worker GLBuffer positionBuffer;
2842*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
2843*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(GLfloat), positions.data(),
2844*8975f5c5SAndroid Build Coastguard Worker GL_STATIC_DRAW);
2845*8975f5c5SAndroid Build Coastguard Worker
2846*8975f5c5SAndroid Build Coastguard Worker const int kInstanceCount = 4;
2847*8975f5c5SAndroid Build Coastguard Worker GLVertexArray vao[2];
2848*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0u; i < 2u; ++i)
2849*8975f5c5SAndroid Build Coastguard Worker {
2850*8975f5c5SAndroid Build Coastguard Worker glBindVertexArray(vao[i]);
2851*8975f5c5SAndroid Build Coastguard Worker
2852*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, offsetBuffer);
2853*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(2);
2854*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(2, 2, GL_FLOAT, false, 0, 0);
2855*8975f5c5SAndroid Build Coastguard Worker glVertexAttribDivisor(2, 1);
2856*8975f5c5SAndroid Build Coastguard Worker
2857*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, colorBuffers[i]);
2858*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(3);
2859*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(3, 4, GL_FLOAT, false, 0, 0);
2860*8975f5c5SAndroid Build Coastguard Worker glVertexAttribDivisor(3, 1);
2861*8975f5c5SAndroid Build Coastguard Worker
2862*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
2863*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(i);
2864*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(i, 2, GL_FLOAT, false, 0, 0);
2865*8975f5c5SAndroid Build Coastguard Worker }
2866*8975f5c5SAndroid Build Coastguard Worker
2867*8975f5c5SAndroid Build Coastguard Worker glClear(GL_COLOR_BUFFER_BIT);
2868*8975f5c5SAndroid Build Coastguard Worker
2869*8975f5c5SAndroid Build Coastguard Worker for (int i = 0; i < 3; i++)
2870*8975f5c5SAndroid Build Coastguard Worker {
2871*8975f5c5SAndroid Build Coastguard Worker glUseProgram(renderProgram);
2872*8975f5c5SAndroid Build Coastguard Worker glBindVertexArray(vao[0]);
2873*8975f5c5SAndroid Build Coastguard Worker glDrawArraysInstanced(GL_TRIANGLES, 0, 6, kInstanceCount);
2874*8975f5c5SAndroid Build Coastguard Worker
2875*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
2876*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::red) << i;
2877*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::green) << i;
2878*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue) << i;
2879*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::yellow) << i;
2880*8975f5c5SAndroid Build Coastguard Worker
2881*8975f5c5SAndroid Build Coastguard Worker glBindVertexArray(vao[1]);
2882*8975f5c5SAndroid Build Coastguard Worker glUseProgram(computeProgram);
2883*8975f5c5SAndroid Build Coastguard Worker glDispatchCompute(1, 1, 1);
2884*8975f5c5SAndroid Build Coastguard Worker
2885*8975f5c5SAndroid Build Coastguard Worker glUseProgram(renderProgram1);
2886*8975f5c5SAndroid Build Coastguard Worker glBindVertexArray(vao[1]);
2887*8975f5c5SAndroid Build Coastguard Worker glDrawArraysInstanced(GL_TRIANGLES, 0, 6, kInstanceCount);
2888*8975f5c5SAndroid Build Coastguard Worker
2889*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
2890*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() / 2, GLColor::yellow) << i;
2891*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::blue) << i;
2892*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green) << i;
2893*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::red) << i;
2894*8975f5c5SAndroid Build Coastguard Worker }
2895*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
2896*8975f5c5SAndroid Build Coastguard Worker }
2897*8975f5c5SAndroid Build Coastguard Worker
TEST_P(VertexAttributeTestES31,UseComputeShaderToUpdateVertexBuffer)2898*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES31, UseComputeShaderToUpdateVertexBuffer)
2899*8975f5c5SAndroid Build Coastguard Worker {
2900*8975f5c5SAndroid Build Coastguard Worker initTest();
2901*8975f5c5SAndroid Build Coastguard Worker constexpr char kComputeShader[] =
2902*8975f5c5SAndroid Build Coastguard Worker R"(#version 310 es
2903*8975f5c5SAndroid Build Coastguard Worker layout(local_size_x=24) in;
2904*8975f5c5SAndroid Build Coastguard Worker layout(std430, binding = 0) buffer buf {
2905*8975f5c5SAndroid Build Coastguard Worker uint outData[24];
2906*8975f5c5SAndroid Build Coastguard Worker };
2907*8975f5c5SAndroid Build Coastguard Worker void main()
2908*8975f5c5SAndroid Build Coastguard Worker {
2909*8975f5c5SAndroid Build Coastguard Worker outData[gl_LocalInvocationIndex] = gl_LocalInvocationIndex;
2910*8975f5c5SAndroid Build Coastguard Worker })";
2911*8975f5c5SAndroid Build Coastguard Worker
2912*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_COMPUTE_PROGRAM(computeProgram, kComputeShader);
2913*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
2914*8975f5c5SAndroid Build Coastguard Worker
2915*8975f5c5SAndroid Build Coastguard Worker GLuint mid = std::numeric_limits<GLuint>::max() >> 1;
2916*8975f5c5SAndroid Build Coastguard Worker GLuint hi = std::numeric_limits<GLuint>::max();
2917*8975f5c5SAndroid Build Coastguard Worker std::array<GLuint, kVertexCount> inputData = {
2918*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
2919*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
2920*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
2921*8975f5c5SAndroid Build Coastguard Worker {
2922*8975f5c5SAndroid Build Coastguard Worker expectedData[i] = Normalize(inputData[i]);
2923*8975f5c5SAndroid Build Coastguard Worker }
2924*8975f5c5SAndroid Build Coastguard Worker
2925*8975f5c5SAndroid Build Coastguard Worker // Normalized unsigned int attribute will be classified as translated static attribute.
2926*8975f5c5SAndroid Build Coastguard Worker TestData data(GL_UNSIGNED_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
2927*8975f5c5SAndroid Build Coastguard Worker GLint typeSize = 4;
2928*8975f5c5SAndroid Build Coastguard Worker GLsizei dataSize = kVertexCount * TypeStride(data.type);
2929*8975f5c5SAndroid Build Coastguard Worker GLBuffer testBuffer;
2930*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, testBuffer);
2931*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, dataSize, data.inputData, GL_STATIC_DRAW);
2932*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, typeSize, data.type, data.normalized, 0,
2933*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<void *>(data.bufferOffset));
2934*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
2935*8975f5c5SAndroid Build Coastguard Worker
2936*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mExpectedBuffer);
2937*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, dataSize, data.expectedData, GL_STATIC_DRAW);
2938*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, typeSize, GL_FLOAT, GL_FALSE, 0, nullptr);
2939*8975f5c5SAndroid Build Coastguard Worker
2940*8975f5c5SAndroid Build Coastguard Worker // Draw twice to make sure that all static attributes dirty bits are synced.
2941*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
2942*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
2943*8975f5c5SAndroid Build Coastguard Worker checkPixels();
2944*8975f5c5SAndroid Build Coastguard Worker
2945*8975f5c5SAndroid Build Coastguard Worker // Modify the testBuffer using a raw buffer
2946*8975f5c5SAndroid Build Coastguard Worker glUseProgram(computeProgram);
2947*8975f5c5SAndroid Build Coastguard Worker glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, testBuffer);
2948*8975f5c5SAndroid Build Coastguard Worker glDispatchCompute(1, 1, 1);
2949*8975f5c5SAndroid Build Coastguard Worker glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
2950*8975f5c5SAndroid Build Coastguard Worker
2951*8975f5c5SAndroid Build Coastguard Worker // Draw again to verify that testBuffer has been changed.
2952*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
2953*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
2954*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
2955*8975f5c5SAndroid Build Coastguard Worker checkPixelsUnEqual();
2956*8975f5c5SAndroid Build Coastguard Worker }
2957*8975f5c5SAndroid Build Coastguard Worker
TEST_P(VertexAttributeTestES31,UsePpoComputeShaderToUpdateVertexBuffer)2958*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES31, UsePpoComputeShaderToUpdateVertexBuffer)
2959*8975f5c5SAndroid Build Coastguard Worker {
2960*8975f5c5SAndroid Build Coastguard Worker // PPOs are only supported in the Vulkan backend
2961*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!isVulkanRenderer());
2962*8975f5c5SAndroid Build Coastguard Worker
2963*8975f5c5SAndroid Build Coastguard Worker initTest();
2964*8975f5c5SAndroid Build Coastguard Worker constexpr char kComputeShader[] =
2965*8975f5c5SAndroid Build Coastguard Worker R"(#version 310 es
2966*8975f5c5SAndroid Build Coastguard Worker layout(local_size_x=24) in;
2967*8975f5c5SAndroid Build Coastguard Worker layout(std430, binding = 0) buffer buf {
2968*8975f5c5SAndroid Build Coastguard Worker uint outData[24];
2969*8975f5c5SAndroid Build Coastguard Worker };
2970*8975f5c5SAndroid Build Coastguard Worker void main()
2971*8975f5c5SAndroid Build Coastguard Worker {
2972*8975f5c5SAndroid Build Coastguard Worker outData[gl_LocalInvocationIndex] = gl_LocalInvocationIndex;
2973*8975f5c5SAndroid Build Coastguard Worker })";
2974*8975f5c5SAndroid Build Coastguard Worker
2975*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
2976*8975f5c5SAndroid Build Coastguard Worker
2977*8975f5c5SAndroid Build Coastguard Worker GLuint mid = std::numeric_limits<GLuint>::max() >> 1;
2978*8975f5c5SAndroid Build Coastguard Worker GLuint hi = std::numeric_limits<GLuint>::max();
2979*8975f5c5SAndroid Build Coastguard Worker std::array<GLuint, kVertexCount> inputData = {
2980*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
2981*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
2982*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
2983*8975f5c5SAndroid Build Coastguard Worker {
2984*8975f5c5SAndroid Build Coastguard Worker expectedData[i] = Normalize(inputData[i]);
2985*8975f5c5SAndroid Build Coastguard Worker }
2986*8975f5c5SAndroid Build Coastguard Worker
2987*8975f5c5SAndroid Build Coastguard Worker // Normalized unsigned int attribute will be classified as translated static attribute.
2988*8975f5c5SAndroid Build Coastguard Worker TestData data(GL_UNSIGNED_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
2989*8975f5c5SAndroid Build Coastguard Worker GLint typeSize = 4;
2990*8975f5c5SAndroid Build Coastguard Worker GLsizei dataSize = kVertexCount * TypeStride(data.type);
2991*8975f5c5SAndroid Build Coastguard Worker GLBuffer testBuffer;
2992*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, testBuffer);
2993*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, dataSize, data.inputData, GL_STATIC_DRAW);
2994*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, typeSize, data.type, data.normalized, 0,
2995*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<void *>(data.bufferOffset));
2996*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
2997*8975f5c5SAndroid Build Coastguard Worker
2998*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mExpectedBuffer);
2999*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, dataSize, data.expectedData, GL_STATIC_DRAW);
3000*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, typeSize, GL_FLOAT, GL_FALSE, 0, nullptr);
3001*8975f5c5SAndroid Build Coastguard Worker
3002*8975f5c5SAndroid Build Coastguard Worker // Draw twice to make sure that all static attributes dirty bits are synced.
3003*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
3004*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
3005*8975f5c5SAndroid Build Coastguard Worker checkPixels();
3006*8975f5c5SAndroid Build Coastguard Worker
3007*8975f5c5SAndroid Build Coastguard Worker // Modify the testBuffer using a raw buffer
3008*8975f5c5SAndroid Build Coastguard Worker GLProgramPipeline pipeline;
3009*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_COMPUTE_PROGRAM(computeProgram, kComputeShader);
3010*8975f5c5SAndroid Build Coastguard Worker glProgramParameteri(computeProgram, GL_PROGRAM_SEPARABLE, GL_TRUE);
3011*8975f5c5SAndroid Build Coastguard Worker glUseProgramStages(pipeline, GL_COMPUTE_SHADER_BIT, computeProgram);
3012*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
3013*8975f5c5SAndroid Build Coastguard Worker glBindProgramPipeline(pipeline);
3014*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
3015*8975f5c5SAndroid Build Coastguard Worker glUseProgram(0);
3016*8975f5c5SAndroid Build Coastguard Worker
3017*8975f5c5SAndroid Build Coastguard Worker glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, testBuffer);
3018*8975f5c5SAndroid Build Coastguard Worker glDispatchCompute(1, 1, 1);
3019*8975f5c5SAndroid Build Coastguard Worker glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
3020*8975f5c5SAndroid Build Coastguard Worker
3021*8975f5c5SAndroid Build Coastguard Worker // Draw again to verify that testBuffer has been changed.
3022*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
3023*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
3024*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
3025*8975f5c5SAndroid Build Coastguard Worker checkPixelsUnEqual();
3026*8975f5c5SAndroid Build Coastguard Worker }
3027*8975f5c5SAndroid Build Coastguard Worker
TEST_P(VertexAttributeTestES31,UseComputeShaderToUpdateVertexBufferSamePpo)3028*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES31, UseComputeShaderToUpdateVertexBufferSamePpo)
3029*8975f5c5SAndroid Build Coastguard Worker {
3030*8975f5c5SAndroid Build Coastguard Worker // PPOs are only supported in the Vulkan backend
3031*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!isVulkanRenderer());
3032*8975f5c5SAndroid Build Coastguard Worker
3033*8975f5c5SAndroid Build Coastguard Worker initTest();
3034*8975f5c5SAndroid Build Coastguard Worker constexpr char kComputeShader[] =
3035*8975f5c5SAndroid Build Coastguard Worker R"(#version 310 es
3036*8975f5c5SAndroid Build Coastguard Worker layout(local_size_x=24) in;
3037*8975f5c5SAndroid Build Coastguard Worker layout(std430, binding = 0) buffer buf {
3038*8975f5c5SAndroid Build Coastguard Worker uint outData[24];
3039*8975f5c5SAndroid Build Coastguard Worker };
3040*8975f5c5SAndroid Build Coastguard Worker void main()
3041*8975f5c5SAndroid Build Coastguard Worker {
3042*8975f5c5SAndroid Build Coastguard Worker outData[gl_LocalInvocationIndex] = gl_LocalInvocationIndex;
3043*8975f5c5SAndroid Build Coastguard Worker })";
3044*8975f5c5SAndroid Build Coastguard Worker
3045*8975f5c5SAndroid Build Coastguard Worker // Mark the program separable and re-link it so it can be bound to the PPO.
3046*8975f5c5SAndroid Build Coastguard Worker glProgramParameteri(mProgram, GL_PROGRAM_SEPARABLE, GL_TRUE);
3047*8975f5c5SAndroid Build Coastguard Worker glLinkProgram(mProgram);
3048*8975f5c5SAndroid Build Coastguard Worker mProgram = CheckLinkStatusAndReturnProgram(mProgram, true);
3049*8975f5c5SAndroid Build Coastguard Worker
3050*8975f5c5SAndroid Build Coastguard Worker GLProgramPipeline pipeline;
3051*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
3052*8975f5c5SAndroid Build Coastguard Worker glBindProgramPipeline(pipeline);
3053*8975f5c5SAndroid Build Coastguard Worker glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, mProgram);
3054*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
3055*8975f5c5SAndroid Build Coastguard Worker glUseProgram(0);
3056*8975f5c5SAndroid Build Coastguard Worker
3057*8975f5c5SAndroid Build Coastguard Worker GLuint mid = std::numeric_limits<GLuint>::max() >> 1;
3058*8975f5c5SAndroid Build Coastguard Worker GLuint hi = std::numeric_limits<GLuint>::max();
3059*8975f5c5SAndroid Build Coastguard Worker std::array<GLuint, kVertexCount> inputData = {
3060*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, 254, 255, 256, mid - 1, mid, mid + 1, hi - 2, hi - 1, hi}};
3061*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
3062*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
3063*8975f5c5SAndroid Build Coastguard Worker {
3064*8975f5c5SAndroid Build Coastguard Worker expectedData[i] = Normalize(inputData[i]);
3065*8975f5c5SAndroid Build Coastguard Worker }
3066*8975f5c5SAndroid Build Coastguard Worker
3067*8975f5c5SAndroid Build Coastguard Worker // Normalized unsigned int attribute will be classified as translated static attribute.
3068*8975f5c5SAndroid Build Coastguard Worker TestData data(GL_UNSIGNED_INT, GL_TRUE, Source::BUFFER, inputData.data(), expectedData.data());
3069*8975f5c5SAndroid Build Coastguard Worker GLint typeSize = 4;
3070*8975f5c5SAndroid Build Coastguard Worker GLsizei dataSize = kVertexCount * TypeStride(data.type);
3071*8975f5c5SAndroid Build Coastguard Worker GLBuffer testBuffer;
3072*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, testBuffer);
3073*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, dataSize, data.inputData, GL_STATIC_DRAW);
3074*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, typeSize, data.type, data.normalized, 0,
3075*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<void *>(data.bufferOffset));
3076*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
3077*8975f5c5SAndroid Build Coastguard Worker
3078*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mExpectedBuffer);
3079*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, dataSize, data.expectedData, GL_STATIC_DRAW);
3080*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, typeSize, GL_FLOAT, GL_FALSE, 0, nullptr);
3081*8975f5c5SAndroid Build Coastguard Worker
3082*8975f5c5SAndroid Build Coastguard Worker // Draw twice to make sure that all static attributes dirty bits are synced.
3083*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
3084*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
3085*8975f5c5SAndroid Build Coastguard Worker checkPixels();
3086*8975f5c5SAndroid Build Coastguard Worker
3087*8975f5c5SAndroid Build Coastguard Worker // Modify the testBuffer using a raw buffer
3088*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_COMPUTE_PROGRAM(computeProgram, kComputeShader);
3089*8975f5c5SAndroid Build Coastguard Worker glProgramParameteri(computeProgram, GL_PROGRAM_SEPARABLE, GL_TRUE);
3090*8975f5c5SAndroid Build Coastguard Worker glUseProgramStages(pipeline, GL_COMPUTE_SHADER_BIT, computeProgram);
3091*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
3092*8975f5c5SAndroid Build Coastguard Worker
3093*8975f5c5SAndroid Build Coastguard Worker glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, testBuffer);
3094*8975f5c5SAndroid Build Coastguard Worker glDispatchCompute(1, 1, 1);
3095*8975f5c5SAndroid Build Coastguard Worker glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
3096*8975f5c5SAndroid Build Coastguard Worker
3097*8975f5c5SAndroid Build Coastguard Worker // Draw again to verify that testBuffer has been changed.
3098*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
3099*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
3100*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
3101*8975f5c5SAndroid Build Coastguard Worker checkPixelsUnEqual();
3102*8975f5c5SAndroid Build Coastguard Worker }
3103*8975f5c5SAndroid Build Coastguard Worker
3104*8975f5c5SAndroid Build Coastguard Worker // Verify that using VertexAttribBinding after VertexAttribPointer won't mess up the draw.
TEST_P(VertexAttributeTestES31,ChangeAttribBindingAfterVertexAttribPointer)3105*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES31, ChangeAttribBindingAfterVertexAttribPointer)
3106*8975f5c5SAndroid Build Coastguard Worker {
3107*8975f5c5SAndroid Build Coastguard Worker initTest();
3108*8975f5c5SAndroid Build Coastguard Worker
3109*8975f5c5SAndroid Build Coastguard Worker constexpr GLint kInputStride = 2;
3110*8975f5c5SAndroid Build Coastguard Worker constexpr GLint kFloatOffset = 10;
3111*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount + kFloatOffset> inputData1;
3112*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount * kInputStride> inputData2;
3113*8975f5c5SAndroid Build Coastguard Worker for (size_t count = 0; count < kVertexCount; ++count)
3114*8975f5c5SAndroid Build Coastguard Worker {
3115*8975f5c5SAndroid Build Coastguard Worker inputData1[kFloatOffset + count] = static_cast<GLfloat>(count);
3116*8975f5c5SAndroid Build Coastguard Worker inputData2[count * kInputStride] = static_cast<GLfloat>(count);
3117*8975f5c5SAndroid Build Coastguard Worker }
3118*8975f5c5SAndroid Build Coastguard Worker
3119*8975f5c5SAndroid Build Coastguard Worker GLBuffer mBuffer1;
3120*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer1);
3121*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, inputData1.size() * kFloatStride, inputData1.data(),
3122*8975f5c5SAndroid Build Coastguard Worker GL_STATIC_DRAW);
3123*8975f5c5SAndroid Build Coastguard Worker // Update the format indexed mTestAttrib and the binding indexed mTestAttrib by
3124*8975f5c5SAndroid Build Coastguard Worker // VertexAttribPointer.
3125*8975f5c5SAndroid Build Coastguard Worker const GLintptr kOffset = static_cast<GLintptr>(kFloatStride * kFloatOffset);
3126*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0,
3127*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<const GLvoid *>(kOffset));
3128*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
3129*8975f5c5SAndroid Build Coastguard Worker
3130*8975f5c5SAndroid Build Coastguard Worker constexpr GLint kTestBinding = 10;
3131*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(mTestAttrib, kTestBinding);
3132*8975f5c5SAndroid Build Coastguard Worker
3133*8975f5c5SAndroid Build Coastguard Worker GLBuffer mBuffer2;
3134*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer2);
3135*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, inputData2.size() * kFloatStride, inputData2.data(),
3136*8975f5c5SAndroid Build Coastguard Worker GL_STATIC_DRAW);
3137*8975f5c5SAndroid Build Coastguard Worker glBindVertexBuffer(kTestBinding, mBuffer2, 0, kFloatStride * kInputStride);
3138*8975f5c5SAndroid Build Coastguard Worker
3139*8975f5c5SAndroid Build Coastguard Worker // The attribute indexed mTestAttrib is using the binding indexed kTestBinding in the first
3140*8975f5c5SAndroid Build Coastguard Worker // draw.
3141*8975f5c5SAndroid Build Coastguard Worker glVertexAttribBinding(mTestAttrib, kTestBinding);
3142*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
3143*8975f5c5SAndroid Build Coastguard Worker checkPixels();
3144*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
3145*8975f5c5SAndroid Build Coastguard Worker
3146*8975f5c5SAndroid Build Coastguard Worker // The attribute indexed mTestAttrib is using the binding indexed mTestAttrib which should be
3147*8975f5c5SAndroid Build Coastguard Worker // set after the call VertexAttribPointer before the first draw.
3148*8975f5c5SAndroid Build Coastguard Worker glVertexAttribBinding(mTestAttrib, mTestAttrib);
3149*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
3150*8975f5c5SAndroid Build Coastguard Worker checkPixels();
3151*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
3152*8975f5c5SAndroid Build Coastguard Worker }
3153*8975f5c5SAndroid Build Coastguard Worker
3154*8975f5c5SAndroid Build Coastguard Worker // Verify that using VertexAttribFormat after VertexAttribPointer won't mess up the draw.
TEST_P(VertexAttributeTestES31,ChangeAttribFormatAfterVertexAttribPointer)3155*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES31, ChangeAttribFormatAfterVertexAttribPointer)
3156*8975f5c5SAndroid Build Coastguard Worker {
3157*8975f5c5SAndroid Build Coastguard Worker initTest();
3158*8975f5c5SAndroid Build Coastguard Worker
3159*8975f5c5SAndroid Build Coastguard Worker constexpr GLuint kFloatOffset = 10;
3160*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount + kFloatOffset> inputData;
3161*8975f5c5SAndroid Build Coastguard Worker for (size_t count = 0; count < kVertexCount; ++count)
3162*8975f5c5SAndroid Build Coastguard Worker {
3163*8975f5c5SAndroid Build Coastguard Worker inputData[kFloatOffset + count] = static_cast<GLfloat>(count);
3164*8975f5c5SAndroid Build Coastguard Worker }
3165*8975f5c5SAndroid Build Coastguard Worker
3166*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
3167*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, inputData.size() * kFloatStride, inputData.data(),
3168*8975f5c5SAndroid Build Coastguard Worker GL_STATIC_DRAW);
3169*8975f5c5SAndroid Build Coastguard Worker
3170*8975f5c5SAndroid Build Coastguard Worker // Call VertexAttribPointer on mTestAttrib. Now the relativeOffset of mTestAttrib should be 0.
3171*8975f5c5SAndroid Build Coastguard Worker const GLuint kOffset = static_cast<GLuint>(kFloatStride * kFloatOffset);
3172*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, 1, GL_FLOAT, GL_FALSE, 0, 0);
3173*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
3174*8975f5c5SAndroid Build Coastguard Worker
3175*8975f5c5SAndroid Build Coastguard Worker // Call VertexAttribFormat on mTestAttrib to modify the relativeOffset to kOffset.
3176*8975f5c5SAndroid Build Coastguard Worker glVertexAttribFormat(mTestAttrib, 1, GL_FLOAT, GL_FALSE, kOffset);
3177*8975f5c5SAndroid Build Coastguard Worker
3178*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
3179*8975f5c5SAndroid Build Coastguard Worker checkPixels();
3180*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
3181*8975f5c5SAndroid Build Coastguard Worker }
3182*8975f5c5SAndroid Build Coastguard Worker
3183*8975f5c5SAndroid Build Coastguard Worker // Verify that only updating a binding without updating the bound format won't mess up this draw.
TEST_P(VertexAttributeTestES31,OnlyUpdateBindingByBindVertexBuffer)3184*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES31, OnlyUpdateBindingByBindVertexBuffer)
3185*8975f5c5SAndroid Build Coastguard Worker {
3186*8975f5c5SAndroid Build Coastguard Worker // Default binding index for test
3187*8975f5c5SAndroid Build Coastguard Worker constexpr GLint kTestBinding = 10;
3188*8975f5c5SAndroid Build Coastguard Worker initOnlyUpdateBindingTest(kTestBinding);
3189*8975f5c5SAndroid Build Coastguard Worker
3190*8975f5c5SAndroid Build Coastguard Worker constexpr GLuint kTestFloatOffset2 = kVertexCount * 2;
3191*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData2 = {};
3192*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kTestFloatOffset2 + kVertexCount> inputData2 = {};
3193*8975f5c5SAndroid Build Coastguard Worker for (size_t count = 0; count < kVertexCount; ++count)
3194*8975f5c5SAndroid Build Coastguard Worker {
3195*8975f5c5SAndroid Build Coastguard Worker GLfloat value2 = static_cast<GLfloat>(count) * 2;
3196*8975f5c5SAndroid Build Coastguard Worker expectedData2[count] = value2;
3197*8975f5c5SAndroid Build Coastguard Worker inputData2[count + kTestFloatOffset2] = value2;
3198*8975f5c5SAndroid Build Coastguard Worker }
3199*8975f5c5SAndroid Build Coastguard Worker
3200*8975f5c5SAndroid Build Coastguard Worker // Set another set of data for mExpectedAttrib.
3201*8975f5c5SAndroid Build Coastguard Worker GLBuffer expectedBuffer2;
3202*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, expectedBuffer2);
3203*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, expectedData2.size() * kFloatStride, expectedData2.data(),
3204*8975f5c5SAndroid Build Coastguard Worker GL_STATIC_DRAW);
3205*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
3206*8975f5c5SAndroid Build Coastguard Worker
3207*8975f5c5SAndroid Build Coastguard Worker GLBuffer testBuffer2;
3208*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, testBuffer2);
3209*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, inputData2.size() * kFloatStride, inputData2.data(),
3210*8975f5c5SAndroid Build Coastguard Worker GL_STATIC_DRAW);
3211*8975f5c5SAndroid Build Coastguard Worker
3212*8975f5c5SAndroid Build Coastguard Worker // Only update the binding kTestBinding in the second draw by BindVertexBuffer.
3213*8975f5c5SAndroid Build Coastguard Worker glBindVertexBuffer(kTestBinding, testBuffer2, kTestFloatOffset2 * kFloatStride, kFloatStride);
3214*8975f5c5SAndroid Build Coastguard Worker
3215*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
3216*8975f5c5SAndroid Build Coastguard Worker checkPixels();
3217*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
3218*8975f5c5SAndroid Build Coastguard Worker }
3219*8975f5c5SAndroid Build Coastguard Worker
3220*8975f5c5SAndroid Build Coastguard Worker // Verify that only updating a binding without updating the bound format won't mess up this draw.
TEST_P(VertexAttributeTestES31,OnlyUpdateBindingByVertexAttribPointer)3221*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES31, OnlyUpdateBindingByVertexAttribPointer)
3222*8975f5c5SAndroid Build Coastguard Worker {
3223*8975f5c5SAndroid Build Coastguard Worker // Default binding index for test
3224*8975f5c5SAndroid Build Coastguard Worker constexpr GLint kTestBinding = 10;
3225*8975f5c5SAndroid Build Coastguard Worker initOnlyUpdateBindingTest(kTestBinding);
3226*8975f5c5SAndroid Build Coastguard Worker
3227*8975f5c5SAndroid Build Coastguard Worker constexpr GLuint kTestFloatOffset2 = kVertexCount * 3;
3228*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData2 = {};
3229*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kTestFloatOffset2 + kVertexCount> inputData2 = {};
3230*8975f5c5SAndroid Build Coastguard Worker for (size_t count = 0; count < kVertexCount; ++count)
3231*8975f5c5SAndroid Build Coastguard Worker {
3232*8975f5c5SAndroid Build Coastguard Worker GLfloat value2 = static_cast<GLfloat>(count) * 3;
3233*8975f5c5SAndroid Build Coastguard Worker expectedData2[count] = value2;
3234*8975f5c5SAndroid Build Coastguard Worker inputData2[count + kTestFloatOffset2] = value2;
3235*8975f5c5SAndroid Build Coastguard Worker }
3236*8975f5c5SAndroid Build Coastguard Worker
3237*8975f5c5SAndroid Build Coastguard Worker // Set another set of data for mExpectedAttrib.
3238*8975f5c5SAndroid Build Coastguard Worker GLBuffer expectedBuffer2;
3239*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, expectedBuffer2);
3240*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, expectedData2.size() * kFloatStride, expectedData2.data(),
3241*8975f5c5SAndroid Build Coastguard Worker GL_STATIC_DRAW);
3242*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
3243*8975f5c5SAndroid Build Coastguard Worker
3244*8975f5c5SAndroid Build Coastguard Worker GLBuffer testBuffer2;
3245*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, testBuffer2);
3246*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, inputData2.size() * kFloatStride, inputData2.data(),
3247*8975f5c5SAndroid Build Coastguard Worker GL_STATIC_DRAW);
3248*8975f5c5SAndroid Build Coastguard Worker
3249*8975f5c5SAndroid Build Coastguard Worker // Only update the binding kTestBinding in the second draw by VertexAttribPointer.
3250*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(
3251*8975f5c5SAndroid Build Coastguard Worker kTestBinding, 1, GL_FLOAT, GL_FALSE, 0,
3252*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<const void *>(static_cast<uintptr_t>(kTestFloatOffset2 * kFloatStride)));
3253*8975f5c5SAndroid Build Coastguard Worker
3254*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
3255*8975f5c5SAndroid Build Coastguard Worker checkPixels();
3256*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
3257*8975f5c5SAndroid Build Coastguard Worker }
3258*8975f5c5SAndroid Build Coastguard Worker
3259*8975f5c5SAndroid Build Coastguard Worker class VertexAttributeCachingTest : public VertexAttributeTest
3260*8975f5c5SAndroid Build Coastguard Worker {
3261*8975f5c5SAndroid Build Coastguard Worker protected:
VertexAttributeCachingTest()3262*8975f5c5SAndroid Build Coastguard Worker VertexAttributeCachingTest() {}
3263*8975f5c5SAndroid Build Coastguard Worker
3264*8975f5c5SAndroid Build Coastguard Worker void testSetUp() override;
3265*8975f5c5SAndroid Build Coastguard Worker
3266*8975f5c5SAndroid Build Coastguard Worker template <typename DestT>
3267*8975f5c5SAndroid Build Coastguard Worker static std::vector<GLfloat> GetExpectedData(const std::vector<GLubyte> &srcData,
3268*8975f5c5SAndroid Build Coastguard Worker GLenum attribType,
3269*8975f5c5SAndroid Build Coastguard Worker GLboolean normalized);
3270*8975f5c5SAndroid Build Coastguard Worker
initDoubleAttribProgram()3271*8975f5c5SAndroid Build Coastguard Worker void initDoubleAttribProgram()
3272*8975f5c5SAndroid Build Coastguard Worker {
3273*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] =
3274*8975f5c5SAndroid Build Coastguard Worker "attribute mediump vec4 position;\n"
3275*8975f5c5SAndroid Build Coastguard Worker "attribute mediump vec4 test;\n"
3276*8975f5c5SAndroid Build Coastguard Worker "attribute mediump vec4 expected;\n"
3277*8975f5c5SAndroid Build Coastguard Worker "attribute mediump vec4 test2;\n"
3278*8975f5c5SAndroid Build Coastguard Worker "attribute mediump vec4 expected2;\n"
3279*8975f5c5SAndroid Build Coastguard Worker "varying mediump vec4 color;\n"
3280*8975f5c5SAndroid Build Coastguard Worker "void main(void)\n"
3281*8975f5c5SAndroid Build Coastguard Worker "{\n"
3282*8975f5c5SAndroid Build Coastguard Worker " gl_Position = position;\n"
3283*8975f5c5SAndroid Build Coastguard Worker " vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);\n"
3284*8975f5c5SAndroid Build Coastguard Worker " color = vec4(lessThanEqual(abs(test - expected), threshold));\n"
3285*8975f5c5SAndroid Build Coastguard Worker " vec4 threshold2 = max(abs(expected2) * 0.01, 1.0 / 64.0);\n"
3286*8975f5c5SAndroid Build Coastguard Worker " color += vec4(lessThanEqual(abs(test2 - expected2), threshold2));\n"
3287*8975f5c5SAndroid Build Coastguard Worker "}\n";
3288*8975f5c5SAndroid Build Coastguard Worker
3289*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] =
3290*8975f5c5SAndroid Build Coastguard Worker "varying mediump vec4 color;\n"
3291*8975f5c5SAndroid Build Coastguard Worker "void main(void)\n"
3292*8975f5c5SAndroid Build Coastguard Worker "{\n"
3293*8975f5c5SAndroid Build Coastguard Worker " gl_FragColor = color;\n"
3294*8975f5c5SAndroid Build Coastguard Worker "}\n";
3295*8975f5c5SAndroid Build Coastguard Worker
3296*8975f5c5SAndroid Build Coastguard Worker mProgram = CompileProgram(kVS, kFS);
3297*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(0u, mProgram);
3298*8975f5c5SAndroid Build Coastguard Worker
3299*8975f5c5SAndroid Build Coastguard Worker mTestAttrib = glGetAttribLocation(mProgram, "test");
3300*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, mTestAttrib);
3301*8975f5c5SAndroid Build Coastguard Worker mExpectedAttrib = glGetAttribLocation(mProgram, "expected");
3302*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, mExpectedAttrib);
3303*8975f5c5SAndroid Build Coastguard Worker
3304*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
3305*8975f5c5SAndroid Build Coastguard Worker }
3306*8975f5c5SAndroid Build Coastguard Worker
3307*8975f5c5SAndroid Build Coastguard Worker struct AttribData
3308*8975f5c5SAndroid Build Coastguard Worker {
3309*8975f5c5SAndroid Build Coastguard Worker AttribData(GLenum typeIn, GLint sizeIn, GLboolean normalizedIn, GLsizei strideIn);
3310*8975f5c5SAndroid Build Coastguard Worker
3311*8975f5c5SAndroid Build Coastguard Worker GLenum type;
3312*8975f5c5SAndroid Build Coastguard Worker GLint size;
3313*8975f5c5SAndroid Build Coastguard Worker GLboolean normalized;
3314*8975f5c5SAndroid Build Coastguard Worker GLsizei stride;
3315*8975f5c5SAndroid Build Coastguard Worker };
3316*8975f5c5SAndroid Build Coastguard Worker
3317*8975f5c5SAndroid Build Coastguard Worker std::vector<AttribData> mTestData;
3318*8975f5c5SAndroid Build Coastguard Worker std::map<GLenum, std::vector<GLfloat>> mExpectedData;
3319*8975f5c5SAndroid Build Coastguard Worker std::map<GLenum, std::vector<GLfloat>> mNormExpectedData;
3320*8975f5c5SAndroid Build Coastguard Worker };
3321*8975f5c5SAndroid Build Coastguard Worker
AttribData(GLenum typeIn,GLint sizeIn,GLboolean normalizedIn,GLsizei strideIn)3322*8975f5c5SAndroid Build Coastguard Worker VertexAttributeCachingTest::AttribData::AttribData(GLenum typeIn,
3323*8975f5c5SAndroid Build Coastguard Worker GLint sizeIn,
3324*8975f5c5SAndroid Build Coastguard Worker GLboolean normalizedIn,
3325*8975f5c5SAndroid Build Coastguard Worker GLsizei strideIn)
3326*8975f5c5SAndroid Build Coastguard Worker : type(typeIn), size(sizeIn), normalized(normalizedIn), stride(strideIn)
3327*8975f5c5SAndroid Build Coastguard Worker {}
3328*8975f5c5SAndroid Build Coastguard Worker
3329*8975f5c5SAndroid Build Coastguard Worker // static
3330*8975f5c5SAndroid Build Coastguard Worker template <typename DestT>
GetExpectedData(const std::vector<GLubyte> & srcData,GLenum attribType,GLboolean normalized)3331*8975f5c5SAndroid Build Coastguard Worker std::vector<GLfloat> VertexAttributeCachingTest::GetExpectedData(
3332*8975f5c5SAndroid Build Coastguard Worker const std::vector<GLubyte> &srcData,
3333*8975f5c5SAndroid Build Coastguard Worker GLenum attribType,
3334*8975f5c5SAndroid Build Coastguard Worker GLboolean normalized)
3335*8975f5c5SAndroid Build Coastguard Worker {
3336*8975f5c5SAndroid Build Coastguard Worker std::vector<GLfloat> expectedData;
3337*8975f5c5SAndroid Build Coastguard Worker
3338*8975f5c5SAndroid Build Coastguard Worker const DestT *typedSrcPtr = reinterpret_cast<const DestT *>(srcData.data());
3339*8975f5c5SAndroid Build Coastguard Worker size_t iterations = srcData.size() / TypeStride(attribType);
3340*8975f5c5SAndroid Build Coastguard Worker
3341*8975f5c5SAndroid Build Coastguard Worker if (normalized)
3342*8975f5c5SAndroid Build Coastguard Worker {
3343*8975f5c5SAndroid Build Coastguard Worker for (size_t index = 0; index < iterations; ++index)
3344*8975f5c5SAndroid Build Coastguard Worker {
3345*8975f5c5SAndroid Build Coastguard Worker expectedData.push_back(Normalize(typedSrcPtr[index]));
3346*8975f5c5SAndroid Build Coastguard Worker }
3347*8975f5c5SAndroid Build Coastguard Worker }
3348*8975f5c5SAndroid Build Coastguard Worker else
3349*8975f5c5SAndroid Build Coastguard Worker {
3350*8975f5c5SAndroid Build Coastguard Worker for (size_t index = 0; index < iterations; ++index)
3351*8975f5c5SAndroid Build Coastguard Worker {
3352*8975f5c5SAndroid Build Coastguard Worker expectedData.push_back(static_cast<GLfloat>(typedSrcPtr[index]));
3353*8975f5c5SAndroid Build Coastguard Worker }
3354*8975f5c5SAndroid Build Coastguard Worker }
3355*8975f5c5SAndroid Build Coastguard Worker
3356*8975f5c5SAndroid Build Coastguard Worker return expectedData;
3357*8975f5c5SAndroid Build Coastguard Worker }
3358*8975f5c5SAndroid Build Coastguard Worker
testSetUp()3359*8975f5c5SAndroid Build Coastguard Worker void VertexAttributeCachingTest::testSetUp()
3360*8975f5c5SAndroid Build Coastguard Worker {
3361*8975f5c5SAndroid Build Coastguard Worker VertexAttributeTest::testSetUp();
3362*8975f5c5SAndroid Build Coastguard Worker
3363*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
3364*8975f5c5SAndroid Build Coastguard Worker
3365*8975f5c5SAndroid Build Coastguard Worker std::vector<GLubyte> srcData;
3366*8975f5c5SAndroid Build Coastguard Worker for (size_t count = 0; count < 4; ++count)
3367*8975f5c5SAndroid Build Coastguard Worker {
3368*8975f5c5SAndroid Build Coastguard Worker for (GLubyte i = 0; i < std::numeric_limits<GLubyte>::max(); ++i)
3369*8975f5c5SAndroid Build Coastguard Worker {
3370*8975f5c5SAndroid Build Coastguard Worker srcData.push_back(i);
3371*8975f5c5SAndroid Build Coastguard Worker }
3372*8975f5c5SAndroid Build Coastguard Worker }
3373*8975f5c5SAndroid Build Coastguard Worker
3374*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, srcData.size(), srcData.data(), GL_STATIC_DRAW);
3375*8975f5c5SAndroid Build Coastguard Worker
3376*8975f5c5SAndroid Build Coastguard Worker GLint viewportSize[4];
3377*8975f5c5SAndroid Build Coastguard Worker glGetIntegerv(GL_VIEWPORT, viewportSize);
3378*8975f5c5SAndroid Build Coastguard Worker
3379*8975f5c5SAndroid Build Coastguard Worker std::vector<GLenum> attribTypes;
3380*8975f5c5SAndroid Build Coastguard Worker attribTypes.push_back(GL_BYTE);
3381*8975f5c5SAndroid Build Coastguard Worker attribTypes.push_back(GL_UNSIGNED_BYTE);
3382*8975f5c5SAndroid Build Coastguard Worker attribTypes.push_back(GL_SHORT);
3383*8975f5c5SAndroid Build Coastguard Worker attribTypes.push_back(GL_UNSIGNED_SHORT);
3384*8975f5c5SAndroid Build Coastguard Worker
3385*8975f5c5SAndroid Build Coastguard Worker if (getClientMajorVersion() >= 3)
3386*8975f5c5SAndroid Build Coastguard Worker {
3387*8975f5c5SAndroid Build Coastguard Worker attribTypes.push_back(GL_INT);
3388*8975f5c5SAndroid Build Coastguard Worker attribTypes.push_back(GL_UNSIGNED_INT);
3389*8975f5c5SAndroid Build Coastguard Worker }
3390*8975f5c5SAndroid Build Coastguard Worker
3391*8975f5c5SAndroid Build Coastguard Worker constexpr GLint kMaxSize = 4;
3392*8975f5c5SAndroid Build Coastguard Worker constexpr GLsizei kMaxStride = 4;
3393*8975f5c5SAndroid Build Coastguard Worker
3394*8975f5c5SAndroid Build Coastguard Worker for (GLenum attribType : attribTypes)
3395*8975f5c5SAndroid Build Coastguard Worker {
3396*8975f5c5SAndroid Build Coastguard Worker for (GLint attribSize = 1; attribSize <= kMaxSize; ++attribSize)
3397*8975f5c5SAndroid Build Coastguard Worker {
3398*8975f5c5SAndroid Build Coastguard Worker for (GLsizei stride = 1; stride <= kMaxStride; ++stride)
3399*8975f5c5SAndroid Build Coastguard Worker {
3400*8975f5c5SAndroid Build Coastguard Worker mTestData.push_back(AttribData(attribType, attribSize, GL_FALSE, stride));
3401*8975f5c5SAndroid Build Coastguard Worker if (attribType != GL_FLOAT)
3402*8975f5c5SAndroid Build Coastguard Worker {
3403*8975f5c5SAndroid Build Coastguard Worker mTestData.push_back(AttribData(attribType, attribSize, GL_TRUE, stride));
3404*8975f5c5SAndroid Build Coastguard Worker }
3405*8975f5c5SAndroid Build Coastguard Worker }
3406*8975f5c5SAndroid Build Coastguard Worker }
3407*8975f5c5SAndroid Build Coastguard Worker }
3408*8975f5c5SAndroid Build Coastguard Worker
3409*8975f5c5SAndroid Build Coastguard Worker mExpectedData[GL_BYTE] = GetExpectedData<GLbyte>(srcData, GL_BYTE, GL_FALSE);
3410*8975f5c5SAndroid Build Coastguard Worker mExpectedData[GL_UNSIGNED_BYTE] = GetExpectedData<GLubyte>(srcData, GL_UNSIGNED_BYTE, GL_FALSE);
3411*8975f5c5SAndroid Build Coastguard Worker mExpectedData[GL_SHORT] = GetExpectedData<GLshort>(srcData, GL_SHORT, GL_FALSE);
3412*8975f5c5SAndroid Build Coastguard Worker mExpectedData[GL_UNSIGNED_SHORT] =
3413*8975f5c5SAndroid Build Coastguard Worker GetExpectedData<GLushort>(srcData, GL_UNSIGNED_SHORT, GL_FALSE);
3414*8975f5c5SAndroid Build Coastguard Worker mExpectedData[GL_INT] = GetExpectedData<GLint>(srcData, GL_INT, GL_FALSE);
3415*8975f5c5SAndroid Build Coastguard Worker mExpectedData[GL_UNSIGNED_INT] = GetExpectedData<GLuint>(srcData, GL_UNSIGNED_INT, GL_FALSE);
3416*8975f5c5SAndroid Build Coastguard Worker
3417*8975f5c5SAndroid Build Coastguard Worker mNormExpectedData[GL_BYTE] = GetExpectedData<GLbyte>(srcData, GL_BYTE, GL_TRUE);
3418*8975f5c5SAndroid Build Coastguard Worker mNormExpectedData[GL_UNSIGNED_BYTE] =
3419*8975f5c5SAndroid Build Coastguard Worker GetExpectedData<GLubyte>(srcData, GL_UNSIGNED_BYTE, GL_TRUE);
3420*8975f5c5SAndroid Build Coastguard Worker mNormExpectedData[GL_SHORT] = GetExpectedData<GLshort>(srcData, GL_SHORT, GL_TRUE);
3421*8975f5c5SAndroid Build Coastguard Worker mNormExpectedData[GL_UNSIGNED_SHORT] =
3422*8975f5c5SAndroid Build Coastguard Worker GetExpectedData<GLushort>(srcData, GL_UNSIGNED_SHORT, GL_TRUE);
3423*8975f5c5SAndroid Build Coastguard Worker mNormExpectedData[GL_INT] = GetExpectedData<GLint>(srcData, GL_INT, GL_TRUE);
3424*8975f5c5SAndroid Build Coastguard Worker mNormExpectedData[GL_UNSIGNED_INT] = GetExpectedData<GLuint>(srcData, GL_UNSIGNED_INT, GL_TRUE);
3425*8975f5c5SAndroid Build Coastguard Worker }
3426*8975f5c5SAndroid Build Coastguard Worker
3427*8975f5c5SAndroid Build Coastguard Worker // In D3D11, we must sometimes translate buffer data into static attribute caches. We also use a
3428*8975f5c5SAndroid Build Coastguard Worker // cache management scheme which garbage collects old attributes after we start using too much
3429*8975f5c5SAndroid Build Coastguard Worker // cache data. This test tries to make as many attribute caches from a single buffer as possible
3430*8975f5c5SAndroid Build Coastguard Worker // to stress-test the caching code.
TEST_P(VertexAttributeCachingTest,BufferMulticaching)3431*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeCachingTest, BufferMulticaching)
3432*8975f5c5SAndroid Build Coastguard Worker {
3433*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
3434*8975f5c5SAndroid Build Coastguard Worker
3435*8975f5c5SAndroid Build Coastguard Worker initBasicProgram();
3436*8975f5c5SAndroid Build Coastguard Worker
3437*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
3438*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mExpectedAttrib);
3439*8975f5c5SAndroid Build Coastguard Worker
3440*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
3441*8975f5c5SAndroid Build Coastguard Worker
3442*8975f5c5SAndroid Build Coastguard Worker for (const AttribData &data : mTestData)
3443*8975f5c5SAndroid Build Coastguard Worker {
3444*8975f5c5SAndroid Build Coastguard Worker const auto &expected =
3445*8975f5c5SAndroid Build Coastguard Worker (data.normalized) ? mNormExpectedData[data.type] : mExpectedData[data.type];
3446*8975f5c5SAndroid Build Coastguard Worker
3447*8975f5c5SAndroid Build Coastguard Worker GLsizei baseStride = static_cast<GLsizei>(data.size) * data.stride;
3448*8975f5c5SAndroid Build Coastguard Worker GLsizei stride = TypeStride(data.type) * baseStride;
3449*8975f5c5SAndroid Build Coastguard Worker
3450*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
3451*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, data.size, data.type, data.normalized, stride, nullptr);
3452*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
3453*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, data.size, GL_FLOAT, GL_FALSE,
3454*8975f5c5SAndroid Build Coastguard Worker sizeof(GLfloat) * baseStride, expected.data());
3455*8975f5c5SAndroid Build Coastguard Worker drawQuad(mProgram, "position", 0.5f);
3456*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
3457*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::white);
3458*8975f5c5SAndroid Build Coastguard Worker }
3459*8975f5c5SAndroid Build Coastguard Worker }
3460*8975f5c5SAndroid Build Coastguard Worker
3461*8975f5c5SAndroid Build Coastguard Worker // With D3D11 dirty bits for VertxArray11, we can leave vertex state unchanged if there aren't any
3462*8975f5c5SAndroid Build Coastguard Worker // GL calls that affect it. This test targets leaving one vertex attribute unchanged between draw
3463*8975f5c5SAndroid Build Coastguard Worker // calls while changing another vertex attribute enough that it clears the static buffer cache
3464*8975f5c5SAndroid Build Coastguard Worker // after enough iterations. It validates the unchanged attributes don't get deleted incidentally.
TEST_P(VertexAttributeCachingTest,BufferMulticachingWithOneUnchangedAttrib)3465*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeCachingTest, BufferMulticachingWithOneUnchangedAttrib)
3466*8975f5c5SAndroid Build Coastguard Worker {
3467*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsAMD() && IsDesktopOpenGL());
3468*8975f5c5SAndroid Build Coastguard Worker
3469*8975f5c5SAndroid Build Coastguard Worker initDoubleAttribProgram();
3470*8975f5c5SAndroid Build Coastguard Worker
3471*8975f5c5SAndroid Build Coastguard Worker GLint testAttrib2Location = glGetAttribLocation(mProgram, "test2");
3472*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, testAttrib2Location);
3473*8975f5c5SAndroid Build Coastguard Worker GLint expectedAttrib2Location = glGetAttribLocation(mProgram, "expected2");
3474*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, expectedAttrib2Location);
3475*8975f5c5SAndroid Build Coastguard Worker
3476*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mTestAttrib);
3477*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(mExpectedAttrib);
3478*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(testAttrib2Location);
3479*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(expectedAttrib2Location);
3480*8975f5c5SAndroid Build Coastguard Worker
3481*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
3482*8975f5c5SAndroid Build Coastguard Worker
3483*8975f5c5SAndroid Build Coastguard Worker // Use an attribute that we know must be converted. This is a bit sensitive.
3484*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
3485*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(testAttrib2Location, 3, GL_UNSIGNED_SHORT, GL_FALSE, 6, nullptr);
3486*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
3487*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(expectedAttrib2Location, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3,
3488*8975f5c5SAndroid Build Coastguard Worker mExpectedData[GL_UNSIGNED_SHORT].data());
3489*8975f5c5SAndroid Build Coastguard Worker
3490*8975f5c5SAndroid Build Coastguard Worker for (const auto &data : mTestData)
3491*8975f5c5SAndroid Build Coastguard Worker {
3492*8975f5c5SAndroid Build Coastguard Worker const auto &expected =
3493*8975f5c5SAndroid Build Coastguard Worker (data.normalized) ? mNormExpectedData[data.type] : mExpectedData[data.type];
3494*8975f5c5SAndroid Build Coastguard Worker
3495*8975f5c5SAndroid Build Coastguard Worker GLsizei baseStride = static_cast<GLsizei>(data.size) * data.stride;
3496*8975f5c5SAndroid Build Coastguard Worker GLsizei stride = TypeStride(data.type) * baseStride;
3497*8975f5c5SAndroid Build Coastguard Worker
3498*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
3499*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mTestAttrib, data.size, data.type, data.normalized, stride, nullptr);
3500*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
3501*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(mExpectedAttrib, data.size, GL_FLOAT, GL_FALSE,
3502*8975f5c5SAndroid Build Coastguard Worker sizeof(GLfloat) * baseStride, expected.data());
3503*8975f5c5SAndroid Build Coastguard Worker drawQuad(mProgram, "position", 0.5f);
3504*8975f5c5SAndroid Build Coastguard Worker
3505*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
3506*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 255, 255, 255);
3507*8975f5c5SAndroid Build Coastguard Worker }
3508*8975f5c5SAndroid Build Coastguard Worker }
3509*8975f5c5SAndroid Build Coastguard Worker
3510*8975f5c5SAndroid Build Coastguard Worker // Test that if there are gaps in the attribute indices, the attributes have their correct values.
TEST_P(VertexAttributeTest,UnusedVertexAttribWorks)3511*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, UnusedVertexAttribWorks)
3512*8975f5c5SAndroid Build Coastguard Worker {
3513*8975f5c5SAndroid Build Coastguard Worker constexpr char kVertexShader[] = R"(attribute vec2 position;
3514*8975f5c5SAndroid Build Coastguard Worker attribute float actualValue;
3515*8975f5c5SAndroid Build Coastguard Worker uniform float expectedValue;
3516*8975f5c5SAndroid Build Coastguard Worker varying float result;
3517*8975f5c5SAndroid Build Coastguard Worker void main()
3518*8975f5c5SAndroid Build Coastguard Worker {
3519*8975f5c5SAndroid Build Coastguard Worker result = (actualValue == expectedValue) ? 1.0 : 0.0;
3520*8975f5c5SAndroid Build Coastguard Worker gl_Position = vec4(position, 0, 1);
3521*8975f5c5SAndroid Build Coastguard Worker })";
3522*8975f5c5SAndroid Build Coastguard Worker
3523*8975f5c5SAndroid Build Coastguard Worker constexpr char kFragmentShader[] = R"(varying mediump float result;
3524*8975f5c5SAndroid Build Coastguard Worker void main()
3525*8975f5c5SAndroid Build Coastguard Worker {
3526*8975f5c5SAndroid Build Coastguard Worker gl_FragColor = result > 0.0 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3527*8975f5c5SAndroid Build Coastguard Worker })";
3528*8975f5c5SAndroid Build Coastguard Worker
3529*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
3530*8975f5c5SAndroid Build Coastguard Worker
3531*8975f5c5SAndroid Build Coastguard Worker // Force a gap in attributes by using location 0 and 3
3532*8975f5c5SAndroid Build Coastguard Worker GLint positionLocation = 0;
3533*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, positionLocation, "position");
3534*8975f5c5SAndroid Build Coastguard Worker
3535*8975f5c5SAndroid Build Coastguard Worker GLint attribLoc = 3;
3536*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, attribLoc, "actualValue");
3537*8975f5c5SAndroid Build Coastguard Worker
3538*8975f5c5SAndroid Build Coastguard Worker // Re-link the program to update the attribute locations
3539*8975f5c5SAndroid Build Coastguard Worker glLinkProgram(program);
3540*8975f5c5SAndroid Build Coastguard Worker ASSERT_TRUE(CheckLinkStatusAndReturnProgram(program, true));
3541*8975f5c5SAndroid Build Coastguard Worker
3542*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
3543*8975f5c5SAndroid Build Coastguard Worker
3544*8975f5c5SAndroid Build Coastguard Worker GLint uniLoc = glGetUniformLocation(program, "expectedValue");
3545*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, uniLoc);
3546*8975f5c5SAndroid Build Coastguard Worker
3547*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(attribLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
3548*8975f5c5SAndroid Build Coastguard Worker
3549*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, positionLocation);
3550*8975f5c5SAndroid Build Coastguard Worker setupQuadVertexBuffer(0.5f, 1.0f);
3551*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
3552*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(positionLocation);
3553*8975f5c5SAndroid Build Coastguard Worker
3554*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, 4> testValues = {{1, 2, 3, 4}};
3555*8975f5c5SAndroid Build Coastguard Worker for (GLfloat testValue : testValues)
3556*8975f5c5SAndroid Build Coastguard Worker {
3557*8975f5c5SAndroid Build Coastguard Worker glUniform1f(uniLoc, testValue);
3558*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib1f(attribLoc, testValue);
3559*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
3560*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
3561*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3562*8975f5c5SAndroid Build Coastguard Worker }
3563*8975f5c5SAndroid Build Coastguard Worker }
3564*8975f5c5SAndroid Build Coastguard Worker
3565*8975f5c5SAndroid Build Coastguard Worker // Tests that repeatedly updating a disabled vertex attribute works as expected.
3566*8975f5c5SAndroid Build Coastguard Worker // This covers an ANGLE bug where dirty bits for current values were ignoring repeated updates.
TEST_P(VertexAttributeTest,DisabledAttribUpdates)3567*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, DisabledAttribUpdates)
3568*8975f5c5SAndroid Build Coastguard Worker {
3569*8975f5c5SAndroid Build Coastguard Worker constexpr char kVertexShader[] = R"(attribute vec2 position;
3570*8975f5c5SAndroid Build Coastguard Worker attribute float actualValue;
3571*8975f5c5SAndroid Build Coastguard Worker uniform float expectedValue;
3572*8975f5c5SAndroid Build Coastguard Worker varying float result;
3573*8975f5c5SAndroid Build Coastguard Worker void main()
3574*8975f5c5SAndroid Build Coastguard Worker {
3575*8975f5c5SAndroid Build Coastguard Worker result = (actualValue == expectedValue) ? 1.0 : 0.0;
3576*8975f5c5SAndroid Build Coastguard Worker gl_Position = vec4(position, 0, 1);
3577*8975f5c5SAndroid Build Coastguard Worker })";
3578*8975f5c5SAndroid Build Coastguard Worker
3579*8975f5c5SAndroid Build Coastguard Worker constexpr char kFragmentShader[] = R"(varying mediump float result;
3580*8975f5c5SAndroid Build Coastguard Worker void main()
3581*8975f5c5SAndroid Build Coastguard Worker {
3582*8975f5c5SAndroid Build Coastguard Worker gl_FragColor = result > 0.0 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3583*8975f5c5SAndroid Build Coastguard Worker })";
3584*8975f5c5SAndroid Build Coastguard Worker
3585*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
3586*8975f5c5SAndroid Build Coastguard Worker
3587*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
3588*8975f5c5SAndroid Build Coastguard Worker GLint attribLoc = glGetAttribLocation(program, "actualValue");
3589*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, attribLoc);
3590*8975f5c5SAndroid Build Coastguard Worker
3591*8975f5c5SAndroid Build Coastguard Worker GLint uniLoc = glGetUniformLocation(program, "expectedValue");
3592*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, uniLoc);
3593*8975f5c5SAndroid Build Coastguard Worker
3594*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(attribLoc, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
3595*8975f5c5SAndroid Build Coastguard Worker
3596*8975f5c5SAndroid Build Coastguard Worker GLint positionLocation = glGetAttribLocation(program, "position");
3597*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, positionLocation);
3598*8975f5c5SAndroid Build Coastguard Worker setupQuadVertexBuffer(0.5f, 1.0f);
3599*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
3600*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(positionLocation);
3601*8975f5c5SAndroid Build Coastguard Worker
3602*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, 4> testValues = {{1, 2, 3, 4}};
3603*8975f5c5SAndroid Build Coastguard Worker for (GLfloat testValue : testValues)
3604*8975f5c5SAndroid Build Coastguard Worker {
3605*8975f5c5SAndroid Build Coastguard Worker glUniform1f(uniLoc, testValue);
3606*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib1f(attribLoc, testValue);
3607*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
3608*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
3609*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3610*8975f5c5SAndroid Build Coastguard Worker }
3611*8975f5c5SAndroid Build Coastguard Worker }
3612*8975f5c5SAndroid Build Coastguard Worker
3613*8975f5c5SAndroid Build Coastguard Worker // Test that even inactive attributes are taken into account when checking for aliasing in case the
3614*8975f5c5SAndroid Build Coastguard Worker // shader version is >= 3.00. GLSL ES 3.00.6 section 12.46.
TEST_P(VertexAttributeTestES3,InactiveAttributeAliasing)3615*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, InactiveAttributeAliasing)
3616*8975f5c5SAndroid Build Coastguard Worker {
3617*8975f5c5SAndroid Build Coastguard Worker constexpr char vertexShader[] =
3618*8975f5c5SAndroid Build Coastguard Worker R"(#version 300 es
3619*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
3620*8975f5c5SAndroid Build Coastguard Worker in vec4 input_active;
3621*8975f5c5SAndroid Build Coastguard Worker in vec4 input_unused;
3622*8975f5c5SAndroid Build Coastguard Worker void main()
3623*8975f5c5SAndroid Build Coastguard Worker {
3624*8975f5c5SAndroid Build Coastguard Worker gl_Position = input_active;
3625*8975f5c5SAndroid Build Coastguard Worker })";
3626*8975f5c5SAndroid Build Coastguard Worker
3627*8975f5c5SAndroid Build Coastguard Worker constexpr char fragmentShader[] =
3628*8975f5c5SAndroid Build Coastguard Worker R"(#version 300 es
3629*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
3630*8975f5c5SAndroid Build Coastguard Worker out vec4 color;
3631*8975f5c5SAndroid Build Coastguard Worker void main()
3632*8975f5c5SAndroid Build Coastguard Worker {
3633*8975f5c5SAndroid Build Coastguard Worker color = vec4(0.0);
3634*8975f5c5SAndroid Build Coastguard Worker })";
3635*8975f5c5SAndroid Build Coastguard Worker
3636*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(program, vertexShader, fragmentShader);
3637*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 0, "input_active");
3638*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 0, "input_unused");
3639*8975f5c5SAndroid Build Coastguard Worker glLinkProgram(program);
3640*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
3641*8975f5c5SAndroid Build Coastguard Worker GLint linkStatus = 0;
3642*8975f5c5SAndroid Build Coastguard Worker glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
3643*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_FALSE(linkStatus);
3644*8975f5c5SAndroid Build Coastguard Worker }
3645*8975f5c5SAndroid Build Coastguard Worker
3646*8975f5c5SAndroid Build Coastguard Worker // Test that enabling inactive attributes doesn't cause a crash
3647*8975f5c5SAndroid Build Coastguard Worker // shader version is >= 3.00
TEST_P(VertexAttributeTestES3,EnabledButInactiveAttributes)3648*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, EnabledButInactiveAttributes)
3649*8975f5c5SAndroid Build Coastguard Worker {
3650*8975f5c5SAndroid Build Coastguard Worker // This is similar to runtest(), and the test is disabled there
3651*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
3652*8975f5c5SAndroid Build Coastguard Worker
3653*8975f5c5SAndroid Build Coastguard Worker constexpr char testVertexShaderSource[] =
3654*8975f5c5SAndroid Build Coastguard Worker R"(#version 300 es
3655*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
3656*8975f5c5SAndroid Build Coastguard Worker in vec4 position;
3657*8975f5c5SAndroid Build Coastguard Worker layout(location = 1) in vec4 test;
3658*8975f5c5SAndroid Build Coastguard Worker layout(location = 2) in vec4 unused1;
3659*8975f5c5SAndroid Build Coastguard Worker layout(location = 3) in vec4 unused2;
3660*8975f5c5SAndroid Build Coastguard Worker layout(location = 4) in vec4 unused3;
3661*8975f5c5SAndroid Build Coastguard Worker layout(location = 5) in vec4 expected;
3662*8975f5c5SAndroid Build Coastguard Worker out vec4 color;
3663*8975f5c5SAndroid Build Coastguard Worker void main(void)
3664*8975f5c5SAndroid Build Coastguard Worker {
3665*8975f5c5SAndroid Build Coastguard Worker gl_Position = position;
3666*8975f5c5SAndroid Build Coastguard Worker vec4 threshold = max(abs(expected) * 0.01, 1.0 / 64.0);
3667*8975f5c5SAndroid Build Coastguard Worker color = vec4(lessThanEqual(abs(test - expected), threshold));
3668*8975f5c5SAndroid Build Coastguard Worker })";
3669*8975f5c5SAndroid Build Coastguard Worker
3670*8975f5c5SAndroid Build Coastguard Worker // Same as previous one, except it uses unused1/2 instead of test/expected, leaving unused3
3671*8975f5c5SAndroid Build Coastguard Worker // unused
3672*8975f5c5SAndroid Build Coastguard Worker constexpr char testVertexShader2Source[] =
3673*8975f5c5SAndroid Build Coastguard Worker R"(#version 300 es
3674*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
3675*8975f5c5SAndroid Build Coastguard Worker in vec4 position;
3676*8975f5c5SAndroid Build Coastguard Worker layout(location = 1) in vec4 test;
3677*8975f5c5SAndroid Build Coastguard Worker layout(location = 2) in vec4 unused1;
3678*8975f5c5SAndroid Build Coastguard Worker layout(location = 3) in vec4 unused2;
3679*8975f5c5SAndroid Build Coastguard Worker layout(location = 4) in vec4 unused3;
3680*8975f5c5SAndroid Build Coastguard Worker layout(location = 5) in vec4 expected;
3681*8975f5c5SAndroid Build Coastguard Worker out vec4 color;
3682*8975f5c5SAndroid Build Coastguard Worker void main(void)
3683*8975f5c5SAndroid Build Coastguard Worker {
3684*8975f5c5SAndroid Build Coastguard Worker gl_Position = position;
3685*8975f5c5SAndroid Build Coastguard Worker vec4 threshold = max(abs(unused2) * 0.01, 1.0 / 64.0);
3686*8975f5c5SAndroid Build Coastguard Worker color = vec4(lessThanEqual(abs(unused1 - unused2), threshold));
3687*8975f5c5SAndroid Build Coastguard Worker })";
3688*8975f5c5SAndroid Build Coastguard Worker
3689*8975f5c5SAndroid Build Coastguard Worker constexpr char testFragmentShaderSource[] =
3690*8975f5c5SAndroid Build Coastguard Worker R"(#version 300 es
3691*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
3692*8975f5c5SAndroid Build Coastguard Worker in vec4 color;
3693*8975f5c5SAndroid Build Coastguard Worker out vec4 out_color;
3694*8975f5c5SAndroid Build Coastguard Worker void main()
3695*8975f5c5SAndroid Build Coastguard Worker {
3696*8975f5c5SAndroid Build Coastguard Worker out_color = color;
3697*8975f5c5SAndroid Build Coastguard Worker })";
3698*8975f5c5SAndroid Build Coastguard Worker
3699*8975f5c5SAndroid Build Coastguard Worker std::array<GLubyte, kVertexCount> inputData = {
3700*8975f5c5SAndroid Build Coastguard Worker {0, 1, 2, 3, 4, 5, 6, 7, 125, 126, 127, 128, 129, 250, 251, 252, 253, 254, 255}};
3701*8975f5c5SAndroid Build Coastguard Worker std::array<GLubyte, kVertexCount> inputData2;
3702*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData;
3703*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, kVertexCount> expectedData2;
3704*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < kVertexCount; i++)
3705*8975f5c5SAndroid Build Coastguard Worker {
3706*8975f5c5SAndroid Build Coastguard Worker expectedData[i] = inputData[i];
3707*8975f5c5SAndroid Build Coastguard Worker inputData2[i] = inputData[i] > 128 ? inputData[i] - 1 : inputData[i] + 1;
3708*8975f5c5SAndroid Build Coastguard Worker expectedData2[i] = inputData2[i];
3709*8975f5c5SAndroid Build Coastguard Worker }
3710*8975f5c5SAndroid Build Coastguard Worker
3711*8975f5c5SAndroid Build Coastguard Worker // Setup the program
3712*8975f5c5SAndroid Build Coastguard Worker mProgram = CompileProgram(testVertexShaderSource, testFragmentShaderSource);
3713*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(0u, mProgram);
3714*8975f5c5SAndroid Build Coastguard Worker
3715*8975f5c5SAndroid Build Coastguard Worker mTestAttrib = glGetAttribLocation(mProgram, "test");
3716*8975f5c5SAndroid Build Coastguard Worker ASSERT_EQ(1, mTestAttrib);
3717*8975f5c5SAndroid Build Coastguard Worker mExpectedAttrib = glGetAttribLocation(mProgram, "expected");
3718*8975f5c5SAndroid Build Coastguard Worker ASSERT_EQ(5, mExpectedAttrib);
3719*8975f5c5SAndroid Build Coastguard Worker
3720*8975f5c5SAndroid Build Coastguard Worker GLint unused1Attrib = 2;
3721*8975f5c5SAndroid Build Coastguard Worker GLint unused2Attrib = 3;
3722*8975f5c5SAndroid Build Coastguard Worker GLint unused3Attrib = 4;
3723*8975f5c5SAndroid Build Coastguard Worker
3724*8975f5c5SAndroid Build Coastguard Worker // Test enabling an unused attribute before glUseProgram
3725*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(unused3Attrib);
3726*8975f5c5SAndroid Build Coastguard Worker
3727*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
3728*8975f5c5SAndroid Build Coastguard Worker
3729*8975f5c5SAndroid Build Coastguard Worker // Setup the test data
3730*8975f5c5SAndroid Build Coastguard Worker TestData data(GL_UNSIGNED_BYTE, GL_FALSE, Source::IMMEDIATE, inputData.data(),
3731*8975f5c5SAndroid Build Coastguard Worker expectedData.data());
3732*8975f5c5SAndroid Build Coastguard Worker setupTest(data, 1);
3733*8975f5c5SAndroid Build Coastguard Worker
3734*8975f5c5SAndroid Build Coastguard Worker // Test enabling an unused attribute after glUseProgram
3735*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(unused1Attrib, 1, data.type, data.normalized, 0, inputData2.data());
3736*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(unused1Attrib);
3737*8975f5c5SAndroid Build Coastguard Worker
3738*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(unused2Attrib, 1, GL_FLOAT, GL_FALSE, 0, expectedData2.data());
3739*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(unused2Attrib);
3740*8975f5c5SAndroid Build Coastguard Worker
3741*8975f5c5SAndroid Build Coastguard Worker // Run the test. This shouldn't use the unused attributes. Note that one of them is nullptr
3742*8975f5c5SAndroid Build Coastguard Worker // which can cause a crash on certain platform-driver combination.
3743*8975f5c5SAndroid Build Coastguard Worker drawQuad(mProgram, "position", 0.5f);
3744*8975f5c5SAndroid Build Coastguard Worker checkPixels();
3745*8975f5c5SAndroid Build Coastguard Worker
3746*8975f5c5SAndroid Build Coastguard Worker // Now test with the same attributes enabled, but with a program with different attributes
3747*8975f5c5SAndroid Build Coastguard Worker // active
3748*8975f5c5SAndroid Build Coastguard Worker mProgram = CompileProgram(testVertexShader2Source, testFragmentShaderSource);
3749*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(0u, mProgram);
3750*8975f5c5SAndroid Build Coastguard Worker
3751*8975f5c5SAndroid Build Coastguard Worker // Make sure all the attributes are in the same location
3752*8975f5c5SAndroid Build Coastguard Worker ASSERT_EQ(glGetAttribLocation(mProgram, "unused1"), unused1Attrib);
3753*8975f5c5SAndroid Build Coastguard Worker ASSERT_EQ(glGetAttribLocation(mProgram, "unused2"), unused2Attrib);
3754*8975f5c5SAndroid Build Coastguard Worker
3755*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
3756*8975f5c5SAndroid Build Coastguard Worker
3757*8975f5c5SAndroid Build Coastguard Worker // Run the test again. unused1/2 were disabled in the previous run (as they were inactive in
3758*8975f5c5SAndroid Build Coastguard Worker // the shader), but should be re-enabled now.
3759*8975f5c5SAndroid Build Coastguard Worker drawQuad(mProgram, "position", 0.5f);
3760*8975f5c5SAndroid Build Coastguard Worker checkPixels();
3761*8975f5c5SAndroid Build Coastguard Worker }
3762*8975f5c5SAndroid Build Coastguard Worker
3763*8975f5c5SAndroid Build Coastguard Worker // Test that default integer attribute works correctly even if there is a gap in
3764*8975f5c5SAndroid Build Coastguard Worker // attribute locations.
TEST_P(VertexAttributeTestES3,DefaultIntAttribWithGap)3765*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, DefaultIntAttribWithGap)
3766*8975f5c5SAndroid Build Coastguard Worker {
3767*8975f5c5SAndroid Build Coastguard Worker constexpr char kVertexShader[] = R"(#version 300 es
3768*8975f5c5SAndroid Build Coastguard Worker layout(location = 0) in vec2 position;
3769*8975f5c5SAndroid Build Coastguard Worker layout(location = 3) in int actualValue;
3770*8975f5c5SAndroid Build Coastguard Worker uniform int expectedValue;
3771*8975f5c5SAndroid Build Coastguard Worker out float result;
3772*8975f5c5SAndroid Build Coastguard Worker void main()
3773*8975f5c5SAndroid Build Coastguard Worker {
3774*8975f5c5SAndroid Build Coastguard Worker result = (actualValue == expectedValue) ? 1.0 : 0.0;
3775*8975f5c5SAndroid Build Coastguard Worker gl_Position = vec4(position, 0, 1);
3776*8975f5c5SAndroid Build Coastguard Worker })";
3777*8975f5c5SAndroid Build Coastguard Worker
3778*8975f5c5SAndroid Build Coastguard Worker constexpr char kFragmentShader[] = R"(#version 300 es
3779*8975f5c5SAndroid Build Coastguard Worker in mediump float result;
3780*8975f5c5SAndroid Build Coastguard Worker layout(location = 0) out lowp vec4 out_color;
3781*8975f5c5SAndroid Build Coastguard Worker void main()
3782*8975f5c5SAndroid Build Coastguard Worker {
3783*8975f5c5SAndroid Build Coastguard Worker out_color = result > 0.0 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3784*8975f5c5SAndroid Build Coastguard Worker })";
3785*8975f5c5SAndroid Build Coastguard Worker
3786*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
3787*8975f5c5SAndroid Build Coastguard Worker
3788*8975f5c5SAndroid Build Coastguard Worker // Re-link the program to update the attribute locations
3789*8975f5c5SAndroid Build Coastguard Worker glLinkProgram(program);
3790*8975f5c5SAndroid Build Coastguard Worker ASSERT_TRUE(CheckLinkStatusAndReturnProgram(program, true));
3791*8975f5c5SAndroid Build Coastguard Worker
3792*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
3793*8975f5c5SAndroid Build Coastguard Worker
3794*8975f5c5SAndroid Build Coastguard Worker GLint uniLoc = glGetUniformLocation(program, "expectedValue");
3795*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, uniLoc);
3796*8975f5c5SAndroid Build Coastguard Worker
3797*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
3798*8975f5c5SAndroid Build Coastguard Worker
3799*8975f5c5SAndroid Build Coastguard Worker setupQuadVertexBuffer(0.5f, 1.0f);
3800*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
3801*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(0);
3802*8975f5c5SAndroid Build Coastguard Worker
3803*8975f5c5SAndroid Build Coastguard Worker std::array<GLint, 4> testValues = {{1, 2, 3, 4}};
3804*8975f5c5SAndroid Build Coastguard Worker for (GLfloat testValue : testValues)
3805*8975f5c5SAndroid Build Coastguard Worker {
3806*8975f5c5SAndroid Build Coastguard Worker glUniform1i(uniLoc, testValue);
3807*8975f5c5SAndroid Build Coastguard Worker glVertexAttribI4i(3, testValue, 0, 0, 0);
3808*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
3809*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
3810*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3811*8975f5c5SAndroid Build Coastguard Worker }
3812*8975f5c5SAndroid Build Coastguard Worker }
3813*8975f5c5SAndroid Build Coastguard Worker
3814*8975f5c5SAndroid Build Coastguard Worker // Test that when three vertex attribute indices are enabled, but only two attributes among them
3815*8975f5c5SAndroid Build Coastguard Worker // include data via glVertexAttribPointer(), there is no crash.
TEST_P(VertexAttributeTest,VertexAttribPointerCopyBufferFromInvalidAddress)3816*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, VertexAttribPointerCopyBufferFromInvalidAddress)
3817*8975f5c5SAndroid Build Coastguard Worker {
3818*8975f5c5SAndroid Build Coastguard Worker const GLfloat vertices[] = {
3819*8975f5c5SAndroid Build Coastguard Worker // position // color // texCoord
3820*8975f5c5SAndroid Build Coastguard Worker -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // Lower left corner
3821*8975f5c5SAndroid Build Coastguard Worker 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, // Bottom right corner
3822*8975f5c5SAndroid Build Coastguard Worker 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f, 1.0f // Top
3823*8975f5c5SAndroid Build Coastguard Worker };
3824*8975f5c5SAndroid Build Coastguard Worker
3825*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] = R"(
3826*8975f5c5SAndroid Build Coastguard Worker attribute highp vec2 position;
3827*8975f5c5SAndroid Build Coastguard Worker attribute mediump vec4 color;
3828*8975f5c5SAndroid Build Coastguard Worker attribute highp vec2 texCoord;
3829*8975f5c5SAndroid Build Coastguard Worker varying mediump vec4 fragColor;
3830*8975f5c5SAndroid Build Coastguard Worker varying highp vec2 fragTexCoord;
3831*8975f5c5SAndroid Build Coastguard Worker void main() {
3832*8975f5c5SAndroid Build Coastguard Worker gl_Position = vec4(position, 0.0, 1.0);
3833*8975f5c5SAndroid Build Coastguard Worker fragColor = color;
3834*8975f5c5SAndroid Build Coastguard Worker fragTexCoord = texCoord;
3835*8975f5c5SAndroid Build Coastguard Worker }
3836*8975f5c5SAndroid Build Coastguard Worker )";
3837*8975f5c5SAndroid Build Coastguard Worker
3838*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] = R"(
3839*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
3840*8975f5c5SAndroid Build Coastguard Worker varying mediump vec4 fragColor;
3841*8975f5c5SAndroid Build Coastguard Worker varying highp vec2 fragTexCoord;
3842*8975f5c5SAndroid Build Coastguard Worker void main() {
3843*8975f5c5SAndroid Build Coastguard Worker if (fragTexCoord.x > 0.5) {
3844*8975f5c5SAndroid Build Coastguard Worker gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
3845*8975f5c5SAndroid Build Coastguard Worker } else {
3846*8975f5c5SAndroid Build Coastguard Worker gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
3847*8975f5c5SAndroid Build Coastguard Worker }
3848*8975f5c5SAndroid Build Coastguard Worker }
3849*8975f5c5SAndroid Build Coastguard Worker )";
3850*8975f5c5SAndroid Build Coastguard Worker
3851*8975f5c5SAndroid Build Coastguard Worker mProgram = CompileProgram(kVS, kFS);
3852*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(0u, mProgram);
3853*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(mProgram, 0, "position");
3854*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(mProgram, 1, "color");
3855*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(mProgram, 2, "texCoord");
3856*8975f5c5SAndroid Build Coastguard Worker glUseProgram(mProgram);
3857*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
3858*8975f5c5SAndroid Build Coastguard Worker
3859*8975f5c5SAndroid Build Coastguard Worker glGenBuffers(1, &mBuffer);
3860*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
3861*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
3862*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
3863*8975f5c5SAndroid Build Coastguard Worker
3864*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(0);
3865*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(1);
3866*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(2);
3867*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
3868*8975f5c5SAndroid Build Coastguard Worker
3869*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid *)0);
3870*8975f5c5SAndroid Build Coastguard Worker // Missing VertexAttribPointer at index 1
3871*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat),
3872*8975f5c5SAndroid Build Coastguard Worker (GLvoid *)(6 * sizeof(GLfloat)));
3873*8975f5c5SAndroid Build Coastguard Worker
3874*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 3);
3875*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
3876*8975f5c5SAndroid Build Coastguard Worker
3877*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(0);
3878*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(1);
3879*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(2);
3880*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
3881*8975f5c5SAndroid Build Coastguard Worker }
3882*8975f5c5SAndroid Build Coastguard Worker
3883*8975f5c5SAndroid Build Coastguard Worker // Test that default unsigned integer attribute works correctly even if there is a gap in
3884*8975f5c5SAndroid Build Coastguard Worker // attribute locations.
TEST_P(VertexAttributeTestES3,DefaultUIntAttribWithGap)3885*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, DefaultUIntAttribWithGap)
3886*8975f5c5SAndroid Build Coastguard Worker {
3887*8975f5c5SAndroid Build Coastguard Worker constexpr char kVertexShader[] = R"(#version 300 es
3888*8975f5c5SAndroid Build Coastguard Worker layout(location = 0) in vec2 position;
3889*8975f5c5SAndroid Build Coastguard Worker layout(location = 3) in uint actualValue;
3890*8975f5c5SAndroid Build Coastguard Worker uniform uint expectedValue;
3891*8975f5c5SAndroid Build Coastguard Worker out float result;
3892*8975f5c5SAndroid Build Coastguard Worker void main()
3893*8975f5c5SAndroid Build Coastguard Worker {
3894*8975f5c5SAndroid Build Coastguard Worker result = (actualValue == expectedValue) ? 1.0 : 0.0;
3895*8975f5c5SAndroid Build Coastguard Worker gl_Position = vec4(position, 0, 1);
3896*8975f5c5SAndroid Build Coastguard Worker })";
3897*8975f5c5SAndroid Build Coastguard Worker
3898*8975f5c5SAndroid Build Coastguard Worker constexpr char kFragmentShader[] = R"(#version 300 es
3899*8975f5c5SAndroid Build Coastguard Worker in mediump float result;
3900*8975f5c5SAndroid Build Coastguard Worker layout(location = 0) out lowp vec4 out_color;
3901*8975f5c5SAndroid Build Coastguard Worker void main()
3902*8975f5c5SAndroid Build Coastguard Worker {
3903*8975f5c5SAndroid Build Coastguard Worker out_color = result > 0.0 ? vec4(0, 1, 0, 1) : vec4(1, 0, 0, 1);
3904*8975f5c5SAndroid Build Coastguard Worker })";
3905*8975f5c5SAndroid Build Coastguard Worker
3906*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(program, kVertexShader, kFragmentShader);
3907*8975f5c5SAndroid Build Coastguard Worker
3908*8975f5c5SAndroid Build Coastguard Worker // Re-link the program to update the attribute locations
3909*8975f5c5SAndroid Build Coastguard Worker glLinkProgram(program);
3910*8975f5c5SAndroid Build Coastguard Worker ASSERT_TRUE(CheckLinkStatusAndReturnProgram(program, true));
3911*8975f5c5SAndroid Build Coastguard Worker
3912*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
3913*8975f5c5SAndroid Build Coastguard Worker
3914*8975f5c5SAndroid Build Coastguard Worker GLint uniLoc = glGetUniformLocation(program, "expectedValue");
3915*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, uniLoc);
3916*8975f5c5SAndroid Build Coastguard Worker
3917*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
3918*8975f5c5SAndroid Build Coastguard Worker
3919*8975f5c5SAndroid Build Coastguard Worker setupQuadVertexBuffer(0.5f, 1.0f);
3920*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
3921*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(0);
3922*8975f5c5SAndroid Build Coastguard Worker
3923*8975f5c5SAndroid Build Coastguard Worker std::array<GLuint, 4> testValues = {{1, 2, 3, 4}};
3924*8975f5c5SAndroid Build Coastguard Worker for (GLfloat testValue : testValues)
3925*8975f5c5SAndroid Build Coastguard Worker {
3926*8975f5c5SAndroid Build Coastguard Worker glUniform1ui(uniLoc, testValue);
3927*8975f5c5SAndroid Build Coastguard Worker glVertexAttribI4ui(3, testValue, 0, 0, 0);
3928*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
3929*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
3930*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
3931*8975f5c5SAndroid Build Coastguard Worker }
3932*8975f5c5SAndroid Build Coastguard Worker }
3933*8975f5c5SAndroid Build Coastguard Worker
3934*8975f5c5SAndroid Build Coastguard Worker // Tests that large strides that read past the end of the buffer work correctly.
3935*8975f5c5SAndroid Build Coastguard Worker // Requires ES 3.1 to query MAX_VERTEX_ATTRIB_STRIDE.
TEST_P(VertexAttributeTestES31,LargeStride)3936*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES31, LargeStride)
3937*8975f5c5SAndroid Build Coastguard Worker {
3938*8975f5c5SAndroid Build Coastguard Worker struct Vertex
3939*8975f5c5SAndroid Build Coastguard Worker {
3940*8975f5c5SAndroid Build Coastguard Worker Vector4 position;
3941*8975f5c5SAndroid Build Coastguard Worker Vector2 color;
3942*8975f5c5SAndroid Build Coastguard Worker };
3943*8975f5c5SAndroid Build Coastguard Worker
3944*8975f5c5SAndroid Build Coastguard Worker constexpr uint32_t kColorOffset = offsetof(Vertex, color);
3945*8975f5c5SAndroid Build Coastguard Worker
3946*8975f5c5SAndroid Build Coastguard Worker // Get MAX_VERTEX_ATTRIB_STRIDE.
3947*8975f5c5SAndroid Build Coastguard Worker GLint maxStride;
3948*8975f5c5SAndroid Build Coastguard Worker glGetIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, &maxStride);
3949*8975f5c5SAndroid Build Coastguard Worker
3950*8975f5c5SAndroid Build Coastguard Worker uint32_t bufferSize = static_cast<uint32_t>(maxStride);
3951*8975f5c5SAndroid Build Coastguard Worker uint32_t stride = sizeof(Vertex);
3952*8975f5c5SAndroid Build Coastguard Worker uint32_t numVertices = bufferSize / stride;
3953*8975f5c5SAndroid Build Coastguard Worker
3954*8975f5c5SAndroid Build Coastguard Worker // The last vertex fits in the buffer size. The last vertex stride extends past it.
3955*8975f5c5SAndroid Build Coastguard Worker ASSERT_LT(numVertices * stride, bufferSize);
3956*8975f5c5SAndroid Build Coastguard Worker ASSERT_GT(numVertices * stride + kColorOffset, bufferSize);
3957*8975f5c5SAndroid Build Coastguard Worker
3958*8975f5c5SAndroid Build Coastguard Worker RNG rng(0);
3959*8975f5c5SAndroid Build Coastguard Worker
3960*8975f5c5SAndroid Build Coastguard Worker std::vector<Vertex> vertexData(bufferSize, {Vector4(), Vector2()});
3961*8975f5c5SAndroid Build Coastguard Worker std::vector<GLColor> expectedColors;
3962*8975f5c5SAndroid Build Coastguard Worker for (uint32_t vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex)
3963*8975f5c5SAndroid Build Coastguard Worker {
3964*8975f5c5SAndroid Build Coastguard Worker int x = vertexIndex % getWindowWidth();
3965*8975f5c5SAndroid Build Coastguard Worker int y = vertexIndex / getWindowWidth();
3966*8975f5c5SAndroid Build Coastguard Worker
3967*8975f5c5SAndroid Build Coastguard Worker // Generate and clamp a 2 component vector.
3968*8975f5c5SAndroid Build Coastguard Worker Vector4 randomVec4 = RandomVec4(rng.randomInt(), 0.0f, 1.0f);
3969*8975f5c5SAndroid Build Coastguard Worker GLColor randomColor(randomVec4);
3970*8975f5c5SAndroid Build Coastguard Worker randomColor[2] = 0;
3971*8975f5c5SAndroid Build Coastguard Worker randomColor[3] = 255;
3972*8975f5c5SAndroid Build Coastguard Worker Vector4 clampedVec = randomColor.toNormalizedVector();
3973*8975f5c5SAndroid Build Coastguard Worker
3974*8975f5c5SAndroid Build Coastguard Worker vertexData[vertexIndex] = {Vector4(x, y, 0.0f, 1.0f),
3975*8975f5c5SAndroid Build Coastguard Worker Vector2(clampedVec[0], clampedVec[1])};
3976*8975f5c5SAndroid Build Coastguard Worker expectedColors.push_back(randomColor);
3977*8975f5c5SAndroid Build Coastguard Worker }
3978*8975f5c5SAndroid Build Coastguard Worker
3979*8975f5c5SAndroid Build Coastguard Worker GLBuffer buffer;
3980*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, buffer);
3981*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, bufferSize, vertexData.data(), GL_STATIC_DRAW);
3982*8975f5c5SAndroid Build Coastguard Worker
3983*8975f5c5SAndroid Build Coastguard Worker vertexData.resize(numVertices);
3984*8975f5c5SAndroid Build Coastguard Worker
3985*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] = R"(#version 310 es
3986*8975f5c5SAndroid Build Coastguard Worker in vec4 pos;
3987*8975f5c5SAndroid Build Coastguard Worker in vec2 color;
3988*8975f5c5SAndroid Build Coastguard Worker out vec2 vcolor;
3989*8975f5c5SAndroid Build Coastguard Worker void main()
3990*8975f5c5SAndroid Build Coastguard Worker {
3991*8975f5c5SAndroid Build Coastguard Worker vcolor = color;
3992*8975f5c5SAndroid Build Coastguard Worker gl_Position = vec4(((pos.x + 0.5) / 64.0) - 1.0, ((pos.y + 0.5) / 64.0) - 1.0, 0, 1);
3993*8975f5c5SAndroid Build Coastguard Worker gl_PointSize = 1.0;
3994*8975f5c5SAndroid Build Coastguard Worker })";
3995*8975f5c5SAndroid Build Coastguard Worker
3996*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] = R"(#version 310 es
3997*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
3998*8975f5c5SAndroid Build Coastguard Worker in vec2 vcolor;
3999*8975f5c5SAndroid Build Coastguard Worker out vec4 fcolor;
4000*8975f5c5SAndroid Build Coastguard Worker void main()
4001*8975f5c5SAndroid Build Coastguard Worker {
4002*8975f5c5SAndroid Build Coastguard Worker fcolor = vec4(vcolor, 0.0, 1.0);
4003*8975f5c5SAndroid Build Coastguard Worker })";
4004*8975f5c5SAndroid Build Coastguard Worker
4005*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(program, kVS, kFS);
4006*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
4007*8975f5c5SAndroid Build Coastguard Worker
4008*8975f5c5SAndroid Build Coastguard Worker GLint posLoc = glGetAttribLocation(program, "pos");
4009*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, posLoc);
4010*8975f5c5SAndroid Build Coastguard Worker GLint colorLoc = glGetAttribLocation(program, "color");
4011*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, colorLoc);
4012*8975f5c5SAndroid Build Coastguard Worker
4013*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, stride, nullptr);
4014*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(posLoc);
4015*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(colorLoc, 2, GL_FLOAT, GL_FALSE, stride,
4016*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<GLvoid *>(static_cast<uintptr_t>(kColorOffset)));
4017*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(colorLoc);
4018*8975f5c5SAndroid Build Coastguard Worker
4019*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_POINTS, 0, numVertices);
4020*8975f5c5SAndroid Build Coastguard Worker
4021*8975f5c5SAndroid Build Coastguard Worker // Validate pixels.
4022*8975f5c5SAndroid Build Coastguard Worker std::vector<GLColor> actualColors(getWindowWidth() * getWindowHeight());
4023*8975f5c5SAndroid Build Coastguard Worker glReadPixels(0, 0, getWindowWidth(), getWindowHeight(), GL_RGBA, GL_UNSIGNED_BYTE,
4024*8975f5c5SAndroid Build Coastguard Worker actualColors.data());
4025*8975f5c5SAndroid Build Coastguard Worker
4026*8975f5c5SAndroid Build Coastguard Worker actualColors.resize(numVertices);
4027*8975f5c5SAndroid Build Coastguard Worker
4028*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
4029*8975f5c5SAndroid Build Coastguard Worker EXPECT_EQ(expectedColors, actualColors);
4030*8975f5c5SAndroid Build Coastguard Worker }
4031*8975f5c5SAndroid Build Coastguard Worker
makeMismatchingSignsTestVS(uint32_t attribCount,uint16_t signedMask)4032*8975f5c5SAndroid Build Coastguard Worker std::string VertexAttributeTestES31::makeMismatchingSignsTestVS(uint32_t attribCount,
4033*8975f5c5SAndroid Build Coastguard Worker uint16_t signedMask)
4034*8975f5c5SAndroid Build Coastguard Worker {
4035*8975f5c5SAndroid Build Coastguard Worker std::ostringstream shader;
4036*8975f5c5SAndroid Build Coastguard Worker
4037*8975f5c5SAndroid Build Coastguard Worker shader << R"(#version 310 es
4038*8975f5c5SAndroid Build Coastguard Worker precision highp float;
4039*8975f5c5SAndroid Build Coastguard Worker
4040*8975f5c5SAndroid Build Coastguard Worker // The signedness is determined by |signedMask|.
4041*8975f5c5SAndroid Build Coastguard Worker )";
4042*8975f5c5SAndroid Build Coastguard Worker
4043*8975f5c5SAndroid Build Coastguard Worker for (uint32_t i = 0; i < attribCount; ++i)
4044*8975f5c5SAndroid Build Coastguard Worker {
4045*8975f5c5SAndroid Build Coastguard Worker shader << "in highp " << ((signedMask >> i & 1) == 0 ? "u" : "i") << "vec4 attrib" << i
4046*8975f5c5SAndroid Build Coastguard Worker << ";\n";
4047*8975f5c5SAndroid Build Coastguard Worker }
4048*8975f5c5SAndroid Build Coastguard Worker
4049*8975f5c5SAndroid Build Coastguard Worker shader << "flat out highp uvec4 v[" << attribCount << "];\n";
4050*8975f5c5SAndroid Build Coastguard Worker
4051*8975f5c5SAndroid Build Coastguard Worker shader << R"(
4052*8975f5c5SAndroid Build Coastguard Worker void main() {
4053*8975f5c5SAndroid Build Coastguard Worker )";
4054*8975f5c5SAndroid Build Coastguard Worker
4055*8975f5c5SAndroid Build Coastguard Worker for (uint32_t i = 0; i < attribCount; ++i)
4056*8975f5c5SAndroid Build Coastguard Worker {
4057*8975f5c5SAndroid Build Coastguard Worker shader << "v[" << i << "] = uvec4(attrib" << i << ");\n";
4058*8975f5c5SAndroid Build Coastguard Worker }
4059*8975f5c5SAndroid Build Coastguard Worker
4060*8975f5c5SAndroid Build Coastguard Worker shader << R"(
4061*8975f5c5SAndroid Build Coastguard Worker // gl_VertexID x y
4062*8975f5c5SAndroid Build Coastguard Worker // 0 -1 -1
4063*8975f5c5SAndroid Build Coastguard Worker // 1 1 -1
4064*8975f5c5SAndroid Build Coastguard Worker // 2 -1 1
4065*8975f5c5SAndroid Build Coastguard Worker // 3 1 1
4066*8975f5c5SAndroid Build Coastguard Worker int bit0 = gl_VertexID & 1;
4067*8975f5c5SAndroid Build Coastguard Worker int bit1 = gl_VertexID >> 1;
4068*8975f5c5SAndroid Build Coastguard Worker gl_Position = vec4(bit0 * 2 - 1, bit1 * 2 - 1, gl_VertexID % 2 == 0 ? -1 : 1, 1);
4069*8975f5c5SAndroid Build Coastguard Worker })";
4070*8975f5c5SAndroid Build Coastguard Worker
4071*8975f5c5SAndroid Build Coastguard Worker return shader.str();
4072*8975f5c5SAndroid Build Coastguard Worker }
4073*8975f5c5SAndroid Build Coastguard Worker
makeMismatchingSignsTestFS(uint32_t attribCount)4074*8975f5c5SAndroid Build Coastguard Worker std::string VertexAttributeTestES31::makeMismatchingSignsTestFS(uint32_t attribCount)
4075*8975f5c5SAndroid Build Coastguard Worker {
4076*8975f5c5SAndroid Build Coastguard Worker std::ostringstream shader;
4077*8975f5c5SAndroid Build Coastguard Worker
4078*8975f5c5SAndroid Build Coastguard Worker shader << R"(#version 310 es
4079*8975f5c5SAndroid Build Coastguard Worker precision highp float;
4080*8975f5c5SAndroid Build Coastguard Worker )";
4081*8975f5c5SAndroid Build Coastguard Worker
4082*8975f5c5SAndroid Build Coastguard Worker shader << "flat in highp uvec4 v[" << attribCount << "];\n";
4083*8975f5c5SAndroid Build Coastguard Worker
4084*8975f5c5SAndroid Build Coastguard Worker shader << R"(out vec4 fragColor;
4085*8975f5c5SAndroid Build Coastguard Worker uniform vec4 colorScale;
4086*8975f5c5SAndroid Build Coastguard Worker
4087*8975f5c5SAndroid Build Coastguard Worker bool isOk(uvec4 inputVarying, uint index)
4088*8975f5c5SAndroid Build Coastguard Worker {
4089*8975f5c5SAndroid Build Coastguard Worker return inputVarying.x == index &&
4090*8975f5c5SAndroid Build Coastguard Worker inputVarying.y == index * 2u &&
4091*8975f5c5SAndroid Build Coastguard Worker inputVarying.z == index + 1u &&
4092*8975f5c5SAndroid Build Coastguard Worker inputVarying.w == index + 0x12345u;
4093*8975f5c5SAndroid Build Coastguard Worker }
4094*8975f5c5SAndroid Build Coastguard Worker
4095*8975f5c5SAndroid Build Coastguard Worker void main()
4096*8975f5c5SAndroid Build Coastguard Worker {
4097*8975f5c5SAndroid Build Coastguard Worker bool result = true;
4098*8975f5c5SAndroid Build Coastguard Worker )";
4099*8975f5c5SAndroid Build Coastguard Worker shader << " for (uint index = 0u; index < " << attribCount << "u; ++index)\n";
4100*8975f5c5SAndroid Build Coastguard Worker shader << R"({
4101*8975f5c5SAndroid Build Coastguard Worker result = result && isOk(v[index], index);
4102*8975f5c5SAndroid Build Coastguard Worker }
4103*8975f5c5SAndroid Build Coastguard Worker
4104*8975f5c5SAndroid Build Coastguard Worker fragColor = vec4(result) * colorScale;
4105*8975f5c5SAndroid Build Coastguard Worker })";
4106*8975f5c5SAndroid Build Coastguard Worker
4107*8975f5c5SAndroid Build Coastguard Worker return shader.str();
4108*8975f5c5SAndroid Build Coastguard Worker }
4109*8975f5c5SAndroid Build Coastguard Worker
setupVertexAttribPointersForMismatchSignsTest(uint16_t currentSignedMask,uint16_t toggleMask)4110*8975f5c5SAndroid Build Coastguard Worker uint16_t VertexAttributeTestES31::setupVertexAttribPointersForMismatchSignsTest(
4111*8975f5c5SAndroid Build Coastguard Worker uint16_t currentSignedMask,
4112*8975f5c5SAndroid Build Coastguard Worker uint16_t toggleMask)
4113*8975f5c5SAndroid Build Coastguard Worker {
4114*8975f5c5SAndroid Build Coastguard Worker uint16_t newSignedMask = currentSignedMask ^ toggleMask;
4115*8975f5c5SAndroid Build Coastguard Worker
4116*8975f5c5SAndroid Build Coastguard Worker for (uint32_t i = 0; i < 16; ++i)
4117*8975f5c5SAndroid Build Coastguard Worker {
4118*8975f5c5SAndroid Build Coastguard Worker if ((toggleMask >> i & 1) == 0)
4119*8975f5c5SAndroid Build Coastguard Worker {
4120*8975f5c5SAndroid Build Coastguard Worker continue;
4121*8975f5c5SAndroid Build Coastguard Worker }
4122*8975f5c5SAndroid Build Coastguard Worker
4123*8975f5c5SAndroid Build Coastguard Worker const GLenum type = (newSignedMask >> i & 1) == 0 ? GL_UNSIGNED_INT : GL_INT;
4124*8975f5c5SAndroid Build Coastguard Worker glVertexAttribIPointer(i, 4, type, sizeof(GLuint[4]),
4125*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<const void *>(sizeof(GLuint[4][4]) * i));
4126*8975f5c5SAndroid Build Coastguard Worker }
4127*8975f5c5SAndroid Build Coastguard Worker
4128*8975f5c5SAndroid Build Coastguard Worker return newSignedMask;
4129*8975f5c5SAndroid Build Coastguard Worker }
4130*8975f5c5SAndroid Build Coastguard Worker
4131*8975f5c5SAndroid Build Coastguard Worker // Test changing between matching and mismatching signedness of vertex attributes, when the
4132*8975f5c5SAndroid Build Coastguard Worker // attribute changes type.
TEST_P(VertexAttributeTestES31,MismatchingSignsChangingAttributeType)4133*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES31, MismatchingSignsChangingAttributeType)
4134*8975f5c5SAndroid Build Coastguard Worker {
4135*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_relaxed_vertex_attribute_type"));
4136*8975f5c5SAndroid Build Coastguard Worker
4137*8975f5c5SAndroid Build Coastguard Worker // GL supports a minimum of 16 vertex attributes, and gl_VertexID is counted as one.
4138*8975f5c5SAndroid Build Coastguard Worker // The signedness pattern used here is:
4139*8975f5c5SAndroid Build Coastguard Worker //
4140*8975f5c5SAndroid Build Coastguard Worker // 0 14
4141*8975f5c5SAndroid Build Coastguard Worker // iiui uuii iuui uui
4142*8975f5c5SAndroid Build Coastguard Worker //
4143*8975f5c5SAndroid Build Coastguard Worker // Which is chosen such that there's no clear repeating / mirror pattern.
4144*8975f5c5SAndroid Build Coastguard Worker const std::string vs = makeMismatchingSignsTestVS(15, 0x49CB);
4145*8975f5c5SAndroid Build Coastguard Worker const std::string fs = makeMismatchingSignsTestFS(15);
4146*8975f5c5SAndroid Build Coastguard Worker
4147*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(program, vs.c_str(), fs.c_str());
4148*8975f5c5SAndroid Build Coastguard Worker for (uint32_t i = 0; i < 15; ++i)
4149*8975f5c5SAndroid Build Coastguard Worker {
4150*8975f5c5SAndroid Build Coastguard Worker char attribName[20];
4151*8975f5c5SAndroid Build Coastguard Worker snprintf(attribName, sizeof(attribName), "attrib%u\n", i);
4152*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, i, attribName);
4153*8975f5c5SAndroid Build Coastguard Worker }
4154*8975f5c5SAndroid Build Coastguard Worker glLinkProgram(program);
4155*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
4156*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
4157*8975f5c5SAndroid Build Coastguard Worker
4158*8975f5c5SAndroid Build Coastguard Worker GLint colorScaleLoc = glGetUniformLocation(program, "colorScale");
4159*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, colorScaleLoc);
4160*8975f5c5SAndroid Build Coastguard Worker
4161*8975f5c5SAndroid Build Coastguard Worker GLuint data[15][4][4];
4162*8975f5c5SAndroid Build Coastguard Worker for (GLuint i = 0; i < 15; ++i)
4163*8975f5c5SAndroid Build Coastguard Worker {
4164*8975f5c5SAndroid Build Coastguard Worker for (GLuint j = 0; j < 4; ++j)
4165*8975f5c5SAndroid Build Coastguard Worker {
4166*8975f5c5SAndroid Build Coastguard Worker // Match the expectation in the shader
4167*8975f5c5SAndroid Build Coastguard Worker data[i][j][0] = i;
4168*8975f5c5SAndroid Build Coastguard Worker data[i][j][1] = i * 2;
4169*8975f5c5SAndroid Build Coastguard Worker data[i][j][2] = i + 1;
4170*8975f5c5SAndroid Build Coastguard Worker data[i][j][3] = i + 0x12345;
4171*8975f5c5SAndroid Build Coastguard Worker }
4172*8975f5c5SAndroid Build Coastguard Worker }
4173*8975f5c5SAndroid Build Coastguard Worker
4174*8975f5c5SAndroid Build Coastguard Worker GLBuffer buffer;
4175*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, buffer);
4176*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
4177*8975f5c5SAndroid Build Coastguard Worker
4178*8975f5c5SAndroid Build Coastguard Worker // Randomly match and mismatch the component type
4179*8975f5c5SAndroid Build Coastguard Worker uint16_t signedMask = setupVertexAttribPointersForMismatchSignsTest(0x0FA5, 0x7FFF);
4180*8975f5c5SAndroid Build Coastguard Worker
4181*8975f5c5SAndroid Build Coastguard Worker for (uint32_t i = 0; i < 15; ++i)
4182*8975f5c5SAndroid Build Coastguard Worker {
4183*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(i);
4184*8975f5c5SAndroid Build Coastguard Worker }
4185*8975f5c5SAndroid Build Coastguard Worker
4186*8975f5c5SAndroid Build Coastguard Worker glClearColor(0, 0, 0, 0);
4187*8975f5c5SAndroid Build Coastguard Worker glClear(GL_COLOR_BUFFER_BIT);
4188*8975f5c5SAndroid Build Coastguard Worker
4189*8975f5c5SAndroid Build Coastguard Worker glEnable(GL_BLEND);
4190*8975f5c5SAndroid Build Coastguard Worker glBlendFunc(GL_ONE, GL_ONE);
4191*8975f5c5SAndroid Build Coastguard Worker
4192*8975f5c5SAndroid Build Coastguard Worker glUniform4f(colorScaleLoc, 1, 0, 0, 0);
4193*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4194*8975f5c5SAndroid Build Coastguard Worker
4195*8975f5c5SAndroid Build Coastguard Worker // Modify the attributes randomly and make sure tests still pass
4196*8975f5c5SAndroid Build Coastguard Worker
4197*8975f5c5SAndroid Build Coastguard Worker signedMask = setupVertexAttribPointersForMismatchSignsTest(signedMask, 0x3572);
4198*8975f5c5SAndroid Build Coastguard Worker glUniform4f(colorScaleLoc, 0, 1, 0, 0);
4199*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4200*8975f5c5SAndroid Build Coastguard Worker
4201*8975f5c5SAndroid Build Coastguard Worker signedMask = setupVertexAttribPointersForMismatchSignsTest(signedMask, 0x4B1C);
4202*8975f5c5SAndroid Build Coastguard Worker glUniform4f(colorScaleLoc, 0, 0, 1, 0);
4203*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4204*8975f5c5SAndroid Build Coastguard Worker
4205*8975f5c5SAndroid Build Coastguard Worker signedMask = setupVertexAttribPointersForMismatchSignsTest(signedMask, 0x19D6);
4206*8975f5c5SAndroid Build Coastguard Worker glUniform4f(colorScaleLoc, 0, 0, 0, 1);
4207*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4208*8975f5c5SAndroid Build Coastguard Worker
4209*8975f5c5SAndroid Build Coastguard Worker // All channels must be 1
4210*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::white);
4211*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
4212*8975f5c5SAndroid Build Coastguard Worker }
4213*8975f5c5SAndroid Build Coastguard Worker
4214*8975f5c5SAndroid Build Coastguard Worker // Test changing between matching and mismatching signedness of vertex attributes, when the
4215*8975f5c5SAndroid Build Coastguard Worker // program itself changes the type.
TEST_P(VertexAttributeTestES31,MismatchingSignsChangingProgramType)4216*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES31, MismatchingSignsChangingProgramType)
4217*8975f5c5SAndroid Build Coastguard Worker {
4218*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_relaxed_vertex_attribute_type"));
4219*8975f5c5SAndroid Build Coastguard Worker
4220*8975f5c5SAndroid Build Coastguard Worker // GL supports a minimum of 16 vertex attributes, and gl_VertexID is counted as one.
4221*8975f5c5SAndroid Build Coastguard Worker constexpr uint32_t kAttribCount[4] = {12, 9, 15, 7};
4222*8975f5c5SAndroid Build Coastguard Worker constexpr uint32_t kAttribSignedMask[4] = {0x94f, 0x6A, 0x765B, 0x29};
4223*8975f5c5SAndroid Build Coastguard Worker
4224*8975f5c5SAndroid Build Coastguard Worker GLProgram programs[4];
4225*8975f5c5SAndroid Build Coastguard Worker
4226*8975f5c5SAndroid Build Coastguard Worker for (uint32_t progIndex = 0; progIndex < 4; ++progIndex)
4227*8975f5c5SAndroid Build Coastguard Worker {
4228*8975f5c5SAndroid Build Coastguard Worker const std::string vs =
4229*8975f5c5SAndroid Build Coastguard Worker makeMismatchingSignsTestVS(kAttribCount[progIndex], kAttribSignedMask[progIndex]);
4230*8975f5c5SAndroid Build Coastguard Worker const std::string fs = makeMismatchingSignsTestFS(kAttribCount[progIndex]);
4231*8975f5c5SAndroid Build Coastguard Worker
4232*8975f5c5SAndroid Build Coastguard Worker programs[progIndex].makeRaster(vs.c_str(), fs.c_str());
4233*8975f5c5SAndroid Build Coastguard Worker for (uint32_t i = 0; i < kAttribCount[progIndex]; ++i)
4234*8975f5c5SAndroid Build Coastguard Worker {
4235*8975f5c5SAndroid Build Coastguard Worker char attribName[20];
4236*8975f5c5SAndroid Build Coastguard Worker snprintf(attribName, sizeof(attribName), "attrib%u\n", i);
4237*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(programs[progIndex], i, attribName);
4238*8975f5c5SAndroid Build Coastguard Worker }
4239*8975f5c5SAndroid Build Coastguard Worker glLinkProgram(programs[progIndex]);
4240*8975f5c5SAndroid Build Coastguard Worker glUseProgram(programs[progIndex]);
4241*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
4242*8975f5c5SAndroid Build Coastguard Worker }
4243*8975f5c5SAndroid Build Coastguard Worker
4244*8975f5c5SAndroid Build Coastguard Worker GLuint data[15][4][4];
4245*8975f5c5SAndroid Build Coastguard Worker for (GLuint i = 0; i < 15; ++i)
4246*8975f5c5SAndroid Build Coastguard Worker {
4247*8975f5c5SAndroid Build Coastguard Worker for (GLuint j = 0; j < 4; ++j)
4248*8975f5c5SAndroid Build Coastguard Worker {
4249*8975f5c5SAndroid Build Coastguard Worker // Match the expectation in the shader
4250*8975f5c5SAndroid Build Coastguard Worker data[i][j][0] = i;
4251*8975f5c5SAndroid Build Coastguard Worker data[i][j][1] = i * 2;
4252*8975f5c5SAndroid Build Coastguard Worker data[i][j][2] = i + 1;
4253*8975f5c5SAndroid Build Coastguard Worker data[i][j][3] = i + 0x12345;
4254*8975f5c5SAndroid Build Coastguard Worker }
4255*8975f5c5SAndroid Build Coastguard Worker }
4256*8975f5c5SAndroid Build Coastguard Worker
4257*8975f5c5SAndroid Build Coastguard Worker GLBuffer buffer;
4258*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, buffer);
4259*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
4260*8975f5c5SAndroid Build Coastguard Worker
4261*8975f5c5SAndroid Build Coastguard Worker // Randomly match and mismatch the component type
4262*8975f5c5SAndroid Build Coastguard Worker setupVertexAttribPointersForMismatchSignsTest(0x55F8, 0x7FFF);
4263*8975f5c5SAndroid Build Coastguard Worker
4264*8975f5c5SAndroid Build Coastguard Worker for (uint32_t i = 0; i < 15; ++i)
4265*8975f5c5SAndroid Build Coastguard Worker {
4266*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(i);
4267*8975f5c5SAndroid Build Coastguard Worker }
4268*8975f5c5SAndroid Build Coastguard Worker
4269*8975f5c5SAndroid Build Coastguard Worker glClearColor(0, 0, 0, 0);
4270*8975f5c5SAndroid Build Coastguard Worker glClear(GL_COLOR_BUFFER_BIT);
4271*8975f5c5SAndroid Build Coastguard Worker
4272*8975f5c5SAndroid Build Coastguard Worker glEnable(GL_BLEND);
4273*8975f5c5SAndroid Build Coastguard Worker glBlendFunc(GL_ONE, GL_ONE);
4274*8975f5c5SAndroid Build Coastguard Worker
4275*8975f5c5SAndroid Build Coastguard Worker glUseProgram(programs[0]);
4276*8975f5c5SAndroid Build Coastguard Worker GLint colorScaleLoc = glGetUniformLocation(programs[0], "colorScale");
4277*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, colorScaleLoc);
4278*8975f5c5SAndroid Build Coastguard Worker glUniform4f(colorScaleLoc, 1, 0, 0, 0);
4279*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4280*8975f5c5SAndroid Build Coastguard Worker
4281*8975f5c5SAndroid Build Coastguard Worker // Change the program, which have randomly different attribute component types and make sure
4282*8975f5c5SAndroid Build Coastguard Worker // tests still pass
4283*8975f5c5SAndroid Build Coastguard Worker
4284*8975f5c5SAndroid Build Coastguard Worker glUseProgram(programs[1]);
4285*8975f5c5SAndroid Build Coastguard Worker colorScaleLoc = glGetUniformLocation(programs[1], "colorScale");
4286*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, colorScaleLoc);
4287*8975f5c5SAndroid Build Coastguard Worker glUniform4f(colorScaleLoc, 0, 1, 0, 0);
4288*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4289*8975f5c5SAndroid Build Coastguard Worker
4290*8975f5c5SAndroid Build Coastguard Worker glUseProgram(programs[2]);
4291*8975f5c5SAndroid Build Coastguard Worker colorScaleLoc = glGetUniformLocation(programs[2], "colorScale");
4292*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, colorScaleLoc);
4293*8975f5c5SAndroid Build Coastguard Worker glUniform4f(colorScaleLoc, 0, 0, 1, 0);
4294*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4295*8975f5c5SAndroid Build Coastguard Worker
4296*8975f5c5SAndroid Build Coastguard Worker glUseProgram(programs[3]);
4297*8975f5c5SAndroid Build Coastguard Worker colorScaleLoc = glGetUniformLocation(programs[3], "colorScale");
4298*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, colorScaleLoc);
4299*8975f5c5SAndroid Build Coastguard Worker glUniform4f(colorScaleLoc, 0, 0, 0, 1);
4300*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
4301*8975f5c5SAndroid Build Coastguard Worker
4302*8975f5c5SAndroid Build Coastguard Worker // All channels must be 1
4303*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::white);
4304*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
4305*8975f5c5SAndroid Build Coastguard Worker }
4306*8975f5c5SAndroid Build Coastguard Worker
4307*8975f5c5SAndroid Build Coastguard Worker // Test that aliasing attribute locations work with es 100 shaders. Note that es 300 and above
4308*8975f5c5SAndroid Build Coastguard Worker // don't allow vertex attribute aliasing. This test excludes matrix types.
TEST_P(VertexAttributeTest,AliasingVectorAttribLocations)4309*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, AliasingVectorAttribLocations)
4310*8975f5c5SAndroid Build Coastguard Worker {
4311*8975f5c5SAndroid Build Coastguard Worker // http://anglebug.com/42263740
4312*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
4313*8975f5c5SAndroid Build Coastguard Worker
4314*8975f5c5SAndroid Build Coastguard Worker // http://anglebug.com/42262130
4315*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
4316*8975f5c5SAndroid Build Coastguard Worker
4317*8975f5c5SAndroid Build Coastguard Worker // http://anglebug.com/42262131
4318*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsD3D());
4319*8975f5c5SAndroid Build Coastguard Worker
4320*8975f5c5SAndroid Build Coastguard Worker // This test needs 10 total attributes. All backends support this except some old Android
4321*8975f5c5SAndroid Build Coastguard Worker // devices.
4322*8975f5c5SAndroid Build Coastguard Worker GLint maxVertexAttribs = 0;
4323*8975f5c5SAndroid Build Coastguard Worker glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
4324*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(maxVertexAttribs < 10);
4325*8975f5c5SAndroid Build Coastguard Worker
4326*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] = R"(attribute vec4 position;
4327*8975f5c5SAndroid Build Coastguard Worker // 4 aliasing attributes
4328*8975f5c5SAndroid Build Coastguard Worker attribute float attr0f;
4329*8975f5c5SAndroid Build Coastguard Worker attribute vec2 attr0v2;
4330*8975f5c5SAndroid Build Coastguard Worker attribute vec3 attr0v3;
4331*8975f5c5SAndroid Build Coastguard Worker attribute vec4 attr0v4;
4332*8975f5c5SAndroid Build Coastguard Worker const vec4 attr0Expected = vec4(0.1, 0.2, 0.3, 0.4);
4333*8975f5c5SAndroid Build Coastguard Worker
4334*8975f5c5SAndroid Build Coastguard Worker // 2 aliasing attributes
4335*8975f5c5SAndroid Build Coastguard Worker attribute vec2 attr1v2;
4336*8975f5c5SAndroid Build Coastguard Worker attribute vec3 attr1v3;
4337*8975f5c5SAndroid Build Coastguard Worker const vec3 attr1Expected = vec3(0.5, 0.6, 0.7);
4338*8975f5c5SAndroid Build Coastguard Worker
4339*8975f5c5SAndroid Build Coastguard Worker // 2 aliasing attributes
4340*8975f5c5SAndroid Build Coastguard Worker attribute vec4 attr2v4;
4341*8975f5c5SAndroid Build Coastguard Worker attribute float attr2f;
4342*8975f5c5SAndroid Build Coastguard Worker const vec4 attr2Expected = vec4(0.8, 0.85, 0.9, 0.95);
4343*8975f5c5SAndroid Build Coastguard Worker
4344*8975f5c5SAndroid Build Coastguard Worker // 2 aliasing attributes
4345*8975f5c5SAndroid Build Coastguard Worker attribute float attr3f1;
4346*8975f5c5SAndroid Build Coastguard Worker attribute float attr3f2;
4347*8975f5c5SAndroid Build Coastguard Worker const float attr3Expected = 1.0;
4348*8975f5c5SAndroid Build Coastguard Worker
4349*8975f5c5SAndroid Build Coastguard Worker uniform float attr0Select;
4350*8975f5c5SAndroid Build Coastguard Worker uniform float attr1Select;
4351*8975f5c5SAndroid Build Coastguard Worker uniform float attr2Select;
4352*8975f5c5SAndroid Build Coastguard Worker uniform float attr3Select;
4353*8975f5c5SAndroid Build Coastguard Worker
4354*8975f5c5SAndroid Build Coastguard Worker // Each channel controlled by success from each set of aliasing attributes. If a channel is 0, the
4355*8975f5c5SAndroid Build Coastguard Worker // attribute test has failed. Otherwise it will be 0.25, 0.5, 0.75 or 1.0, depending on how many
4356*8975f5c5SAndroid Build Coastguard Worker // channels there are in the compared attribute (except attr3).
4357*8975f5c5SAndroid Build Coastguard Worker varying mediump vec4 color;
4358*8975f5c5SAndroid Build Coastguard Worker void main()
4359*8975f5c5SAndroid Build Coastguard Worker {
4360*8975f5c5SAndroid Build Coastguard Worker gl_Position = position;
4361*8975f5c5SAndroid Build Coastguard Worker
4362*8975f5c5SAndroid Build Coastguard Worker vec4 result = vec4(0);
4363*8975f5c5SAndroid Build Coastguard Worker
4364*8975f5c5SAndroid Build Coastguard Worker if (attr0Select < 0.5)
4365*8975f5c5SAndroid Build Coastguard Worker result.r = abs(attr0f - attr0Expected.x) < 0.01 ? 0.25 : 0.0;
4366*8975f5c5SAndroid Build Coastguard Worker else if (attr0Select < 1.5)
4367*8975f5c5SAndroid Build Coastguard Worker result.r = all(lessThan(abs(attr0v2 - attr0Expected.xy), vec2(0.01))) ? 0.5 : 0.0;
4368*8975f5c5SAndroid Build Coastguard Worker else if (attr0Select < 2.5)
4369*8975f5c5SAndroid Build Coastguard Worker result.r = all(lessThan(abs(attr0v3 - attr0Expected.xyz), vec3(0.01))) ? 0.75 : 0.0;
4370*8975f5c5SAndroid Build Coastguard Worker else
4371*8975f5c5SAndroid Build Coastguard Worker result.r = all(lessThan(abs(attr0v4 - attr0Expected), vec4(0.01 )))? 1.0 : 0.0;
4372*8975f5c5SAndroid Build Coastguard Worker
4373*8975f5c5SAndroid Build Coastguard Worker if (attr1Select < 0.5)
4374*8975f5c5SAndroid Build Coastguard Worker result.g = all(lessThan(abs(attr1v2 - attr1Expected.xy), vec2(0.01 )))? 0.5 : 0.0;
4375*8975f5c5SAndroid Build Coastguard Worker else
4376*8975f5c5SAndroid Build Coastguard Worker result.g = all(lessThan(abs(attr1v3 - attr1Expected), vec3(0.01 )))? 0.75 : 0.0;
4377*8975f5c5SAndroid Build Coastguard Worker
4378*8975f5c5SAndroid Build Coastguard Worker if (attr2Select < 0.5)
4379*8975f5c5SAndroid Build Coastguard Worker result.b = abs(attr2f - attr2Expected.x) < 0.01 ? 0.25 : 0.0;
4380*8975f5c5SAndroid Build Coastguard Worker else
4381*8975f5c5SAndroid Build Coastguard Worker result.b = all(lessThan(abs(attr2v4 - attr2Expected), vec4(0.01))) ? 1.0 : 0.0;
4382*8975f5c5SAndroid Build Coastguard Worker
4383*8975f5c5SAndroid Build Coastguard Worker if (attr3Select < 0.5)
4384*8975f5c5SAndroid Build Coastguard Worker result.a = abs(attr3f1 - attr3Expected) < 0.01 ? 0.25 : 0.0;
4385*8975f5c5SAndroid Build Coastguard Worker else
4386*8975f5c5SAndroid Build Coastguard Worker result.a = abs(attr3f2 - attr3Expected) < 0.01 ? 0.5 : 0.0;
4387*8975f5c5SAndroid Build Coastguard Worker
4388*8975f5c5SAndroid Build Coastguard Worker color = result;
4389*8975f5c5SAndroid Build Coastguard Worker })";
4390*8975f5c5SAndroid Build Coastguard Worker
4391*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] = R"(varying mediump vec4 color;
4392*8975f5c5SAndroid Build Coastguard Worker void main(void)
4393*8975f5c5SAndroid Build Coastguard Worker {
4394*8975f5c5SAndroid Build Coastguard Worker gl_FragColor = color;
4395*8975f5c5SAndroid Build Coastguard Worker })";
4396*8975f5c5SAndroid Build Coastguard Worker
4397*8975f5c5SAndroid Build Coastguard Worker // Compile shaders.
4398*8975f5c5SAndroid Build Coastguard Worker GLuint program = CompileProgram(kVS, kFS);
4399*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(program, 0u);
4400*8975f5c5SAndroid Build Coastguard Worker
4401*8975f5c5SAndroid Build Coastguard Worker // Setup bindings.
4402*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 0, "attr0f");
4403*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 0, "attr0v2");
4404*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 0, "attr0v3");
4405*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 0, "attr0v4");
4406*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 1, "attr1v2");
4407*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 1, "attr1v3");
4408*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 2, "attr2v4");
4409*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 2, "attr2f");
4410*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 3, "attr3f1");
4411*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 3, "attr3f2");
4412*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
4413*8975f5c5SAndroid Build Coastguard Worker
4414*8975f5c5SAndroid Build Coastguard Worker // Link program and get uniform locations.
4415*8975f5c5SAndroid Build Coastguard Worker glLinkProgram(program);
4416*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
4417*8975f5c5SAndroid Build Coastguard Worker GLint attr0SelectLoc = glGetUniformLocation(program, "attr0Select");
4418*8975f5c5SAndroid Build Coastguard Worker GLint attr1SelectLoc = glGetUniformLocation(program, "attr1Select");
4419*8975f5c5SAndroid Build Coastguard Worker GLint attr2SelectLoc = glGetUniformLocation(program, "attr2Select");
4420*8975f5c5SAndroid Build Coastguard Worker GLint attr3SelectLoc = glGetUniformLocation(program, "attr3Select");
4421*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, attr0SelectLoc);
4422*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, attr1SelectLoc);
4423*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, attr2SelectLoc);
4424*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, attr3SelectLoc);
4425*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
4426*8975f5c5SAndroid Build Coastguard Worker
4427*8975f5c5SAndroid Build Coastguard Worker // Set values for attributes.
4428*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib4f(0, 0.1f, 0.2f, 0.3f, 0.4f);
4429*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib3f(1, 0.5f, 0.6f, 0.7f);
4430*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib4f(2, 0.8f, 0.85f, 0.9f, 0.95f);
4431*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib1f(3, 1.0f);
4432*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(0);
4433*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(1);
4434*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(2);
4435*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(3);
4436*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
4437*8975f5c5SAndroid Build Coastguard Worker
4438*8975f5c5SAndroid Build Coastguard Worker // Go through different combination of attributes and make sure reading through every alias is
4439*8975f5c5SAndroid Build Coastguard Worker // correctly handled.
4440*8975f5c5SAndroid Build Coastguard Worker GLColor expected;
4441*8975f5c5SAndroid Build Coastguard Worker for (uint32_t attr0Select = 0; attr0Select < 4; ++attr0Select)
4442*8975f5c5SAndroid Build Coastguard Worker {
4443*8975f5c5SAndroid Build Coastguard Worker glUniform1f(attr0SelectLoc, attr0Select);
4444*8975f5c5SAndroid Build Coastguard Worker expected.R = attr0Select * 64 + 63;
4445*8975f5c5SAndroid Build Coastguard Worker
4446*8975f5c5SAndroid Build Coastguard Worker for (uint32_t attr1Select = 0; attr1Select < 2; ++attr1Select)
4447*8975f5c5SAndroid Build Coastguard Worker {
4448*8975f5c5SAndroid Build Coastguard Worker glUniform1f(attr1SelectLoc, attr1Select);
4449*8975f5c5SAndroid Build Coastguard Worker expected.G = attr1Select * 64 + 127;
4450*8975f5c5SAndroid Build Coastguard Worker
4451*8975f5c5SAndroid Build Coastguard Worker for (uint32_t attr2Select = 0; attr2Select < 2; ++attr2Select)
4452*8975f5c5SAndroid Build Coastguard Worker {
4453*8975f5c5SAndroid Build Coastguard Worker glUniform1f(attr2SelectLoc, attr2Select);
4454*8975f5c5SAndroid Build Coastguard Worker expected.B = attr2Select * 192 + 63;
4455*8975f5c5SAndroid Build Coastguard Worker
4456*8975f5c5SAndroid Build Coastguard Worker for (uint32_t attr3Select = 0; attr3Select < 2; ++attr3Select)
4457*8975f5c5SAndroid Build Coastguard Worker {
4458*8975f5c5SAndroid Build Coastguard Worker glUniform1f(attr3SelectLoc, attr3Select);
4459*8975f5c5SAndroid Build Coastguard Worker expected.A = attr3Select * 64 + 63;
4460*8975f5c5SAndroid Build Coastguard Worker
4461*8975f5c5SAndroid Build Coastguard Worker drawQuad(program, "position", 0.5f);
4462*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
4463*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_NEAR(0, 0, expected, 1);
4464*8975f5c5SAndroid Build Coastguard Worker }
4465*8975f5c5SAndroid Build Coastguard Worker }
4466*8975f5c5SAndroid Build Coastguard Worker }
4467*8975f5c5SAndroid Build Coastguard Worker }
4468*8975f5c5SAndroid Build Coastguard Worker }
4469*8975f5c5SAndroid Build Coastguard Worker
4470*8975f5c5SAndroid Build Coastguard Worker // Test that aliasing attribute locations work with es 100 shaders. Note that es 300 and above
4471*8975f5c5SAndroid Build Coastguard Worker // don't allow vertex attribute aliasing. This test includes matrix types.
TEST_P(VertexAttributeTest,AliasingMatrixAttribLocations)4472*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, AliasingMatrixAttribLocations)
4473*8975f5c5SAndroid Build Coastguard Worker {
4474*8975f5c5SAndroid Build Coastguard Worker // http://anglebug.com/42263740
4475*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
4476*8975f5c5SAndroid Build Coastguard Worker
4477*8975f5c5SAndroid Build Coastguard Worker // http://anglebug.com/42262130
4478*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
4479*8975f5c5SAndroid Build Coastguard Worker
4480*8975f5c5SAndroid Build Coastguard Worker // http://anglebug.com/42262131
4481*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsD3D());
4482*8975f5c5SAndroid Build Coastguard Worker
4483*8975f5c5SAndroid Build Coastguard Worker // This test needs 16 total attributes. All backends support this except some old Android
4484*8975f5c5SAndroid Build Coastguard Worker // devices.
4485*8975f5c5SAndroid Build Coastguard Worker GLint maxVertexAttribs = 0;
4486*8975f5c5SAndroid Build Coastguard Worker glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
4487*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(maxVertexAttribs < 16);
4488*8975f5c5SAndroid Build Coastguard Worker
4489*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] = R"(attribute vec4 position;
4490*8975f5c5SAndroid Build Coastguard Worker // attributes aliasing location 0 and above
4491*8975f5c5SAndroid Build Coastguard Worker attribute float attr0f;
4492*8975f5c5SAndroid Build Coastguard Worker attribute mat3 attr0m3;
4493*8975f5c5SAndroid Build Coastguard Worker attribute mat2 attr0m2;
4494*8975f5c5SAndroid Build Coastguard Worker
4495*8975f5c5SAndroid Build Coastguard Worker // attributes aliasing location 1 and above
4496*8975f5c5SAndroid Build Coastguard Worker attribute vec4 attr1v4;
4497*8975f5c5SAndroid Build Coastguard Worker
4498*8975f5c5SAndroid Build Coastguard Worker // attributes aliasing location 2 and above
4499*8975f5c5SAndroid Build Coastguard Worker attribute mat4 attr2m4;
4500*8975f5c5SAndroid Build Coastguard Worker
4501*8975f5c5SAndroid Build Coastguard Worker // attributes aliasing location 3 and above
4502*8975f5c5SAndroid Build Coastguard Worker attribute mat2 attr3m2;
4503*8975f5c5SAndroid Build Coastguard Worker
4504*8975f5c5SAndroid Build Coastguard Worker // attributes aliasing location 5 and above
4505*8975f5c5SAndroid Build Coastguard Worker attribute vec2 attr5v2;
4506*8975f5c5SAndroid Build Coastguard Worker
4507*8975f5c5SAndroid Build Coastguard Worker // In summary (attr prefix shortened to a):
4508*8975f5c5SAndroid Build Coastguard Worker //
4509*8975f5c5SAndroid Build Coastguard Worker // location 0: a0f a0m3[0] a0m2[0]
4510*8975f5c5SAndroid Build Coastguard Worker // location 1: a0m3[1] a0m2[1] a1v4
4511*8975f5c5SAndroid Build Coastguard Worker // location 2: a0m3[2] a2m4[0]
4512*8975f5c5SAndroid Build Coastguard Worker // location 3: a2m4[1] a3m2[0]
4513*8975f5c5SAndroid Build Coastguard Worker // location 4: a2m4[2] a3m2[1]
4514*8975f5c5SAndroid Build Coastguard Worker // location 5: a2m4[3] a5v2
4515*8975f5c5SAndroid Build Coastguard Worker
4516*8975f5c5SAndroid Build Coastguard Worker const vec3 loc0Expected = vec3(0.05, 0.1, 0.15);
4517*8975f5c5SAndroid Build Coastguard Worker const vec4 loc1Expected = vec4(0.2, 0.25, 0.3, 0.35);
4518*8975f5c5SAndroid Build Coastguard Worker const vec4 loc2Expected = vec4(0.4, 0.45, 0.5, 0.55);
4519*8975f5c5SAndroid Build Coastguard Worker const vec4 loc3Expected = vec4(0.6, 0.65, 0.7, 0.75);
4520*8975f5c5SAndroid Build Coastguard Worker const vec4 loc4Expected = vec4(0.8, 0.85, 0.9, 0.95);
4521*8975f5c5SAndroid Build Coastguard Worker const vec4 loc5Expected = vec4(0.25, 0.5, 0.75, 1.0);
4522*8975f5c5SAndroid Build Coastguard Worker
4523*8975f5c5SAndroid Build Coastguard Worker uniform float loc0Select;
4524*8975f5c5SAndroid Build Coastguard Worker uniform float loc1Select;
4525*8975f5c5SAndroid Build Coastguard Worker uniform float loc2Select;
4526*8975f5c5SAndroid Build Coastguard Worker uniform float loc3Select;
4527*8975f5c5SAndroid Build Coastguard Worker uniform float loc4Select;
4528*8975f5c5SAndroid Build Coastguard Worker uniform float loc5Select;
4529*8975f5c5SAndroid Build Coastguard Worker
4530*8975f5c5SAndroid Build Coastguard Worker // Each channel controlled by success from each set of aliasing locations. Locations 2 and 3
4531*8975f5c5SAndroid Build Coastguard Worker // contribute to B together, while locations 4 and 5 contribute to A together. If a channel is 0,
4532*8975f5c5SAndroid Build Coastguard Worker // the attribute test has failed. Otherwise it will be 1/N, 2/N, ..., 1, depending on how many
4533*8975f5c5SAndroid Build Coastguard Worker // possible values there are for the controlling uniforms.
4534*8975f5c5SAndroid Build Coastguard Worker varying mediump vec4 color;
4535*8975f5c5SAndroid Build Coastguard Worker void main()
4536*8975f5c5SAndroid Build Coastguard Worker {
4537*8975f5c5SAndroid Build Coastguard Worker gl_Position = position;
4538*8975f5c5SAndroid Build Coastguard Worker
4539*8975f5c5SAndroid Build Coastguard Worker vec4 result = vec4(0);
4540*8975f5c5SAndroid Build Coastguard Worker
4541*8975f5c5SAndroid Build Coastguard Worker if (loc0Select < 0.5)
4542*8975f5c5SAndroid Build Coastguard Worker result.r = abs(attr0f - loc0Expected.x) < 0.01 ? 0.333333 : 0.0;
4543*8975f5c5SAndroid Build Coastguard Worker else if (loc0Select < 1.5)
4544*8975f5c5SAndroid Build Coastguard Worker result.r = all(lessThan(abs(attr0m2[0] - loc0Expected.xy), vec2(0.01))) ? 0.666667 : 0.0;
4545*8975f5c5SAndroid Build Coastguard Worker else
4546*8975f5c5SAndroid Build Coastguard Worker result.r = all(lessThan(abs(attr0m3[0] - loc0Expected), vec3(0.01))) ? 1.0 : 0.0;
4547*8975f5c5SAndroid Build Coastguard Worker
4548*8975f5c5SAndroid Build Coastguard Worker if (loc1Select < 0.5)
4549*8975f5c5SAndroid Build Coastguard Worker result.g = all(lessThan(abs(attr0m3[1] - loc1Expected.xyz), vec3(0.01))) ? 0.333333 : 0.0;
4550*8975f5c5SAndroid Build Coastguard Worker else if (loc1Select < 1.5)
4551*8975f5c5SAndroid Build Coastguard Worker result.g = all(lessThan(abs(attr0m2[1] - loc1Expected.xy), vec2(0.01))) ? 0.666667 : 0.0;
4552*8975f5c5SAndroid Build Coastguard Worker else
4553*8975f5c5SAndroid Build Coastguard Worker result.g = all(lessThan(abs(attr1v4 - loc1Expected), vec4(0.01))) ? 1.0 : 0.0;
4554*8975f5c5SAndroid Build Coastguard Worker
4555*8975f5c5SAndroid Build Coastguard Worker bool loc2Ok = false;
4556*8975f5c5SAndroid Build Coastguard Worker bool loc3Ok = false;
4557*8975f5c5SAndroid Build Coastguard Worker
4558*8975f5c5SAndroid Build Coastguard Worker if (loc2Select < 0.5)
4559*8975f5c5SAndroid Build Coastguard Worker loc2Ok = all(lessThan(abs(attr0m3[2] - loc2Expected.xyz), vec3(0.01)));
4560*8975f5c5SAndroid Build Coastguard Worker else
4561*8975f5c5SAndroid Build Coastguard Worker loc2Ok = all(lessThan(abs(attr2m4[0] - loc2Expected), vec4(0.01)));
4562*8975f5c5SAndroid Build Coastguard Worker
4563*8975f5c5SAndroid Build Coastguard Worker if (loc3Select < 0.5)
4564*8975f5c5SAndroid Build Coastguard Worker loc3Ok = all(lessThan(abs(attr2m4[1] - loc3Expected), vec4(0.01)));
4565*8975f5c5SAndroid Build Coastguard Worker else
4566*8975f5c5SAndroid Build Coastguard Worker loc3Ok = all(lessThan(abs(attr3m2[0] - loc3Expected.xy), vec2(0.01)));
4567*8975f5c5SAndroid Build Coastguard Worker
4568*8975f5c5SAndroid Build Coastguard Worker if (loc2Ok && loc3Ok)
4569*8975f5c5SAndroid Build Coastguard Worker {
4570*8975f5c5SAndroid Build Coastguard Worker if (loc2Select < 0.5)
4571*8975f5c5SAndroid Build Coastguard Worker if (loc3Select < 0.5)
4572*8975f5c5SAndroid Build Coastguard Worker result.b = 0.25;
4573*8975f5c5SAndroid Build Coastguard Worker else
4574*8975f5c5SAndroid Build Coastguard Worker result.b = 0.5;
4575*8975f5c5SAndroid Build Coastguard Worker else
4576*8975f5c5SAndroid Build Coastguard Worker if (loc3Select < 0.5)
4577*8975f5c5SAndroid Build Coastguard Worker result.b = 0.75;
4578*8975f5c5SAndroid Build Coastguard Worker else
4579*8975f5c5SAndroid Build Coastguard Worker result.b = 1.0;
4580*8975f5c5SAndroid Build Coastguard Worker }
4581*8975f5c5SAndroid Build Coastguard Worker
4582*8975f5c5SAndroid Build Coastguard Worker bool loc4Ok = false;
4583*8975f5c5SAndroid Build Coastguard Worker bool loc5Ok = false;
4584*8975f5c5SAndroid Build Coastguard Worker
4585*8975f5c5SAndroid Build Coastguard Worker if (loc4Select < 0.5)
4586*8975f5c5SAndroid Build Coastguard Worker loc4Ok = all(lessThan(abs(attr2m4[2] - loc4Expected), vec4(0.01)));
4587*8975f5c5SAndroid Build Coastguard Worker else
4588*8975f5c5SAndroid Build Coastguard Worker loc4Ok = all(lessThan(abs(attr3m2[1] - loc4Expected.xy), vec2(0.01)));
4589*8975f5c5SAndroid Build Coastguard Worker
4590*8975f5c5SAndroid Build Coastguard Worker if (loc5Select < 0.5)
4591*8975f5c5SAndroid Build Coastguard Worker loc5Ok = all(lessThan(abs(attr2m4[3] - loc5Expected), vec4(0.01)));
4592*8975f5c5SAndroid Build Coastguard Worker else
4593*8975f5c5SAndroid Build Coastguard Worker loc5Ok = all(lessThan(abs(attr5v2 - loc5Expected.xy), vec2(0.01)));
4594*8975f5c5SAndroid Build Coastguard Worker
4595*8975f5c5SAndroid Build Coastguard Worker if (loc4Ok && loc5Ok)
4596*8975f5c5SAndroid Build Coastguard Worker {
4597*8975f5c5SAndroid Build Coastguard Worker if (loc4Select < 0.5)
4598*8975f5c5SAndroid Build Coastguard Worker if (loc5Select < 0.5)
4599*8975f5c5SAndroid Build Coastguard Worker result.a = 0.25;
4600*8975f5c5SAndroid Build Coastguard Worker else
4601*8975f5c5SAndroid Build Coastguard Worker result.a = 0.5;
4602*8975f5c5SAndroid Build Coastguard Worker else
4603*8975f5c5SAndroid Build Coastguard Worker if (loc5Select < 0.5)
4604*8975f5c5SAndroid Build Coastguard Worker result.a = 0.75;
4605*8975f5c5SAndroid Build Coastguard Worker else
4606*8975f5c5SAndroid Build Coastguard Worker result.a = 1.0;
4607*8975f5c5SAndroid Build Coastguard Worker }
4608*8975f5c5SAndroid Build Coastguard Worker
4609*8975f5c5SAndroid Build Coastguard Worker color = result;
4610*8975f5c5SAndroid Build Coastguard Worker })";
4611*8975f5c5SAndroid Build Coastguard Worker
4612*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] = R"(varying mediump vec4 color;
4613*8975f5c5SAndroid Build Coastguard Worker void main(void)
4614*8975f5c5SAndroid Build Coastguard Worker {
4615*8975f5c5SAndroid Build Coastguard Worker gl_FragColor = color;
4616*8975f5c5SAndroid Build Coastguard Worker })";
4617*8975f5c5SAndroid Build Coastguard Worker
4618*8975f5c5SAndroid Build Coastguard Worker // Compile shaders.
4619*8975f5c5SAndroid Build Coastguard Worker GLuint program = CompileProgram(kVS, kFS);
4620*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(program, 0u);
4621*8975f5c5SAndroid Build Coastguard Worker
4622*8975f5c5SAndroid Build Coastguard Worker // Setup bindings.
4623*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 0, "attr0f");
4624*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 0, "attr0m3");
4625*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 0, "attr0m2");
4626*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 1, "attr1v4");
4627*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 2, "attr2m4");
4628*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 3, "attr3m2");
4629*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 5, "attr5v2");
4630*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
4631*8975f5c5SAndroid Build Coastguard Worker
4632*8975f5c5SAndroid Build Coastguard Worker // Link program and get uniform locations.
4633*8975f5c5SAndroid Build Coastguard Worker glLinkProgram(program);
4634*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
4635*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
4636*8975f5c5SAndroid Build Coastguard Worker
4637*8975f5c5SAndroid Build Coastguard Worker GLint loc0SelectLoc = glGetUniformLocation(program, "loc0Select");
4638*8975f5c5SAndroid Build Coastguard Worker GLint loc1SelectLoc = glGetUniformLocation(program, "loc1Select");
4639*8975f5c5SAndroid Build Coastguard Worker GLint loc2SelectLoc = glGetUniformLocation(program, "loc2Select");
4640*8975f5c5SAndroid Build Coastguard Worker GLint loc3SelectLoc = glGetUniformLocation(program, "loc3Select");
4641*8975f5c5SAndroid Build Coastguard Worker GLint loc4SelectLoc = glGetUniformLocation(program, "loc4Select");
4642*8975f5c5SAndroid Build Coastguard Worker GLint loc5SelectLoc = glGetUniformLocation(program, "loc5Select");
4643*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, loc0SelectLoc);
4644*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, loc1SelectLoc);
4645*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, loc2SelectLoc);
4646*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, loc3SelectLoc);
4647*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, loc4SelectLoc);
4648*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, loc5SelectLoc);
4649*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
4650*8975f5c5SAndroid Build Coastguard Worker
4651*8975f5c5SAndroid Build Coastguard Worker // Set values for attributes.
4652*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib3f(0, 0.05, 0.1, 0.15);
4653*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib4f(1, 0.2, 0.25, 0.3, 0.35);
4654*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib4f(2, 0.4, 0.45, 0.5, 0.55);
4655*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib4f(3, 0.6, 0.65, 0.7, 0.75);
4656*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib4f(4, 0.8, 0.85, 0.9, 0.95);
4657*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib4f(5, 0.25, 0.5, 0.75, 1.0);
4658*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(0);
4659*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(1);
4660*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(2);
4661*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(3);
4662*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(4);
4663*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(5);
4664*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
4665*8975f5c5SAndroid Build Coastguard Worker
4666*8975f5c5SAndroid Build Coastguard Worker // Go through different combination of attributes and make sure reading through every alias is
4667*8975f5c5SAndroid Build Coastguard Worker // correctly handled.
4668*8975f5c5SAndroid Build Coastguard Worker GLColor expected;
4669*8975f5c5SAndroid Build Coastguard Worker for (uint32_t loc0Select = 0; loc0Select < 3; ++loc0Select)
4670*8975f5c5SAndroid Build Coastguard Worker {
4671*8975f5c5SAndroid Build Coastguard Worker glUniform1f(loc0SelectLoc, loc0Select);
4672*8975f5c5SAndroid Build Coastguard Worker expected.R = loc0Select * 85 + 85;
4673*8975f5c5SAndroid Build Coastguard Worker
4674*8975f5c5SAndroid Build Coastguard Worker for (uint32_t loc1Select = 0; loc1Select < 3; ++loc1Select)
4675*8975f5c5SAndroid Build Coastguard Worker {
4676*8975f5c5SAndroid Build Coastguard Worker glUniform1f(loc1SelectLoc, loc1Select);
4677*8975f5c5SAndroid Build Coastguard Worker expected.G = loc1Select * 85 + 85;
4678*8975f5c5SAndroid Build Coastguard Worker
4679*8975f5c5SAndroid Build Coastguard Worker for (uint32_t loc2Select = 0; loc2Select < 2; ++loc2Select)
4680*8975f5c5SAndroid Build Coastguard Worker {
4681*8975f5c5SAndroid Build Coastguard Worker glUniform1f(loc2SelectLoc, loc2Select);
4682*8975f5c5SAndroid Build Coastguard Worker
4683*8975f5c5SAndroid Build Coastguard Worker for (uint32_t loc3Select = 0; loc3Select < 2; ++loc3Select)
4684*8975f5c5SAndroid Build Coastguard Worker {
4685*8975f5c5SAndroid Build Coastguard Worker glUniform1f(loc3SelectLoc, loc3Select);
4686*8975f5c5SAndroid Build Coastguard Worker expected.B = (loc2Select << 1 | loc3Select) * 64 + 63;
4687*8975f5c5SAndroid Build Coastguard Worker
4688*8975f5c5SAndroid Build Coastguard Worker for (uint32_t loc4Select = 0; loc4Select < 2; ++loc4Select)
4689*8975f5c5SAndroid Build Coastguard Worker {
4690*8975f5c5SAndroid Build Coastguard Worker glUniform1f(loc4SelectLoc, loc4Select);
4691*8975f5c5SAndroid Build Coastguard Worker
4692*8975f5c5SAndroid Build Coastguard Worker for (uint32_t loc5Select = 0; loc5Select < 2; ++loc5Select)
4693*8975f5c5SAndroid Build Coastguard Worker {
4694*8975f5c5SAndroid Build Coastguard Worker glUniform1f(loc5SelectLoc, loc5Select);
4695*8975f5c5SAndroid Build Coastguard Worker expected.A = (loc4Select << 1 | loc5Select) * 64 + 63;
4696*8975f5c5SAndroid Build Coastguard Worker
4697*8975f5c5SAndroid Build Coastguard Worker drawQuad(program, "position", 0.5f);
4698*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
4699*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_NEAR(0, 0, expected, 1);
4700*8975f5c5SAndroid Build Coastguard Worker }
4701*8975f5c5SAndroid Build Coastguard Worker }
4702*8975f5c5SAndroid Build Coastguard Worker }
4703*8975f5c5SAndroid Build Coastguard Worker }
4704*8975f5c5SAndroid Build Coastguard Worker }
4705*8975f5c5SAndroid Build Coastguard Worker }
4706*8975f5c5SAndroid Build Coastguard Worker }
4707*8975f5c5SAndroid Build Coastguard Worker
4708*8975f5c5SAndroid Build Coastguard Worker // Test that aliasing attribute locations work with differing precisions.
TEST_P(VertexAttributeTest,AliasingVectorAttribLocationsDifferingPrecisions)4709*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, AliasingVectorAttribLocationsDifferingPrecisions)
4710*8975f5c5SAndroid Build Coastguard Worker {
4711*8975f5c5SAndroid Build Coastguard Worker // http://anglebug.com/42263740
4712*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
4713*8975f5c5SAndroid Build Coastguard Worker
4714*8975f5c5SAndroid Build Coastguard Worker // http://anglebug.com/42262130
4715*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
4716*8975f5c5SAndroid Build Coastguard Worker
4717*8975f5c5SAndroid Build Coastguard Worker // http://anglebug.com/42262131
4718*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsD3D());
4719*8975f5c5SAndroid Build Coastguard Worker
4720*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] = R"(attribute vec4 position;
4721*8975f5c5SAndroid Build Coastguard Worker // aliasing attributes.
4722*8975f5c5SAndroid Build Coastguard Worker attribute mediump vec2 attr0v2;
4723*8975f5c5SAndroid Build Coastguard Worker attribute highp vec3 attr0v3;
4724*8975f5c5SAndroid Build Coastguard Worker const vec3 attr0Expected = vec3(0.125, 0.25, 0.375);
4725*8975f5c5SAndroid Build Coastguard Worker
4726*8975f5c5SAndroid Build Coastguard Worker // aliasing attributes.
4727*8975f5c5SAndroid Build Coastguard Worker attribute highp vec2 attr1v2;
4728*8975f5c5SAndroid Build Coastguard Worker attribute mediump vec3 attr1v3;
4729*8975f5c5SAndroid Build Coastguard Worker const vec3 attr1Expected = vec3(0.5, 0.625, 0.75);
4730*8975f5c5SAndroid Build Coastguard Worker
4731*8975f5c5SAndroid Build Coastguard Worker uniform float attr0Select;
4732*8975f5c5SAndroid Build Coastguard Worker uniform float attr1Select;
4733*8975f5c5SAndroid Build Coastguard Worker
4734*8975f5c5SAndroid Build Coastguard Worker // Each channel controlled by success from each set of aliasing attributes (R and G used only). If
4735*8975f5c5SAndroid Build Coastguard Worker // a channel is 0, the attribute test has failed. Otherwise it will be 0.5 or 1.0.
4736*8975f5c5SAndroid Build Coastguard Worker varying mediump vec4 color;
4737*8975f5c5SAndroid Build Coastguard Worker void main()
4738*8975f5c5SAndroid Build Coastguard Worker {
4739*8975f5c5SAndroid Build Coastguard Worker gl_Position = position;
4740*8975f5c5SAndroid Build Coastguard Worker
4741*8975f5c5SAndroid Build Coastguard Worker vec4 result = vec4(0, 0, 0, 1);
4742*8975f5c5SAndroid Build Coastguard Worker
4743*8975f5c5SAndroid Build Coastguard Worker if (attr0Select < 0.5)
4744*8975f5c5SAndroid Build Coastguard Worker result.r = all(lessThan(abs(attr0v2 - attr0Expected.xy), vec2(0.01))) ? 0.5 : 0.0;
4745*8975f5c5SAndroid Build Coastguard Worker else
4746*8975f5c5SAndroid Build Coastguard Worker result.r = all(lessThan(abs(attr0v3 - attr0Expected), vec3(0.01))) ? 1.0 : 0.0;
4747*8975f5c5SAndroid Build Coastguard Worker
4748*8975f5c5SAndroid Build Coastguard Worker if (attr1Select < 0.5)
4749*8975f5c5SAndroid Build Coastguard Worker result.g = all(lessThan(abs(attr1v2 - attr1Expected.xy), vec2(0.01))) ? 0.5 : 0.0;
4750*8975f5c5SAndroid Build Coastguard Worker else
4751*8975f5c5SAndroid Build Coastguard Worker result.g = all(lessThan(abs(attr1v3 - attr1Expected), vec3(0.01))) ? 1.0 : 0.0;
4752*8975f5c5SAndroid Build Coastguard Worker
4753*8975f5c5SAndroid Build Coastguard Worker color = result;
4754*8975f5c5SAndroid Build Coastguard Worker })";
4755*8975f5c5SAndroid Build Coastguard Worker
4756*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] = R"(varying mediump vec4 color;
4757*8975f5c5SAndroid Build Coastguard Worker void main(void)
4758*8975f5c5SAndroid Build Coastguard Worker {
4759*8975f5c5SAndroid Build Coastguard Worker gl_FragColor = color;
4760*8975f5c5SAndroid Build Coastguard Worker })";
4761*8975f5c5SAndroid Build Coastguard Worker
4762*8975f5c5SAndroid Build Coastguard Worker // Compile shaders.
4763*8975f5c5SAndroid Build Coastguard Worker GLuint program = CompileProgram(kVS, kFS);
4764*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(program, 0u);
4765*8975f5c5SAndroid Build Coastguard Worker
4766*8975f5c5SAndroid Build Coastguard Worker // Setup bindings.
4767*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 0, "attr0v2");
4768*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 0, "attr0v3");
4769*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 1, "attr1v2");
4770*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 1, "attr1v3");
4771*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
4772*8975f5c5SAndroid Build Coastguard Worker
4773*8975f5c5SAndroid Build Coastguard Worker // Link program and get uniform locations.
4774*8975f5c5SAndroid Build Coastguard Worker glLinkProgram(program);
4775*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
4776*8975f5c5SAndroid Build Coastguard Worker GLint attr0SelectLoc = glGetUniformLocation(program, "attr0Select");
4777*8975f5c5SAndroid Build Coastguard Worker GLint attr1SelectLoc = glGetUniformLocation(program, "attr1Select");
4778*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, attr0SelectLoc);
4779*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, attr1SelectLoc);
4780*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
4781*8975f5c5SAndroid Build Coastguard Worker
4782*8975f5c5SAndroid Build Coastguard Worker // Set values for attributes.
4783*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib3f(0, 0.125f, 0.25f, 0.375f);
4784*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib3f(1, 0.5f, 0.625f, 0.75f);
4785*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(0);
4786*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(1);
4787*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
4788*8975f5c5SAndroid Build Coastguard Worker
4789*8975f5c5SAndroid Build Coastguard Worker // Go through different combination of attributes and make sure reading through every alias is
4790*8975f5c5SAndroid Build Coastguard Worker // correctly handled.
4791*8975f5c5SAndroid Build Coastguard Worker GLColor expected;
4792*8975f5c5SAndroid Build Coastguard Worker expected.B = 0;
4793*8975f5c5SAndroid Build Coastguard Worker expected.A = 255;
4794*8975f5c5SAndroid Build Coastguard Worker for (uint32_t attr0Select = 0; attr0Select < 2; ++attr0Select)
4795*8975f5c5SAndroid Build Coastguard Worker {
4796*8975f5c5SAndroid Build Coastguard Worker glUniform1f(attr0SelectLoc, attr0Select);
4797*8975f5c5SAndroid Build Coastguard Worker expected.R = attr0Select * 128 + 127;
4798*8975f5c5SAndroid Build Coastguard Worker
4799*8975f5c5SAndroid Build Coastguard Worker for (uint32_t attr1Select = 0; attr1Select < 2; ++attr1Select)
4800*8975f5c5SAndroid Build Coastguard Worker {
4801*8975f5c5SAndroid Build Coastguard Worker glUniform1f(attr1SelectLoc, attr1Select);
4802*8975f5c5SAndroid Build Coastguard Worker expected.G = attr1Select * 128 + 127;
4803*8975f5c5SAndroid Build Coastguard Worker
4804*8975f5c5SAndroid Build Coastguard Worker drawQuad(program, "position", 0.5f);
4805*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
4806*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_NEAR(0, 0, expected, 1);
4807*8975f5c5SAndroid Build Coastguard Worker }
4808*8975f5c5SAndroid Build Coastguard Worker }
4809*8975f5c5SAndroid Build Coastguard Worker }
4810*8975f5c5SAndroid Build Coastguard Worker
4811*8975f5c5SAndroid Build Coastguard Worker // Test that unsupported vertex format specified on non-existing attribute doesn't crash.
TEST_P(VertexAttributeTest,VertexFormatConversionOfNonExistingAttribute)4812*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, VertexFormatConversionOfNonExistingAttribute)
4813*8975f5c5SAndroid Build Coastguard Worker {
4814*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] = R"(precision highp float;
4815*8975f5c5SAndroid Build Coastguard Worker attribute vec3 attr1;
4816*8975f5c5SAndroid Build Coastguard Worker void main(void) {
4817*8975f5c5SAndroid Build Coastguard Worker gl_Position = vec4(attr1, 1.0);
4818*8975f5c5SAndroid Build Coastguard Worker })";
4819*8975f5c5SAndroid Build Coastguard Worker
4820*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] = R"(precision highp float;
4821*8975f5c5SAndroid Build Coastguard Worker void main(void) {
4822*8975f5c5SAndroid Build Coastguard Worker gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
4823*8975f5c5SAndroid Build Coastguard Worker })";
4824*8975f5c5SAndroid Build Coastguard Worker
4825*8975f5c5SAndroid Build Coastguard Worker GLBuffer emptyBuffer;
4826*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, emptyBuffer);
4827*8975f5c5SAndroid Build Coastguard Worker
4828*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(program, kVS, kFS);
4829*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 0, "attr1");
4830*8975f5c5SAndroid Build Coastguard Worker glLinkProgram(program);
4831*8975f5c5SAndroid Build Coastguard Worker ASSERT_TRUE(CheckLinkStatusAndReturnProgram(program, true));
4832*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
4833*8975f5c5SAndroid Build Coastguard Worker
4834*8975f5c5SAndroid Build Coastguard Worker // Use the RGB8 format for non-existing attribute 1.
4835*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(1);
4836*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(1, 3, GL_UNSIGNED_BYTE, false, 1, 0);
4837*8975f5c5SAndroid Build Coastguard Worker
4838*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 3);
4839*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
4840*8975f5c5SAndroid Build Coastguard Worker }
4841*8975f5c5SAndroid Build Coastguard Worker
4842*8975f5c5SAndroid Build Coastguard Worker // Covers a bug with integer formats and an element size larger than the vertex stride.
TEST_P(VertexAttributeTestES3,StrideSmallerThanIntegerElementSize)4843*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, StrideSmallerThanIntegerElementSize)
4844*8975f5c5SAndroid Build Coastguard Worker {
4845*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] = R"(#version 300 es
4846*8975f5c5SAndroid Build Coastguard Worker in vec4 position;
4847*8975f5c5SAndroid Build Coastguard Worker in ivec2 intAttrib;
4848*8975f5c5SAndroid Build Coastguard Worker in vec2 floatAttrib;
4849*8975f5c5SAndroid Build Coastguard Worker out vec4 colorVarying;
4850*8975f5c5SAndroid Build Coastguard Worker void main()
4851*8975f5c5SAndroid Build Coastguard Worker {
4852*8975f5c5SAndroid Build Coastguard Worker gl_Position = position;
4853*8975f5c5SAndroid Build Coastguard Worker if (vec2(intAttrib) == floatAttrib)
4854*8975f5c5SAndroid Build Coastguard Worker {
4855*8975f5c5SAndroid Build Coastguard Worker colorVarying = vec4(0, 1, 0, 1);
4856*8975f5c5SAndroid Build Coastguard Worker }
4857*8975f5c5SAndroid Build Coastguard Worker else
4858*8975f5c5SAndroid Build Coastguard Worker {
4859*8975f5c5SAndroid Build Coastguard Worker colorVarying = vec4(1, 0, 0, 1);
4860*8975f5c5SAndroid Build Coastguard Worker }
4861*8975f5c5SAndroid Build Coastguard Worker })";
4862*8975f5c5SAndroid Build Coastguard Worker
4863*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] = R"(#version 300 es
4864*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
4865*8975f5c5SAndroid Build Coastguard Worker in vec4 colorVarying;
4866*8975f5c5SAndroid Build Coastguard Worker out vec4 fragColor;
4867*8975f5c5SAndroid Build Coastguard Worker void main()
4868*8975f5c5SAndroid Build Coastguard Worker {
4869*8975f5c5SAndroid Build Coastguard Worker fragColor = colorVarying;
4870*8975f5c5SAndroid Build Coastguard Worker })";
4871*8975f5c5SAndroid Build Coastguard Worker
4872*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(testProgram, kVS, kFS);
4873*8975f5c5SAndroid Build Coastguard Worker glUseProgram(testProgram);
4874*8975f5c5SAndroid Build Coastguard Worker
4875*8975f5c5SAndroid Build Coastguard Worker GLBuffer positionBuffer;
4876*8975f5c5SAndroid Build Coastguard Worker {
4877*8975f5c5SAndroid Build Coastguard Worker const std::array<Vector3, 6> &quadVerts = GetQuadVertices();
4878*8975f5c5SAndroid Build Coastguard Worker
4879*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
4880*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
4881*8975f5c5SAndroid Build Coastguard Worker GL_STATIC_DRAW);
4882*8975f5c5SAndroid Build Coastguard Worker
4883*8975f5c5SAndroid Build Coastguard Worker GLint posLoc = glGetAttribLocation(testProgram, "position");
4884*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(posLoc, -1);
4885*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
4886*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(posLoc);
4887*8975f5c5SAndroid Build Coastguard Worker }
4888*8975f5c5SAndroid Build Coastguard Worker
4889*8975f5c5SAndroid Build Coastguard Worker GLBuffer intBuffer;
4890*8975f5c5SAndroid Build Coastguard Worker {
4891*8975f5c5SAndroid Build Coastguard Worker std::array<GLbyte, 12> intData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
4892*8975f5c5SAndroid Build Coastguard Worker
4893*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, intBuffer);
4894*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, intData.size() * sizeof(intData[0]), intData.data(),
4895*8975f5c5SAndroid Build Coastguard Worker GL_STATIC_DRAW);
4896*8975f5c5SAndroid Build Coastguard Worker
4897*8975f5c5SAndroid Build Coastguard Worker GLint intLoc = glGetAttribLocation(testProgram, "intAttrib");
4898*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(intLoc, -1);
4899*8975f5c5SAndroid Build Coastguard Worker glVertexAttribIPointer(intLoc, 2, GL_BYTE, 1, nullptr);
4900*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(intLoc);
4901*8975f5c5SAndroid Build Coastguard Worker }
4902*8975f5c5SAndroid Build Coastguard Worker
4903*8975f5c5SAndroid Build Coastguard Worker GLBuffer floatBuffer;
4904*8975f5c5SAndroid Build Coastguard Worker {
4905*8975f5c5SAndroid Build Coastguard Worker std::array<GLfloat, 12> floatData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
4906*8975f5c5SAndroid Build Coastguard Worker
4907*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, floatBuffer);
4908*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, floatData.size() * sizeof(floatData[0]), floatData.data(),
4909*8975f5c5SAndroid Build Coastguard Worker GL_STATIC_DRAW);
4910*8975f5c5SAndroid Build Coastguard Worker
4911*8975f5c5SAndroid Build Coastguard Worker GLint floatLoc = glGetAttribLocation(testProgram, "floatAttrib");
4912*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(floatLoc, -1);
4913*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(floatLoc, 2, GL_FLOAT, GL_FALSE, 4, nullptr);
4914*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(floatLoc);
4915*8975f5c5SAndroid Build Coastguard Worker }
4916*8975f5c5SAndroid Build Coastguard Worker
4917*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
4918*8975f5c5SAndroid Build Coastguard Worker
4919*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
4920*8975f5c5SAndroid Build Coastguard Worker
4921*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green);
4922*8975f5c5SAndroid Build Coastguard Worker }
4923*8975f5c5SAndroid Build Coastguard Worker
4924*8975f5c5SAndroid Build Coastguard Worker // Test that pipeline is recreated properly when switching from ARRAY buffer to client buffer,
4925*8975f5c5SAndroid Build Coastguard Worker // while removing client buffer. Bug observed in Dragonmania game.
TEST_P(VertexAttributeTestES31,ArrayToClientBufferStride)4926*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES31, ArrayToClientBufferStride)
4927*8975f5c5SAndroid Build Coastguard Worker {
4928*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] = R"(#version 310 es
4929*8975f5c5SAndroid Build Coastguard Worker precision highp float;
4930*8975f5c5SAndroid Build Coastguard Worker in vec4 in_pos;
4931*8975f5c5SAndroid Build Coastguard Worker in vec4 in_color;
4932*8975f5c5SAndroid Build Coastguard Worker out vec4 color;
4933*8975f5c5SAndroid Build Coastguard Worker void main(void) {
4934*8975f5c5SAndroid Build Coastguard Worker gl_Position = in_pos;
4935*8975f5c5SAndroid Build Coastguard Worker color = in_color;
4936*8975f5c5SAndroid Build Coastguard Worker })";
4937*8975f5c5SAndroid Build Coastguard Worker
4938*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] = R"(#version 310 es
4939*8975f5c5SAndroid Build Coastguard Worker precision highp float;
4940*8975f5c5SAndroid Build Coastguard Worker in vec4 color;
4941*8975f5c5SAndroid Build Coastguard Worker out vec4 frag_color;
4942*8975f5c5SAndroid Build Coastguard Worker void main(void) {
4943*8975f5c5SAndroid Build Coastguard Worker frag_color = color;
4944*8975f5c5SAndroid Build Coastguard Worker })";
4945*8975f5c5SAndroid Build Coastguard Worker swapBuffers();
4946*8975f5c5SAndroid Build Coastguard Worker
4947*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(program, kVS, kFS);
4948*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
4949*8975f5c5SAndroid Build Coastguard Worker GLint posLoc = glGetAttribLocation(program, "in_pos");
4950*8975f5c5SAndroid Build Coastguard Worker GLint colorLoc = glGetAttribLocation(program, "in_color");
4951*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(posLoc, -1);
4952*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(colorLoc, -1);
4953*8975f5c5SAndroid Build Coastguard Worker
4954*8975f5c5SAndroid Build Coastguard Worker const std::array<Vector3, 6> &quadVerts = GetQuadVertices();
4955*8975f5c5SAndroid Build Coastguard Worker // Data for packed attributes.
4956*8975f5c5SAndroid Build Coastguard Worker std::array<float, ((3 + 4) * 6)> data;
4957*8975f5c5SAndroid Build Coastguard Worker
4958*8975f5c5SAndroid Build Coastguard Worker float kYellow[4] = {1.0f, 1.0f, 0.0f, 1.0f};
4959*8975f5c5SAndroid Build Coastguard Worker float kGreen[4] = {0.0f, 1.0f, 0.0f, 1.0f};
4960*8975f5c5SAndroid Build Coastguard Worker
4961*8975f5c5SAndroid Build Coastguard Worker for (int i = 0; i < 6; i++)
4962*8975f5c5SAndroid Build Coastguard Worker {
4963*8975f5c5SAndroid Build Coastguard Worker memcpy(&data[i * (3 + 4)], &quadVerts[i], sizeof(Vector3));
4964*8975f5c5SAndroid Build Coastguard Worker memcpy(&data[i * (3 + 4) + 3], &kYellow, 4 * sizeof(float));
4965*8975f5c5SAndroid Build Coastguard Worker }
4966*8975f5c5SAndroid Build Coastguard Worker
4967*8975f5c5SAndroid Build Coastguard Worker {
4968*8975f5c5SAndroid Build Coastguard Worker GLBuffer buffer;
4969*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, buffer);
4970*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(data[0]), data.data(), GL_STATIC_DRAW);
4971*8975f5c5SAndroid Build Coastguard Worker
4972*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(posLoc);
4973*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(colorLoc);
4974*8975f5c5SAndroid Build Coastguard Worker
4975*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(posLoc, 3, GL_FLOAT, false, 28, reinterpret_cast<void *>(0));
4976*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(colorLoc, 4, GL_FLOAT, false, 28, reinterpret_cast<void *>(12));
4977*8975f5c5SAndroid Build Coastguard Worker
4978*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
4979*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::yellow);
4980*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
4981*8975f5c5SAndroid Build Coastguard Worker // Unbind before destroy.
4982*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
4983*8975f5c5SAndroid Build Coastguard Worker }
4984*8975f5c5SAndroid Build Coastguard Worker
4985*8975f5c5SAndroid Build Coastguard Worker // Modify color to green.
4986*8975f5c5SAndroid Build Coastguard Worker for (int i = 0; i < 6; i++)
4987*8975f5c5SAndroid Build Coastguard Worker {
4988*8975f5c5SAndroid Build Coastguard Worker memcpy(&data[i * (3 + 4) + 3], &kGreen, 4 * sizeof(float));
4989*8975f5c5SAndroid Build Coastguard Worker }
4990*8975f5c5SAndroid Build Coastguard Worker
4991*8975f5c5SAndroid Build Coastguard Worker // Provide client pointer.
4992*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(posLoc, 3, GL_FLOAT, false, 28, data.data());
4993*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(colorLoc, 4, GL_FLOAT, false, 28, &data[3]);
4994*8975f5c5SAndroid Build Coastguard Worker
4995*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
4996*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green);
4997*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
4998*8975f5c5SAndroid Build Coastguard Worker }
4999*8975f5c5SAndroid Build Coastguard Worker
5000*8975f5c5SAndroid Build Coastguard Worker // Create a vertex array with an empty array buffer and attribute offsets.
5001*8975f5c5SAndroid Build Coastguard Worker // This succeded in the end2end and capture/replay tests, but resulted in a trace
5002*8975f5c5SAndroid Build Coastguard Worker // producing a GL error when using MEC.
5003*8975f5c5SAndroid Build Coastguard Worker // Validation complained about the following:
5004*8975f5c5SAndroid Build Coastguard Worker // "Client data cannot be used with a non-default vertex array object."
5005*8975f5c5SAndroid Build Coastguard Worker
5006*8975f5c5SAndroid Build Coastguard Worker // To capture this test with MEC run:
5007*8975f5c5SAndroid Build Coastguard Worker // mkdir src/tests/capture_replay_tests/empty_array_buffer_test
5008*8975f5c5SAndroid Build Coastguard Worker // ANGLE_CAPTURE_ENABLED=1 ANGLE_CAPTURE_FRAME_START=2 \
5009*8975f5c5SAndroid Build Coastguard Worker // ANGLE_CAPTURE_FRAME_END=2 ANGLE_CAPTURE_LABEL=empty_array_buffer_test \
5010*8975f5c5SAndroid Build Coastguard Worker // ANGLE_CAPTURE_OUT_DIR=src/tests/capture_replay_tests/empty_array_buffer_test \
5011*8975f5c5SAndroid Build Coastguard Worker // ./out/Debug/angle_end2end_tests \
5012*8975f5c5SAndroid Build Coastguard Worker // --gtest_filter="VertexAttributeTestES3.EmptyArrayBuffer/ES3_Vulkan"
TEST_P(VertexAttributeTestES3,EmptyArrayBuffer)5013*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, EmptyArrayBuffer)
5014*8975f5c5SAndroid Build Coastguard Worker {
5015*8975f5c5SAndroid Build Coastguard Worker GLVertexArray vertexArray;
5016*8975f5c5SAndroid Build Coastguard Worker glBindVertexArray(vertexArray);
5017*8975f5c5SAndroid Build Coastguard Worker
5018*8975f5c5SAndroid Build Coastguard Worker GLBuffer emptyArrayBuffer;
5019*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, emptyArrayBuffer);
5020*8975f5c5SAndroid Build Coastguard Worker
5021*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(0);
5022*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(1);
5023*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(2);
5024*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_TRUE, 20, reinterpret_cast<const void *>(16));
5025*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 20, reinterpret_cast<const void *>(8));
5026*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 20, nullptr);
5027*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
5028*8975f5c5SAndroid Build Coastguard Worker
5029*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
5030*8975f5c5SAndroid Build Coastguard Worker glBindVertexArray(0);
5031*8975f5c5SAndroid Build Coastguard Worker
5032*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
5033*8975f5c5SAndroid Build Coastguard Worker
5034*8975f5c5SAndroid Build Coastguard Worker // Swap a frame for MEC
5035*8975f5c5SAndroid Build Coastguard Worker swapBuffers();
5036*8975f5c5SAndroid Build Coastguard Worker }
5037*8975f5c5SAndroid Build Coastguard Worker
5038*8975f5c5SAndroid Build Coastguard Worker // Set an attrib pointer and delete it's buffer after usage, while keeping the vertex array.
5039*8975f5c5SAndroid Build Coastguard Worker // This will cause MEC to capture an invalid attribute pointer and also trigger
5040*8975f5c5SAndroid Build Coastguard Worker // "Client data cannot be used with a non-default vertex array object."
TEST_P(VertexAttributeTestES3,InvalidAttribPointer)5041*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, InvalidAttribPointer)
5042*8975f5c5SAndroid Build Coastguard Worker {
5043*8975f5c5SAndroid Build Coastguard Worker GLVertexArray vertexArray;
5044*8975f5c5SAndroid Build Coastguard Worker glBindVertexArray(vertexArray);
5045*8975f5c5SAndroid Build Coastguard Worker
5046*8975f5c5SAndroid Build Coastguard Worker std::array<GLbyte, 12> vertexData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
5047*8975f5c5SAndroid Build Coastguard Worker
5048*8975f5c5SAndroid Build Coastguard Worker {
5049*8975f5c5SAndroid Build Coastguard Worker GLBuffer toBeDeletedArrayBuffer;
5050*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, toBeDeletedArrayBuffer);
5051*8975f5c5SAndroid Build Coastguard Worker
5052*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, vertexData.size(), vertexData.data(), GL_DYNAMIC_DRAW);
5053*8975f5c5SAndroid Build Coastguard Worker
5054*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(0);
5055*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(1);
5056*8975f5c5SAndroid Build Coastguard Worker
5057*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6, nullptr);
5058*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6, reinterpret_cast<const void *>(6));
5059*8975f5c5SAndroid Build Coastguard Worker
5060*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
5061*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(0);
5062*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(1);
5063*8975f5c5SAndroid Build Coastguard Worker
5064*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
5065*8975f5c5SAndroid Build Coastguard Worker }
5066*8975f5c5SAndroid Build Coastguard Worker
5067*8975f5c5SAndroid Build Coastguard Worker // Set an attrib pointer that will be actually picked up by MEC, since the buffer will be kept.
5068*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(0);
5069*8975f5c5SAndroid Build Coastguard Worker
5070*8975f5c5SAndroid Build Coastguard Worker GLBuffer arrayBuffer;
5071*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, arrayBuffer);
5072*8975f5c5SAndroid Build Coastguard Worker
5073*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, vertexData.size(), vertexData.data(), GL_DYNAMIC_DRAW);
5074*8975f5c5SAndroid Build Coastguard Worker
5075*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3, reinterpret_cast<const void *>(3));
5076*8975f5c5SAndroid Build Coastguard Worker
5077*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
5078*8975f5c5SAndroid Build Coastguard Worker
5079*8975f5c5SAndroid Build Coastguard Worker // Swap a frame for MEC
5080*8975f5c5SAndroid Build Coastguard Worker swapBuffers();
5081*8975f5c5SAndroid Build Coastguard Worker
5082*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, 0);
5083*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(0);
5084*8975f5c5SAndroid Build Coastguard Worker }
5085*8975f5c5SAndroid Build Coastguard Worker
5086*8975f5c5SAndroid Build Coastguard Worker // Test maxinum attribs full of Client buffers and then switch to mixed.
TEST_P(VertexAttributeTestES3,fullClientBuffersSwitchToMixed)5087*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, fullClientBuffersSwitchToMixed)
5088*8975f5c5SAndroid Build Coastguard Worker {
5089*8975f5c5SAndroid Build Coastguard Worker GLint maxAttribs;
5090*8975f5c5SAndroid Build Coastguard Worker glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs);
5091*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR();
5092*8975f5c5SAndroid Build Coastguard Worker
5093*8975f5c5SAndroid Build Coastguard Worker // Reserve one attrib for position
5094*8975f5c5SAndroid Build Coastguard Worker GLint drawAttribs = maxAttribs - 1;
5095*8975f5c5SAndroid Build Coastguard Worker
5096*8975f5c5SAndroid Build Coastguard Worker GLuint program = compileMultiAttribProgram(drawAttribs);
5097*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(0u, program);
5098*8975f5c5SAndroid Build Coastguard Worker
5099*8975f5c5SAndroid Build Coastguard Worker const std::array<Vector2, 4> kIndexedQuadVertices = {{
5100*8975f5c5SAndroid Build Coastguard Worker Vector2(-1.0f, 1.0f),
5101*8975f5c5SAndroid Build Coastguard Worker Vector2(-1.0f, -1.0f),
5102*8975f5c5SAndroid Build Coastguard Worker Vector2(1.0f, -1.0f),
5103*8975f5c5SAndroid Build Coastguard Worker Vector2(1.0f, 1.0f),
5104*8975f5c5SAndroid Build Coastguard Worker }};
5105*8975f5c5SAndroid Build Coastguard Worker
5106*8975f5c5SAndroid Build Coastguard Worker GLsizei stride = (maxAttribs + 1) * sizeof(GLfloat);
5107*8975f5c5SAndroid Build Coastguard Worker
5108*8975f5c5SAndroid Build Coastguard Worker constexpr std::array<GLushort, 6> kIndexedQuadIndices = {{0, 1, 2, 0, 2, 3}};
5109*8975f5c5SAndroid Build Coastguard Worker GLuint indexBuffer = 0;
5110*8975f5c5SAndroid Build Coastguard Worker glGenBuffers(1, &indexBuffer);
5111*8975f5c5SAndroid Build Coastguard Worker
5112*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
5113*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kIndexedQuadIndices), kIndexedQuadIndices.data(),
5114*8975f5c5SAndroid Build Coastguard Worker GL_STATIC_DRAW);
5115*8975f5c5SAndroid Build Coastguard Worker
5116*8975f5c5SAndroid Build Coastguard Worker // Vertex drawAttribs color attributes plus position (x, y).
5117*8975f5c5SAndroid Build Coastguard Worker GLint totalComponents = drawAttribs + 2;
5118*8975f5c5SAndroid Build Coastguard Worker std::vector<GLfloat> vertexData(totalComponents * 4, 0.0f);
5119*8975f5c5SAndroid Build Coastguard Worker for (GLint index = 0; index < 4; ++index)
5120*8975f5c5SAndroid Build Coastguard Worker {
5121*8975f5c5SAndroid Build Coastguard Worker vertexData[index * totalComponents + drawAttribs] = kIndexedQuadVertices[index].x();
5122*8975f5c5SAndroid Build Coastguard Worker vertexData[index * totalComponents + drawAttribs + 1] = kIndexedQuadVertices[index].y();
5123*8975f5c5SAndroid Build Coastguard Worker }
5124*8975f5c5SAndroid Build Coastguard Worker
5125*8975f5c5SAndroid Build Coastguard Worker GLfloat attributeValue = 0.0f;
5126*8975f5c5SAndroid Build Coastguard Worker GLfloat delta = 1.0f / 256.0f;
5127*8975f5c5SAndroid Build Coastguard Worker for (GLint attribIndex = 0; attribIndex < drawAttribs; ++attribIndex)
5128*8975f5c5SAndroid Build Coastguard Worker {
5129*8975f5c5SAndroid Build Coastguard Worker vertexData[attribIndex] = attributeValue;
5130*8975f5c5SAndroid Build Coastguard Worker vertexData[attribIndex + totalComponents] = attributeValue;
5131*8975f5c5SAndroid Build Coastguard Worker vertexData[attribIndex + totalComponents * 2] = attributeValue;
5132*8975f5c5SAndroid Build Coastguard Worker vertexData[attribIndex + totalComponents * 3] = attributeValue;
5133*8975f5c5SAndroid Build Coastguard Worker attributeValue += delta;
5134*8975f5c5SAndroid Build Coastguard Worker }
5135*8975f5c5SAndroid Build Coastguard Worker
5136*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
5137*8975f5c5SAndroid Build Coastguard Worker for (GLint attribIndex = 0; attribIndex < drawAttribs; ++attribIndex)
5138*8975f5c5SAndroid Build Coastguard Worker {
5139*8975f5c5SAndroid Build Coastguard Worker std::stringstream attribStream;
5140*8975f5c5SAndroid Build Coastguard Worker attribStream << "a" << attribIndex;
5141*8975f5c5SAndroid Build Coastguard Worker GLint location = glGetAttribLocation(program, attribStream.str().c_str());
5142*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, location);
5143*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(location, 1, GL_FLOAT, GL_FALSE, stride,
5144*8975f5c5SAndroid Build Coastguard Worker vertexData.data() + attribIndex);
5145*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(location);
5146*8975f5c5SAndroid Build Coastguard Worker }
5147*8975f5c5SAndroid Build Coastguard Worker GLint posLoc = glGetAttribLocation(program, "position");
5148*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, posLoc);
5149*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(posLoc);
5150*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, stride, vertexData.data() + drawAttribs);
5151*8975f5c5SAndroid Build Coastguard Worker glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
5152*8975f5c5SAndroid Build Coastguard Worker
5153*8975f5c5SAndroid Build Coastguard Worker // the result color should be (0 + 1 + 2 + ... + 14)/256 * 255;
5154*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
5155*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_NEAR(0, 0, 105, 0, 0, 255, 1);
5156*8975f5c5SAndroid Build Coastguard Worker
5157*8975f5c5SAndroid Build Coastguard Worker // disable a few attribute use default attribute color
5158*8975f5c5SAndroid Build Coastguard Worker GLint l0 = glGetAttribLocation(program, "a0");
5159*8975f5c5SAndroid Build Coastguard Worker GLint l5 = glGetAttribLocation(program, "a5");
5160*8975f5c5SAndroid Build Coastguard Worker GLint l13 = glGetAttribLocation(program, "a13");
5161*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(l0);
5162*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib1f(l0, 1.0f / 16.0f);
5163*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(l5);
5164*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib1f(l5, 1.0f / 16.0f);
5165*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(l13);
5166*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib1f(l13, 1.0f / 16.0f);
5167*8975f5c5SAndroid Build Coastguard Worker
5168*8975f5c5SAndroid Build Coastguard Worker glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
5169*8975f5c5SAndroid Build Coastguard Worker
5170*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
5171*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_NEAR(0, 0, 134, 0, 0, 255, 1);
5172*8975f5c5SAndroid Build Coastguard Worker
5173*8975f5c5SAndroid Build Coastguard Worker // disable all the client buffers.
5174*8975f5c5SAndroid Build Coastguard Worker for (GLint attribIndex = 0; attribIndex < drawAttribs; ++attribIndex)
5175*8975f5c5SAndroid Build Coastguard Worker {
5176*8975f5c5SAndroid Build Coastguard Worker std::stringstream attribStream;
5177*8975f5c5SAndroid Build Coastguard Worker attribStream << "a" << attribIndex;
5178*8975f5c5SAndroid Build Coastguard Worker GLint location = glGetAttribLocation(program, attribStream.str().c_str());
5179*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, location);
5180*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(location);
5181*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib1f(location, 1.0f / 16.0f);
5182*8975f5c5SAndroid Build Coastguard Worker }
5183*8975f5c5SAndroid Build Coastguard Worker
5184*8975f5c5SAndroid Build Coastguard Worker glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
5185*8975f5c5SAndroid Build Coastguard Worker
5186*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
5187*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_NEAR(0, 0, 239, 0, 0, 255, 1);
5188*8975f5c5SAndroid Build Coastguard Worker
5189*8975f5c5SAndroid Build Coastguard Worker // enable all the client buffers.
5190*8975f5c5SAndroid Build Coastguard Worker for (GLint attribIndex = 0; attribIndex < drawAttribs; ++attribIndex)
5191*8975f5c5SAndroid Build Coastguard Worker {
5192*8975f5c5SAndroid Build Coastguard Worker std::stringstream attribStream;
5193*8975f5c5SAndroid Build Coastguard Worker attribStream << "a" << attribIndex;
5194*8975f5c5SAndroid Build Coastguard Worker GLint location = glGetAttribLocation(program, attribStream.str().c_str());
5195*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, location);
5196*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(location, 1, GL_FLOAT, GL_FALSE, stride,
5197*8975f5c5SAndroid Build Coastguard Worker vertexData.data() + attribIndex);
5198*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(location);
5199*8975f5c5SAndroid Build Coastguard Worker }
5200*8975f5c5SAndroid Build Coastguard Worker glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr);
5201*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
5202*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_NEAR(0, 0, 105, 0, 0, 255, 1);
5203*8975f5c5SAndroid Build Coastguard Worker }
5204*8975f5c5SAndroid Build Coastguard Worker
5205*8975f5c5SAndroid Build Coastguard Worker // Test bind an empty buffer for vertex attribute does not crash
TEST_P(VertexAttributeTestES3,emptyBuffer)5206*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, emptyBuffer)
5207*8975f5c5SAndroid Build Coastguard Worker {
5208*8975f5c5SAndroid Build Coastguard Worker constexpr char vs2[] =
5209*8975f5c5SAndroid Build Coastguard Worker R"(#version 300 es
5210*8975f5c5SAndroid Build Coastguard Worker in uvec4 attr0;
5211*8975f5c5SAndroid Build Coastguard Worker void main()
5212*8975f5c5SAndroid Build Coastguard Worker {
5213*8975f5c5SAndroid Build Coastguard Worker gl_Position = vec4(attr0.x, 0.0, 0.0, 0.0);
5214*8975f5c5SAndroid Build Coastguard Worker })";
5215*8975f5c5SAndroid Build Coastguard Worker constexpr char fs[] =
5216*8975f5c5SAndroid Build Coastguard Worker R"(#version 300 es
5217*8975f5c5SAndroid Build Coastguard Worker precision highp float;
5218*8975f5c5SAndroid Build Coastguard Worker out vec4 color;
5219*8975f5c5SAndroid Build Coastguard Worker void main()
5220*8975f5c5SAndroid Build Coastguard Worker {
5221*8975f5c5SAndroid Build Coastguard Worker color = vec4(1.0, 0.0, 0.0, 1.0);
5222*8975f5c5SAndroid Build Coastguard Worker })";
5223*8975f5c5SAndroid Build Coastguard Worker GLuint program2 = CompileProgram(vs2, fs);
5224*8975f5c5SAndroid Build Coastguard Worker GLBuffer buf;
5225*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, buf);
5226*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(0);
5227*8975f5c5SAndroid Build Coastguard Worker glVertexAttribIPointer(0, 4, GL_UNSIGNED_BYTE, 0, 0);
5228*8975f5c5SAndroid Build Coastguard Worker glVertexAttribDivisor(0, 2);
5229*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program2);
5230*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_POINTS, 0, 1);
5231*8975f5c5SAndroid Build Coastguard Worker
5232*8975f5c5SAndroid Build Coastguard Worker swapBuffers();
5233*8975f5c5SAndroid Build Coastguard Worker }
5234*8975f5c5SAndroid Build Coastguard Worker
5235*8975f5c5SAndroid Build Coastguard Worker // This is a test for use with ANGLE's Capture/Replay.
5236*8975f5c5SAndroid Build Coastguard Worker // It emulates a situation we see in some apps, where attribs are passed in but may not be used.
5237*8975f5c5SAndroid Build Coastguard Worker // In particular, that test asks for all active attributes and iterates through each one. Before any
5238*8975f5c5SAndroid Build Coastguard Worker // changes to FrameCapture, this will create calls that look up attributes that are considered
5239*8975f5c5SAndroid Build Coastguard Worker // unused on some platforms, making the trace non-portable. Whether they are used depends on how
5240*8975f5c5SAndroid Build Coastguard Worker // well the stack optimizes the shader pipeline. In this instance, we are just passing them across
5241*8975f5c5SAndroid Build Coastguard Worker // the pipeline boundary where they are dead in the fragment shader, but other cases have included
5242*8975f5c5SAndroid Build Coastguard Worker // attributes passed to empty functions, or some eliminated with math. The more optimizations
5243*8975f5c5SAndroid Build Coastguard Worker // applied by the driver, the higher chance of getting an unused attribute.
TEST_P(VertexAttributeTestES3,UnusedAttribsMEC)5244*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, UnusedAttribsMEC)
5245*8975f5c5SAndroid Build Coastguard Worker {
5246*8975f5c5SAndroid Build Coastguard Worker constexpr char vertexShader[] =
5247*8975f5c5SAndroid Build Coastguard Worker R"(#version 300 es
5248*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
5249*8975f5c5SAndroid Build Coastguard Worker in vec4 position;
5250*8975f5c5SAndroid Build Coastguard Worker in vec4 input_unused;
5251*8975f5c5SAndroid Build Coastguard Worker out vec4 passthrough;
5252*8975f5c5SAndroid Build Coastguard Worker void main()
5253*8975f5c5SAndroid Build Coastguard Worker {
5254*8975f5c5SAndroid Build Coastguard Worker passthrough = input_unused;
5255*8975f5c5SAndroid Build Coastguard Worker gl_Position = position;
5256*8975f5c5SAndroid Build Coastguard Worker })";
5257*8975f5c5SAndroid Build Coastguard Worker
5258*8975f5c5SAndroid Build Coastguard Worker constexpr char fragmentShader[] =
5259*8975f5c5SAndroid Build Coastguard Worker R"(#version 300 es
5260*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
5261*8975f5c5SAndroid Build Coastguard Worker in vec4 passthrough;
5262*8975f5c5SAndroid Build Coastguard Worker out vec4 color;
5263*8975f5c5SAndroid Build Coastguard Worker void main()
5264*8975f5c5SAndroid Build Coastguard Worker {
5265*8975f5c5SAndroid Build Coastguard Worker // ignore passthrough - this makes it unused with cross stage optimizations
5266*8975f5c5SAndroid Build Coastguard Worker color = vec4(1.0);
5267*8975f5c5SAndroid Build Coastguard Worker })";
5268*8975f5c5SAndroid Build Coastguard Worker
5269*8975f5c5SAndroid Build Coastguard Worker GLuint program = CompileProgram(vertexShader, fragmentShader);
5270*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
5271*8975f5c5SAndroid Build Coastguard Worker
5272*8975f5c5SAndroid Build Coastguard Worker // Set up vertex data
5273*8975f5c5SAndroid Build Coastguard Worker GLBuffer positionBuffer;
5274*8975f5c5SAndroid Build Coastguard Worker const std::array<Vector3, 6> &quadVerts = GetQuadVertices();
5275*8975f5c5SAndroid Build Coastguard Worker glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
5276*8975f5c5SAndroid Build Coastguard Worker glBufferData(GL_ARRAY_BUFFER, quadVerts.size() * sizeof(quadVerts[0]), quadVerts.data(),
5277*8975f5c5SAndroid Build Coastguard Worker GL_STATIC_DRAW);
5278*8975f5c5SAndroid Build Coastguard Worker
5279*8975f5c5SAndroid Build Coastguard Worker // Loop through a sequence multiple times, so MEC can capture it.
5280*8975f5c5SAndroid Build Coastguard Worker // Ask about vertex attribs and set them up, regardless of whether they are used.
5281*8975f5c5SAndroid Build Coastguard Worker // This matches behavior seen in some apps.
5282*8975f5c5SAndroid Build Coastguard Worker for (int i = 0; i < 10; i++)
5283*8975f5c5SAndroid Build Coastguard Worker {
5284*8975f5c5SAndroid Build Coastguard Worker // Look up the number of attribs
5285*8975f5c5SAndroid Build Coastguard Worker GLint activeAttribCount = 0;
5286*8975f5c5SAndroid Build Coastguard Worker glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &activeAttribCount);
5287*8975f5c5SAndroid Build Coastguard Worker
5288*8975f5c5SAndroid Build Coastguard Worker // Look up how big they might get
5289*8975f5c5SAndroid Build Coastguard Worker GLint maxActiveAttribLength = 0;
5290*8975f5c5SAndroid Build Coastguard Worker glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxActiveAttribLength);
5291*8975f5c5SAndroid Build Coastguard Worker
5292*8975f5c5SAndroid Build Coastguard Worker GLsizei attribLength = 0;
5293*8975f5c5SAndroid Build Coastguard Worker GLint attribSize = 0;
5294*8975f5c5SAndroid Build Coastguard Worker GLenum attribType = 0;
5295*8975f5c5SAndroid Build Coastguard Worker GLchar attribName[16] = {0};
5296*8975f5c5SAndroid Build Coastguard Worker ASSERT(maxActiveAttribLength < 16);
5297*8975f5c5SAndroid Build Coastguard Worker
5298*8975f5c5SAndroid Build Coastguard Worker // Look up each attribute and set them up
5299*8975f5c5SAndroid Build Coastguard Worker for (int j = 0; j < activeAttribCount; j++)
5300*8975f5c5SAndroid Build Coastguard Worker {
5301*8975f5c5SAndroid Build Coastguard Worker glGetActiveAttrib(program, j, maxActiveAttribLength, &attribLength, &attribSize,
5302*8975f5c5SAndroid Build Coastguard Worker &attribType, attribName);
5303*8975f5c5SAndroid Build Coastguard Worker GLint posLoc = glGetAttribLocation(program, attribName);
5304*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(posLoc, -1);
5305*8975f5c5SAndroid Build Coastguard Worker glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, j, nullptr);
5306*8975f5c5SAndroid Build Coastguard Worker glEnableVertexAttribArray(posLoc);
5307*8975f5c5SAndroid Build Coastguard Worker }
5308*8975f5c5SAndroid Build Coastguard Worker
5309*8975f5c5SAndroid Build Coastguard Worker // Draw and swap on each loop to trigger MEC
5310*8975f5c5SAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLES, 0, 6);
5311*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::white);
5312*8975f5c5SAndroid Build Coastguard Worker swapBuffers();
5313*8975f5c5SAndroid Build Coastguard Worker }
5314*8975f5c5SAndroid Build Coastguard Worker }
5315*8975f5c5SAndroid Build Coastguard Worker
5316*8975f5c5SAndroid Build Coastguard Worker // Test that a particular vertex attribute naming does not affect the functionality.
5317*8975f5c5SAndroid Build Coastguard Worker // Tests the vertex attrib aliasing part. Note that aliasing works with es 100 shaders.
TEST_P(VertexAttributeTest,AliasingAttribNaming)5318*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTest, AliasingAttribNaming)
5319*8975f5c5SAndroid Build Coastguard Worker {
5320*8975f5c5SAndroid Build Coastguard Worker // http://anglebug.com/42263740
5321*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
5322*8975f5c5SAndroid Build Coastguard Worker
5323*8975f5c5SAndroid Build Coastguard Worker // http://anglebug.com/42262130
5324*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
5325*8975f5c5SAndroid Build Coastguard Worker
5326*8975f5c5SAndroid Build Coastguard Worker // http://anglebug.com/42262131
5327*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsD3D());
5328*8975f5c5SAndroid Build Coastguard Worker
5329*8975f5c5SAndroid Build Coastguard Worker // This test needs 16 total attributes. All backends support this except some old Android
5330*8975f5c5SAndroid Build Coastguard Worker // devices.
5331*8975f5c5SAndroid Build Coastguard Worker GLint maxVertexAttribs = 0;
5332*8975f5c5SAndroid Build Coastguard Worker glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
5333*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(maxVertexAttribs < 16);
5334*8975f5c5SAndroid Build Coastguard Worker
5335*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] = R"(attribute vec4 position;
5336*8975f5c5SAndroid Build Coastguard Worker // attributes aliasing location 0 and above
5337*8975f5c5SAndroid Build Coastguard Worker attribute mat3 a;
5338*8975f5c5SAndroid Build Coastguard Worker attribute mat2 a_;
5339*8975f5c5SAndroid Build Coastguard Worker
5340*8975f5c5SAndroid Build Coastguard Worker // attributes aliasing location 1 and above
5341*8975f5c5SAndroid Build Coastguard Worker attribute vec4 a_1;
5342*8975f5c5SAndroid Build Coastguard Worker
5343*8975f5c5SAndroid Build Coastguard Worker // attributes aliasing location 2 and above
5344*8975f5c5SAndroid Build Coastguard Worker attribute mat4 a_0;
5345*8975f5c5SAndroid Build Coastguard Worker
5346*8975f5c5SAndroid Build Coastguard Worker // In summary:
5347*8975f5c5SAndroid Build Coastguard Worker //
5348*8975f5c5SAndroid Build Coastguard Worker // location 0: a[0] a_[0]
5349*8975f5c5SAndroid Build Coastguard Worker // location 1: a[1] a_[1] a_1
5350*8975f5c5SAndroid Build Coastguard Worker // location 2: a[2] a_0[0]
5351*8975f5c5SAndroid Build Coastguard Worker // location 3: a_0[1] (untested)
5352*8975f5c5SAndroid Build Coastguard Worker // location 4: a_0[2] (untested)
5353*8975f5c5SAndroid Build Coastguard Worker // location 5: a_0[3] (untested)
5354*8975f5c5SAndroid Build Coastguard Worker
5355*8975f5c5SAndroid Build Coastguard Worker const vec3 loc0Expected = vec3(0.05, 0.1, 0.15);
5356*8975f5c5SAndroid Build Coastguard Worker const vec4 loc1Expected = vec4(0.2, 0.25, 0.3, 0.35);
5357*8975f5c5SAndroid Build Coastguard Worker const vec4 loc2Expected = vec4(0.4, 0.45, 0.5, 0.55);
5358*8975f5c5SAndroid Build Coastguard Worker
5359*8975f5c5SAndroid Build Coastguard Worker uniform float loc0Select;
5360*8975f5c5SAndroid Build Coastguard Worker uniform float loc1Select;
5361*8975f5c5SAndroid Build Coastguard Worker uniform float loc2Select;
5362*8975f5c5SAndroid Build Coastguard Worker
5363*8975f5c5SAndroid Build Coastguard Worker // Each channel controlled by success from each set of aliasing locations. If a channel is 0,
5364*8975f5c5SAndroid Build Coastguard Worker // the attribute test has failed. Otherwise it will be 1/N, 2/N, ..., 1, depending on how many
5365*8975f5c5SAndroid Build Coastguard Worker // possible values there are for the controlling uniforms.
5366*8975f5c5SAndroid Build Coastguard Worker varying mediump vec4 color;
5367*8975f5c5SAndroid Build Coastguard Worker void main()
5368*8975f5c5SAndroid Build Coastguard Worker {
5369*8975f5c5SAndroid Build Coastguard Worker gl_Position = position;
5370*8975f5c5SAndroid Build Coastguard Worker
5371*8975f5c5SAndroid Build Coastguard Worker vec4 result = vec4(0);
5372*8975f5c5SAndroid Build Coastguard Worker
5373*8975f5c5SAndroid Build Coastguard Worker if (loc0Select < 0.5)
5374*8975f5c5SAndroid Build Coastguard Worker result.r = all(lessThan(abs(a[0] - loc0Expected.xyz), vec3(0.01))) ? 0.5 : 0.0;
5375*8975f5c5SAndroid Build Coastguard Worker else
5376*8975f5c5SAndroid Build Coastguard Worker result.r = all(lessThan(abs(a_[0] - loc0Expected.xy), vec2(0.01))) ? 1.0 : 0.0;
5377*8975f5c5SAndroid Build Coastguard Worker
5378*8975f5c5SAndroid Build Coastguard Worker if (loc1Select < 0.5)
5379*8975f5c5SAndroid Build Coastguard Worker result.g = all(lessThan(abs(a[1] - loc1Expected.xyz), vec3(0.01))) ? 0.333333 : 0.0;
5380*8975f5c5SAndroid Build Coastguard Worker else if (loc1Select < 1.5)
5381*8975f5c5SAndroid Build Coastguard Worker result.g = all(lessThan(abs(a_[1] - loc1Expected.xy), vec2(0.01))) ? 0.666667 : 0.0;
5382*8975f5c5SAndroid Build Coastguard Worker else
5383*8975f5c5SAndroid Build Coastguard Worker result.g = all(lessThan(abs(a_1 - loc1Expected), vec4(0.01))) ? 1.0 : 0.0;
5384*8975f5c5SAndroid Build Coastguard Worker
5385*8975f5c5SAndroid Build Coastguard Worker if (loc2Select < 0.5)
5386*8975f5c5SAndroid Build Coastguard Worker result.b = all(lessThan(abs(a[2] - loc2Expected.xyz), vec3(0.01))) ? 0.5 : 0.0;
5387*8975f5c5SAndroid Build Coastguard Worker else
5388*8975f5c5SAndroid Build Coastguard Worker result.b = all(lessThan(abs(a_0[0] - loc2Expected), vec4(0.01))) ? 1.0 : 0.0;
5389*8975f5c5SAndroid Build Coastguard Worker result.a = 1.0;
5390*8975f5c5SAndroid Build Coastguard Worker color = result;
5391*8975f5c5SAndroid Build Coastguard Worker })";
5392*8975f5c5SAndroid Build Coastguard Worker
5393*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] = R"(varying mediump vec4 color;
5394*8975f5c5SAndroid Build Coastguard Worker void main(void)
5395*8975f5c5SAndroid Build Coastguard Worker {
5396*8975f5c5SAndroid Build Coastguard Worker gl_FragColor = color;
5397*8975f5c5SAndroid Build Coastguard Worker })";
5398*8975f5c5SAndroid Build Coastguard Worker
5399*8975f5c5SAndroid Build Coastguard Worker // Compile shaders.
5400*8975f5c5SAndroid Build Coastguard Worker GLuint program = CompileProgram(kVS, kFS);
5401*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(program, 0u);
5402*8975f5c5SAndroid Build Coastguard Worker
5403*8975f5c5SAndroid Build Coastguard Worker // Setup bindings.
5404*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 0, "a");
5405*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 0, "a_");
5406*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 1, "a_1");
5407*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 2, "a_0");
5408*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
5409*8975f5c5SAndroid Build Coastguard Worker
5410*8975f5c5SAndroid Build Coastguard Worker // Link program and get uniform locations.
5411*8975f5c5SAndroid Build Coastguard Worker glLinkProgram(program);
5412*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
5413*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
5414*8975f5c5SAndroid Build Coastguard Worker
5415*8975f5c5SAndroid Build Coastguard Worker GLint loc0SelectLoc = glGetUniformLocation(program, "loc0Select");
5416*8975f5c5SAndroid Build Coastguard Worker GLint loc1SelectLoc = glGetUniformLocation(program, "loc1Select");
5417*8975f5c5SAndroid Build Coastguard Worker GLint loc2SelectLoc = glGetUniformLocation(program, "loc2Select");
5418*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, loc0SelectLoc);
5419*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, loc1SelectLoc);
5420*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(-1, loc2SelectLoc);
5421*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
5422*8975f5c5SAndroid Build Coastguard Worker
5423*8975f5c5SAndroid Build Coastguard Worker // Set values for attributes.
5424*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib3f(0, 0.05, 0.1, 0.15);
5425*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib4f(1, 0.2, 0.25, 0.3, 0.35);
5426*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib4f(2, 0.4, 0.45, 0.5, 0.55);
5427*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(0);
5428*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(1);
5429*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(2);
5430*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
5431*8975f5c5SAndroid Build Coastguard Worker
5432*8975f5c5SAndroid Build Coastguard Worker // Go through different combination of attributes and make sure reading through every alias is
5433*8975f5c5SAndroid Build Coastguard Worker // correctly handled.
5434*8975f5c5SAndroid Build Coastguard Worker GLColor expected;
5435*8975f5c5SAndroid Build Coastguard Worker expected.A = 255;
5436*8975f5c5SAndroid Build Coastguard Worker for (uint32_t loc0Select = 0; loc0Select < 2; ++loc0Select)
5437*8975f5c5SAndroid Build Coastguard Worker {
5438*8975f5c5SAndroid Build Coastguard Worker glUniform1f(loc0SelectLoc, loc0Select);
5439*8975f5c5SAndroid Build Coastguard Worker expected.R = loc0Select * 127 + 127;
5440*8975f5c5SAndroid Build Coastguard Worker
5441*8975f5c5SAndroid Build Coastguard Worker for (uint32_t loc1Select = 0; loc1Select < 3; ++loc1Select)
5442*8975f5c5SAndroid Build Coastguard Worker {
5443*8975f5c5SAndroid Build Coastguard Worker glUniform1f(loc1SelectLoc, loc1Select);
5444*8975f5c5SAndroid Build Coastguard Worker expected.G = loc1Select * 85 + 85;
5445*8975f5c5SAndroid Build Coastguard Worker
5446*8975f5c5SAndroid Build Coastguard Worker for (uint32_t loc2Select = 0; loc2Select < 2; ++loc2Select)
5447*8975f5c5SAndroid Build Coastguard Worker {
5448*8975f5c5SAndroid Build Coastguard Worker glUniform1f(loc2SelectLoc, loc2Select);
5449*8975f5c5SAndroid Build Coastguard Worker expected.B = loc2Select * 127 + 127;
5450*8975f5c5SAndroid Build Coastguard Worker drawQuad(program, "position", 0.5f);
5451*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
5452*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_NEAR(0, 0, expected, 1);
5453*8975f5c5SAndroid Build Coastguard Worker }
5454*8975f5c5SAndroid Build Coastguard Worker }
5455*8975f5c5SAndroid Build Coastguard Worker }
5456*8975f5c5SAndroid Build Coastguard Worker }
5457*8975f5c5SAndroid Build Coastguard Worker
5458*8975f5c5SAndroid Build Coastguard Worker // Test that a particular vertex attribute naming does not affect the functionality.
TEST_P(VertexAttributeTestES3,AttribNaming)5459*8975f5c5SAndroid Build Coastguard Worker TEST_P(VertexAttributeTestES3, AttribNaming)
5460*8975f5c5SAndroid Build Coastguard Worker {
5461*8975f5c5SAndroid Build Coastguard Worker // http://anglebug.com/42263740
5462*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL());
5463*8975f5c5SAndroid Build Coastguard Worker
5464*8975f5c5SAndroid Build Coastguard Worker // http://anglebug.com/42262130
5465*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsMac() && IsOpenGL());
5466*8975f5c5SAndroid Build Coastguard Worker
5467*8975f5c5SAndroid Build Coastguard Worker // http://anglebug.com/42262131
5468*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(IsD3D());
5469*8975f5c5SAndroid Build Coastguard Worker
5470*8975f5c5SAndroid Build Coastguard Worker // This test needs roughly 16 total attributes. All backends support this except some old
5471*8975f5c5SAndroid Build Coastguard Worker // Android devices.
5472*8975f5c5SAndroid Build Coastguard Worker GLint maxVertexAttribs = 0;
5473*8975f5c5SAndroid Build Coastguard Worker glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
5474*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(maxVertexAttribs < 16);
5475*8975f5c5SAndroid Build Coastguard Worker
5476*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] = R"(#version 300 es
5477*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
5478*8975f5c5SAndroid Build Coastguard Worker in vec4 position;
5479*8975f5c5SAndroid Build Coastguard Worker in mat3 a;
5480*8975f5c5SAndroid Build Coastguard Worker in mat2 a_;
5481*8975f5c5SAndroid Build Coastguard Worker in vec4 a_1;
5482*8975f5c5SAndroid Build Coastguard Worker in vec4 a_0;
5483*8975f5c5SAndroid Build Coastguard Worker const mat3 aExpected = mat3(0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8);
5484*8975f5c5SAndroid Build Coastguard Worker const mat2 a_Expected = mat2(1.0, 1.1, 1.2, 1.3);
5485*8975f5c5SAndroid Build Coastguard Worker const vec4 a_1Expected = vec4(2.0, 2.1, 2.2, 2.3);
5486*8975f5c5SAndroid Build Coastguard Worker const vec4 a_0Expected = vec4(3.0, 3.1, 3.2, 3.3);
5487*8975f5c5SAndroid Build Coastguard Worker out mediump vec4 color;
5488*8975f5c5SAndroid Build Coastguard Worker void main()
5489*8975f5c5SAndroid Build Coastguard Worker {
5490*8975f5c5SAndroid Build Coastguard Worker gl_Position = position;
5491*8975f5c5SAndroid Build Coastguard Worker
5492*8975f5c5SAndroid Build Coastguard Worker vec4 result = vec4(0);
5493*8975f5c5SAndroid Build Coastguard Worker mat3 diff3 = a - aExpected;
5494*8975f5c5SAndroid Build Coastguard Worker result.r = all(lessThan(abs(diff3[0]) + abs(diff3[1]) + abs(diff3[2]), vec3(0.01))) ? 1.0 : 0.0;
5495*8975f5c5SAndroid Build Coastguard Worker mat2 diff2 = a_ - a_Expected;
5496*8975f5c5SAndroid Build Coastguard Worker result.g = all(lessThan(abs(diff2[0]) + abs(diff2[1]), vec2(0.01))) ? 1.0 : 0.0;
5497*8975f5c5SAndroid Build Coastguard Worker result.b = all(lessThan(abs(a_1 - a_1Expected), vec4(0.01))) ? 1.0 : 0.0;
5498*8975f5c5SAndroid Build Coastguard Worker result.a = all(lessThan(abs(a_0 - a_0Expected), vec4(0.01))) ? 1.0 : 0.0;
5499*8975f5c5SAndroid Build Coastguard Worker color = result;
5500*8975f5c5SAndroid Build Coastguard Worker })";
5501*8975f5c5SAndroid Build Coastguard Worker
5502*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] = R"(#version 300 es
5503*8975f5c5SAndroid Build Coastguard Worker in mediump vec4 color;
5504*8975f5c5SAndroid Build Coastguard Worker out mediump vec4 fragColor;
5505*8975f5c5SAndroid Build Coastguard Worker void main(void)
5506*8975f5c5SAndroid Build Coastguard Worker {
5507*8975f5c5SAndroid Build Coastguard Worker fragColor = color;
5508*8975f5c5SAndroid Build Coastguard Worker })";
5509*8975f5c5SAndroid Build Coastguard Worker
5510*8975f5c5SAndroid Build Coastguard Worker GLuint program = CompileProgram(kVS, kFS);
5511*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(program, 0u);
5512*8975f5c5SAndroid Build Coastguard Worker
5513*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 0, "a");
5514*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 4, "a_");
5515*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 6, "a_1");
5516*8975f5c5SAndroid Build Coastguard Worker glBindAttribLocation(program, 7, "a_0");
5517*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
5518*8975f5c5SAndroid Build Coastguard Worker
5519*8975f5c5SAndroid Build Coastguard Worker glLinkProgram(program);
5520*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program);
5521*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
5522*8975f5c5SAndroid Build Coastguard Worker
5523*8975f5c5SAndroid Build Coastguard Worker // Set values for attributes.
5524*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib3f(0, 0.0, 0.1, 0.2);
5525*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib3f(1, 0.3, 0.4, 0.5);
5526*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib3f(2, 0.6, 0.7, 0.8);
5527*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib2f(4, 1.0, 1.1);
5528*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib2f(5, 1.2, 1.3);
5529*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib4f(6, 2.0, 2.1, 2.2, 2.3);
5530*8975f5c5SAndroid Build Coastguard Worker glVertexAttrib4f(7, 3.0, 3.1, 3.2, 3.3);
5531*8975f5c5SAndroid Build Coastguard Worker
5532*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(0);
5533*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(1);
5534*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(2);
5535*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(3);
5536*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(4);
5537*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(5);
5538*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(6);
5539*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(7);
5540*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(8);
5541*8975f5c5SAndroid Build Coastguard Worker glDisableVertexAttribArray(9);
5542*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
5543*8975f5c5SAndroid Build Coastguard Worker
5544*8975f5c5SAndroid Build Coastguard Worker // Go through different combination of attributes and make sure reading through every alias is
5545*8975f5c5SAndroid Build Coastguard Worker // correctly handled.
5546*8975f5c5SAndroid Build Coastguard Worker GLColor expected{255, 255, 255, 255};
5547*8975f5c5SAndroid Build Coastguard Worker drawQuad(program, "position", 0.5f);
5548*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR();
5549*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_NEAR(0, 0, expected, 1);
5550*8975f5c5SAndroid Build Coastguard Worker }
5551*8975f5c5SAndroid Build Coastguard Worker
5552*8975f5c5SAndroid Build Coastguard Worker // VAO emulation fails on Mac but is not used on Mac in the wild. http://anglebug.com/40096758
5553*8975f5c5SAndroid Build Coastguard Worker #if !defined(__APPLE__)
5554*8975f5c5SAndroid Build Coastguard Worker # define EMULATED_VAO_CONFIGS \
5555*8975f5c5SAndroid Build Coastguard Worker ES2_OPENGL().enable(Feature::SyncAllVertexArraysToDefault), \
5556*8975f5c5SAndroid Build Coastguard Worker ES2_OPENGLES().enable(Feature::SyncAllVertexArraysToDefault), \
5557*8975f5c5SAndroid Build Coastguard Worker ES3_OPENGL().enable(Feature::SyncAllVertexArraysToDefault), \
5558*8975f5c5SAndroid Build Coastguard Worker ES3_OPENGLES().enable(Feature::SyncAllVertexArraysToDefault),
5559*8975f5c5SAndroid Build Coastguard Worker #else
5560*8975f5c5SAndroid Build Coastguard Worker # define EMULATED_VAO_CONFIGS
5561*8975f5c5SAndroid Build Coastguard Worker #endif
5562*8975f5c5SAndroid Build Coastguard Worker
5563*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(
5564*8975f5c5SAndroid Build Coastguard Worker VertexAttributeTest,
5565*8975f5c5SAndroid Build Coastguard Worker ES2_VULKAN().enable(Feature::ForceFallbackFormat),
5566*8975f5c5SAndroid Build Coastguard Worker ES2_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5567*8975f5c5SAndroid Build Coastguard Worker ES3_VULKAN().enable(Feature::ForceFallbackFormat),
5568*8975f5c5SAndroid Build Coastguard Worker ES3_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5569*8975f5c5SAndroid Build Coastguard Worker ES3_METAL().disable(Feature::HasExplicitMemBarrier).disable(Feature::HasCheapRenderPass),
5570*8975f5c5SAndroid Build Coastguard Worker ES3_METAL().disable(Feature::HasExplicitMemBarrier).enable(Feature::HasCheapRenderPass),
5571*8975f5c5SAndroid Build Coastguard Worker ES2_OPENGL().enable(Feature::ForceMinimumMaxVertexAttributes),
5572*8975f5c5SAndroid Build Coastguard Worker ES2_OPENGLES().enable(Feature::ForceMinimumMaxVertexAttributes),
5573*8975f5c5SAndroid Build Coastguard Worker EMULATED_VAO_CONFIGS);
5574*8975f5c5SAndroid Build Coastguard Worker
5575*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(
5576*8975f5c5SAndroid Build Coastguard Worker VertexAttributeOORTest,
5577*8975f5c5SAndroid Build Coastguard Worker ES2_VULKAN().enable(Feature::ForceFallbackFormat),
5578*8975f5c5SAndroid Build Coastguard Worker ES2_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5579*8975f5c5SAndroid Build Coastguard Worker ES3_VULKAN().enable(Feature::ForceFallbackFormat),
5580*8975f5c5SAndroid Build Coastguard Worker ES3_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5581*8975f5c5SAndroid Build Coastguard Worker ES3_METAL().disable(Feature::HasExplicitMemBarrier).disable(Feature::HasCheapRenderPass),
5582*8975f5c5SAndroid Build Coastguard Worker ES3_METAL().disable(Feature::HasExplicitMemBarrier).enable(Feature::HasCheapRenderPass));
5583*8975f5c5SAndroid Build Coastguard Worker
5584*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(RobustVertexAttributeTest);
5585*8975f5c5SAndroid Build Coastguard Worker
5586*8975f5c5SAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VertexAttributeTestES3);
5587*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES3_AND(
5588*8975f5c5SAndroid Build Coastguard Worker VertexAttributeTestES3,
5589*8975f5c5SAndroid Build Coastguard Worker ES3_VULKAN().enable(Feature::ForceFallbackFormat),
5590*8975f5c5SAndroid Build Coastguard Worker ES3_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5591*8975f5c5SAndroid Build Coastguard Worker ES3_METAL().disable(Feature::HasExplicitMemBarrier).disable(Feature::HasCheapRenderPass),
5592*8975f5c5SAndroid Build Coastguard Worker ES3_METAL().disable(Feature::HasExplicitMemBarrier).enable(Feature::HasCheapRenderPass),
5593*8975f5c5SAndroid Build Coastguard Worker ES3_VULKAN()
5594*8975f5c5SAndroid Build Coastguard Worker .disable(Feature::UseVertexInputBindingStrideDynamicState)
5595*8975f5c5SAndroid Build Coastguard Worker .disable(Feature::SupportsGraphicsPipelineLibrary));
5596*8975f5c5SAndroid Build Coastguard Worker
5597*8975f5c5SAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VertexAttributeTestES31);
5598*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES31_AND(VertexAttributeTestES31,
5599*8975f5c5SAndroid Build Coastguard Worker ES31_VULKAN().enable(Feature::ForceFallbackFormat),
5600*8975f5c5SAndroid Build Coastguard Worker ES31_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5601*8975f5c5SAndroid Build Coastguard Worker ES31_VULKAN()
5602*8975f5c5SAndroid Build Coastguard Worker .disable(Feature::UseVertexInputBindingStrideDynamicState)
5603*8975f5c5SAndroid Build Coastguard Worker .disable(Feature::SupportsGraphicsPipelineLibrary));
5604*8975f5c5SAndroid Build Coastguard Worker
5605*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(
5606*8975f5c5SAndroid Build Coastguard Worker VertexAttributeCachingTest,
5607*8975f5c5SAndroid Build Coastguard Worker ES2_VULKAN().enable(Feature::ForceFallbackFormat),
5608*8975f5c5SAndroid Build Coastguard Worker ES2_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5609*8975f5c5SAndroid Build Coastguard Worker ES3_VULKAN().enable(Feature::ForceFallbackFormat),
5610*8975f5c5SAndroid Build Coastguard Worker ES3_VULKAN_SWIFTSHADER().enable(Feature::ForceFallbackFormat),
5611*8975f5c5SAndroid Build Coastguard Worker ES3_METAL().disable(Feature::HasExplicitMemBarrier).disable(Feature::HasCheapRenderPass),
5612*8975f5c5SAndroid Build Coastguard Worker ES3_METAL().disable(Feature::HasExplicitMemBarrier).enable(Feature::HasCheapRenderPass));
5613*8975f5c5SAndroid Build Coastguard Worker
5614*8975f5c5SAndroid Build Coastguard Worker } // anonymous namespace
5615