xref: /aosp_15_r20/external/angle/src/tests/gl_tests/BufferDataTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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 
7*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/ANGLETest.h"
8*8975f5c5SAndroid Build Coastguard Worker #include "test_utils/gl_raii.h"
9*8975f5c5SAndroid Build Coastguard Worker 
10*8975f5c5SAndroid Build Coastguard Worker #include "util/random_utils.h"
11*8975f5c5SAndroid Build Coastguard Worker 
12*8975f5c5SAndroid Build Coastguard Worker #include <stdint.h>
13*8975f5c5SAndroid Build Coastguard Worker #include <thread>
14*8975f5c5SAndroid Build Coastguard Worker 
15*8975f5c5SAndroid Build Coastguard Worker using namespace angle;
16*8975f5c5SAndroid Build Coastguard Worker 
17*8975f5c5SAndroid Build Coastguard Worker class BufferDataTest : public ANGLETest<>
18*8975f5c5SAndroid Build Coastguard Worker {
19*8975f5c5SAndroid Build Coastguard Worker   protected:
BufferDataTest()20*8975f5c5SAndroid Build Coastguard Worker     BufferDataTest()
21*8975f5c5SAndroid Build Coastguard Worker     {
22*8975f5c5SAndroid Build Coastguard Worker         setWindowWidth(16);
23*8975f5c5SAndroid Build Coastguard Worker         setWindowHeight(16);
24*8975f5c5SAndroid Build Coastguard Worker         setConfigRedBits(8);
25*8975f5c5SAndroid Build Coastguard Worker         setConfigGreenBits(8);
26*8975f5c5SAndroid Build Coastguard Worker         setConfigBlueBits(8);
27*8975f5c5SAndroid Build Coastguard Worker         setConfigAlphaBits(8);
28*8975f5c5SAndroid Build Coastguard Worker         setConfigDepthBits(24);
29*8975f5c5SAndroid Build Coastguard Worker 
30*8975f5c5SAndroid Build Coastguard Worker         mBuffer         = 0;
31*8975f5c5SAndroid Build Coastguard Worker         mProgram        = 0;
32*8975f5c5SAndroid Build Coastguard Worker         mAttribLocation = -1;
33*8975f5c5SAndroid Build Coastguard Worker     }
34*8975f5c5SAndroid Build Coastguard Worker 
testSetUp()35*8975f5c5SAndroid Build Coastguard Worker     void testSetUp() override
36*8975f5c5SAndroid Build Coastguard Worker     {
37*8975f5c5SAndroid Build Coastguard Worker         constexpr char kVS[] = R"(attribute vec4 position;
38*8975f5c5SAndroid Build Coastguard Worker attribute float in_attrib;
39*8975f5c5SAndroid Build Coastguard Worker varying float v_attrib;
40*8975f5c5SAndroid Build Coastguard Worker void main()
41*8975f5c5SAndroid Build Coastguard Worker {
42*8975f5c5SAndroid Build Coastguard Worker     v_attrib = in_attrib;
43*8975f5c5SAndroid Build Coastguard Worker     gl_Position = position;
44*8975f5c5SAndroid Build Coastguard Worker })";
45*8975f5c5SAndroid Build Coastguard Worker 
46*8975f5c5SAndroid Build Coastguard Worker         constexpr char kFS[] = R"(precision mediump float;
47*8975f5c5SAndroid Build Coastguard Worker varying float v_attrib;
48*8975f5c5SAndroid Build Coastguard Worker void main()
49*8975f5c5SAndroid Build Coastguard Worker {
50*8975f5c5SAndroid Build Coastguard Worker     gl_FragColor = vec4(v_attrib, 0, 0, 1);
51*8975f5c5SAndroid Build Coastguard Worker })";
52*8975f5c5SAndroid Build Coastguard Worker 
53*8975f5c5SAndroid Build Coastguard Worker         glGenBuffers(1, &mBuffer);
54*8975f5c5SAndroid Build Coastguard Worker         ASSERT_NE(mBuffer, 0U);
55*8975f5c5SAndroid Build Coastguard Worker 
56*8975f5c5SAndroid Build Coastguard Worker         mProgram = CompileProgram(kVS, kFS);
57*8975f5c5SAndroid Build Coastguard Worker         ASSERT_NE(mProgram, 0U);
58*8975f5c5SAndroid Build Coastguard Worker 
59*8975f5c5SAndroid Build Coastguard Worker         mAttribLocation = glGetAttribLocation(mProgram, "in_attrib");
60*8975f5c5SAndroid Build Coastguard Worker         ASSERT_NE(mAttribLocation, -1);
61*8975f5c5SAndroid Build Coastguard Worker 
62*8975f5c5SAndroid Build Coastguard Worker         glClearColor(0, 0, 0, 0);
63*8975f5c5SAndroid Build Coastguard Worker         glClearDepthf(0.0);
64*8975f5c5SAndroid Build Coastguard Worker         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
65*8975f5c5SAndroid Build Coastguard Worker 
66*8975f5c5SAndroid Build Coastguard Worker         glDisable(GL_DEPTH_TEST);
67*8975f5c5SAndroid Build Coastguard Worker 
68*8975f5c5SAndroid Build Coastguard Worker         ASSERT_GL_NO_ERROR();
69*8975f5c5SAndroid Build Coastguard Worker     }
70*8975f5c5SAndroid Build Coastguard Worker 
testTearDown()71*8975f5c5SAndroid Build Coastguard Worker     void testTearDown() override
72*8975f5c5SAndroid Build Coastguard Worker     {
73*8975f5c5SAndroid Build Coastguard Worker         glDeleteBuffers(1, &mBuffer);
74*8975f5c5SAndroid Build Coastguard Worker         glDeleteProgram(mProgram);
75*8975f5c5SAndroid Build Coastguard Worker     }
76*8975f5c5SAndroid Build Coastguard Worker 
77*8975f5c5SAndroid Build Coastguard Worker     GLuint mBuffer;
78*8975f5c5SAndroid Build Coastguard Worker     GLuint mProgram;
79*8975f5c5SAndroid Build Coastguard Worker     GLint mAttribLocation;
80*8975f5c5SAndroid Build Coastguard Worker };
81*8975f5c5SAndroid Build Coastguard Worker 
82*8975f5c5SAndroid Build Coastguard Worker // If glBufferData was not called yet the capturing must not try to
83*8975f5c5SAndroid Build Coastguard Worker // read the data. http://anglebug.com/42264622
TEST_P(BufferDataTest,Uninitialized)84*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTest, Uninitialized)
85*8975f5c5SAndroid Build Coastguard Worker {
86*8975f5c5SAndroid Build Coastguard Worker     // Trigger frame capture to try capturing the
87*8975f5c5SAndroid Build Coastguard Worker     // generated but uninitialized buffer
88*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
89*8975f5c5SAndroid Build Coastguard Worker     swapBuffers();
90*8975f5c5SAndroid Build Coastguard Worker }
91*8975f5c5SAndroid Build Coastguard Worker 
TEST_P(BufferDataTest,ZeroNonNULLData)92*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTest, ZeroNonNULLData)
93*8975f5c5SAndroid Build Coastguard Worker {
94*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
95*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
96*8975f5c5SAndroid Build Coastguard Worker 
97*8975f5c5SAndroid Build Coastguard Worker     char *zeroData = new char[0];
98*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, 0, zeroData, GL_STATIC_DRAW);
99*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
100*8975f5c5SAndroid Build Coastguard Worker 
101*8975f5c5SAndroid Build Coastguard Worker     glBufferSubData(GL_ARRAY_BUFFER, 0, 0, zeroData);
102*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
103*8975f5c5SAndroid Build Coastguard Worker 
104*8975f5c5SAndroid Build Coastguard Worker     delete[] zeroData;
105*8975f5c5SAndroid Build Coastguard Worker }
106*8975f5c5SAndroid Build Coastguard Worker 
TEST_P(BufferDataTest,NULLResolvedData)107*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTest, NULLResolvedData)
108*8975f5c5SAndroid Build Coastguard Worker {
109*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
110*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, 128, nullptr, GL_DYNAMIC_DRAW);
111*8975f5c5SAndroid Build Coastguard Worker 
112*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(mProgram);
113*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
114*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(mAttribLocation);
115*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, 0);
116*8975f5c5SAndroid Build Coastguard Worker 
117*8975f5c5SAndroid Build Coastguard Worker     drawQuad(mProgram, "position", 0.5f);
118*8975f5c5SAndroid Build Coastguard Worker }
119*8975f5c5SAndroid Build Coastguard Worker 
120*8975f5c5SAndroid Build Coastguard Worker // Internally in D3D, we promote dynamic data to static after many draw loops. This code tests
121*8975f5c5SAndroid Build Coastguard Worker // path.
TEST_P(BufferDataTest,RepeatedDrawWithDynamic)122*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTest, RepeatedDrawWithDynamic)
123*8975f5c5SAndroid Build Coastguard Worker {
124*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLfloat> data;
125*8975f5c5SAndroid Build Coastguard Worker     for (int i = 0; i < 16; ++i)
126*8975f5c5SAndroid Build Coastguard Worker     {
127*8975f5c5SAndroid Build Coastguard Worker         data.push_back(static_cast<GLfloat>(i));
128*8975f5c5SAndroid Build Coastguard Worker     }
129*8975f5c5SAndroid Build Coastguard Worker 
130*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(mProgram);
131*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
132*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), GL_DYNAMIC_DRAW);
133*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
134*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, 0);
135*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(mAttribLocation);
136*8975f5c5SAndroid Build Coastguard Worker 
137*8975f5c5SAndroid Build Coastguard Worker     for (int drawCount = 0; drawCount < 40; ++drawCount)
138*8975f5c5SAndroid Build Coastguard Worker     {
139*8975f5c5SAndroid Build Coastguard Worker         drawQuad(mProgram, "position", 0.5f);
140*8975f5c5SAndroid Build Coastguard Worker     }
141*8975f5c5SAndroid Build Coastguard Worker 
142*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
143*8975f5c5SAndroid Build Coastguard Worker }
144*8975f5c5SAndroid Build Coastguard Worker 
145*8975f5c5SAndroid Build Coastguard Worker // Tests for a bug where vertex attribute translation was not being invalidated when switching to
146*8975f5c5SAndroid Build Coastguard Worker // DYNAMIC
TEST_P(BufferDataTest,RepeatedDrawDynamicBug)147*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTest, RepeatedDrawDynamicBug)
148*8975f5c5SAndroid Build Coastguard Worker {
149*8975f5c5SAndroid Build Coastguard Worker     // http://anglebug.com/42261546: Seems to be an Intel driver bug.
150*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsWindows());
151*8975f5c5SAndroid Build Coastguard Worker 
152*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(mProgram);
153*8975f5c5SAndroid Build Coastguard Worker 
154*8975f5c5SAndroid Build Coastguard Worker     GLint positionLocation = glGetAttribLocation(mProgram, "position");
155*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, positionLocation);
156*8975f5c5SAndroid Build Coastguard Worker 
157*8975f5c5SAndroid Build Coastguard Worker     auto quadVertices = GetQuadVertices();
158*8975f5c5SAndroid Build Coastguard Worker     for (angle::Vector3 &vertex : quadVertices)
159*8975f5c5SAndroid Build Coastguard Worker     {
160*8975f5c5SAndroid Build Coastguard Worker         vertex.x() *= 1.0f;
161*8975f5c5SAndroid Build Coastguard Worker         vertex.y() *= 1.0f;
162*8975f5c5SAndroid Build Coastguard Worker         vertex.z() = 0.0f;
163*8975f5c5SAndroid Build Coastguard Worker     }
164*8975f5c5SAndroid Build Coastguard Worker 
165*8975f5c5SAndroid Build Coastguard Worker     // Set up quad vertices with DYNAMIC data
166*8975f5c5SAndroid Build Coastguard Worker     GLBuffer positionBuffer;
167*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
168*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * quadVertices.size() * 3, quadVertices.data(),
169*8975f5c5SAndroid Build Coastguard Worker                  GL_DYNAMIC_DRAW);
170*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
171*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(positionLocation);
172*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, 0);
173*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
174*8975f5c5SAndroid Build Coastguard Worker 
175*8975f5c5SAndroid Build Coastguard Worker     // Set up color data so red is drawn
176*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLfloat> data(6, 1.0f);
177*8975f5c5SAndroid Build Coastguard Worker 
178*8975f5c5SAndroid Build Coastguard Worker     // Set data to DYNAMIC
179*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
180*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), GL_DYNAMIC_DRAW);
181*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
182*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(mAttribLocation);
183*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
184*8975f5c5SAndroid Build Coastguard Worker 
185*8975f5c5SAndroid Build Coastguard Worker     // Draw enough times to promote data to DIRECT mode
186*8975f5c5SAndroid Build Coastguard Worker     for (int i = 0; i < 20; i++)
187*8975f5c5SAndroid Build Coastguard Worker     {
188*8975f5c5SAndroid Build Coastguard Worker         glDrawArrays(GL_TRIANGLES, 0, 6);
189*8975f5c5SAndroid Build Coastguard Worker     }
190*8975f5c5SAndroid Build Coastguard Worker 
191*8975f5c5SAndroid Build Coastguard Worker     // Verify red was drawn
192*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
193*8975f5c5SAndroid Build Coastguard Worker 
194*8975f5c5SAndroid Build Coastguard Worker     // Set up color value so black is drawn
195*8975f5c5SAndroid Build Coastguard Worker     std::fill(data.begin(), data.end(), 0.0f);
196*8975f5c5SAndroid Build Coastguard Worker 
197*8975f5c5SAndroid Build Coastguard Worker     // Update the data, changing back to DYNAMIC mode.
198*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), GL_DYNAMIC_DRAW);
199*8975f5c5SAndroid Build Coastguard Worker 
200*8975f5c5SAndroid Build Coastguard Worker     // This draw should produce a black quad
201*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 6);
202*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
203*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
204*8975f5c5SAndroid Build Coastguard Worker }
205*8975f5c5SAndroid Build Coastguard Worker 
206*8975f5c5SAndroid Build Coastguard Worker using BufferSubDataTestParams = std::tuple<angle::PlatformParameters, bool>;
207*8975f5c5SAndroid Build Coastguard Worker 
BufferSubDataTestPrint(const::testing::TestParamInfo<BufferSubDataTestParams> & paramsInfo)208*8975f5c5SAndroid Build Coastguard Worker std::string BufferSubDataTestPrint(
209*8975f5c5SAndroid Build Coastguard Worker     const ::testing::TestParamInfo<BufferSubDataTestParams> &paramsInfo)
210*8975f5c5SAndroid Build Coastguard Worker {
211*8975f5c5SAndroid Build Coastguard Worker     const BufferSubDataTestParams &params = paramsInfo.param;
212*8975f5c5SAndroid Build Coastguard Worker     std::ostringstream out;
213*8975f5c5SAndroid Build Coastguard Worker 
214*8975f5c5SAndroid Build Coastguard Worker     out << std::get<0>(params) << "__";
215*8975f5c5SAndroid Build Coastguard Worker 
216*8975f5c5SAndroid Build Coastguard Worker     const bool useCopySubData = std::get<1>(params);
217*8975f5c5SAndroid Build Coastguard Worker     if (useCopySubData)
218*8975f5c5SAndroid Build Coastguard Worker     {
219*8975f5c5SAndroid Build Coastguard Worker         out << "CopyBufferSubData";
220*8975f5c5SAndroid Build Coastguard Worker     }
221*8975f5c5SAndroid Build Coastguard Worker     else
222*8975f5c5SAndroid Build Coastguard Worker     {
223*8975f5c5SAndroid Build Coastguard Worker         out << "BufferSubData";
224*8975f5c5SAndroid Build Coastguard Worker     }
225*8975f5c5SAndroid Build Coastguard Worker 
226*8975f5c5SAndroid Build Coastguard Worker     return out.str();
227*8975f5c5SAndroid Build Coastguard Worker }
228*8975f5c5SAndroid Build Coastguard Worker 
229*8975f5c5SAndroid Build Coastguard Worker class BufferSubDataTest : public ANGLETest<BufferSubDataTestParams>
230*8975f5c5SAndroid Build Coastguard Worker {
231*8975f5c5SAndroid Build Coastguard Worker   protected:
BufferSubDataTest()232*8975f5c5SAndroid Build Coastguard Worker     BufferSubDataTest()
233*8975f5c5SAndroid Build Coastguard Worker     {
234*8975f5c5SAndroid Build Coastguard Worker         setWindowWidth(16);
235*8975f5c5SAndroid Build Coastguard Worker         setWindowHeight(16);
236*8975f5c5SAndroid Build Coastguard Worker         setConfigRedBits(8);
237*8975f5c5SAndroid Build Coastguard Worker         setConfigGreenBits(8);
238*8975f5c5SAndroid Build Coastguard Worker         setConfigBlueBits(8);
239*8975f5c5SAndroid Build Coastguard Worker         setConfigAlphaBits(8);
240*8975f5c5SAndroid Build Coastguard Worker         setConfigDepthBits(24);
241*8975f5c5SAndroid Build Coastguard Worker 
242*8975f5c5SAndroid Build Coastguard Worker         mBuffer = 0;
243*8975f5c5SAndroid Build Coastguard Worker     }
244*8975f5c5SAndroid Build Coastguard Worker 
testSetUp()245*8975f5c5SAndroid Build Coastguard Worker     void testSetUp() override
246*8975f5c5SAndroid Build Coastguard Worker     {
247*8975f5c5SAndroid Build Coastguard Worker         glGenBuffers(1, &mBuffer);
248*8975f5c5SAndroid Build Coastguard Worker         ASSERT_NE(mBuffer, 0U);
249*8975f5c5SAndroid Build Coastguard Worker 
250*8975f5c5SAndroid Build Coastguard Worker         glClearColor(0, 0, 0, 0);
251*8975f5c5SAndroid Build Coastguard Worker         glClearDepthf(0.0);
252*8975f5c5SAndroid Build Coastguard Worker         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
253*8975f5c5SAndroid Build Coastguard Worker 
254*8975f5c5SAndroid Build Coastguard Worker         glDisable(GL_DEPTH_TEST);
255*8975f5c5SAndroid Build Coastguard Worker 
256*8975f5c5SAndroid Build Coastguard Worker         ASSERT_GL_NO_ERROR();
257*8975f5c5SAndroid Build Coastguard Worker     }
258*8975f5c5SAndroid Build Coastguard Worker 
updateBuffer(GLenum target,GLintptr offset,GLsizeiptr size,const void * data)259*8975f5c5SAndroid Build Coastguard Worker     void updateBuffer(GLenum target, GLintptr offset, GLsizeiptr size, const void *data)
260*8975f5c5SAndroid Build Coastguard Worker     {
261*8975f5c5SAndroid Build Coastguard Worker         const bool useCopySubData = std::get<1>(GetParam());
262*8975f5c5SAndroid Build Coastguard Worker         if (!useCopySubData)
263*8975f5c5SAndroid Build Coastguard Worker         {
264*8975f5c5SAndroid Build Coastguard Worker             // If using glBufferSubData, directly upload data on the specified target (where the
265*8975f5c5SAndroid Build Coastguard Worker             // buffer is already bound)
266*8975f5c5SAndroid Build Coastguard Worker             glBufferSubData(target, offset, size, data);
267*8975f5c5SAndroid Build Coastguard Worker         }
268*8975f5c5SAndroid Build Coastguard Worker         else
269*8975f5c5SAndroid Build Coastguard Worker         {
270*8975f5c5SAndroid Build Coastguard Worker             // Otherwise copy through a temp buffer.  Use a non-zero offset for more coverage.
271*8975f5c5SAndroid Build Coastguard Worker             constexpr GLintptr kStagingOffset = 935;
272*8975f5c5SAndroid Build Coastguard Worker             GLBuffer staging;
273*8975f5c5SAndroid Build Coastguard Worker             glBindBuffer(GL_COPY_READ_BUFFER, staging);
274*8975f5c5SAndroid Build Coastguard Worker             glBufferData(GL_COPY_READ_BUFFER, offset + size + kStagingOffset * 3 / 2, nullptr,
275*8975f5c5SAndroid Build Coastguard Worker                          GL_STATIC_DRAW);
276*8975f5c5SAndroid Build Coastguard Worker             glBufferSubData(GL_COPY_READ_BUFFER, kStagingOffset, size, data);
277*8975f5c5SAndroid Build Coastguard Worker             glCopyBufferSubData(GL_COPY_READ_BUFFER, target, kStagingOffset, offset, size);
278*8975f5c5SAndroid Build Coastguard Worker         }
279*8975f5c5SAndroid Build Coastguard Worker     }
280*8975f5c5SAndroid Build Coastguard Worker 
testTearDown()281*8975f5c5SAndroid Build Coastguard Worker     void testTearDown() override { glDeleteBuffers(1, &mBuffer); }
282*8975f5c5SAndroid Build Coastguard Worker     GLuint mBuffer;
283*8975f5c5SAndroid Build Coastguard Worker };
284*8975f5c5SAndroid Build Coastguard Worker 
285*8975f5c5SAndroid Build Coastguard Worker // Test that updating a small index buffer after drawing with it works.
286*8975f5c5SAndroid Build Coastguard Worker // In the Vulkan backend, the CPU may be used to perform this copy.
TEST_P(BufferSubDataTest,SmallIndexBufferUpdateAfterDraw)287*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferSubDataTest, SmallIndexBufferUpdateAfterDraw)
288*8975f5c5SAndroid Build Coastguard Worker {
289*8975f5c5SAndroid Build Coastguard Worker     constexpr std::array<GLfloat, 4> kRed   = {1.0f, 0.0f, 0.0f, 1.0f};
290*8975f5c5SAndroid Build Coastguard Worker     constexpr std::array<GLfloat, 4> kGreen = {0.0f, 1.0f, 0.0f, 1.0f};
291*8975f5c5SAndroid Build Coastguard Worker     // Index buffer data
292*8975f5c5SAndroid Build Coastguard Worker     GLuint indexData[] = {0, 1, 2, 0};
293*8975f5c5SAndroid Build Coastguard Worker     // Vertex buffer data fully cover the screen
294*8975f5c5SAndroid Build Coastguard Worker     float vertexData[] = {-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f};
295*8975f5c5SAndroid Build Coastguard Worker 
296*8975f5c5SAndroid Build Coastguard Worker     GLBuffer indexBuffer;
297*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
298*8975f5c5SAndroid Build Coastguard Worker     GLint vPos = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
299*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(vPos, -1);
300*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
301*8975f5c5SAndroid Build Coastguard Worker     GLint colorUniformLocation =
302*8975f5c5SAndroid Build Coastguard Worker         glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
303*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(colorUniformLocation, -1);
304*8975f5c5SAndroid Build Coastguard Worker 
305*8975f5c5SAndroid Build Coastguard Worker     // Bind vertex buffer
306*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
307*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
308*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(vPos, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
309*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(vPos);
310*8975f5c5SAndroid Build Coastguard Worker 
311*8975f5c5SAndroid Build Coastguard Worker     // Bind index buffer
312*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
313*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_DYNAMIC_DRAW);
314*8975f5c5SAndroid Build Coastguard Worker 
315*8975f5c5SAndroid Build Coastguard Worker     glUniform4fv(colorUniformLocation, 1, kRed.data());
316*8975f5c5SAndroid Build Coastguard Worker     // Draw left red triangle
317*8975f5c5SAndroid Build Coastguard Worker     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
318*8975f5c5SAndroid Build Coastguard Worker     // Update the index buffer data.
319*8975f5c5SAndroid Build Coastguard Worker     indexData[1] = 1;
320*8975f5c5SAndroid Build Coastguard Worker     indexData[2] = 2;
321*8975f5c5SAndroid Build Coastguard Worker     indexData[3] = 3;
322*8975f5c5SAndroid Build Coastguard Worker     // Partial copy to trigger the buffer pool allocation
323*8975f5c5SAndroid Build Coastguard Worker     updateBuffer(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint), 3 * sizeof(GLuint), &indexData[1]);
324*8975f5c5SAndroid Build Coastguard Worker     // Draw triangle with index (1, 2, 3).
325*8975f5c5SAndroid Build Coastguard Worker     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, (const void *)sizeof(GLuint));
326*8975f5c5SAndroid Build Coastguard Worker     // Update the index buffer again
327*8975f5c5SAndroid Build Coastguard Worker     indexData[0] = 0;
328*8975f5c5SAndroid Build Coastguard Worker     indexData[1] = 0;
329*8975f5c5SAndroid Build Coastguard Worker     indexData[2] = 2;
330*8975f5c5SAndroid Build Coastguard Worker     glUniform4fv(colorUniformLocation, 1, kGreen.data());
331*8975f5c5SAndroid Build Coastguard Worker     updateBuffer(GL_ELEMENT_ARRAY_BUFFER, 0, 3 * sizeof(GLuint), &indexData[0]);
332*8975f5c5SAndroid Build Coastguard Worker     // Draw triangle with index (0, 2, 3), hope angle copy the last index 3 back.
333*8975f5c5SAndroid Build Coastguard Worker     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, (const void *)sizeof(GLuint));
334*8975f5c5SAndroid Build Coastguard Worker 
335*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::red);
336*8975f5c5SAndroid Build Coastguard Worker     // Verify pixel top left corner is green
337*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, GLColor::green);
338*8975f5c5SAndroid Build Coastguard Worker }
339*8975f5c5SAndroid Build Coastguard Worker 
340*8975f5c5SAndroid Build Coastguard Worker // Test that updating a small index buffer after drawing with it works.
341*8975f5c5SAndroid Build Coastguard Worker // In the Vulkan backend, the CPU may be used to perform this copy.
TEST_P(BufferSubDataTest,SmallVertexDataUpdateAfterDraw)342*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferSubDataTest, SmallVertexDataUpdateAfterDraw)
343*8975f5c5SAndroid Build Coastguard Worker {
344*8975f5c5SAndroid Build Coastguard Worker     constexpr std::array<GLfloat, 4> kGreen = {0.0f, 1.0f, 0.0f, 1.0f};
345*8975f5c5SAndroid Build Coastguard Worker     // Index buffer data
346*8975f5c5SAndroid Build Coastguard Worker     GLuint indexData[] = {0, 1, 2, 0};
347*8975f5c5SAndroid Build Coastguard Worker     // Vertex buffer data lower left triangle
348*8975f5c5SAndroid Build Coastguard Worker     // 2
349*8975f5c5SAndroid Build Coastguard Worker     //
350*8975f5c5SAndroid Build Coastguard Worker     // o    1
351*8975f5c5SAndroid Build Coastguard Worker     float vertexData1[] = {
352*8975f5c5SAndroid Build Coastguard Worker         -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f,
353*8975f5c5SAndroid Build Coastguard Worker     };
354*8975f5c5SAndroid Build Coastguard Worker     // Vertex buffer data upper right triangle
355*8975f5c5SAndroid Build Coastguard Worker     // 2      1
356*8975f5c5SAndroid Build Coastguard Worker     //
357*8975f5c5SAndroid Build Coastguard Worker     //        0
358*8975f5c5SAndroid Build Coastguard Worker     float vertexData2[] = {
359*8975f5c5SAndroid Build Coastguard Worker         1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
360*8975f5c5SAndroid Build Coastguard Worker     };
361*8975f5c5SAndroid Build Coastguard Worker     GLBuffer indexBuffer;
362*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
363*8975f5c5SAndroid Build Coastguard Worker     GLint vPos = glGetAttribLocation(program, essl1_shaders::PositionAttrib());
364*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(vPos, -1);
365*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
366*8975f5c5SAndroid Build Coastguard Worker     GLint colorUniformLocation =
367*8975f5c5SAndroid Build Coastguard Worker         glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
368*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(colorUniformLocation, -1);
369*8975f5c5SAndroid Build Coastguard Worker 
370*8975f5c5SAndroid Build Coastguard Worker     // Bind vertex buffer
371*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
372*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData1), vertexData1, GL_DYNAMIC_DRAW);
373*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(vPos, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
374*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(vPos);
375*8975f5c5SAndroid Build Coastguard Worker 
376*8975f5c5SAndroid Build Coastguard Worker     // Bind index buffer
377*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
378*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexData), indexData, GL_DYNAMIC_DRAW);
379*8975f5c5SAndroid Build Coastguard Worker 
380*8975f5c5SAndroid Build Coastguard Worker     glUniform4fv(colorUniformLocation, 1, kGreen.data());
381*8975f5c5SAndroid Build Coastguard Worker     // Draw left red triangle
382*8975f5c5SAndroid Build Coastguard Worker     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, nullptr);
383*8975f5c5SAndroid Build Coastguard Worker     // Update the vertex buffer data.
384*8975f5c5SAndroid Build Coastguard Worker     // Partial copy to trigger the buffer pool allocation
385*8975f5c5SAndroid Build Coastguard Worker     updateBuffer(GL_ARRAY_BUFFER, 0, sizeof(vertexData2), vertexData2);
386*8975f5c5SAndroid Build Coastguard Worker     // Draw triangle with index (0,1,2).
387*8975f5c5SAndroid Build Coastguard Worker     glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, (const void *)sizeof(GLuint));
388*8975f5c5SAndroid Build Coastguard Worker     // Verify pixel corners are green
389*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
390*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, getWindowHeight() - 1, GLColor::green);
391*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, 0, GLColor::green);
392*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::green);
393*8975f5c5SAndroid Build Coastguard Worker }
394*8975f5c5SAndroid Build Coastguard Worker class IndexedBufferCopyTest : public ANGLETest<>
395*8975f5c5SAndroid Build Coastguard Worker {
396*8975f5c5SAndroid Build Coastguard Worker   protected:
IndexedBufferCopyTest()397*8975f5c5SAndroid Build Coastguard Worker     IndexedBufferCopyTest()
398*8975f5c5SAndroid Build Coastguard Worker     {
399*8975f5c5SAndroid Build Coastguard Worker         setWindowWidth(16);
400*8975f5c5SAndroid Build Coastguard Worker         setWindowHeight(16);
401*8975f5c5SAndroid Build Coastguard Worker         setConfigRedBits(8);
402*8975f5c5SAndroid Build Coastguard Worker         setConfigGreenBits(8);
403*8975f5c5SAndroid Build Coastguard Worker         setConfigBlueBits(8);
404*8975f5c5SAndroid Build Coastguard Worker         setConfigAlphaBits(8);
405*8975f5c5SAndroid Build Coastguard Worker         setConfigDepthBits(24);
406*8975f5c5SAndroid Build Coastguard Worker     }
407*8975f5c5SAndroid Build Coastguard Worker 
testSetUp()408*8975f5c5SAndroid Build Coastguard Worker     void testSetUp() override
409*8975f5c5SAndroid Build Coastguard Worker     {
410*8975f5c5SAndroid Build Coastguard Worker         constexpr char kVS[] = R"(attribute vec3 in_attrib;
411*8975f5c5SAndroid Build Coastguard Worker varying vec3 v_attrib;
412*8975f5c5SAndroid Build Coastguard Worker void main()
413*8975f5c5SAndroid Build Coastguard Worker {
414*8975f5c5SAndroid Build Coastguard Worker     v_attrib = in_attrib;
415*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(0.0, 0.0, 0.5, 1.0);
416*8975f5c5SAndroid Build Coastguard Worker     gl_PointSize = 100.0;
417*8975f5c5SAndroid Build Coastguard Worker })";
418*8975f5c5SAndroid Build Coastguard Worker 
419*8975f5c5SAndroid Build Coastguard Worker         constexpr char kFS[] = R"(precision mediump float;
420*8975f5c5SAndroid Build Coastguard Worker varying vec3 v_attrib;
421*8975f5c5SAndroid Build Coastguard Worker void main()
422*8975f5c5SAndroid Build Coastguard Worker {
423*8975f5c5SAndroid Build Coastguard Worker     gl_FragColor = vec4(v_attrib, 1);
424*8975f5c5SAndroid Build Coastguard Worker })";
425*8975f5c5SAndroid Build Coastguard Worker 
426*8975f5c5SAndroid Build Coastguard Worker         glGenBuffers(2, mBuffers);
427*8975f5c5SAndroid Build Coastguard Worker         ASSERT_NE(mBuffers[0], 0U);
428*8975f5c5SAndroid Build Coastguard Worker         ASSERT_NE(mBuffers[1], 0U);
429*8975f5c5SAndroid Build Coastguard Worker 
430*8975f5c5SAndroid Build Coastguard Worker         glGenBuffers(1, &mElementBuffer);
431*8975f5c5SAndroid Build Coastguard Worker         ASSERT_NE(mElementBuffer, 0U);
432*8975f5c5SAndroid Build Coastguard Worker 
433*8975f5c5SAndroid Build Coastguard Worker         mProgram = CompileProgram(kVS, kFS);
434*8975f5c5SAndroid Build Coastguard Worker         ASSERT_NE(mProgram, 0U);
435*8975f5c5SAndroid Build Coastguard Worker 
436*8975f5c5SAndroid Build Coastguard Worker         mAttribLocation = glGetAttribLocation(mProgram, "in_attrib");
437*8975f5c5SAndroid Build Coastguard Worker         ASSERT_NE(mAttribLocation, -1);
438*8975f5c5SAndroid Build Coastguard Worker 
439*8975f5c5SAndroid Build Coastguard Worker         glClearColor(0, 0, 0, 0);
440*8975f5c5SAndroid Build Coastguard Worker         glDisable(GL_DEPTH_TEST);
441*8975f5c5SAndroid Build Coastguard Worker         glClear(GL_COLOR_BUFFER_BIT);
442*8975f5c5SAndroid Build Coastguard Worker 
443*8975f5c5SAndroid Build Coastguard Worker         ASSERT_GL_NO_ERROR();
444*8975f5c5SAndroid Build Coastguard Worker     }
445*8975f5c5SAndroid Build Coastguard Worker 
testTearDown()446*8975f5c5SAndroid Build Coastguard Worker     void testTearDown() override
447*8975f5c5SAndroid Build Coastguard Worker     {
448*8975f5c5SAndroid Build Coastguard Worker         glDeleteBuffers(2, mBuffers);
449*8975f5c5SAndroid Build Coastguard Worker         glDeleteBuffers(1, &mElementBuffer);
450*8975f5c5SAndroid Build Coastguard Worker         glDeleteProgram(mProgram);
451*8975f5c5SAndroid Build Coastguard Worker     }
452*8975f5c5SAndroid Build Coastguard Worker 
453*8975f5c5SAndroid Build Coastguard Worker     GLuint mBuffers[2];
454*8975f5c5SAndroid Build Coastguard Worker     GLuint mElementBuffer;
455*8975f5c5SAndroid Build Coastguard Worker     GLuint mProgram;
456*8975f5c5SAndroid Build Coastguard Worker     GLint mAttribLocation;
457*8975f5c5SAndroid Build Coastguard Worker };
458*8975f5c5SAndroid Build Coastguard Worker 
459*8975f5c5SAndroid Build Coastguard Worker // The following test covers an ANGLE bug where our index ranges
460*8975f5c5SAndroid Build Coastguard Worker // weren't updated from CopyBufferSubData calls
461*8975f5c5SAndroid Build Coastguard Worker // https://code.google.com/p/angleproject/issues/detail?id=709
TEST_P(IndexedBufferCopyTest,IndexRangeBug)462*8975f5c5SAndroid Build Coastguard Worker TEST_P(IndexedBufferCopyTest, IndexRangeBug)
463*8975f5c5SAndroid Build Coastguard Worker {
464*8975f5c5SAndroid Build Coastguard Worker     // TODO(geofflang): Figure out why this fails on AMD OpenGL (http://anglebug.com/42260302)
465*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsAMD() && IsOpenGL());
466*8975f5c5SAndroid Build Coastguard Worker 
467*8975f5c5SAndroid Build Coastguard Worker     unsigned char vertexData[] = {255, 0, 0, 0, 0, 0};
468*8975f5c5SAndroid Build Coastguard Worker     unsigned int indexData[]   = {0, 1};
469*8975f5c5SAndroid Build Coastguard Worker 
470*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mBuffers[0]);
471*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(char) * 6, vertexData, GL_STATIC_DRAW);
472*8975f5c5SAndroid Build Coastguard Worker 
473*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(mProgram);
474*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(mAttribLocation, 3, GL_UNSIGNED_BYTE, GL_TRUE, 3, nullptr);
475*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(mAttribLocation);
476*8975f5c5SAndroid Build Coastguard Worker 
477*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
478*8975f5c5SAndroid Build Coastguard Worker 
479*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mElementBuffer);
480*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * 1, indexData, GL_STATIC_DRAW);
481*8975f5c5SAndroid Build Coastguard Worker 
482*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(mProgram);
483*8975f5c5SAndroid Build Coastguard Worker 
484*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
485*8975f5c5SAndroid Build Coastguard Worker 
486*8975f5c5SAndroid Build Coastguard Worker     glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, nullptr);
487*8975f5c5SAndroid Build Coastguard Worker 
488*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
489*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
490*8975f5c5SAndroid Build Coastguard Worker 
491*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_COPY_READ_BUFFER, mBuffers[1]);
492*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_COPY_READ_BUFFER, 4, &indexData[1], GL_STATIC_DRAW);
493*8975f5c5SAndroid Build Coastguard Worker 
494*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_COPY_WRITE_BUFFER, mElementBuffer);
495*8975f5c5SAndroid Build Coastguard Worker 
496*8975f5c5SAndroid Build Coastguard Worker     glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, sizeof(int));
497*8975f5c5SAndroid Build Coastguard Worker 
498*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
499*8975f5c5SAndroid Build Coastguard Worker 
500*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
501*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_EQ(0, 0, 0, 0, 0, 0);
502*8975f5c5SAndroid Build Coastguard Worker 
503*8975f5c5SAndroid Build Coastguard Worker     unsigned char newData[] = {0, 255, 0};
504*8975f5c5SAndroid Build Coastguard Worker     glBufferSubData(GL_ARRAY_BUFFER, 3, 3, newData);
505*8975f5c5SAndroid Build Coastguard Worker 
506*8975f5c5SAndroid Build Coastguard Worker     glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, nullptr);
507*8975f5c5SAndroid Build Coastguard Worker 
508*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
509*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
510*8975f5c5SAndroid Build Coastguard Worker }
511*8975f5c5SAndroid Build Coastguard Worker 
512*8975f5c5SAndroid Build Coastguard Worker class BufferDataTestES3 : public BufferDataTest
513*8975f5c5SAndroid Build Coastguard Worker {};
514*8975f5c5SAndroid Build Coastguard Worker 
515*8975f5c5SAndroid Build Coastguard Worker // The following test covers an ANGLE bug where the buffer storage
516*8975f5c5SAndroid Build Coastguard Worker // is not resized by Buffer11::getLatestBufferStorage when needed.
517*8975f5c5SAndroid Build Coastguard Worker // https://code.google.com/p/angleproject/issues/detail?id=897
TEST_P(BufferDataTestES3,BufferResizing)518*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTestES3, BufferResizing)
519*8975f5c5SAndroid Build Coastguard Worker {
520*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
521*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
522*8975f5c5SAndroid Build Coastguard Worker 
523*8975f5c5SAndroid Build Coastguard Worker     // Allocate a buffer with one byte
524*8975f5c5SAndroid Build Coastguard Worker     uint8_t singleByte[] = {0xaa};
525*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, 1, singleByte, GL_STATIC_DRAW);
526*8975f5c5SAndroid Build Coastguard Worker 
527*8975f5c5SAndroid Build Coastguard Worker     // Resize the buffer
528*8975f5c5SAndroid Build Coastguard Worker     // To trigger the bug, the buffer need to be big enough because some hardware copy buffers
529*8975f5c5SAndroid Build Coastguard Worker     // by chunks of pages instead of the minimum number of bytes needed.
530*8975f5c5SAndroid Build Coastguard Worker     const size_t numBytes = 4096 * 4;
531*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, numBytes, nullptr, GL_STATIC_DRAW);
532*8975f5c5SAndroid Build Coastguard Worker 
533*8975f5c5SAndroid Build Coastguard Worker     // Copy the original data to the buffer
534*8975f5c5SAndroid Build Coastguard Worker     uint8_t srcBytes[numBytes];
535*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < numBytes; ++i)
536*8975f5c5SAndroid Build Coastguard Worker     {
537*8975f5c5SAndroid Build Coastguard Worker         srcBytes[i] = static_cast<uint8_t>(i);
538*8975f5c5SAndroid Build Coastguard Worker     }
539*8975f5c5SAndroid Build Coastguard Worker 
540*8975f5c5SAndroid Build Coastguard Worker     void *dest = glMapBufferRange(GL_ARRAY_BUFFER, 0, numBytes,
541*8975f5c5SAndroid Build Coastguard Worker                                   GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
542*8975f5c5SAndroid Build Coastguard Worker 
543*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
544*8975f5c5SAndroid Build Coastguard Worker 
545*8975f5c5SAndroid Build Coastguard Worker     memcpy(dest, srcBytes, numBytes);
546*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_ARRAY_BUFFER);
547*8975f5c5SAndroid Build Coastguard Worker 
548*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
549*8975f5c5SAndroid Build Coastguard Worker 
550*8975f5c5SAndroid Build Coastguard Worker     // Create a new buffer and copy the data to it
551*8975f5c5SAndroid Build Coastguard Worker     GLuint readBuffer;
552*8975f5c5SAndroid Build Coastguard Worker     glGenBuffers(1, &readBuffer);
553*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_COPY_WRITE_BUFFER, readBuffer);
554*8975f5c5SAndroid Build Coastguard Worker     uint8_t zeros[numBytes];
555*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < numBytes; ++i)
556*8975f5c5SAndroid Build Coastguard Worker     {
557*8975f5c5SAndroid Build Coastguard Worker         zeros[i] = 0;
558*8975f5c5SAndroid Build Coastguard Worker     }
559*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_COPY_WRITE_BUFFER, numBytes, zeros, GL_STATIC_DRAW);
560*8975f5c5SAndroid Build Coastguard Worker     glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, numBytes);
561*8975f5c5SAndroid Build Coastguard Worker 
562*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
563*8975f5c5SAndroid Build Coastguard Worker 
564*8975f5c5SAndroid Build Coastguard Worker     // Read back the data and compare it to the original
565*8975f5c5SAndroid Build Coastguard Worker     uint8_t *data = reinterpret_cast<uint8_t *>(
566*8975f5c5SAndroid Build Coastguard Worker         glMapBufferRange(GL_COPY_WRITE_BUFFER, 0, numBytes, GL_MAP_READ_BIT));
567*8975f5c5SAndroid Build Coastguard Worker 
568*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
569*8975f5c5SAndroid Build Coastguard Worker 
570*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < numBytes; ++i)
571*8975f5c5SAndroid Build Coastguard Worker     {
572*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(srcBytes[i], data[i]);
573*8975f5c5SAndroid Build Coastguard Worker     }
574*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_COPY_WRITE_BUFFER);
575*8975f5c5SAndroid Build Coastguard Worker 
576*8975f5c5SAndroid Build Coastguard Worker     glDeleteBuffers(1, &readBuffer);
577*8975f5c5SAndroid Build Coastguard Worker 
578*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
579*8975f5c5SAndroid Build Coastguard Worker }
580*8975f5c5SAndroid Build Coastguard Worker 
581*8975f5c5SAndroid Build Coastguard Worker // Test to verify mapping a buffer after copying to it contains flushed/updated data
TEST_P(BufferDataTestES3,CopyBufferSubDataMapReadTest)582*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTestES3, CopyBufferSubDataMapReadTest)
583*8975f5c5SAndroid Build Coastguard Worker {
584*8975f5c5SAndroid Build Coastguard Worker     const char simpleVertex[]   = R"(attribute vec2 position;
585*8975f5c5SAndroid Build Coastguard Worker attribute vec4 color;
586*8975f5c5SAndroid Build Coastguard Worker varying vec4 vColor;
587*8975f5c5SAndroid Build Coastguard Worker void main()
588*8975f5c5SAndroid Build Coastguard Worker {
589*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(position, 0, 1);
590*8975f5c5SAndroid Build Coastguard Worker     vColor = color;
591*8975f5c5SAndroid Build Coastguard Worker }
592*8975f5c5SAndroid Build Coastguard Worker )";
593*8975f5c5SAndroid Build Coastguard Worker     const char simpleFragment[] = R"(precision mediump float;
594*8975f5c5SAndroid Build Coastguard Worker varying vec4 vColor;
595*8975f5c5SAndroid Build Coastguard Worker void main()
596*8975f5c5SAndroid Build Coastguard Worker {
597*8975f5c5SAndroid Build Coastguard Worker     gl_FragColor = vColor;
598*8975f5c5SAndroid Build Coastguard Worker }
599*8975f5c5SAndroid Build Coastguard Worker )";
600*8975f5c5SAndroid Build Coastguard Worker 
601*8975f5c5SAndroid Build Coastguard Worker     const uint32_t numComponents = 3;
602*8975f5c5SAndroid Build Coastguard Worker     const uint32_t width         = 4;
603*8975f5c5SAndroid Build Coastguard Worker     const uint32_t height        = 4;
604*8975f5c5SAndroid Build Coastguard Worker     const size_t numElements     = width * height * numComponents;
605*8975f5c5SAndroid Build Coastguard Worker     std::vector<uint8_t> srcData(numElements);
606*8975f5c5SAndroid Build Coastguard Worker     std::vector<uint8_t> dstData(numElements);
607*8975f5c5SAndroid Build Coastguard Worker 
608*8975f5c5SAndroid Build Coastguard Worker     for (uint8_t i = 0; i < srcData.size(); i++)
609*8975f5c5SAndroid Build Coastguard Worker     {
610*8975f5c5SAndroid Build Coastguard Worker         srcData[i] = 128;
611*8975f5c5SAndroid Build Coastguard Worker     }
612*8975f5c5SAndroid Build Coastguard Worker     for (uint8_t i = 0; i < dstData.size(); i++)
613*8975f5c5SAndroid Build Coastguard Worker     {
614*8975f5c5SAndroid Build Coastguard Worker         dstData[i] = 0;
615*8975f5c5SAndroid Build Coastguard Worker     }
616*8975f5c5SAndroid Build Coastguard Worker 
617*8975f5c5SAndroid Build Coastguard Worker     GLBuffer srcBuffer;
618*8975f5c5SAndroid Build Coastguard Worker     GLBuffer dstBuffer;
619*8975f5c5SAndroid Build Coastguard Worker 
620*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, srcBuffer);
621*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, srcData.size(), srcData.data(), GL_STATIC_DRAW);
622*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
623*8975f5c5SAndroid Build Coastguard Worker 
624*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, dstBuffer);
625*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_PIXEL_UNPACK_BUFFER, dstData.size(), dstData.data(), GL_STATIC_READ);
626*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
627*8975f5c5SAndroid Build Coastguard Worker 
628*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, simpleVertex, simpleFragment);
629*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
630*8975f5c5SAndroid Build Coastguard Worker 
631*8975f5c5SAndroid Build Coastguard Worker     GLint colorLoc = glGetAttribLocation(program, "color");
632*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, colorLoc);
633*8975f5c5SAndroid Build Coastguard Worker 
634*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, srcBuffer);
635*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(colorLoc, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
636*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(colorLoc);
637*8975f5c5SAndroid Build Coastguard Worker 
638*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, "position", 0.5f, 1.0f, true);
639*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
640*8975f5c5SAndroid Build Coastguard Worker 
641*8975f5c5SAndroid Build Coastguard Worker     glCopyBufferSubData(GL_ARRAY_BUFFER, GL_PIXEL_UNPACK_BUFFER, 0, 0, numElements);
642*8975f5c5SAndroid Build Coastguard Worker 
643*8975f5c5SAndroid Build Coastguard Worker     // With GL_MAP_READ_BIT, we expect the data to be flushed and updated to match srcData
644*8975f5c5SAndroid Build Coastguard Worker     uint8_t *data = reinterpret_cast<uint8_t *>(
645*8975f5c5SAndroid Build Coastguard Worker         glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, numElements, GL_MAP_READ_BIT));
646*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
647*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < numElements; ++i)
648*8975f5c5SAndroid Build Coastguard Worker     {
649*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(srcData[i], data[i]);
650*8975f5c5SAndroid Build Coastguard Worker     }
651*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
652*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
653*8975f5c5SAndroid Build Coastguard Worker }
654*8975f5c5SAndroid Build Coastguard Worker 
655*8975f5c5SAndroid Build Coastguard Worker // Test to verify mapping a buffer after copying to it contains expected data
656*8975f5c5SAndroid Build Coastguard Worker // with GL_MAP_UNSYNCHRONIZED_BIT
TEST_P(BufferDataTestES3,MapBufferUnsynchronizedReadTest)657*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTestES3, MapBufferUnsynchronizedReadTest)
658*8975f5c5SAndroid Build Coastguard Worker {
659*8975f5c5SAndroid Build Coastguard Worker     const char simpleVertex[]   = R"(attribute vec2 position;
660*8975f5c5SAndroid Build Coastguard Worker attribute vec4 color;
661*8975f5c5SAndroid Build Coastguard Worker varying vec4 vColor;
662*8975f5c5SAndroid Build Coastguard Worker void main()
663*8975f5c5SAndroid Build Coastguard Worker {
664*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(position, 0, 1);
665*8975f5c5SAndroid Build Coastguard Worker     vColor = color;
666*8975f5c5SAndroid Build Coastguard Worker }
667*8975f5c5SAndroid Build Coastguard Worker )";
668*8975f5c5SAndroid Build Coastguard Worker     const char simpleFragment[] = R"(precision mediump float;
669*8975f5c5SAndroid Build Coastguard Worker varying vec4 vColor;
670*8975f5c5SAndroid Build Coastguard Worker void main()
671*8975f5c5SAndroid Build Coastguard Worker {
672*8975f5c5SAndroid Build Coastguard Worker     gl_FragColor = vColor;
673*8975f5c5SAndroid Build Coastguard Worker }
674*8975f5c5SAndroid Build Coastguard Worker )";
675*8975f5c5SAndroid Build Coastguard Worker 
676*8975f5c5SAndroid Build Coastguard Worker     const uint32_t numComponents = 3;
677*8975f5c5SAndroid Build Coastguard Worker     const uint32_t width         = 4;
678*8975f5c5SAndroid Build Coastguard Worker     const uint32_t height        = 4;
679*8975f5c5SAndroid Build Coastguard Worker     const size_t numElements     = width * height * numComponents;
680*8975f5c5SAndroid Build Coastguard Worker     std::vector<uint8_t> srcData(numElements);
681*8975f5c5SAndroid Build Coastguard Worker     std::vector<uint8_t> dstData(numElements);
682*8975f5c5SAndroid Build Coastguard Worker 
683*8975f5c5SAndroid Build Coastguard Worker     for (uint8_t i = 0; i < srcData.size(); i++)
684*8975f5c5SAndroid Build Coastguard Worker     {
685*8975f5c5SAndroid Build Coastguard Worker         srcData[i] = 128;
686*8975f5c5SAndroid Build Coastguard Worker     }
687*8975f5c5SAndroid Build Coastguard Worker     for (uint8_t i = 0; i < dstData.size(); i++)
688*8975f5c5SAndroid Build Coastguard Worker     {
689*8975f5c5SAndroid Build Coastguard Worker         dstData[i] = 0;
690*8975f5c5SAndroid Build Coastguard Worker     }
691*8975f5c5SAndroid Build Coastguard Worker 
692*8975f5c5SAndroid Build Coastguard Worker     GLBuffer srcBuffer;
693*8975f5c5SAndroid Build Coastguard Worker     GLBuffer dstBuffer;
694*8975f5c5SAndroid Build Coastguard Worker 
695*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, srcBuffer);
696*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, srcData.size(), srcData.data(), GL_STATIC_DRAW);
697*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
698*8975f5c5SAndroid Build Coastguard Worker 
699*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, dstBuffer);
700*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_PIXEL_UNPACK_BUFFER, dstData.size(), dstData.data(), GL_STATIC_READ);
701*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
702*8975f5c5SAndroid Build Coastguard Worker 
703*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, simpleVertex, simpleFragment);
704*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
705*8975f5c5SAndroid Build Coastguard Worker 
706*8975f5c5SAndroid Build Coastguard Worker     GLint colorLoc = glGetAttribLocation(program, "color");
707*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, colorLoc);
708*8975f5c5SAndroid Build Coastguard Worker 
709*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, srcBuffer);
710*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(colorLoc, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
711*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(colorLoc);
712*8975f5c5SAndroid Build Coastguard Worker 
713*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, "position", 0.5f, 1.0f, true);
714*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
715*8975f5c5SAndroid Build Coastguard Worker 
716*8975f5c5SAndroid Build Coastguard Worker     glCopyBufferSubData(GL_ARRAY_BUFFER, GL_PIXEL_UNPACK_BUFFER, 0, 0, numElements);
717*8975f5c5SAndroid Build Coastguard Worker 
718*8975f5c5SAndroid Build Coastguard Worker     // Synchronize.
719*8975f5c5SAndroid Build Coastguard Worker     glFinish();
720*8975f5c5SAndroid Build Coastguard Worker 
721*8975f5c5SAndroid Build Coastguard Worker     // Map with GL_MAP_UNSYNCHRONIZED_BIT and overwrite buffers data with srcData
722*8975f5c5SAndroid Build Coastguard Worker     uint8_t *data = reinterpret_cast<uint8_t *>(glMapBufferRange(
723*8975f5c5SAndroid Build Coastguard Worker         GL_PIXEL_UNPACK_BUFFER, 0, numElements, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT));
724*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
725*8975f5c5SAndroid Build Coastguard Worker     memcpy(data, srcData.data(), srcData.size());
726*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
727*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
728*8975f5c5SAndroid Build Coastguard Worker 
729*8975f5c5SAndroid Build Coastguard Worker     // Map without GL_MAP_UNSYNCHRONIZED_BIT and read data. We expect it to be srcData
730*8975f5c5SAndroid Build Coastguard Worker     data = reinterpret_cast<uint8_t *>(
731*8975f5c5SAndroid Build Coastguard Worker         glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, numElements, GL_MAP_READ_BIT));
732*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
733*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < numElements; ++i)
734*8975f5c5SAndroid Build Coastguard Worker     {
735*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(srcData[i], data[i]);
736*8975f5c5SAndroid Build Coastguard Worker     }
737*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
738*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
739*8975f5c5SAndroid Build Coastguard Worker }
740*8975f5c5SAndroid Build Coastguard Worker 
741*8975f5c5SAndroid Build Coastguard Worker // Verify the functionality of glMapBufferRange()'s GL_MAP_UNSYNCHRONIZED_BIT
742*8975f5c5SAndroid Build Coastguard Worker // NOTE: On Vulkan, if we ever use memory that's not `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT`, then
743*8975f5c5SAndroid Build Coastguard Worker // this could incorrectly pass.
TEST_P(BufferDataTestES3,MapBufferRangeUnsynchronizedBit)744*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTestES3, MapBufferRangeUnsynchronizedBit)
745*8975f5c5SAndroid Build Coastguard Worker {
746*8975f5c5SAndroid Build Coastguard Worker     // We can currently only control the behavior of the Vulkan backend's synchronizing operation's
747*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsVulkan());
748*8975f5c5SAndroid Build Coastguard Worker 
749*8975f5c5SAndroid Build Coastguard Worker     const size_t numElements = 10;
750*8975f5c5SAndroid Build Coastguard Worker     std::vector<uint8_t> srcData(numElements);
751*8975f5c5SAndroid Build Coastguard Worker     std::vector<uint8_t> dstData(numElements);
752*8975f5c5SAndroid Build Coastguard Worker 
753*8975f5c5SAndroid Build Coastguard Worker     for (uint8_t i = 0; i < srcData.size(); i++)
754*8975f5c5SAndroid Build Coastguard Worker     {
755*8975f5c5SAndroid Build Coastguard Worker         srcData[i] = i;
756*8975f5c5SAndroid Build Coastguard Worker     }
757*8975f5c5SAndroid Build Coastguard Worker     for (uint8_t i = 0; i < dstData.size(); i++)
758*8975f5c5SAndroid Build Coastguard Worker     {
759*8975f5c5SAndroid Build Coastguard Worker         dstData[i] = static_cast<uint8_t>(i + dstData.size());
760*8975f5c5SAndroid Build Coastguard Worker     }
761*8975f5c5SAndroid Build Coastguard Worker 
762*8975f5c5SAndroid Build Coastguard Worker     GLBuffer srcBuffer;
763*8975f5c5SAndroid Build Coastguard Worker     GLBuffer dstBuffer;
764*8975f5c5SAndroid Build Coastguard Worker 
765*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_COPY_READ_BUFFER, srcBuffer);
766*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
767*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_COPY_WRITE_BUFFER, dstBuffer);
768*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
769*8975f5c5SAndroid Build Coastguard Worker 
770*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_COPY_READ_BUFFER, srcData.size(), srcData.data(), GL_STATIC_DRAW);
771*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
772*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_COPY_WRITE_BUFFER, dstData.size(), dstData.data(), GL_STATIC_READ);
773*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
774*8975f5c5SAndroid Build Coastguard Worker 
775*8975f5c5SAndroid Build Coastguard Worker     glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, numElements);
776*8975f5c5SAndroid Build Coastguard Worker 
777*8975f5c5SAndroid Build Coastguard Worker     // With GL_MAP_UNSYNCHRONIZED_BIT, we expect the data to be stale and match dstData
778*8975f5c5SAndroid Build Coastguard Worker     // NOTE: We are specifying GL_MAP_WRITE_BIT so we can use GL_MAP_UNSYNCHRONIZED_BIT. This is
779*8975f5c5SAndroid Build Coastguard Worker     // venturing into undefined behavior, since we are actually planning on reading from this
780*8975f5c5SAndroid Build Coastguard Worker     // pointer.
781*8975f5c5SAndroid Build Coastguard Worker     auto *data = reinterpret_cast<uint8_t *>(glMapBufferRange(
782*8975f5c5SAndroid Build Coastguard Worker         GL_COPY_WRITE_BUFFER, 0, numElements, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT));
783*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
784*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < numElements; ++i)
785*8975f5c5SAndroid Build Coastguard Worker     {
786*8975f5c5SAndroid Build Coastguard Worker         // Allow for the possibility that data matches either "dstData" or "srcData"
787*8975f5c5SAndroid Build Coastguard Worker         if (dstData[i] != data[i])
788*8975f5c5SAndroid Build Coastguard Worker         {
789*8975f5c5SAndroid Build Coastguard Worker             EXPECT_EQ(srcData[i], data[i]);
790*8975f5c5SAndroid Build Coastguard Worker         }
791*8975f5c5SAndroid Build Coastguard Worker     }
792*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_COPY_WRITE_BUFFER);
793*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
794*8975f5c5SAndroid Build Coastguard Worker 
795*8975f5c5SAndroid Build Coastguard Worker     // Without GL_MAP_UNSYNCHRONIZED_BIT, we expect the data to be copied and match srcData
796*8975f5c5SAndroid Build Coastguard Worker     data = reinterpret_cast<uint8_t *>(
797*8975f5c5SAndroid Build Coastguard Worker         glMapBufferRange(GL_COPY_WRITE_BUFFER, 0, numElements, GL_MAP_READ_BIT));
798*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
799*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < numElements; ++i)
800*8975f5c5SAndroid Build Coastguard Worker     {
801*8975f5c5SAndroid Build Coastguard Worker         EXPECT_EQ(srcData[i], data[i]);
802*8975f5c5SAndroid Build Coastguard Worker     }
803*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_COPY_WRITE_BUFFER);
804*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
805*8975f5c5SAndroid Build Coastguard Worker }
806*8975f5c5SAndroid Build Coastguard Worker 
807*8975f5c5SAndroid Build Coastguard Worker // Verify OES_mapbuffer is present if EXT_map_buffer_range is.
TEST_P(BufferDataTest,ExtensionDependency)808*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTest, ExtensionDependency)
809*8975f5c5SAndroid Build Coastguard Worker {
810*8975f5c5SAndroid Build Coastguard Worker     if (IsGLExtensionEnabled("GL_EXT_map_buffer_range"))
811*8975f5c5SAndroid Build Coastguard Worker     {
812*8975f5c5SAndroid Build Coastguard Worker         ASSERT_TRUE(IsGLExtensionEnabled("GL_OES_mapbuffer"));
813*8975f5c5SAndroid Build Coastguard Worker     }
814*8975f5c5SAndroid Build Coastguard Worker }
815*8975f5c5SAndroid Build Coastguard Worker 
816*8975f5c5SAndroid Build Coastguard Worker // Test mapping with the OES extension.
TEST_P(BufferDataTest,MapBufferOES)817*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTest, MapBufferOES)
818*8975f5c5SAndroid Build Coastguard Worker {
819*8975f5c5SAndroid Build Coastguard Worker     if (!IsGLExtensionEnabled("GL_EXT_map_buffer_range"))
820*8975f5c5SAndroid Build Coastguard Worker     {
821*8975f5c5SAndroid Build Coastguard Worker         // Needed for test validation.
822*8975f5c5SAndroid Build Coastguard Worker         return;
823*8975f5c5SAndroid Build Coastguard Worker     }
824*8975f5c5SAndroid Build Coastguard Worker 
825*8975f5c5SAndroid Build Coastguard Worker     std::vector<uint8_t> data(1024);
826*8975f5c5SAndroid Build Coastguard Worker     FillVectorWithRandomUBytes(&data);
827*8975f5c5SAndroid Build Coastguard Worker 
828*8975f5c5SAndroid Build Coastguard Worker     GLBuffer buffer;
829*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, buffer);
830*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, data.size(), nullptr, GL_STATIC_DRAW);
831*8975f5c5SAndroid Build Coastguard Worker 
832*8975f5c5SAndroid Build Coastguard Worker     // Validate that other map flags don't work.
833*8975f5c5SAndroid Build Coastguard Worker     void *badMapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_MAP_READ_BIT);
834*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(nullptr, badMapPtr);
835*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_ENUM);
836*8975f5c5SAndroid Build Coastguard Worker 
837*8975f5c5SAndroid Build Coastguard Worker     // Map and write.
838*8975f5c5SAndroid Build Coastguard Worker     void *mapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
839*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(nullptr, mapPtr);
840*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
841*8975f5c5SAndroid Build Coastguard Worker     memcpy(mapPtr, data.data(), data.size());
842*8975f5c5SAndroid Build Coastguard Worker     glUnmapBufferOES(GL_ARRAY_BUFFER);
843*8975f5c5SAndroid Build Coastguard Worker 
844*8975f5c5SAndroid Build Coastguard Worker     // Validate data with EXT_map_buffer_range
845*8975f5c5SAndroid Build Coastguard Worker     void *readMapPtr = glMapBufferRangeEXT(GL_ARRAY_BUFFER, 0, data.size(), GL_MAP_READ_BIT_EXT);
846*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(nullptr, readMapPtr);
847*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
848*8975f5c5SAndroid Build Coastguard Worker     std::vector<uint8_t> actualData(data.size());
849*8975f5c5SAndroid Build Coastguard Worker     memcpy(actualData.data(), readMapPtr, data.size());
850*8975f5c5SAndroid Build Coastguard Worker     glUnmapBufferOES(GL_ARRAY_BUFFER);
851*8975f5c5SAndroid Build Coastguard Worker 
852*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(data, actualData);
853*8975f5c5SAndroid Build Coastguard Worker }
854*8975f5c5SAndroid Build Coastguard Worker 
855*8975f5c5SAndroid Build Coastguard Worker // Test to verify mapping a dynamic buffer with GL_MAP_UNSYNCHRONIZED_BIT to modify a portion
856*8975f5c5SAndroid Build Coastguard Worker // won't affect draw calls using other portions.
TEST_P(BufferDataTest,MapDynamicBufferUnsynchronizedEXTTest)857*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTest, MapDynamicBufferUnsynchronizedEXTTest)
858*8975f5c5SAndroid Build Coastguard Worker {
859*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
860*8975f5c5SAndroid Build Coastguard Worker 
861*8975f5c5SAndroid Build Coastguard Worker     const char simpleVertex[]   = R"(attribute vec2 position;
862*8975f5c5SAndroid Build Coastguard Worker attribute vec4 color;
863*8975f5c5SAndroid Build Coastguard Worker varying vec4 vColor;
864*8975f5c5SAndroid Build Coastguard Worker void main()
865*8975f5c5SAndroid Build Coastguard Worker {
866*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(position, 0, 1);
867*8975f5c5SAndroid Build Coastguard Worker     vColor = color;
868*8975f5c5SAndroid Build Coastguard Worker }
869*8975f5c5SAndroid Build Coastguard Worker )";
870*8975f5c5SAndroid Build Coastguard Worker     const char simpleFragment[] = R"(precision mediump float;
871*8975f5c5SAndroid Build Coastguard Worker varying vec4 vColor;
872*8975f5c5SAndroid Build Coastguard Worker void main()
873*8975f5c5SAndroid Build Coastguard Worker {
874*8975f5c5SAndroid Build Coastguard Worker     gl_FragColor = vColor;
875*8975f5c5SAndroid Build Coastguard Worker }
876*8975f5c5SAndroid Build Coastguard Worker )";
877*8975f5c5SAndroid Build Coastguard Worker 
878*8975f5c5SAndroid Build Coastguard Worker     constexpr int kNumVertices = 6;
879*8975f5c5SAndroid Build Coastguard Worker 
880*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLubyte> color(8 * kNumVertices);
881*8975f5c5SAndroid Build Coastguard Worker     for (int i = 0; i < kNumVertices; ++i)
882*8975f5c5SAndroid Build Coastguard Worker     {
883*8975f5c5SAndroid Build Coastguard Worker         color[4 * i]     = 255;
884*8975f5c5SAndroid Build Coastguard Worker         color[4 * i + 3] = 255;
885*8975f5c5SAndroid Build Coastguard Worker     }
886*8975f5c5SAndroid Build Coastguard Worker     GLBuffer buffer;
887*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, buffer);
888*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, color.size(), color.data(), GL_DYNAMIC_DRAW);
889*8975f5c5SAndroid Build Coastguard Worker 
890*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, simpleVertex, simpleFragment);
891*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
892*8975f5c5SAndroid Build Coastguard Worker 
893*8975f5c5SAndroid Build Coastguard Worker     GLint colorLoc = glGetAttribLocation(program, "color");
894*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, colorLoc);
895*8975f5c5SAndroid Build Coastguard Worker 
896*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
897*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(colorLoc);
898*8975f5c5SAndroid Build Coastguard Worker 
899*8975f5c5SAndroid Build Coastguard Worker     glViewport(0, 0, 2, 2);
900*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, "position", 0.5f, 1.0f, true);
901*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
902*8975f5c5SAndroid Build Coastguard Worker 
903*8975f5c5SAndroid Build Coastguard Worker     // Map with GL_MAP_UNSYNCHRONIZED_BIT and overwrite buffers data at offset 24
904*8975f5c5SAndroid Build Coastguard Worker     uint8_t *data = reinterpret_cast<uint8_t *>(
905*8975f5c5SAndroid Build Coastguard Worker         glMapBufferRangeEXT(GL_ARRAY_BUFFER, 4 * kNumVertices, 4 * kNumVertices,
906*8975f5c5SAndroid Build Coastguard Worker                             GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT));
907*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
908*8975f5c5SAndroid Build Coastguard Worker     for (int i = 0; i < kNumVertices; ++i)
909*8975f5c5SAndroid Build Coastguard Worker     {
910*8975f5c5SAndroid Build Coastguard Worker         data[4 * i]     = 0;
911*8975f5c5SAndroid Build Coastguard Worker         data[4 * i + 1] = 255;
912*8975f5c5SAndroid Build Coastguard Worker         data[4 * i + 2] = 0;
913*8975f5c5SAndroid Build Coastguard Worker         data[4 * i + 3] = 255;
914*8975f5c5SAndroid Build Coastguard Worker     }
915*8975f5c5SAndroid Build Coastguard Worker     glUnmapBufferOES(GL_ARRAY_BUFFER);
916*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
917*8975f5c5SAndroid Build Coastguard Worker 
918*8975f5c5SAndroid Build Coastguard Worker     // Re-draw using offset = 0 but to different viewport
919*8975f5c5SAndroid Build Coastguard Worker     glViewport(0, 2, 2, 2);
920*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, "position", 0.5f, 1.0f, true);
921*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
922*8975f5c5SAndroid Build Coastguard Worker 
923*8975f5c5SAndroid Build Coastguard Worker     // Change vertex attribute to use buffer starting from offset 24
924*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0,
925*8975f5c5SAndroid Build Coastguard Worker                           reinterpret_cast<void *>(4 * kNumVertices));
926*8975f5c5SAndroid Build Coastguard Worker 
927*8975f5c5SAndroid Build Coastguard Worker     glViewport(2, 2, 2, 2);
928*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, "position", 0.5f, 1.0f, true);
929*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
930*8975f5c5SAndroid Build Coastguard Worker 
931*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
932*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(1, 3, GLColor::red);
933*8975f5c5SAndroid Build Coastguard Worker 
934*8975f5c5SAndroid Build Coastguard Worker     // The result below is undefined. The glBufferData at the top puts
935*8975f5c5SAndroid Build Coastguard Worker     // [red, red, red, ..., zero, zero, zero, ...]
936*8975f5c5SAndroid Build Coastguard Worker     // in the buffer and the glMap,glUnmap tries to overwrite the zeros with green
937*8975f5c5SAndroid Build Coastguard Worker     // but because UNSYNCHRONIZED was passed in there's no guarantee those
938*8975f5c5SAndroid Build Coastguard Worker     // zeros have been written yet. If they haven't they'll overwrite the
939*8975f5c5SAndroid Build Coastguard Worker     // greens.
940*8975f5c5SAndroid Build Coastguard Worker     // EXPECT_PIXEL_COLOR_EQ(3, 3, GLColor::green);
941*8975f5c5SAndroid Build Coastguard Worker }
942*8975f5c5SAndroid Build Coastguard Worker 
943*8975f5c5SAndroid Build Coastguard Worker // Verify that we can map and write the buffer between draws and the second draw sees the new buffer
944*8975f5c5SAndroid Build Coastguard Worker // data, using drawQuad().
TEST_P(BufferDataTest,MapWriteArrayBufferDataDrawQuad)945*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTest, MapWriteArrayBufferDataDrawQuad)
946*8975f5c5SAndroid Build Coastguard Worker {
947*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
948*8975f5c5SAndroid Build Coastguard Worker 
949*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLfloat> data(6, 0.0f);
950*8975f5c5SAndroid Build Coastguard Worker 
951*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(mProgram);
952*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
953*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), nullptr, GL_STATIC_DRAW);
954*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
955*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(mAttribLocation);
956*8975f5c5SAndroid Build Coastguard Worker 
957*8975f5c5SAndroid Build Coastguard Worker     // Don't read back to verify black, so we don't break the render pass.
958*8975f5c5SAndroid Build Coastguard Worker     drawQuad(mProgram, "position", 0.5f);
959*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
960*8975f5c5SAndroid Build Coastguard Worker 
961*8975f5c5SAndroid Build Coastguard Worker     // Map and write.
962*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLfloat> data2(6, 1.0f);
963*8975f5c5SAndroid Build Coastguard Worker     void *mapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
964*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(nullptr, mapPtr);
965*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
966*8975f5c5SAndroid Build Coastguard Worker     memcpy(mapPtr, data2.data(), sizeof(GLfloat) * data2.size());
967*8975f5c5SAndroid Build Coastguard Worker     glUnmapBufferOES(GL_ARRAY_BUFFER);
968*8975f5c5SAndroid Build Coastguard Worker 
969*8975f5c5SAndroid Build Coastguard Worker     drawQuad(mProgram, "position", 0.5f);
970*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(8, 8, GLColor::red);
971*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
972*8975f5c5SAndroid Build Coastguard Worker }
973*8975f5c5SAndroid Build Coastguard Worker 
974*8975f5c5SAndroid Build Coastguard Worker // Verify that we can map and write the buffer between draws and the second draw sees the new buffer
975*8975f5c5SAndroid Build Coastguard Worker // data, calling glDrawArrays() directly.
TEST_P(BufferDataTest,MapWriteArrayBufferDataDrawArrays)976*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTest, MapWriteArrayBufferDataDrawArrays)
977*8975f5c5SAndroid Build Coastguard Worker {
978*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
979*8975f5c5SAndroid Build Coastguard Worker 
980*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLfloat> data(6, 0.0f);
981*8975f5c5SAndroid Build Coastguard Worker 
982*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(mProgram);
983*8975f5c5SAndroid Build Coastguard Worker 
984*8975f5c5SAndroid Build Coastguard Worker     GLint positionLocation = glGetAttribLocation(mProgram, "position");
985*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, positionLocation);
986*8975f5c5SAndroid Build Coastguard Worker 
987*8975f5c5SAndroid Build Coastguard Worker     // Set up position attribute, don't use drawQuad.
988*8975f5c5SAndroid Build Coastguard Worker     auto quadVertices = GetQuadVertices();
989*8975f5c5SAndroid Build Coastguard Worker 
990*8975f5c5SAndroid Build Coastguard Worker     GLBuffer positionBuffer;
991*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
992*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * quadVertices.size() * 3, quadVertices.data(),
993*8975f5c5SAndroid Build Coastguard Worker                  GL_DYNAMIC_DRAW);
994*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
995*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(positionLocation);
996*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
997*8975f5c5SAndroid Build Coastguard Worker 
998*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
999*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), nullptr, GL_STATIC_DRAW);
1000*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1001*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(mAttribLocation);
1002*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1003*8975f5c5SAndroid Build Coastguard Worker 
1004*8975f5c5SAndroid Build Coastguard Worker     // Don't read back to verify black, so we don't break the render pass.
1005*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 6);
1006*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1007*8975f5c5SAndroid Build Coastguard Worker 
1008*8975f5c5SAndroid Build Coastguard Worker     // Map and write.
1009*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLfloat> data2(6, 1.0f);
1010*8975f5c5SAndroid Build Coastguard Worker     void *mapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
1011*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(nullptr, mapPtr);
1012*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1013*8975f5c5SAndroid Build Coastguard Worker     memcpy(mapPtr, data2.data(), sizeof(GLfloat) * data2.size());
1014*8975f5c5SAndroid Build Coastguard Worker     glUnmapBufferOES(GL_ARRAY_BUFFER);
1015*8975f5c5SAndroid Build Coastguard Worker 
1016*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 6);
1017*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(8, 8, GLColor::red);
1018*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1019*8975f5c5SAndroid Build Coastguard Worker }
1020*8975f5c5SAndroid Build Coastguard Worker 
1021*8975f5c5SAndroid Build Coastguard Worker // Verify that buffer sub data uploads are properly validated within the buffer size range on 32-bit
1022*8975f5c5SAndroid Build Coastguard Worker // systems.
TEST_P(BufferDataTest,BufferSizeValidation32Bit)1023*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTest, BufferSizeValidation32Bit)
1024*8975f5c5SAndroid Build Coastguard Worker {
1025*8975f5c5SAndroid Build Coastguard Worker     GLBuffer buffer;
1026*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, buffer);
1027*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, 100, nullptr, GL_STATIC_DRAW);
1028*8975f5c5SAndroid Build Coastguard Worker 
1029*8975f5c5SAndroid Build Coastguard Worker     GLubyte data = 0;
1030*8975f5c5SAndroid Build Coastguard Worker     glBufferSubData(GL_ARRAY_BUFFER, std::numeric_limits<uint32_t>::max(), 1, &data);
1031*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_VALUE);
1032*8975f5c5SAndroid Build Coastguard Worker }
1033*8975f5c5SAndroid Build Coastguard Worker 
1034*8975f5c5SAndroid Build Coastguard Worker // Some drivers generate errors when array buffer bindings are left mapped during draw calls.
1035*8975f5c5SAndroid Build Coastguard Worker // crbug.com/1345777
TEST_P(BufferDataTestES3,GLDriverErrorWhenMappingArrayBuffersDuringDraw)1036*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTestES3, GLDriverErrorWhenMappingArrayBuffersDuringDraw)
1037*8975f5c5SAndroid Build Coastguard Worker {
1038*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1039*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(program, 0u);
1040*8975f5c5SAndroid Build Coastguard Worker 
1041*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
1042*8975f5c5SAndroid Build Coastguard Worker 
1043*8975f5c5SAndroid Build Coastguard Worker     auto quadVertices = GetQuadVertices();
1044*8975f5c5SAndroid Build Coastguard Worker 
1045*8975f5c5SAndroid Build Coastguard Worker     GLBuffer vb;
1046*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, vb);
1047*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * quadVertices.size(), quadVertices.data(),
1048*8975f5c5SAndroid Build Coastguard Worker                  GL_STATIC_DRAW);
1049*8975f5c5SAndroid Build Coastguard Worker 
1050*8975f5c5SAndroid Build Coastguard Worker     GLint positionLocation = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
1051*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, positionLocation);
1052*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1053*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(positionLocation);
1054*8975f5c5SAndroid Build Coastguard Worker 
1055*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 6);
1056*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1057*8975f5c5SAndroid Build Coastguard Worker 
1058*8975f5c5SAndroid Build Coastguard Worker     GLBuffer pb;
1059*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pb);
1060*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_PIXEL_UNPACK_BUFFER, 1024, nullptr, GL_STREAM_DRAW);
1061*8975f5c5SAndroid Build Coastguard Worker     glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, 1024, GL_MAP_WRITE_BIT);
1062*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1063*8975f5c5SAndroid Build Coastguard Worker 
1064*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 6);
1065*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1066*8975f5c5SAndroid Build Coastguard Worker }
1067*8975f5c5SAndroid Build Coastguard Worker 
1068*8975f5c5SAndroid Build Coastguard Worker // Tests a null crash bug caused by copying from null back-end buffer pointer
1069*8975f5c5SAndroid Build Coastguard Worker // when calling bufferData again after drawing without calling bufferData in D3D11.
TEST_P(BufferDataTestES3,DrawWithNotCallingBufferData)1070*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTestES3, DrawWithNotCallingBufferData)
1071*8975f5c5SAndroid Build Coastguard Worker {
1072*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
1073*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(drawRed);
1074*8975f5c5SAndroid Build Coastguard Worker 
1075*8975f5c5SAndroid Build Coastguard Worker     GLint mem = 0;
1076*8975f5c5SAndroid Build Coastguard Worker     GLBuffer buffer;
1077*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, buffer);
1078*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(0);
1079*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
1080*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 3);
1081*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_COPY_WRITE_BUFFER, buffer);
1082*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_COPY_WRITE_BUFFER, 1, &mem, GL_STREAM_DRAW);
1083*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1084*8975f5c5SAndroid Build Coastguard Worker }
1085*8975f5c5SAndroid Build Coastguard Worker 
1086*8975f5c5SAndroid Build Coastguard Worker // Tests a bug where copying buffer data immediately after creation hit a nullptr in D3D11.
TEST_P(BufferDataTestES3,NoBufferInitDataCopyBug)1087*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTestES3, NoBufferInitDataCopyBug)
1088*8975f5c5SAndroid Build Coastguard Worker {
1089*8975f5c5SAndroid Build Coastguard Worker     constexpr GLsizei size = 64;
1090*8975f5c5SAndroid Build Coastguard Worker 
1091*8975f5c5SAndroid Build Coastguard Worker     GLBuffer sourceBuffer;
1092*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_COPY_READ_BUFFER, sourceBuffer);
1093*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_COPY_READ_BUFFER, size, nullptr, GL_STATIC_DRAW);
1094*8975f5c5SAndroid Build Coastguard Worker 
1095*8975f5c5SAndroid Build Coastguard Worker     GLBuffer destBuffer;
1096*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, destBuffer);
1097*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, size, nullptr, GL_STATIC_DRAW);
1098*8975f5c5SAndroid Build Coastguard Worker 
1099*8975f5c5SAndroid Build Coastguard Worker     glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_ARRAY_BUFFER, 0, 0, size);
1100*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1101*8975f5c5SAndroid Build Coastguard Worker }
1102*8975f5c5SAndroid Build Coastguard Worker 
1103*8975f5c5SAndroid Build Coastguard Worker // This a shortened version of dEQP functional.buffer.copy.basic.array_copy_read. It provoked
1104*8975f5c5SAndroid Build Coastguard Worker // a bug in copyBufferSubData. The bug appeared to be that conversion buffers were not marked
1105*8975f5c5SAndroid Build Coastguard Worker // as dirty and therefore after copyBufferSubData the next draw call using the buffer that
1106*8975f5c5SAndroid Build Coastguard Worker // just had data copied to it was not re-converted. It's not clear to me how this ever worked
1107*8975f5c5SAndroid Build Coastguard Worker // or why changes to bufferSubData from
1108*8975f5c5SAndroid Build Coastguard Worker // https://chromium-review.googlesource.com/c/angle/angle/+/3842641 made this issue appear and
1109*8975f5c5SAndroid Build Coastguard Worker // why it wasn't already broken.
TEST_P(BufferDataTestES3,CopyBufferSubDataDraw)1110*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTestES3, CopyBufferSubDataDraw)
1111*8975f5c5SAndroid Build Coastguard Worker {
1112*8975f5c5SAndroid Build Coastguard Worker     const char simpleVertex[]   = R"(attribute vec2 position;
1113*8975f5c5SAndroid Build Coastguard Worker attribute vec4 color;
1114*8975f5c5SAndroid Build Coastguard Worker varying vec4 vColor;
1115*8975f5c5SAndroid Build Coastguard Worker void main()
1116*8975f5c5SAndroid Build Coastguard Worker {
1117*8975f5c5SAndroid Build Coastguard Worker     gl_Position = vec4(position, 0, 1);
1118*8975f5c5SAndroid Build Coastguard Worker     vColor = color;
1119*8975f5c5SAndroid Build Coastguard Worker }
1120*8975f5c5SAndroid Build Coastguard Worker )";
1121*8975f5c5SAndroid Build Coastguard Worker     const char simpleFragment[] = R"(precision mediump float;
1122*8975f5c5SAndroid Build Coastguard Worker varying vec4 vColor;
1123*8975f5c5SAndroid Build Coastguard Worker void main()
1124*8975f5c5SAndroid Build Coastguard Worker {
1125*8975f5c5SAndroid Build Coastguard Worker     gl_FragColor = vColor;
1126*8975f5c5SAndroid Build Coastguard Worker }
1127*8975f5c5SAndroid Build Coastguard Worker )";
1128*8975f5c5SAndroid Build Coastguard Worker 
1129*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, simpleVertex, simpleFragment);
1130*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
1131*8975f5c5SAndroid Build Coastguard Worker 
1132*8975f5c5SAndroid Build Coastguard Worker     GLint colorLoc = glGetAttribLocation(program, "color");
1133*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, colorLoc);
1134*8975f5c5SAndroid Build Coastguard Worker     GLint posLoc = glGetAttribLocation(program, "position");
1135*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, posLoc);
1136*8975f5c5SAndroid Build Coastguard Worker 
1137*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0, 0, 0, 0);
1138*8975f5c5SAndroid Build Coastguard Worker 
1139*8975f5c5SAndroid Build Coastguard Worker     GLBuffer srcBuffer;  // green
1140*8975f5c5SAndroid Build Coastguard Worker     GLBuffer dstBuffer;  // red
1141*8975f5c5SAndroid Build Coastguard Worker 
1142*8975f5c5SAndroid Build Coastguard Worker     constexpr size_t numElements = 399;
1143*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLColorRGB> reds(numElements, GLColorRGB::red);
1144*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLColorRGB> greens(numElements, GLColorRGB::green);
1145*8975f5c5SAndroid Build Coastguard Worker     constexpr size_t sizeOfElem  = sizeof(decltype(greens)::value_type);
1146*8975f5c5SAndroid Build Coastguard Worker     constexpr size_t sizeInBytes = numElements * sizeOfElem;
1147*8975f5c5SAndroid Build Coastguard Worker 
1148*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, srcBuffer);
1149*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeInBytes, greens.data(), GL_STREAM_DRAW);
1150*8975f5c5SAndroid Build Coastguard Worker 
1151*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_COPY_READ_BUFFER, dstBuffer);
1152*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_COPY_READ_BUFFER, sizeInBytes, reds.data(), GL_STREAM_DRAW);
1153*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1154*8975f5c5SAndroid Build Coastguard Worker 
1155*8975f5c5SAndroid Build Coastguard Worker     constexpr size_t numQuads = numElements / 4;
1156*8975f5c5SAndroid Build Coastguard Worker 
1157*8975f5c5SAndroid Build Coastguard Worker     // Generate quads that fill clip space to use all the vertex colors
1158*8975f5c5SAndroid Build Coastguard Worker     std::vector<float> positions(numQuads * 4 * 2);
1159*8975f5c5SAndroid Build Coastguard Worker     for (size_t quad = 0; quad < numQuads; ++quad)
1160*8975f5c5SAndroid Build Coastguard Worker     {
1161*8975f5c5SAndroid Build Coastguard Worker         size_t offset = quad * 4 * 2;
1162*8975f5c5SAndroid Build Coastguard Worker         float x0      = float(quad + 0) / numQuads * 2.0f - 1.0f;
1163*8975f5c5SAndroid Build Coastguard Worker         float x1      = float(quad + 1) / numQuads * 2.0f - 1.0f;
1164*8975f5c5SAndroid Build Coastguard Worker 
1165*8975f5c5SAndroid Build Coastguard Worker         /*
1166*8975f5c5SAndroid Build Coastguard Worker            2--3
1167*8975f5c5SAndroid Build Coastguard Worker            |  |
1168*8975f5c5SAndroid Build Coastguard Worker            0--1
1169*8975f5c5SAndroid Build Coastguard Worker         */
1170*8975f5c5SAndroid Build Coastguard Worker         positions[offset + 0] = x0;
1171*8975f5c5SAndroid Build Coastguard Worker         positions[offset + 1] = -1;
1172*8975f5c5SAndroid Build Coastguard Worker         positions[offset + 2] = x1;
1173*8975f5c5SAndroid Build Coastguard Worker         positions[offset + 3] = -1;
1174*8975f5c5SAndroid Build Coastguard Worker         positions[offset + 4] = x0;
1175*8975f5c5SAndroid Build Coastguard Worker         positions[offset + 5] = 1;
1176*8975f5c5SAndroid Build Coastguard Worker         positions[offset + 6] = x1;
1177*8975f5c5SAndroid Build Coastguard Worker         positions[offset + 7] = 1;
1178*8975f5c5SAndroid Build Coastguard Worker     }
1179*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, 0);
1180*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(posLoc);
1181*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, positions.data());
1182*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1183*8975f5c5SAndroid Build Coastguard Worker 
1184*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, srcBuffer);
1185*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(colorLoc);
1186*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(colorLoc, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
1187*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1188*8975f5c5SAndroid Build Coastguard Worker 
1189*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
1190*8975f5c5SAndroid Build Coastguard Worker 
1191*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLushort> indices(numQuads * 6);
1192*8975f5c5SAndroid Build Coastguard Worker     for (size_t quad = 0; quad < numQuads; ++quad)
1193*8975f5c5SAndroid Build Coastguard Worker     {
1194*8975f5c5SAndroid Build Coastguard Worker         size_t ndx          = quad * 4;
1195*8975f5c5SAndroid Build Coastguard Worker         size_t offset       = quad * 6;
1196*8975f5c5SAndroid Build Coastguard Worker         indices[offset + 0] = ndx;
1197*8975f5c5SAndroid Build Coastguard Worker         indices[offset + 1] = ndx + 1;
1198*8975f5c5SAndroid Build Coastguard Worker         indices[offset + 2] = ndx + 2;
1199*8975f5c5SAndroid Build Coastguard Worker         indices[offset + 3] = ndx + 2;
1200*8975f5c5SAndroid Build Coastguard Worker         indices[offset + 4] = ndx + 1;
1201*8975f5c5SAndroid Build Coastguard Worker         indices[offset + 5] = ndx + 3;
1202*8975f5c5SAndroid Build Coastguard Worker     }
1203*8975f5c5SAndroid Build Coastguard Worker     GLBuffer indexBuffer;
1204*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1205*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(decltype(indices)::value_type),
1206*8975f5c5SAndroid Build Coastguard Worker                  indices.data(), GL_STATIC_DRAW);
1207*8975f5c5SAndroid Build Coastguard Worker 
1208*8975f5c5SAndroid Build Coastguard Worker     // Draw with srcBuffer (green)
1209*8975f5c5SAndroid Build Coastguard Worker     glDrawElements(GL_TRIANGLES, numQuads * 6, GL_UNSIGNED_SHORT, 0);
1210*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_RECT_EQ(0, 0, 16, 16, GLColor::green);
1211*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1212*8975f5c5SAndroid Build Coastguard Worker 
1213*8975f5c5SAndroid Build Coastguard Worker     // Draw with dstBuffer (red)
1214*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, dstBuffer);
1215*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(colorLoc);
1216*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(colorLoc, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
1217*8975f5c5SAndroid Build Coastguard Worker     glDrawElements(GL_TRIANGLES, numQuads * 6, GL_UNSIGNED_SHORT, 0);
1218*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_RECT_EQ(0, 0, 16, 16, GLColor::red);
1219*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1220*8975f5c5SAndroid Build Coastguard Worker 
1221*8975f5c5SAndroid Build Coastguard Worker     // Copy src to dst. Yes, we're using GL_COPY_READ_BUFFER as dest because that's what the dEQP
1222*8975f5c5SAndroid Build Coastguard Worker     // test was testing.
1223*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, srcBuffer);
1224*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_COPY_READ_BUFFER, dstBuffer);
1225*8975f5c5SAndroid Build Coastguard Worker     glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_READ_BUFFER, 0, 0, sizeInBytes);
1226*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1227*8975f5c5SAndroid Build Coastguard Worker 
1228*8975f5c5SAndroid Build Coastguard Worker     // Draw with srcBuffer. It should still be green.
1229*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, srcBuffer);
1230*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(colorLoc);
1231*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(colorLoc, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
1232*8975f5c5SAndroid Build Coastguard Worker     glDrawElements(GL_TRIANGLES, numQuads * 6, GL_UNSIGNED_SHORT, 0);
1233*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_RECT_EQ(0, 0, 16, 16, GLColor::green);
1234*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1235*8975f5c5SAndroid Build Coastguard Worker 
1236*8975f5c5SAndroid Build Coastguard Worker     // Draw with dstBuffer. It should now be green too.
1237*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, dstBuffer);
1238*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(colorLoc);
1239*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(colorLoc, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, nullptr);
1240*8975f5c5SAndroid Build Coastguard Worker     glDrawElements(GL_TRIANGLES, numQuads * 6, GL_UNSIGNED_SHORT, 0);
1241*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_RECT_EQ(0, 0, 16, 16, GLColor::green);
1242*8975f5c5SAndroid Build Coastguard Worker 
1243*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1244*8975f5c5SAndroid Build Coastguard Worker }
1245*8975f5c5SAndroid Build Coastguard Worker 
1246*8975f5c5SAndroid Build Coastguard Worker // Ensures that calling glBufferData on a mapped buffer results in an unmapped buffer
TEST_P(BufferDataTestES3,BufferDataUnmap)1247*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTestES3, BufferDataUnmap)
1248*8975f5c5SAndroid Build Coastguard Worker {
1249*8975f5c5SAndroid Build Coastguard Worker     // Per the OpenGL ES 3.0 spec, buffers are implicity unmapped when a call to
1250*8975f5c5SAndroid Build Coastguard Worker     // BufferData happens on a mapped buffer:
1251*8975f5c5SAndroid Build Coastguard Worker     //
1252*8975f5c5SAndroid Build Coastguard Worker     //    If any portion of the buffer object is mapped in the current context or
1253*8975f5c5SAndroid Build Coastguard Worker     //    any context current to another thread, it is as though UnmapBuffer
1254*8975f5c5SAndroid Build Coastguard Worker     //    (see section 2.10.3) is executed in each such context prior to deleting
1255*8975f5c5SAndroid Build Coastguard Worker     //    the existing data store.
1256*8975f5c5SAndroid Build Coastguard Worker     //
1257*8975f5c5SAndroid Build Coastguard Worker 
1258*8975f5c5SAndroid Build Coastguard Worker     std::vector<uint8_t> data1(16);
1259*8975f5c5SAndroid Build Coastguard Worker     std::vector<uint8_t> data2(16);
1260*8975f5c5SAndroid Build Coastguard Worker 
1261*8975f5c5SAndroid Build Coastguard Worker     GLBuffer dataBuffer;
1262*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, dataBuffer);
1263*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, data1.size(), data1.data(), GL_STATIC_DRAW);
1264*8975f5c5SAndroid Build Coastguard Worker 
1265*8975f5c5SAndroid Build Coastguard Worker     // Map the buffer once
1266*8975f5c5SAndroid Build Coastguard Worker     glMapBufferRange(GL_ARRAY_BUFFER, 0, data1.size(),
1267*8975f5c5SAndroid Build Coastguard Worker                      GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
1268*8975f5c5SAndroid Build Coastguard Worker                          GL_MAP_UNSYNCHRONIZED_BIT);
1269*8975f5c5SAndroid Build Coastguard Worker 
1270*8975f5c5SAndroid Build Coastguard Worker     // Then repopulate the buffer. This should cause the buffer to become unmapped.
1271*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, data2.size(), data2.data(), GL_STATIC_DRAW);
1272*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1273*8975f5c5SAndroid Build Coastguard Worker 
1274*8975f5c5SAndroid Build Coastguard Worker     // Try to unmap the buffer, this should fail
1275*8975f5c5SAndroid Build Coastguard Worker     bool result = glUnmapBuffer(GL_ARRAY_BUFFER);
1276*8975f5c5SAndroid Build Coastguard Worker     ASSERT_EQ(result, false);
1277*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1278*8975f5c5SAndroid Build Coastguard Worker 
1279*8975f5c5SAndroid Build Coastguard Worker     // Try to map the buffer again, which should succeed
1280*8975f5c5SAndroid Build Coastguard Worker     glMapBufferRange(GL_ARRAY_BUFFER, 0, data2.size(),
1281*8975f5c5SAndroid Build Coastguard Worker                      GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
1282*8975f5c5SAndroid Build Coastguard Worker                          GL_MAP_UNSYNCHRONIZED_BIT);
1283*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1284*8975f5c5SAndroid Build Coastguard Worker }
1285*8975f5c5SAndroid Build Coastguard Worker 
1286*8975f5c5SAndroid Build Coastguard Worker // Ensures that mapping buffer with GL_MAP_INVALIDATE_BUFFER_BIT followed by glBufferSubData calls
1287*8975f5c5SAndroid Build Coastguard Worker // works.  Regression test for the Vulkan backend where that flag caused use after free.
TEST_P(BufferSubDataTest,MapInvalidateThenBufferSubData)1288*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferSubDataTest, MapInvalidateThenBufferSubData)
1289*8975f5c5SAndroid Build Coastguard Worker {
1290*8975f5c5SAndroid Build Coastguard Worker     // http://anglebug.com/42264515
1291*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsWindows() && IsOpenGL() && IsIntel());
1292*8975f5c5SAndroid Build Coastguard Worker 
1293*8975f5c5SAndroid Build Coastguard Worker     // http://anglebug.com/42264516
1294*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
1295*8975f5c5SAndroid Build Coastguard Worker 
1296*8975f5c5SAndroid Build Coastguard Worker     const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
1297*8975f5c5SAndroid Build Coastguard Worker                                                  GLColor::red};
1298*8975f5c5SAndroid Build Coastguard Worker     const std::array<GLColor, 4> kUpdateData1 = {GLColor::white, GLColor::white, GLColor::white,
1299*8975f5c5SAndroid Build Coastguard Worker                                                  GLColor::white};
1300*8975f5c5SAndroid Build Coastguard Worker     const std::array<GLColor, 4> kUpdateData2 = {GLColor::blue, GLColor::blue, GLColor::blue,
1301*8975f5c5SAndroid Build Coastguard Worker                                                  GLColor::blue};
1302*8975f5c5SAndroid Build Coastguard Worker 
1303*8975f5c5SAndroid Build Coastguard Worker     GLBuffer buffer;
1304*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_UNIFORM_BUFFER, buffer);
1305*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
1306*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
1307*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1308*8975f5c5SAndroid Build Coastguard Worker 
1309*8975f5c5SAndroid Build Coastguard Worker     // Draw
1310*8975f5c5SAndroid Build Coastguard Worker     constexpr char kVerifyUBO[] = R"(#version 300 es
1311*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
1312*8975f5c5SAndroid Build Coastguard Worker uniform block {
1313*8975f5c5SAndroid Build Coastguard Worker     uvec4 data;
1314*8975f5c5SAndroid Build Coastguard Worker } ubo;
1315*8975f5c5SAndroid Build Coastguard Worker uniform uint expect;
1316*8975f5c5SAndroid Build Coastguard Worker uniform vec4 successOutput;
1317*8975f5c5SAndroid Build Coastguard Worker out vec4 colorOut;
1318*8975f5c5SAndroid Build Coastguard Worker void main()
1319*8975f5c5SAndroid Build Coastguard Worker {
1320*8975f5c5SAndroid Build Coastguard Worker     if (all(equal(ubo.data, uvec4(expect))))
1321*8975f5c5SAndroid Build Coastguard Worker         colorOut = successOutput;
1322*8975f5c5SAndroid Build Coastguard Worker     else
1323*8975f5c5SAndroid Build Coastguard Worker         colorOut = vec4(1.0, 0, 0, 1.0);
1324*8975f5c5SAndroid Build Coastguard Worker })";
1325*8975f5c5SAndroid Build Coastguard Worker 
1326*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(verifyUbo, essl3_shaders::vs::Simple(), kVerifyUBO);
1327*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(verifyUbo);
1328*8975f5c5SAndroid Build Coastguard Worker 
1329*8975f5c5SAndroid Build Coastguard Worker     GLint expectLoc = glGetUniformLocation(verifyUbo, "expect");
1330*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(-1, expectLoc);
1331*8975f5c5SAndroid Build Coastguard Worker     GLint successLoc = glGetUniformLocation(verifyUbo, "successOutput");
1332*8975f5c5SAndroid Build Coastguard Worker     EXPECT_NE(-1, successLoc);
1333*8975f5c5SAndroid Build Coastguard Worker 
1334*8975f5c5SAndroid Build Coastguard Worker     glUniform1ui(expectLoc, kInitialData[0].asUint());
1335*8975f5c5SAndroid Build Coastguard Worker     glUniform4f(successLoc, 0, 1, 0, 1);
1336*8975f5c5SAndroid Build Coastguard Worker 
1337*8975f5c5SAndroid Build Coastguard Worker     drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
1338*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1339*8975f5c5SAndroid Build Coastguard Worker 
1340*8975f5c5SAndroid Build Coastguard Worker     // Dont't verify the buffer.  This is testing GL_MAP_INVALIDATE_BUFFER_BIT while the buffer is
1341*8975f5c5SAndroid Build Coastguard Worker     // in use by the GPU.
1342*8975f5c5SAndroid Build Coastguard Worker 
1343*8975f5c5SAndroid Build Coastguard Worker     // Map the buffer and update it.
1344*8975f5c5SAndroid Build Coastguard Worker     void *mappedBuffer = glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData),
1345*8975f5c5SAndroid Build Coastguard Worker                                           GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
1346*8975f5c5SAndroid Build Coastguard Worker 
1347*8975f5c5SAndroid Build Coastguard Worker     memcpy(mappedBuffer, kUpdateData1.data(), sizeof(kInitialData));
1348*8975f5c5SAndroid Build Coastguard Worker 
1349*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_UNIFORM_BUFFER);
1350*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1351*8975f5c5SAndroid Build Coastguard Worker 
1352*8975f5c5SAndroid Build Coastguard Worker     // Verify that the buffer has the updated value.
1353*8975f5c5SAndroid Build Coastguard Worker     glUniform1ui(expectLoc, kUpdateData1[0].asUint());
1354*8975f5c5SAndroid Build Coastguard Worker     glUniform4f(successLoc, 0, 0, 1, 1);
1355*8975f5c5SAndroid Build Coastguard Worker 
1356*8975f5c5SAndroid Build Coastguard Worker     drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
1357*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1358*8975f5c5SAndroid Build Coastguard Worker 
1359*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
1360*8975f5c5SAndroid Build Coastguard Worker 
1361*8975f5c5SAndroid Build Coastguard Worker     // Update the buffer with glBufferSubData or glCopyBufferSubData
1362*8975f5c5SAndroid Build Coastguard Worker     updateBuffer(GL_UNIFORM_BUFFER, 0, sizeof(kUpdateData2), kUpdateData2.data());
1363*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1364*8975f5c5SAndroid Build Coastguard Worker 
1365*8975f5c5SAndroid Build Coastguard Worker     // Verify that the buffer has the updated value.
1366*8975f5c5SAndroid Build Coastguard Worker     glUniform1ui(expectLoc, kUpdateData2[0].asUint());
1367*8975f5c5SAndroid Build Coastguard Worker     glUniform4f(successLoc, 0, 1, 1, 1);
1368*8975f5c5SAndroid Build Coastguard Worker 
1369*8975f5c5SAndroid Build Coastguard Worker     drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
1370*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1371*8975f5c5SAndroid Build Coastguard Worker 
1372*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
1373*8975f5c5SAndroid Build Coastguard Worker }
1374*8975f5c5SAndroid Build Coastguard Worker 
1375*8975f5c5SAndroid Build Coastguard Worker // Verify that previous draws are not affected when a buffer is respecified with null data
1376*8975f5c5SAndroid Build Coastguard Worker // and updated by calling map.
TEST_P(BufferDataTestES3,BufferDataWithNullFollowedByMap)1377*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTestES3, BufferDataWithNullFollowedByMap)
1378*8975f5c5SAndroid Build Coastguard Worker {
1379*8975f5c5SAndroid Build Coastguard Worker     // Draw without using drawQuad.
1380*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(mProgram);
1381*8975f5c5SAndroid Build Coastguard Worker 
1382*8975f5c5SAndroid Build Coastguard Worker     // Set up position attribute
1383*8975f5c5SAndroid Build Coastguard Worker     const auto &quadVertices = GetQuadVertices();
1384*8975f5c5SAndroid Build Coastguard Worker     GLint positionLocation   = glGetAttribLocation(mProgram, "position");
1385*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, positionLocation);
1386*8975f5c5SAndroid Build Coastguard Worker     GLBuffer positionBuffer;
1387*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
1388*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * quadVertices.size() * 3, quadVertices.data(),
1389*8975f5c5SAndroid Build Coastguard Worker                  GL_DYNAMIC_DRAW);
1390*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1391*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(positionLocation);
1392*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1393*8975f5c5SAndroid Build Coastguard Worker 
1394*8975f5c5SAndroid Build Coastguard Worker     // Set up "in_attrib" attribute
1395*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLfloat> kData(6, 1.0f);
1396*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1397*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * kData.size(), kData.data(), GL_STATIC_DRAW);
1398*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1399*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(mAttribLocation);
1400*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1401*8975f5c5SAndroid Build Coastguard Worker 
1402*8975f5c5SAndroid Build Coastguard Worker     // This draw (draw_0) renders red to the entire window.
1403*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 6);
1404*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1405*8975f5c5SAndroid Build Coastguard Worker 
1406*8975f5c5SAndroid Build Coastguard Worker     // Respecify buffer bound to "in_attrib" attribute then map it and fill it with zeroes.
1407*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLfloat> kZeros(6, 0.0f);
1408*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * kZeros.size(), nullptr, GL_STATIC_DRAW);
1409*8975f5c5SAndroid Build Coastguard Worker     uint8_t *mapPtr = reinterpret_cast<uint8_t *>(
1410*8975f5c5SAndroid Build Coastguard Worker         glMapBufferRange(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * kZeros.size(),
1411*8975f5c5SAndroid Build Coastguard Worker                          GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT));
1412*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(nullptr, mapPtr);
1413*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1414*8975f5c5SAndroid Build Coastguard Worker     memcpy(mapPtr, kZeros.data(), sizeof(GLfloat) * kZeros.size());
1415*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_ARRAY_BUFFER);
1416*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1417*8975f5c5SAndroid Build Coastguard Worker 
1418*8975f5c5SAndroid Build Coastguard Worker     // This draw (draw_1) renders black to the upper right triangle.
1419*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 3, 3);
1420*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1421*8975f5c5SAndroid Build Coastguard Worker 
1422*8975f5c5SAndroid Build Coastguard Worker     // Respecification and data update of mBuffer should not have affected draw_0.
1423*8975f5c5SAndroid Build Coastguard Worker     // Expect bottom left to be red and top right to be black.
1424*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
1425*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::black);
1426*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1427*8975f5c5SAndroid Build Coastguard Worker }
1428*8975f5c5SAndroid Build Coastguard Worker 
1429*8975f5c5SAndroid Build Coastguard Worker // Test glFenceSync call breaks renderPass followed by glCopyBufferSubData that read access the same
1430*8975f5c5SAndroid Build Coastguard Worker // buffer that renderPass reads. There was a bug that this triggers assertion angleproject.com/7903.
TEST_P(BufferDataTestES3,bufferReadFromRenderPassAndOutsideRenderPassWithFenceSyncInBetween)1431*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTestES3, bufferReadFromRenderPassAndOutsideRenderPassWithFenceSyncInBetween)
1432*8975f5c5SAndroid Build Coastguard Worker {
1433*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(mProgram);
1434*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1435*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLfloat> data(6, 1.0f);
1436*8975f5c5SAndroid Build Coastguard Worker     GLsizei bufferSize = sizeof(GLfloat) * data.size();
1437*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, bufferSize, data.data(), GL_DYNAMIC_DRAW);
1438*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1439*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(mAttribLocation);
1440*8975f5c5SAndroid Build Coastguard Worker     glScissor(0, 0, getWindowWidth() / 2, getWindowHeight());
1441*8975f5c5SAndroid Build Coastguard Worker     drawQuad(mProgram, "position", 0.5f);
1442*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1443*8975f5c5SAndroid Build Coastguard Worker 
1444*8975f5c5SAndroid Build Coastguard Worker     GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
1445*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1446*8975f5c5SAndroid Build Coastguard Worker 
1447*8975f5c5SAndroid Build Coastguard Worker     GLBuffer dstBuffer;
1448*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_COPY_WRITE_BUFFER, dstBuffer);
1449*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_COPY_WRITE_BUFFER, bufferSize, nullptr, GL_STATIC_DRAW);
1450*8975f5c5SAndroid Build Coastguard Worker     glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, bufferSize);
1451*8975f5c5SAndroid Build Coastguard Worker 
1452*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, dstBuffer);
1453*8975f5c5SAndroid Build Coastguard Worker     glScissor(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight());
1454*8975f5c5SAndroid Build Coastguard Worker     drawQuad(mProgram, "position", 0.5f);
1455*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1456*8975f5c5SAndroid Build Coastguard Worker     glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
1457*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red);
1458*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() - 1, getWindowHeight() - 1, GLColor::red);
1459*8975f5c5SAndroid Build Coastguard Worker }
1460*8975f5c5SAndroid Build Coastguard Worker 
1461*8975f5c5SAndroid Build Coastguard Worker class BufferStorageTestES3 : public BufferDataTest
1462*8975f5c5SAndroid Build Coastguard Worker {};
1463*8975f5c5SAndroid Build Coastguard Worker 
1464*8975f5c5SAndroid Build Coastguard Worker // Tests that proper error value is returned when bad size is passed in
TEST_P(BufferStorageTestES3,BufferStorageInvalidSize)1465*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferStorageTestES3, BufferStorageInvalidSize)
1466*8975f5c5SAndroid Build Coastguard Worker {
1467*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1468*8975f5c5SAndroid Build Coastguard Worker 
1469*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLfloat> data(6, 1.0f);
1470*8975f5c5SAndroid Build Coastguard Worker 
1471*8975f5c5SAndroid Build Coastguard Worker     GLBuffer buffer;
1472*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, buffer);
1473*8975f5c5SAndroid Build Coastguard Worker     glBufferStorageEXT(GL_ARRAY_BUFFER, 0, data.data(), 0);
1474*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_VALUE);
1475*8975f5c5SAndroid Build Coastguard Worker }
1476*8975f5c5SAndroid Build Coastguard Worker 
1477*8975f5c5SAndroid Build Coastguard Worker // Tests that buffer storage can be allocated with the GL_MAP_PERSISTENT_BIT_EXT and
1478*8975f5c5SAndroid Build Coastguard Worker // GL_MAP_COHERENT_BIT_EXT flags
TEST_P(BufferStorageTestES3,BufferStorageFlagsPersistentCoherentWrite)1479*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferStorageTestES3, BufferStorageFlagsPersistentCoherentWrite)
1480*8975f5c5SAndroid Build Coastguard Worker {
1481*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1482*8975f5c5SAndroid Build Coastguard Worker 
1483*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLfloat> data(6, 1.0f);
1484*8975f5c5SAndroid Build Coastguard Worker 
1485*8975f5c5SAndroid Build Coastguard Worker     GLBuffer buffer;
1486*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, buffer);
1487*8975f5c5SAndroid Build Coastguard Worker     glBufferStorageEXT(GL_ARRAY_BUFFER, data.size(), data.data(),
1488*8975f5c5SAndroid Build Coastguard Worker                        GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1489*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1490*8975f5c5SAndroid Build Coastguard Worker }
1491*8975f5c5SAndroid Build Coastguard Worker 
1492*8975f5c5SAndroid Build Coastguard Worker // Verify that glBufferStorage makes a buffer immutable
TEST_P(BufferStorageTestES3,StorageBufferBufferData)1493*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferStorageTestES3, StorageBufferBufferData)
1494*8975f5c5SAndroid Build Coastguard Worker {
1495*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1496*8975f5c5SAndroid Build Coastguard Worker                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1497*8975f5c5SAndroid Build Coastguard Worker 
1498*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLfloat> data(6, 1.0f);
1499*8975f5c5SAndroid Build Coastguard Worker 
1500*8975f5c5SAndroid Build Coastguard Worker     GLBuffer buffer;
1501*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, buffer);
1502*8975f5c5SAndroid Build Coastguard Worker     glBufferStorageEXT(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), 0);
1503*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1504*8975f5c5SAndroid Build Coastguard Worker 
1505*8975f5c5SAndroid Build Coastguard Worker     // Verify that calling glBufferStorageEXT again produces an error.
1506*8975f5c5SAndroid Build Coastguard Worker     glBufferStorageEXT(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), 0);
1507*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1508*8975f5c5SAndroid Build Coastguard Worker 
1509*8975f5c5SAndroid Build Coastguard Worker     // Verify that calling glBufferData after calling glBufferStorageEXT produces an error.
1510*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), GL_STATIC_DRAW);
1511*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1512*8975f5c5SAndroid Build Coastguard Worker }
1513*8975f5c5SAndroid Build Coastguard Worker 
1514*8975f5c5SAndroid Build Coastguard Worker // Verify that glBufferStorageEXT can be called after glBufferData
TEST_P(BufferStorageTestES3,BufferDataStorageBuffer)1515*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferStorageTestES3, BufferDataStorageBuffer)
1516*8975f5c5SAndroid Build Coastguard Worker {
1517*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1518*8975f5c5SAndroid Build Coastguard Worker                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1519*8975f5c5SAndroid Build Coastguard Worker 
1520*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLfloat> data(6, 1.0f);
1521*8975f5c5SAndroid Build Coastguard Worker 
1522*8975f5c5SAndroid Build Coastguard Worker     GLBuffer buffer;
1523*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, buffer);
1524*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), GL_STATIC_DRAW);
1525*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1526*8975f5c5SAndroid Build Coastguard Worker 
1527*8975f5c5SAndroid Build Coastguard Worker     // Verify that calling glBufferStorageEXT produces no error
1528*8975f5c5SAndroid Build Coastguard Worker     glBufferStorageEXT(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), data.data(), 0);
1529*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1530*8975f5c5SAndroid Build Coastguard Worker }
1531*8975f5c5SAndroid Build Coastguard Worker 
1532*8975f5c5SAndroid Build Coastguard Worker // Verify that consecutive BufferStorage calls don't clobber data
1533*8975f5c5SAndroid Build Coastguard Worker // This is a regression test for an AllocateNonZeroMemory bug, where the offset
1534*8975f5c5SAndroid Build Coastguard Worker // of the suballocation wasn't being used properly
TEST_P(BufferStorageTestES3,BufferStorageClobber)1535*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferStorageTestES3, BufferStorageClobber)
1536*8975f5c5SAndroid Build Coastguard Worker {
1537*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1538*8975f5c5SAndroid Build Coastguard Worker                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1539*8975f5c5SAndroid Build Coastguard Worker 
1540*8975f5c5SAndroid Build Coastguard Worker     constexpr size_t largeSizes[] = {101, 103, 107, 109, 113, 127, 131, 137, 139};
1541*8975f5c5SAndroid Build Coastguard Worker     constexpr size_t smallSizes[] = {7, 11, 13, 17, 19, 23, 29, 31, 37, 41};
1542*8975f5c5SAndroid Build Coastguard Worker     constexpr size_t readBackSize = 16;
1543*8975f5c5SAndroid Build Coastguard Worker 
1544*8975f5c5SAndroid Build Coastguard Worker     for (size_t largeSize : largeSizes)
1545*8975f5c5SAndroid Build Coastguard Worker     {
1546*8975f5c5SAndroid Build Coastguard Worker         std::vector<GLubyte> data0(largeSize * 1024, 0x1E);
1547*8975f5c5SAndroid Build Coastguard Worker 
1548*8975f5c5SAndroid Build Coastguard Worker         // Check for a test author error, we can't read back more than the size of data0.
1549*8975f5c5SAndroid Build Coastguard Worker         ASSERT(readBackSize <= data0.size());
1550*8975f5c5SAndroid Build Coastguard Worker 
1551*8975f5c5SAndroid Build Coastguard Worker         // Do a large write first, ensure this is a device-local buffer only (no storage flags)
1552*8975f5c5SAndroid Build Coastguard Worker         GLBuffer buffer0;
1553*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ARRAY_BUFFER, buffer0);
1554*8975f5c5SAndroid Build Coastguard Worker         glBufferStorageEXT(GL_ARRAY_BUFFER, sizeof(GLubyte) * data0.size(), data0.data(), 0);
1555*8975f5c5SAndroid Build Coastguard Worker         ASSERT_GL_NO_ERROR();
1556*8975f5c5SAndroid Build Coastguard Worker 
1557*8975f5c5SAndroid Build Coastguard Worker         // Do a bunch of smaller writes next, creating/deleting buffers as
1558*8975f5c5SAndroid Build Coastguard Worker         // we go (we just want to try to fuzz it so we might write to the
1559*8975f5c5SAndroid Build Coastguard Worker         // same suballocation as the above)
1560*8975f5c5SAndroid Build Coastguard Worker         for (size_t smallSize : smallSizes)
1561*8975f5c5SAndroid Build Coastguard Worker         {
1562*8975f5c5SAndroid Build Coastguard Worker             std::vector<GLubyte> data1(smallSize, 0x4A);
1563*8975f5c5SAndroid Build Coastguard Worker             GLBuffer buffer1;
1564*8975f5c5SAndroid Build Coastguard Worker             glBindBuffer(GL_ARRAY_BUFFER, buffer1);
1565*8975f5c5SAndroid Build Coastguard Worker             glBufferStorageEXT(GL_ARRAY_BUFFER, sizeof(GLubyte) * data1.size(), data1.data(), 0);
1566*8975f5c5SAndroid Build Coastguard Worker             ASSERT_GL_NO_ERROR();
1567*8975f5c5SAndroid Build Coastguard Worker 
1568*8975f5c5SAndroid Build Coastguard Worker             // Force the buffer write (and other buffer creation setup work) to
1569*8975f5c5SAndroid Build Coastguard Worker             // flush
1570*8975f5c5SAndroid Build Coastguard Worker             glFinish();
1571*8975f5c5SAndroid Build Coastguard Worker         }
1572*8975f5c5SAndroid Build Coastguard Worker 
1573*8975f5c5SAndroid Build Coastguard Worker         // Create a staging area to read back the buffer
1574*8975f5c5SAndroid Build Coastguard Worker         GLBuffer mappable;
1575*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ARRAY_BUFFER, mappable);
1576*8975f5c5SAndroid Build Coastguard Worker         glBufferStorageEXT(GL_ARRAY_BUFFER, sizeof(GLubyte) * readBackSize, nullptr,
1577*8975f5c5SAndroid Build Coastguard Worker                            GL_MAP_READ_BIT);
1578*8975f5c5SAndroid Build Coastguard Worker         ASSERT_GL_NO_ERROR();
1579*8975f5c5SAndroid Build Coastguard Worker 
1580*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_COPY_READ_BUFFER, buffer0);
1581*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_COPY_WRITE_BUFFER, mappable);
1582*8975f5c5SAndroid Build Coastguard Worker         glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0,
1583*8975f5c5SAndroid Build Coastguard Worker                             sizeof(GLubyte) * readBackSize);
1584*8975f5c5SAndroid Build Coastguard Worker         ASSERT_GL_NO_ERROR();
1585*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_COPY_READ_BUFFER, 0);
1586*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
1587*8975f5c5SAndroid Build Coastguard Worker 
1588*8975f5c5SAndroid Build Coastguard Worker         GLubyte *mapped = reinterpret_cast<GLubyte *>(
1589*8975f5c5SAndroid Build Coastguard Worker             glMapBufferRange(GL_ARRAY_BUFFER, 0, sizeof(GLubyte) * readBackSize, GL_MAP_READ_BIT));
1590*8975f5c5SAndroid Build Coastguard Worker         ASSERT_NE(mapped, nullptr);
1591*8975f5c5SAndroid Build Coastguard Worker         ASSERT_GL_NO_ERROR();
1592*8975f5c5SAndroid Build Coastguard Worker         for (size_t i = 0; i < readBackSize; i++)
1593*8975f5c5SAndroid Build Coastguard Worker         {
1594*8975f5c5SAndroid Build Coastguard Worker             EXPECT_EQ(mapped[i], data0[i])
1595*8975f5c5SAndroid Build Coastguard Worker                 << "Expected " << static_cast<int>(data0[i]) << " at index " << i << ", got "
1596*8975f5c5SAndroid Build Coastguard Worker                 << static_cast<int>(mapped[i]);
1597*8975f5c5SAndroid Build Coastguard Worker         }
1598*8975f5c5SAndroid Build Coastguard Worker     }
1599*8975f5c5SAndroid Build Coastguard Worker }
1600*8975f5c5SAndroid Build Coastguard Worker 
1601*8975f5c5SAndroid Build Coastguard Worker // Verify that we can perform subdata updates to a buffer marked with GL_DYNAMIC_STORAGE_BIT_EXT
1602*8975f5c5SAndroid Build Coastguard Worker // usage flag
TEST_P(BufferStorageTestES3,StorageBufferSubData)1603*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferStorageTestES3, StorageBufferSubData)
1604*8975f5c5SAndroid Build Coastguard Worker {
1605*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1606*8975f5c5SAndroid Build Coastguard Worker                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1607*8975f5c5SAndroid Build Coastguard Worker 
1608*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLfloat> data(6, 0.0f);
1609*8975f5c5SAndroid Build Coastguard Worker 
1610*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(mProgram);
1611*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
1612*8975f5c5SAndroid Build Coastguard Worker     glBufferStorageEXT(GL_ARRAY_BUFFER, sizeof(GLfloat) * data.size(), nullptr,
1613*8975f5c5SAndroid Build Coastguard Worker                        GL_DYNAMIC_STORAGE_BIT_EXT);
1614*8975f5c5SAndroid Build Coastguard Worker     glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * data.size(), data.data());
1615*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
1616*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(mAttribLocation);
1617*8975f5c5SAndroid Build Coastguard Worker 
1618*8975f5c5SAndroid Build Coastguard Worker     drawQuad(mProgram, "position", 0.5f);
1619*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(8, 8, GLColor::black);
1620*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1621*8975f5c5SAndroid Build Coastguard Worker 
1622*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLfloat> data2(6, 1.0f);
1623*8975f5c5SAndroid Build Coastguard Worker     glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * data2.size(), data2.data());
1624*8975f5c5SAndroid Build Coastguard Worker 
1625*8975f5c5SAndroid Build Coastguard Worker     drawQuad(mProgram, "position", 0.5f);
1626*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(8, 8, GLColor::red);
1627*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1628*8975f5c5SAndroid Build Coastguard Worker }
1629*8975f5c5SAndroid Build Coastguard Worker 
1630*8975f5c5SAndroid Build Coastguard Worker // Test interaction between GL_OES_mapbuffer and GL_EXT_buffer_storage extensions.
TEST_P(BufferStorageTestES3,StorageBufferMapBufferOES)1631*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferStorageTestES3, StorageBufferMapBufferOES)
1632*8975f5c5SAndroid Build Coastguard Worker {
1633*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1634*8975f5c5SAndroid Build Coastguard Worker                        !IsGLExtensionEnabled("GL_EXT_buffer_storage") ||
1635*8975f5c5SAndroid Build Coastguard Worker                        !IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
1636*8975f5c5SAndroid Build Coastguard Worker 
1637*8975f5c5SAndroid Build Coastguard Worker     std::vector<uint8_t> data(1024);
1638*8975f5c5SAndroid Build Coastguard Worker     FillVectorWithRandomUBytes(&data);
1639*8975f5c5SAndroid Build Coastguard Worker 
1640*8975f5c5SAndroid Build Coastguard Worker     GLBuffer buffer;
1641*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, buffer);
1642*8975f5c5SAndroid Build Coastguard Worker     glBufferStorageEXT(GL_ARRAY_BUFFER, data.size(), nullptr, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT);
1643*8975f5c5SAndroid Build Coastguard Worker 
1644*8975f5c5SAndroid Build Coastguard Worker     // Validate that other map flags don't work.
1645*8975f5c5SAndroid Build Coastguard Worker     void *badMapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_MAP_READ_BIT);
1646*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(nullptr, badMapPtr);
1647*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_ENUM);
1648*8975f5c5SAndroid Build Coastguard Worker 
1649*8975f5c5SAndroid Build Coastguard Worker     // Map and write.
1650*8975f5c5SAndroid Build Coastguard Worker     void *mapPtr = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
1651*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(nullptr, mapPtr);
1652*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1653*8975f5c5SAndroid Build Coastguard Worker     memcpy(mapPtr, data.data(), data.size());
1654*8975f5c5SAndroid Build Coastguard Worker     glUnmapBufferOES(GL_ARRAY_BUFFER);
1655*8975f5c5SAndroid Build Coastguard Worker 
1656*8975f5c5SAndroid Build Coastguard Worker     // Validate data with EXT_map_buffer_range
1657*8975f5c5SAndroid Build Coastguard Worker     void *readMapPtr = glMapBufferRangeEXT(GL_ARRAY_BUFFER, 0, data.size(), GL_MAP_READ_BIT_EXT);
1658*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(nullptr, readMapPtr);
1659*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1660*8975f5c5SAndroid Build Coastguard Worker     std::vector<uint8_t> actualData(data.size());
1661*8975f5c5SAndroid Build Coastguard Worker     memcpy(actualData.data(), readMapPtr, data.size());
1662*8975f5c5SAndroid Build Coastguard Worker     glUnmapBufferOES(GL_ARRAY_BUFFER);
1663*8975f5c5SAndroid Build Coastguard Worker 
1664*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(data, actualData);
1665*8975f5c5SAndroid Build Coastguard Worker }
1666*8975f5c5SAndroid Build Coastguard Worker 
1667*8975f5c5SAndroid Build Coastguard Worker // Verify persistently mapped buffers can use glCopyBufferSubData
1668*8975f5c5SAndroid Build Coastguard Worker // Tests a pattern used by Fortnite's GLES backend
TEST_P(BufferStorageTestES3,StorageCopyBufferSubDataMapped)1669*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferStorageTestES3, StorageCopyBufferSubDataMapped)
1670*8975f5c5SAndroid Build Coastguard Worker {
1671*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1672*8975f5c5SAndroid Build Coastguard Worker                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1673*8975f5c5SAndroid Build Coastguard Worker 
1674*8975f5c5SAndroid Build Coastguard Worker     const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::green, GLColor::blue,
1675*8975f5c5SAndroid Build Coastguard Worker                                                  GLColor::yellow};
1676*8975f5c5SAndroid Build Coastguard Worker 
1677*8975f5c5SAndroid Build Coastguard Worker     // Set up the read buffer
1678*8975f5c5SAndroid Build Coastguard Worker     GLBuffer readBuffer;
1679*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, readBuffer);
1680*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_DRAW);
1681*8975f5c5SAndroid Build Coastguard Worker 
1682*8975f5c5SAndroid Build Coastguard Worker     // Set up the write buffer to be persistently mapped
1683*8975f5c5SAndroid Build Coastguard Worker     GLBuffer writeBuffer;
1684*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_COPY_WRITE_BUFFER, writeBuffer);
1685*8975f5c5SAndroid Build Coastguard Worker     glBufferStorageEXT(GL_COPY_WRITE_BUFFER, 16, nullptr,
1686*8975f5c5SAndroid Build Coastguard Worker                        GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1687*8975f5c5SAndroid Build Coastguard Worker     void *readMapPtr =
1688*8975f5c5SAndroid Build Coastguard Worker         glMapBufferRange(GL_COPY_WRITE_BUFFER, 0, 16,
1689*8975f5c5SAndroid Build Coastguard Worker                          GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1690*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(nullptr, readMapPtr);
1691*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1692*8975f5c5SAndroid Build Coastguard Worker 
1693*8975f5c5SAndroid Build Coastguard Worker     // Verify we can copy into the write buffer
1694*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_COPY_READ_BUFFER, readBuffer);
1695*8975f5c5SAndroid Build Coastguard Worker     glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, 16);
1696*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1697*8975f5c5SAndroid Build Coastguard Worker 
1698*8975f5c5SAndroid Build Coastguard Worker     // Flush the buffer.
1699*8975f5c5SAndroid Build Coastguard Worker     glFinish();
1700*8975f5c5SAndroid Build Coastguard Worker 
1701*8975f5c5SAndroid Build Coastguard Worker     // Check the contents
1702*8975f5c5SAndroid Build Coastguard Worker     std::array<GLColor, 4> resultingData;
1703*8975f5c5SAndroid Build Coastguard Worker     memcpy(resultingData.data(), readMapPtr, resultingData.size() * sizeof(GLColor));
1704*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_COPY_WRITE_BUFFER);
1705*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(kInitialData, resultingData);
1706*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1707*8975f5c5SAndroid Build Coastguard Worker }
1708*8975f5c5SAndroid Build Coastguard Worker 
1709*8975f5c5SAndroid Build Coastguard Worker // Verify persistently mapped element array buffers can use glDrawElements
TEST_P(BufferStorageTestES3,DrawElementsElementArrayBufferMapped)1710*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferStorageTestES3, DrawElementsElementArrayBufferMapped)
1711*8975f5c5SAndroid Build Coastguard Worker {
1712*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1713*8975f5c5SAndroid Build Coastguard Worker                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1714*8975f5c5SAndroid Build Coastguard Worker 
1715*8975f5c5SAndroid Build Coastguard Worker     GLfloat kVertexBuffer[] = {-1.0f, -1.0f, 1.0f,  // (x, y, R)
1716*8975f5c5SAndroid Build Coastguard Worker                                -1.0f, 1.0f,  1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
1717*8975f5c5SAndroid Build Coastguard Worker     // Set up array buffer
1718*8975f5c5SAndroid Build Coastguard Worker     GLBuffer readBuffer;
1719*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, readBuffer);
1720*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(kVertexBuffer), kVertexBuffer, GL_DYNAMIC_DRAW);
1721*8975f5c5SAndroid Build Coastguard Worker     GLint vLoc = glGetAttribLocation(mProgram, "position");
1722*8975f5c5SAndroid Build Coastguard Worker     GLint cLoc = mAttribLocation;
1723*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(vLoc, 2, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr);
1724*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(vLoc);
1725*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(cLoc, 1, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (const GLvoid *)8);
1726*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(cLoc);
1727*8975f5c5SAndroid Build Coastguard Worker 
1728*8975f5c5SAndroid Build Coastguard Worker     // Set up the element array buffer to be persistently mapped
1729*8975f5c5SAndroid Build Coastguard Worker     GLshort kElementArrayBuffer[] = {0, 0, 0, 0, 0, 0};
1730*8975f5c5SAndroid Build Coastguard Worker 
1731*8975f5c5SAndroid Build Coastguard Worker     GLBuffer indexBuffer;
1732*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1733*8975f5c5SAndroid Build Coastguard Worker     glBufferStorageEXT(GL_ELEMENT_ARRAY_BUFFER, sizeof(kElementArrayBuffer), kElementArrayBuffer,
1734*8975f5c5SAndroid Build Coastguard Worker                        GL_DYNAMIC_STORAGE_BIT_EXT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT |
1735*8975f5c5SAndroid Build Coastguard Worker                            GL_MAP_COHERENT_BIT_EXT);
1736*8975f5c5SAndroid Build Coastguard Worker 
1737*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(mProgram);
1738*8975f5c5SAndroid Build Coastguard Worker 
1739*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0, 0, 0, 0);
1740*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
1741*8975f5c5SAndroid Build Coastguard Worker 
1742*8975f5c5SAndroid Build Coastguard Worker     glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);
1743*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1744*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack);
1745*8975f5c5SAndroid Build Coastguard Worker 
1746*8975f5c5SAndroid Build Coastguard Worker     GLshort *mappedPtr = (GLshort *)glMapBufferRange(
1747*8975f5c5SAndroid Build Coastguard Worker         GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(kElementArrayBuffer),
1748*8975f5c5SAndroid Build Coastguard Worker         GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1749*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(nullptr, mappedPtr);
1750*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1751*8975f5c5SAndroid Build Coastguard Worker 
1752*8975f5c5SAndroid Build Coastguard Worker     mappedPtr[0] = 0;
1753*8975f5c5SAndroid Build Coastguard Worker     mappedPtr[1] = 1;
1754*8975f5c5SAndroid Build Coastguard Worker     mappedPtr[2] = 2;
1755*8975f5c5SAndroid Build Coastguard Worker     mappedPtr[3] = 2;
1756*8975f5c5SAndroid Build Coastguard Worker     mappedPtr[4] = 1;
1757*8975f5c5SAndroid Build Coastguard Worker     mappedPtr[5] = 3;
1758*8975f5c5SAndroid Build Coastguard Worker     glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);
1759*8975f5c5SAndroid Build Coastguard Worker 
1760*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
1761*8975f5c5SAndroid Build Coastguard Worker 
1762*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1763*8975f5c5SAndroid Build Coastguard Worker 
1764*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
1765*8975f5c5SAndroid Build Coastguard Worker }
1766*8975f5c5SAndroid Build Coastguard Worker 
1767*8975f5c5SAndroid Build Coastguard Worker // Test that maps a coherent buffer storage and does not call glUnmapBuffer.
TEST_P(BufferStorageTestES3,NoUnmap)1768*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferStorageTestES3, NoUnmap)
1769*8975f5c5SAndroid Build Coastguard Worker {
1770*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1771*8975f5c5SAndroid Build Coastguard Worker                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1772*8975f5c5SAndroid Build Coastguard Worker 
1773*8975f5c5SAndroid Build Coastguard Worker     GLsizei size = sizeof(GLfloat) * 128;
1774*8975f5c5SAndroid Build Coastguard Worker 
1775*8975f5c5SAndroid Build Coastguard Worker     GLBuffer buffer;
1776*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, buffer);
1777*8975f5c5SAndroid Build Coastguard Worker     glBufferStorageEXT(GL_ARRAY_BUFFER, size, nullptr,
1778*8975f5c5SAndroid Build Coastguard Worker                        GL_DYNAMIC_STORAGE_BIT_EXT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT |
1779*8975f5c5SAndroid Build Coastguard Worker                            GL_MAP_COHERENT_BIT_EXT);
1780*8975f5c5SAndroid Build Coastguard Worker 
1781*8975f5c5SAndroid Build Coastguard Worker     GLshort *mappedPtr = (GLshort *)glMapBufferRange(
1782*8975f5c5SAndroid Build Coastguard Worker         GL_ARRAY_BUFFER, 0, size,
1783*8975f5c5SAndroid Build Coastguard Worker         GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1784*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(nullptr, mappedPtr);
1785*8975f5c5SAndroid Build Coastguard Worker 
1786*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1787*8975f5c5SAndroid Build Coastguard Worker }
1788*8975f5c5SAndroid Build Coastguard Worker 
1789*8975f5c5SAndroid Build Coastguard Worker // Test that we are able to perform glTex*D calls while a pixel unpack buffer is bound
1790*8975f5c5SAndroid Build Coastguard Worker // and persistently mapped.
TEST_P(BufferStorageTestES3,TexImage2DPixelUnpackBufferMappedPersistently)1791*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferStorageTestES3, TexImage2DPixelUnpackBufferMappedPersistently)
1792*8975f5c5SAndroid Build Coastguard Worker {
1793*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1794*8975f5c5SAndroid Build Coastguard Worker                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1795*8975f5c5SAndroid Build Coastguard Worker 
1796*8975f5c5SAndroid Build Coastguard Worker     std::vector<uint8_t> data(64);
1797*8975f5c5SAndroid Build Coastguard Worker     FillVectorWithRandomUBytes(&data);
1798*8975f5c5SAndroid Build Coastguard Worker 
1799*8975f5c5SAndroid Build Coastguard Worker     GLBuffer buffer;
1800*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
1801*8975f5c5SAndroid Build Coastguard Worker     glBufferStorageEXT(GL_PIXEL_UNPACK_BUFFER, data.size(), data.data(),
1802*8975f5c5SAndroid Build Coastguard Worker                        GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT);
1803*8975f5c5SAndroid Build Coastguard Worker 
1804*8975f5c5SAndroid Build Coastguard Worker     // Map the buffer.
1805*8975f5c5SAndroid Build Coastguard Worker     void *mapPtr = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, data.size(),
1806*8975f5c5SAndroid Build Coastguard Worker                                     GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT);
1807*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(nullptr, mapPtr);
1808*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1809*8975f5c5SAndroid Build Coastguard Worker 
1810*8975f5c5SAndroid Build Coastguard Worker     // Create a 2D texture and fill it using the persistenly mapped unpack buffer
1811*8975f5c5SAndroid Build Coastguard Worker     GLTexture tex;
1812*8975f5c5SAndroid Build Coastguard Worker     glBindTexture(GL_TEXTURE_2D, tex);
1813*8975f5c5SAndroid Build Coastguard Worker 
1814*8975f5c5SAndroid Build Coastguard Worker     constexpr GLsizei kTextureWidth  = 4;
1815*8975f5c5SAndroid Build Coastguard Worker     constexpr GLsizei kTextureHeight = 4;
1816*8975f5c5SAndroid Build Coastguard Worker     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kTextureWidth, kTextureHeight, 0, GL_RGBA,
1817*8975f5c5SAndroid Build Coastguard Worker                  GL_UNSIGNED_BYTE, 0);
1818*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1819*8975f5c5SAndroid Build Coastguard Worker 
1820*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
1821*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1822*8975f5c5SAndroid Build Coastguard Worker }
1823*8975f5c5SAndroid Build Coastguard Worker 
1824*8975f5c5SAndroid Build Coastguard Worker // Verify persistently mapped buffers can use glBufferSubData
TEST_P(BufferStorageTestES3,StorageBufferSubDataMapped)1825*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferStorageTestES3, StorageBufferSubDataMapped)
1826*8975f5c5SAndroid Build Coastguard Worker {
1827*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1828*8975f5c5SAndroid Build Coastguard Worker                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1829*8975f5c5SAndroid Build Coastguard Worker 
1830*8975f5c5SAndroid Build Coastguard Worker     const std::array<GLColor, 4> kUpdateData1 = {GLColor::red, GLColor::green, GLColor::blue,
1831*8975f5c5SAndroid Build Coastguard Worker                                                  GLColor::yellow};
1832*8975f5c5SAndroid Build Coastguard Worker 
1833*8975f5c5SAndroid Build Coastguard Worker     // Set up the buffer to be persistently mapped and dynamic
1834*8975f5c5SAndroid Build Coastguard Worker     GLBuffer buffer;
1835*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, buffer);
1836*8975f5c5SAndroid Build Coastguard Worker     glBufferStorageEXT(GL_ARRAY_BUFFER, 16, nullptr,
1837*8975f5c5SAndroid Build Coastguard Worker                        GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT |
1838*8975f5c5SAndroid Build Coastguard Worker                            GL_MAP_COHERENT_BIT_EXT | GL_DYNAMIC_STORAGE_BIT_EXT);
1839*8975f5c5SAndroid Build Coastguard Worker     void *readMapPtr = glMapBufferRange(
1840*8975f5c5SAndroid Build Coastguard Worker         GL_ARRAY_BUFFER, 0, 16,
1841*8975f5c5SAndroid Build Coastguard Worker         GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1842*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(nullptr, readMapPtr);
1843*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1844*8975f5c5SAndroid Build Coastguard Worker 
1845*8975f5c5SAndroid Build Coastguard Worker     // Verify we can push new data into the buffer
1846*8975f5c5SAndroid Build Coastguard Worker     glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLColor) * kUpdateData1.size(), kUpdateData1.data());
1847*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1848*8975f5c5SAndroid Build Coastguard Worker 
1849*8975f5c5SAndroid Build Coastguard Worker     // Flush the buffer.
1850*8975f5c5SAndroid Build Coastguard Worker     glFinish();
1851*8975f5c5SAndroid Build Coastguard Worker 
1852*8975f5c5SAndroid Build Coastguard Worker     // Check the contents
1853*8975f5c5SAndroid Build Coastguard Worker     std::array<GLColor, 4> persistentData1;
1854*8975f5c5SAndroid Build Coastguard Worker     memcpy(persistentData1.data(), readMapPtr, persistentData1.size() * sizeof(GLColor));
1855*8975f5c5SAndroid Build Coastguard Worker     EXPECT_EQ(kUpdateData1, persistentData1);
1856*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_ARRAY_BUFFER);
1857*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1858*8975f5c5SAndroid Build Coastguard Worker }
1859*8975f5c5SAndroid Build Coastguard Worker 
1860*8975f5c5SAndroid Build Coastguard Worker // Verify that persistently mapped coherent buffers can be used as uniform buffers,
1861*8975f5c5SAndroid Build Coastguard Worker // and written to by using the pointer from glMapBufferRange.
TEST_P(BufferStorageTestES3,UniformBufferMapped)1862*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferStorageTestES3, UniformBufferMapped)
1863*8975f5c5SAndroid Build Coastguard Worker {
1864*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1865*8975f5c5SAndroid Build Coastguard Worker                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1866*8975f5c5SAndroid Build Coastguard Worker 
1867*8975f5c5SAndroid Build Coastguard Worker     const char *mkFS = R"(#version 300 es
1868*8975f5c5SAndroid Build Coastguard Worker precision highp float;
1869*8975f5c5SAndroid Build Coastguard Worker uniform uni { vec4 color; };
1870*8975f5c5SAndroid Build Coastguard Worker out vec4 fragColor;
1871*8975f5c5SAndroid Build Coastguard Worker void main()
1872*8975f5c5SAndroid Build Coastguard Worker {
1873*8975f5c5SAndroid Build Coastguard Worker     fragColor = color;
1874*8975f5c5SAndroid Build Coastguard Worker })";
1875*8975f5c5SAndroid Build Coastguard Worker 
1876*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), mkFS);
1877*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(program, 0u);
1878*8975f5c5SAndroid Build Coastguard Worker 
1879*8975f5c5SAndroid Build Coastguard Worker     GLint uniformBufferIndex = glGetUniformBlockIndex(program, "uni");
1880*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(uniformBufferIndex, -1);
1881*8975f5c5SAndroid Build Coastguard Worker 
1882*8975f5c5SAndroid Build Coastguard Worker     GLBuffer uniformBuffer;
1883*8975f5c5SAndroid Build Coastguard Worker 
1884*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1885*8975f5c5SAndroid Build Coastguard Worker 
1886*8975f5c5SAndroid Build Coastguard Worker     glViewport(0, 0, getWindowWidth(), getWindowHeight());
1887*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
1888*8975f5c5SAndroid Build Coastguard Worker 
1889*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer);
1890*8975f5c5SAndroid Build Coastguard Worker 
1891*8975f5c5SAndroid Build Coastguard Worker     glBufferStorageEXT(GL_UNIFORM_BUFFER, sizeof(float) * 4, nullptr,
1892*8975f5c5SAndroid Build Coastguard Worker                        GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1893*8975f5c5SAndroid Build Coastguard Worker 
1894*8975f5c5SAndroid Build Coastguard Worker     float *mapPtr = static_cast<float *>(
1895*8975f5c5SAndroid Build Coastguard Worker         glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(float) * 4,
1896*8975f5c5SAndroid Build Coastguard Worker                          GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_PERSISTENT_BIT_EXT |
1897*8975f5c5SAndroid Build Coastguard Worker                              GL_MAP_COHERENT_BIT_EXT));
1898*8975f5c5SAndroid Build Coastguard Worker 
1899*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(mapPtr, nullptr);
1900*8975f5c5SAndroid Build Coastguard Worker 
1901*8975f5c5SAndroid Build Coastguard Worker     glBindBufferBase(GL_UNIFORM_BUFFER, 0, uniformBuffer);
1902*8975f5c5SAndroid Build Coastguard Worker 
1903*8975f5c5SAndroid Build Coastguard Worker     glUniformBlockBinding(program, uniformBufferIndex, 0);
1904*8975f5c5SAndroid Build Coastguard Worker 
1905*8975f5c5SAndroid Build Coastguard Worker     mapPtr[0] = 0.5f;
1906*8975f5c5SAndroid Build Coastguard Worker     mapPtr[1] = 0.75f;
1907*8975f5c5SAndroid Build Coastguard Worker     mapPtr[2] = 0.25f;
1908*8975f5c5SAndroid Build Coastguard Worker     mapPtr[3] = 1.0f;
1909*8975f5c5SAndroid Build Coastguard Worker 
1910*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
1911*8975f5c5SAndroid Build Coastguard Worker 
1912*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_NEAR(0, 0, 128, 191, 64, 255, 1);
1913*8975f5c5SAndroid Build Coastguard Worker 
1914*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_UNIFORM_BUFFER);
1915*8975f5c5SAndroid Build Coastguard Worker 
1916*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(program);
1917*8975f5c5SAndroid Build Coastguard Worker 
1918*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
1919*8975f5c5SAndroid Build Coastguard Worker }
1920*8975f5c5SAndroid Build Coastguard Worker 
1921*8975f5c5SAndroid Build Coastguard Worker // Verify that persistently mapped coherent buffers can be used as vertex array buffers,
1922*8975f5c5SAndroid Build Coastguard Worker // and written to by using the pointer from glMapBufferRange.
TEST_P(BufferStorageTestES3,VertexBufferMapped)1923*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferStorageTestES3, VertexBufferMapped)
1924*8975f5c5SAndroid Build Coastguard Worker {
1925*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
1926*8975f5c5SAndroid Build Coastguard Worker                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
1927*8975f5c5SAndroid Build Coastguard Worker 
1928*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
1929*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(program, 0u);
1930*8975f5c5SAndroid Build Coastguard Worker 
1931*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
1932*8975f5c5SAndroid Build Coastguard Worker 
1933*8975f5c5SAndroid Build Coastguard Worker     auto quadVertices = GetQuadVertices();
1934*8975f5c5SAndroid Build Coastguard Worker 
1935*8975f5c5SAndroid Build Coastguard Worker     size_t bufferSize = sizeof(GLfloat) * quadVertices.size() * 3;
1936*8975f5c5SAndroid Build Coastguard Worker 
1937*8975f5c5SAndroid Build Coastguard Worker     GLBuffer positionBuffer;
1938*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
1939*8975f5c5SAndroid Build Coastguard Worker 
1940*8975f5c5SAndroid Build Coastguard Worker     glBufferStorageEXT(GL_ARRAY_BUFFER, bufferSize, nullptr,
1941*8975f5c5SAndroid Build Coastguard Worker                        GL_DYNAMIC_STORAGE_BIT_EXT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT |
1942*8975f5c5SAndroid Build Coastguard Worker                            GL_MAP_COHERENT_BIT_EXT);
1943*8975f5c5SAndroid Build Coastguard Worker 
1944*8975f5c5SAndroid Build Coastguard Worker     GLint positionLocation = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
1945*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, positionLocation);
1946*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
1947*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(positionLocation);
1948*8975f5c5SAndroid Build Coastguard Worker 
1949*8975f5c5SAndroid Build Coastguard Worker     void *mappedPtr =
1950*8975f5c5SAndroid Build Coastguard Worker         glMapBufferRange(GL_ARRAY_BUFFER, 0, bufferSize,
1951*8975f5c5SAndroid Build Coastguard Worker                          GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1952*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(nullptr, mappedPtr);
1953*8975f5c5SAndroid Build Coastguard Worker 
1954*8975f5c5SAndroid Build Coastguard Worker     memcpy(mappedPtr, reinterpret_cast<void *>(quadVertices.data()), bufferSize);
1955*8975f5c5SAndroid Build Coastguard Worker 
1956*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, quadVertices.size());
1957*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(8, 8, GLColor::red);
1958*8975f5c5SAndroid Build Coastguard Worker 
1959*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_ARRAY_BUFFER);
1960*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(program);
1961*8975f5c5SAndroid Build Coastguard Worker 
1962*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
1963*8975f5c5SAndroid Build Coastguard Worker }
1964*8975f5c5SAndroid Build Coastguard Worker 
TestPageSharingBuffers(std::function<void (void)> swapCallback,size_t bufferSize,const std::array<Vector3,6> & quadVertices,GLint positionLocation)1965*8975f5c5SAndroid Build Coastguard Worker void TestPageSharingBuffers(std::function<void(void)> swapCallback,
1966*8975f5c5SAndroid Build Coastguard Worker                             size_t bufferSize,
1967*8975f5c5SAndroid Build Coastguard Worker                             const std::array<Vector3, 6> &quadVertices,
1968*8975f5c5SAndroid Build Coastguard Worker                             GLint positionLocation)
1969*8975f5c5SAndroid Build Coastguard Worker {
1970*8975f5c5SAndroid Build Coastguard Worker     size_t dataSize = sizeof(GLfloat) * quadVertices.size() * 3;
1971*8975f5c5SAndroid Build Coastguard Worker 
1972*8975f5c5SAndroid Build Coastguard Worker     if (bufferSize == 0)
1973*8975f5c5SAndroid Build Coastguard Worker     {
1974*8975f5c5SAndroid Build Coastguard Worker         bufferSize = dataSize;
1975*8975f5c5SAndroid Build Coastguard Worker     }
1976*8975f5c5SAndroid Build Coastguard Worker 
1977*8975f5c5SAndroid Build Coastguard Worker     constexpr size_t bufferCount = 10;
1978*8975f5c5SAndroid Build Coastguard Worker 
1979*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLBuffer> buffers(bufferCount);
1980*8975f5c5SAndroid Build Coastguard Worker     std::vector<void *> mapPointers(bufferCount);
1981*8975f5c5SAndroid Build Coastguard Worker 
1982*8975f5c5SAndroid Build Coastguard Worker     // Init and map
1983*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < bufferCount; i++)
1984*8975f5c5SAndroid Build Coastguard Worker     {
1985*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ARRAY_BUFFER, buffers[i]);
1986*8975f5c5SAndroid Build Coastguard Worker 
1987*8975f5c5SAndroid Build Coastguard Worker         glBufferStorageEXT(GL_ARRAY_BUFFER, bufferSize, nullptr,
1988*8975f5c5SAndroid Build Coastguard Worker                            GL_DYNAMIC_STORAGE_BIT_EXT | GL_MAP_WRITE_BIT |
1989*8975f5c5SAndroid Build Coastguard Worker                                GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1990*8975f5c5SAndroid Build Coastguard Worker 
1991*8975f5c5SAndroid Build Coastguard Worker         glEnableVertexAttribArray(positionLocation);
1992*8975f5c5SAndroid Build Coastguard Worker 
1993*8975f5c5SAndroid Build Coastguard Worker         mapPointers[i] = glMapBufferRange(
1994*8975f5c5SAndroid Build Coastguard Worker             GL_ARRAY_BUFFER, 0, bufferSize,
1995*8975f5c5SAndroid Build Coastguard Worker             GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
1996*8975f5c5SAndroid Build Coastguard Worker         ASSERT_NE(nullptr, mapPointers[i]);
1997*8975f5c5SAndroid Build Coastguard Worker     }
1998*8975f5c5SAndroid Build Coastguard Worker 
1999*8975f5c5SAndroid Build Coastguard Worker     // Write, draw and unmap
2000*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < bufferCount; i++)
2001*8975f5c5SAndroid Build Coastguard Worker     {
2002*8975f5c5SAndroid Build Coastguard Worker         memcpy(mapPointers[i], reinterpret_cast<const void *>(quadVertices.data()), dataSize);
2003*8975f5c5SAndroid Build Coastguard Worker 
2004*8975f5c5SAndroid Build Coastguard Worker         // Write something to last float
2005*8975f5c5SAndroid Build Coastguard Worker         if (bufferSize > dataSize + sizeof(GLfloat))
2006*8975f5c5SAndroid Build Coastguard Worker         {
2007*8975f5c5SAndroid Build Coastguard Worker             size_t lastPosition = bufferSize / sizeof(GLfloat) - 1;
2008*8975f5c5SAndroid Build Coastguard Worker             reinterpret_cast<float *>(mapPointers[i])[lastPosition] = 1.0f;
2009*8975f5c5SAndroid Build Coastguard Worker         }
2010*8975f5c5SAndroid Build Coastguard Worker 
2011*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ARRAY_BUFFER, buffers[i]);
2012*8975f5c5SAndroid Build Coastguard Worker         glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
2013*8975f5c5SAndroid Build Coastguard Worker         glDrawArrays(GL_TRIANGLES, 0, quadVertices.size());
2014*8975f5c5SAndroid Build Coastguard Worker         EXPECT_PIXEL_COLOR_EQ(8, 8, GLColor::red);
2015*8975f5c5SAndroid Build Coastguard Worker         swapCallback();
2016*8975f5c5SAndroid Build Coastguard Worker         glUnmapBuffer(GL_ARRAY_BUFFER);
2017*8975f5c5SAndroid Build Coastguard Worker     }
2018*8975f5c5SAndroid Build Coastguard Worker }
2019*8975f5c5SAndroid Build Coastguard Worker 
2020*8975f5c5SAndroid Build Coastguard Worker // Create multiple persistently mapped coherent buffers of different sizes that will likely share a
2021*8975f5c5SAndroid Build Coastguard Worker // page. Map all buffers together and unmap each buffer after writing to it and using it for a draw.
2022*8975f5c5SAndroid Build Coastguard Worker // This tests the behaviour of the coherent buffer tracker in frame capture when buffers that share
2023*8975f5c5SAndroid Build Coastguard Worker // a page are written to after the other one is removed.
TEST_P(BufferStorageTestES3,PageSharingBuffers)2024*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferStorageTestES3, PageSharingBuffers)
2025*8975f5c5SAndroid Build Coastguard Worker {
2026*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
2027*8975f5c5SAndroid Build Coastguard Worker                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
2028*8975f5c5SAndroid Build Coastguard Worker 
2029*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
2030*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(program, 0u);
2031*8975f5c5SAndroid Build Coastguard Worker 
2032*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
2033*8975f5c5SAndroid Build Coastguard Worker 
2034*8975f5c5SAndroid Build Coastguard Worker     auto quadVertices = GetQuadVertices();
2035*8975f5c5SAndroid Build Coastguard Worker 
2036*8975f5c5SAndroid Build Coastguard Worker     std::function<void(void)> swapCallback = [this]() { swapBuffers(); };
2037*8975f5c5SAndroid Build Coastguard Worker 
2038*8975f5c5SAndroid Build Coastguard Worker     GLint positionLocation = glGetAttribLocation(program, essl3_shaders::PositionAttrib());
2039*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, positionLocation);
2040*8975f5c5SAndroid Build Coastguard Worker 
2041*8975f5c5SAndroid Build Coastguard Worker     TestPageSharingBuffers(swapCallback, 0, quadVertices, positionLocation);
2042*8975f5c5SAndroid Build Coastguard Worker     TestPageSharingBuffers(swapCallback, 1000, quadVertices, positionLocation);
2043*8975f5c5SAndroid Build Coastguard Worker     TestPageSharingBuffers(swapCallback, 4096, quadVertices, positionLocation);
2044*8975f5c5SAndroid Build Coastguard Worker     TestPageSharingBuffers(swapCallback, 6144, quadVertices, positionLocation);
2045*8975f5c5SAndroid Build Coastguard Worker     TestPageSharingBuffers(swapCallback, 40960, quadVertices, positionLocation);
2046*8975f5c5SAndroid Build Coastguard Worker 
2047*8975f5c5SAndroid Build Coastguard Worker     glDeleteProgram(program);
2048*8975f5c5SAndroid Build Coastguard Worker 
2049*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
2050*8975f5c5SAndroid Build Coastguard Worker }
2051*8975f5c5SAndroid Build Coastguard Worker 
2052*8975f5c5SAndroid Build Coastguard Worker class BufferStorageTestES3Threaded : public ANGLETest<>
2053*8975f5c5SAndroid Build Coastguard Worker {
2054*8975f5c5SAndroid Build Coastguard Worker   protected:
BufferStorageTestES3Threaded()2055*8975f5c5SAndroid Build Coastguard Worker     BufferStorageTestES3Threaded()
2056*8975f5c5SAndroid Build Coastguard Worker     {
2057*8975f5c5SAndroid Build Coastguard Worker         setWindowWidth(16);
2058*8975f5c5SAndroid Build Coastguard Worker         setWindowHeight(16);
2059*8975f5c5SAndroid Build Coastguard Worker         setConfigRedBits(8);
2060*8975f5c5SAndroid Build Coastguard Worker         setConfigGreenBits(8);
2061*8975f5c5SAndroid Build Coastguard Worker         setConfigBlueBits(8);
2062*8975f5c5SAndroid Build Coastguard Worker         setConfigAlphaBits(8);
2063*8975f5c5SAndroid Build Coastguard Worker         setConfigDepthBits(24);
2064*8975f5c5SAndroid Build Coastguard Worker 
2065*8975f5c5SAndroid Build Coastguard Worker         mProgram = 0;
2066*8975f5c5SAndroid Build Coastguard Worker     }
2067*8975f5c5SAndroid Build Coastguard Worker 
testSetUp()2068*8975f5c5SAndroid Build Coastguard Worker     void testSetUp() override
2069*8975f5c5SAndroid Build Coastguard Worker     {
2070*8975f5c5SAndroid Build Coastguard Worker         constexpr char kVS[] = R"(#version 300 es
2071*8975f5c5SAndroid Build Coastguard Worker 
2072*8975f5c5SAndroid Build Coastguard Worker in vec4 position;
2073*8975f5c5SAndroid Build Coastguard Worker in vec4 color;
2074*8975f5c5SAndroid Build Coastguard Worker out vec4 out_color;
2075*8975f5c5SAndroid Build Coastguard Worker 
2076*8975f5c5SAndroid Build Coastguard Worker void main()
2077*8975f5c5SAndroid Build Coastguard Worker {
2078*8975f5c5SAndroid Build Coastguard Worker     out_color = color;
2079*8975f5c5SAndroid Build Coastguard Worker     gl_Position = position;
2080*8975f5c5SAndroid Build Coastguard Worker })";
2081*8975f5c5SAndroid Build Coastguard Worker 
2082*8975f5c5SAndroid Build Coastguard Worker         constexpr char kFS[] = R"(#version 300 es
2083*8975f5c5SAndroid Build Coastguard Worker precision highp float;
2084*8975f5c5SAndroid Build Coastguard Worker 
2085*8975f5c5SAndroid Build Coastguard Worker in vec4 out_color;
2086*8975f5c5SAndroid Build Coastguard Worker out vec4 fragColor;
2087*8975f5c5SAndroid Build Coastguard Worker 
2088*8975f5c5SAndroid Build Coastguard Worker void main()
2089*8975f5c5SAndroid Build Coastguard Worker {
2090*8975f5c5SAndroid Build Coastguard Worker     fragColor = vec4(out_color);
2091*8975f5c5SAndroid Build Coastguard Worker })";
2092*8975f5c5SAndroid Build Coastguard Worker 
2093*8975f5c5SAndroid Build Coastguard Worker         mProgram = CompileProgram(kVS, kFS);
2094*8975f5c5SAndroid Build Coastguard Worker         ASSERT_NE(mProgram, 0U);
2095*8975f5c5SAndroid Build Coastguard Worker 
2096*8975f5c5SAndroid Build Coastguard Worker         glClearColor(0, 0, 0, 0);
2097*8975f5c5SAndroid Build Coastguard Worker         glClearDepthf(0.0);
2098*8975f5c5SAndroid Build Coastguard Worker         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2099*8975f5c5SAndroid Build Coastguard Worker 
2100*8975f5c5SAndroid Build Coastguard Worker         glDisable(GL_DEPTH_TEST);
2101*8975f5c5SAndroid Build Coastguard Worker 
2102*8975f5c5SAndroid Build Coastguard Worker         ASSERT_GL_NO_ERROR();
2103*8975f5c5SAndroid Build Coastguard Worker     }
2104*8975f5c5SAndroid Build Coastguard Worker 
testTearDown()2105*8975f5c5SAndroid Build Coastguard Worker     void testTearDown() override { glDeleteProgram(mProgram); }
2106*8975f5c5SAndroid Build Coastguard Worker 
updateColors(int i,int offset,const GLColor & color)2107*8975f5c5SAndroid Build Coastguard Worker     void updateColors(int i, int offset, const GLColor &color)
2108*8975f5c5SAndroid Build Coastguard Worker     {
2109*8975f5c5SAndroid Build Coastguard Worker         Vector4 colorVec               = color.toNormalizedVector();
2110*8975f5c5SAndroid Build Coastguard Worker         mMappedPtr[offset + i * 4 + 0] = colorVec.x();
2111*8975f5c5SAndroid Build Coastguard Worker         mMappedPtr[offset + i * 4 + 1] = colorVec.y();
2112*8975f5c5SAndroid Build Coastguard Worker         mMappedPtr[offset + i * 4 + 2] = colorVec.z();
2113*8975f5c5SAndroid Build Coastguard Worker         mMappedPtr[offset + i * 4 + 3] = colorVec.w();
2114*8975f5c5SAndroid Build Coastguard Worker     }
2115*8975f5c5SAndroid Build Coastguard Worker 
updateThreadedAndDraw(int offset,const GLColor & color)2116*8975f5c5SAndroid Build Coastguard Worker     void updateThreadedAndDraw(int offset, const GLColor &color)
2117*8975f5c5SAndroid Build Coastguard Worker     {
2118*8975f5c5SAndroid Build Coastguard Worker         std::mutex mutex;
2119*8975f5c5SAndroid Build Coastguard Worker         std::vector<std::thread> threads(4);
2120*8975f5c5SAndroid Build Coastguard Worker         for (size_t i = 0; i < 4; i++)
2121*8975f5c5SAndroid Build Coastguard Worker         {
2122*8975f5c5SAndroid Build Coastguard Worker             threads[i] = std::thread([&, i]() {
2123*8975f5c5SAndroid Build Coastguard Worker                 std::lock_guard<decltype(mutex)> lock(mutex);
2124*8975f5c5SAndroid Build Coastguard Worker                 updateColors(i, offset, color);
2125*8975f5c5SAndroid Build Coastguard Worker             });
2126*8975f5c5SAndroid Build Coastguard Worker         }
2127*8975f5c5SAndroid Build Coastguard Worker 
2128*8975f5c5SAndroid Build Coastguard Worker         glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
2129*8975f5c5SAndroid Build Coastguard Worker 
2130*8975f5c5SAndroid Build Coastguard Worker         for (std::thread &thread : threads)
2131*8975f5c5SAndroid Build Coastguard Worker         {
2132*8975f5c5SAndroid Build Coastguard Worker             thread.join();
2133*8975f5c5SAndroid Build Coastguard Worker         }
2134*8975f5c5SAndroid Build Coastguard Worker     }
2135*8975f5c5SAndroid Build Coastguard Worker 
2136*8975f5c5SAndroid Build Coastguard Worker     GLuint mProgram;
2137*8975f5c5SAndroid Build Coastguard Worker     GLfloat *mMappedPtr = nullptr;
2138*8975f5c5SAndroid Build Coastguard Worker };
2139*8975f5c5SAndroid Build Coastguard Worker 
2140*8975f5c5SAndroid Build Coastguard Worker // Test using a large buffer storage for a color vertex array buffer, which is
2141*8975f5c5SAndroid Build Coastguard Worker // off set every iteration step via glVertexAttribPointer.
2142*8975f5c5SAndroid Build Coastguard Worker // Write to the buffer storage map pointer from multiple threads for the next iteration,
2143*8975f5c5SAndroid Build Coastguard Worker // while drawing the current one.
TEST_P(BufferStorageTestES3Threaded,VertexBuffer)2144*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferStorageTestES3Threaded, VertexBuffer)
2145*8975f5c5SAndroid Build Coastguard Worker {
2146*8975f5c5SAndroid Build Coastguard Worker     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
2147*8975f5c5SAndroid Build Coastguard Worker                        !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
2148*8975f5c5SAndroid Build Coastguard Worker 
2149*8975f5c5SAndroid Build Coastguard Worker     auto vertices = GetIndexedQuadVertices();
2150*8975f5c5SAndroid Build Coastguard Worker 
2151*8975f5c5SAndroid Build Coastguard Worker     // Set up position buffer
2152*8975f5c5SAndroid Build Coastguard Worker     GLBuffer positionBuffer;
2153*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
2154*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * vertices.size(), vertices.data(),
2155*8975f5c5SAndroid Build Coastguard Worker                  GL_STATIC_DRAW);
2156*8975f5c5SAndroid Build Coastguard Worker 
2157*8975f5c5SAndroid Build Coastguard Worker     GLint positionLoc = glGetAttribLocation(mProgram, "position");
2158*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(positionLoc, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr);
2159*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(positionLoc);
2160*8975f5c5SAndroid Build Coastguard Worker 
2161*8975f5c5SAndroid Build Coastguard Worker     // Set up color buffer
2162*8975f5c5SAndroid Build Coastguard Worker     GLBuffer colorBuffer;
2163*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
2164*8975f5c5SAndroid Build Coastguard Worker 
2165*8975f5c5SAndroid Build Coastguard Worker     // Let's create a big buffer which fills 10 pages at pagesize 4096
2166*8975f5c5SAndroid Build Coastguard Worker     GLint bufferSize   = sizeof(GLfloat) * 1024 * 10;
2167*8975f5c5SAndroid Build Coastguard Worker     GLint offsetFloats = 0;
2168*8975f5c5SAndroid Build Coastguard Worker 
2169*8975f5c5SAndroid Build Coastguard Worker     glBufferStorageEXT(GL_ARRAY_BUFFER, bufferSize, nullptr,
2170*8975f5c5SAndroid Build Coastguard Worker                        GL_DYNAMIC_STORAGE_BIT_EXT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT |
2171*8975f5c5SAndroid Build Coastguard Worker                            GL_MAP_COHERENT_BIT_EXT);
2172*8975f5c5SAndroid Build Coastguard Worker     GLint colorLoc = glGetAttribLocation(mProgram, "color");
2173*8975f5c5SAndroid Build Coastguard Worker     glEnableVertexAttribArray(colorLoc);
2174*8975f5c5SAndroid Build Coastguard Worker 
2175*8975f5c5SAndroid Build Coastguard Worker     auto indices = GetQuadIndices();
2176*8975f5c5SAndroid Build Coastguard Worker 
2177*8975f5c5SAndroid Build Coastguard Worker     GLBuffer indexBuffer;
2178*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
2179*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices[0]) * indices.size(), indices.data(),
2180*8975f5c5SAndroid Build Coastguard Worker                  GL_STATIC_DRAW);
2181*8975f5c5SAndroid Build Coastguard Worker 
2182*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(mProgram);
2183*8975f5c5SAndroid Build Coastguard Worker 
2184*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0, 0, 0, 0);
2185*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
2186*8975f5c5SAndroid Build Coastguard Worker 
2187*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
2188*8975f5c5SAndroid Build Coastguard Worker 
2189*8975f5c5SAndroid Build Coastguard Worker     mMappedPtr = (GLfloat *)glMapBufferRange(
2190*8975f5c5SAndroid Build Coastguard Worker         GL_ARRAY_BUFFER, 0, bufferSize,
2191*8975f5c5SAndroid Build Coastguard Worker         GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT);
2192*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(nullptr, mMappedPtr);
2193*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
2194*8975f5c5SAndroid Build Coastguard Worker 
2195*8975f5c5SAndroid Build Coastguard Worker     // Initial color
2196*8975f5c5SAndroid Build Coastguard Worker     for (int i = 0; i < 4; i++)
2197*8975f5c5SAndroid Build Coastguard Worker     {
2198*8975f5c5SAndroid Build Coastguard Worker         updateColors(i, offsetFloats, GLColor::black);
2199*8975f5c5SAndroid Build Coastguard Worker     }
2200*8975f5c5SAndroid Build Coastguard Worker 
2201*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLColor> colors = {GLColor::red, GLColor::green, GLColor::blue};
2202*8975f5c5SAndroid Build Coastguard Worker 
2203*8975f5c5SAndroid Build Coastguard Worker     // 4 vertices, 4 floats
2204*8975f5c5SAndroid Build Coastguard Worker     GLint contentSize = 4 * 4;
2205*8975f5c5SAndroid Build Coastguard Worker 
2206*8975f5c5SAndroid Build Coastguard Worker     // Update and draw last
2207*8975f5c5SAndroid Build Coastguard Worker     int i = 0;
2208*8975f5c5SAndroid Build Coastguard Worker     while (bufferSize > (int)((offsetFloats + contentSize) * sizeof(GLfloat)))
2209*8975f5c5SAndroid Build Coastguard Worker     {
2210*8975f5c5SAndroid Build Coastguard Worker         glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat),
2211*8975f5c5SAndroid Build Coastguard Worker                               reinterpret_cast<const GLvoid *>(offsetFloats * sizeof(GLfloat)));
2212*8975f5c5SAndroid Build Coastguard Worker 
2213*8975f5c5SAndroid Build Coastguard Worker         offsetFloats += contentSize;
2214*8975f5c5SAndroid Build Coastguard Worker         GLColor color = colors[i % colors.size()];
2215*8975f5c5SAndroid Build Coastguard Worker         updateThreadedAndDraw(offsetFloats, color);
2216*8975f5c5SAndroid Build Coastguard Worker 
2217*8975f5c5SAndroid Build Coastguard Worker         if (i > 0)
2218*8975f5c5SAndroid Build Coastguard Worker         {
2219*8975f5c5SAndroid Build Coastguard Worker             GLColor lastColor = colors[(i - 1) % colors.size()];
2220*8975f5c5SAndroid Build Coastguard Worker             EXPECT_PIXEL_COLOR_EQ(0, 0, lastColor);
2221*8975f5c5SAndroid Build Coastguard Worker         }
2222*8975f5c5SAndroid Build Coastguard Worker         ASSERT_GL_NO_ERROR();
2223*8975f5c5SAndroid Build Coastguard Worker         i++;
2224*8975f5c5SAndroid Build Coastguard Worker     }
2225*8975f5c5SAndroid Build Coastguard Worker 
2226*8975f5c5SAndroid Build Coastguard Worker     // Last draw
2227*8975f5c5SAndroid Build Coastguard Worker     glVertexAttribPointer(colorLoc, 3, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat),
2228*8975f5c5SAndroid Build Coastguard Worker                           reinterpret_cast<const GLvoid *>(offsetFloats * sizeof(GLfloat)));
2229*8975f5c5SAndroid Build Coastguard Worker     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
2230*8975f5c5SAndroid Build Coastguard Worker 
2231*8975f5c5SAndroid Build Coastguard Worker     glUnmapBuffer(GL_ARRAY_BUFFER);
2232*8975f5c5SAndroid Build Coastguard Worker 
2233*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
2234*8975f5c5SAndroid Build Coastguard Worker }
2235*8975f5c5SAndroid Build Coastguard Worker 
2236*8975f5c5SAndroid Build Coastguard Worker // Test that buffer self-copy works when buffer is used as UBO
TEST_P(BufferDataTestES3,CopyBufferSubDataSelfDependency)2237*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataTestES3, CopyBufferSubDataSelfDependency)
2238*8975f5c5SAndroid Build Coastguard Worker {
2239*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] = R"(#version 300 es
2240*8975f5c5SAndroid Build Coastguard Worker precision mediump float;
2241*8975f5c5SAndroid Build Coastguard Worker out vec4 color;
2242*8975f5c5SAndroid Build Coastguard Worker 
2243*8975f5c5SAndroid Build Coastguard Worker uniform UBO
2244*8975f5c5SAndroid Build Coastguard Worker {
2245*8975f5c5SAndroid Build Coastguard Worker     vec4 data[128];
2246*8975f5c5SAndroid Build Coastguard Worker };
2247*8975f5c5SAndroid Build Coastguard Worker 
2248*8975f5c5SAndroid Build Coastguard Worker void main()
2249*8975f5c5SAndroid Build Coastguard Worker {
2250*8975f5c5SAndroid Build Coastguard Worker     color = data[12];
2251*8975f5c5SAndroid Build Coastguard Worker })";
2252*8975f5c5SAndroid Build Coastguard Worker 
2253*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Simple(), kFS);
2254*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
2255*8975f5c5SAndroid Build Coastguard Worker 
2256*8975f5c5SAndroid Build Coastguard Worker     constexpr uint32_t kVec4Size   = 4 * sizeof(float);
2257*8975f5c5SAndroid Build Coastguard Worker     constexpr uint32_t kUBOSize    = 128 * kVec4Size;
2258*8975f5c5SAndroid Build Coastguard Worker     constexpr uint32_t kDataOffset = 12 * kVec4Size;
2259*8975f5c5SAndroid Build Coastguard Worker 
2260*8975f5c5SAndroid Build Coastguard Worker     // Init data is 4 times the size of UBO as the buffer is created larger than the UBO throughout
2261*8975f5c5SAndroid Build Coastguard Worker     // the test.
2262*8975f5c5SAndroid Build Coastguard Worker     const std::vector<float> kInitData(kUBOSize, 123.45);
2263*8975f5c5SAndroid Build Coastguard Worker 
2264*8975f5c5SAndroid Build Coastguard Worker     // Set up a throw-away buffer just to make buffer suballocations not use offset 0.
2265*8975f5c5SAndroid Build Coastguard Worker     GLBuffer throwaway;
2266*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_UNIFORM_BUFFER, throwaway);
2267*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_UNIFORM_BUFFER, 1024, nullptr, GL_DYNAMIC_DRAW);
2268*8975f5c5SAndroid Build Coastguard Worker 
2269*8975f5c5SAndroid Build Coastguard Worker     // Set up the buffer
2270*8975f5c5SAndroid Build Coastguard Worker     GLBuffer buffer;
2271*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_UNIFORM_BUFFER, buffer);
2272*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_UNIFORM_BUFFER, kUBOSize * 2, kInitData.data(), GL_DYNAMIC_DRAW);
2273*8975f5c5SAndroid Build Coastguard Worker 
2274*8975f5c5SAndroid Build Coastguard Worker     const std::vector<float> kColorData = {
2275*8975f5c5SAndroid Build Coastguard Worker         0.75,
2276*8975f5c5SAndroid Build Coastguard Worker         0.5,
2277*8975f5c5SAndroid Build Coastguard Worker         0.25,
2278*8975f5c5SAndroid Build Coastguard Worker         1.0,
2279*8975f5c5SAndroid Build Coastguard Worker     };
2280*8975f5c5SAndroid Build Coastguard Worker     glBufferSubData(GL_UNIFORM_BUFFER, kDataOffset, kVec4Size, kColorData.data());
2281*8975f5c5SAndroid Build Coastguard Worker 
2282*8975f5c5SAndroid Build Coastguard Worker     glClearColor(0, 0, 0, 1);
2283*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
2284*8975f5c5SAndroid Build Coastguard Worker     const int w = getWindowWidth();
2285*8975f5c5SAndroid Build Coastguard Worker     const int h = getWindowHeight();
2286*8975f5c5SAndroid Build Coastguard Worker 
2287*8975f5c5SAndroid Build Coastguard Worker     // Use the buffer, then do a big self-copy
2288*8975f5c5SAndroid Build Coastguard Worker     glBindBufferRange(GL_UNIFORM_BUFFER, 0, buffer, 0, kUBOSize);
2289*8975f5c5SAndroid Build Coastguard Worker     glScissor(0, 0, w / 2, h / 2);
2290*8975f5c5SAndroid Build Coastguard Worker     glEnable(GL_SCISSOR_TEST);
2291*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5);
2292*8975f5c5SAndroid Build Coastguard Worker 
2293*8975f5c5SAndroid Build Coastguard Worker     // Duplicate the buffer in the second half
2294*8975f5c5SAndroid Build Coastguard Worker     glCopyBufferSubData(GL_UNIFORM_BUFFER, GL_UNIFORM_BUFFER, 0, kUBOSize, kUBOSize);
2295*8975f5c5SAndroid Build Coastguard Worker 
2296*8975f5c5SAndroid Build Coastguard Worker     // Draw again, making sure the copy succeeded.
2297*8975f5c5SAndroid Build Coastguard Worker     glBindBufferRange(GL_UNIFORM_BUFFER, 0, buffer, kUBOSize, kUBOSize);
2298*8975f5c5SAndroid Build Coastguard Worker     glScissor(w / 2, 0, w / 2, h / 2);
2299*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5);
2300*8975f5c5SAndroid Build Coastguard Worker 
2301*8975f5c5SAndroid Build Coastguard Worker     // Do a small self-copy
2302*8975f5c5SAndroid Build Coastguard Worker     constexpr uint32_t kCopySrcOffset = 4 * kVec4Size;
2303*8975f5c5SAndroid Build Coastguard Worker     constexpr uint32_t kCopyDstOffset = (64 + 4) * kVec4Size;
2304*8975f5c5SAndroid Build Coastguard Worker     glCopyBufferSubData(GL_UNIFORM_BUFFER, GL_UNIFORM_BUFFER, kCopySrcOffset, kCopyDstOffset,
2305*8975f5c5SAndroid Build Coastguard Worker                         kDataOffset);
2306*8975f5c5SAndroid Build Coastguard Worker 
2307*8975f5c5SAndroid Build Coastguard Worker     // color data was previously at [12], and is now available at [68 + 12 - 4]
2308*8975f5c5SAndroid Build Coastguard Worker     glBindBufferRange(GL_UNIFORM_BUFFER, 0, buffer, kCopyDstOffset - kCopySrcOffset, kUBOSize);
2309*8975f5c5SAndroid Build Coastguard Worker     glScissor(0, h / 2, w / 2, h / 2);
2310*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5);
2311*8975f5c5SAndroid Build Coastguard Worker 
2312*8975f5c5SAndroid Build Coastguard Worker     // Validate results
2313*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_NEAR(0, 0, 191, 127, 63, 255, 1);
2314*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_NEAR(w / 2 + 1, 0, 191, 127, 63, 255, 1);
2315*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_NEAR(0, h / 2 + 1, 191, 127, 63, 255, 1);
2316*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_COLOR_EQ(w / 2 + 1, h / 2 + 1, GLColor::black);
2317*8975f5c5SAndroid Build Coastguard Worker 
2318*8975f5c5SAndroid Build Coastguard Worker     // Do a big copy again, but this time the buffer is unused by the GPU
2319*8975f5c5SAndroid Build Coastguard Worker     glCopyBufferSubData(GL_UNIFORM_BUFFER, GL_UNIFORM_BUFFER, kUBOSize, 0, kUBOSize);
2320*8975f5c5SAndroid Build Coastguard Worker     glBindBufferRange(GL_UNIFORM_BUFFER, 0, buffer, 0, kUBOSize);
2321*8975f5c5SAndroid Build Coastguard Worker     glScissor(w / 2, h / 2, w / 2, h / 2);
2322*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5);
2323*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_NEAR(w / 2 + 1, h / 2 + 1, 191, 127, 63, 255, 1);
2324*8975f5c5SAndroid Build Coastguard Worker 
2325*8975f5c5SAndroid Build Coastguard Worker     // Do a small copy again, but this time the buffer is unused by the GPU
2326*8975f5c5SAndroid Build Coastguard Worker     glCopyBufferSubData(GL_UNIFORM_BUFFER, GL_UNIFORM_BUFFER, kUBOSize + kCopySrcOffset,
2327*8975f5c5SAndroid Build Coastguard Worker                         kCopyDstOffset, kDataOffset);
2328*8975f5c5SAndroid Build Coastguard Worker     glBindBufferRange(GL_UNIFORM_BUFFER, 0, buffer, kCopyDstOffset - kCopySrcOffset, kUBOSize);
2329*8975f5c5SAndroid Build Coastguard Worker     glDisable(GL_SCISSOR_TEST);
2330*8975f5c5SAndroid Build Coastguard Worker     glClear(GL_COLOR_BUFFER_BIT);
2331*8975f5c5SAndroid Build Coastguard Worker     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5);
2332*8975f5c5SAndroid Build Coastguard Worker     EXPECT_PIXEL_NEAR(0, 0, 191, 127, 63, 255, 1);
2333*8975f5c5SAndroid Build Coastguard Worker 
2334*8975f5c5SAndroid Build Coastguard Worker     ASSERT_GL_NO_ERROR();
2335*8975f5c5SAndroid Build Coastguard Worker }
2336*8975f5c5SAndroid Build Coastguard Worker 
2337*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES2(BufferDataTest);
2338*8975f5c5SAndroid Build Coastguard Worker 
2339*8975f5c5SAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BufferSubDataTest);
2340*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_COMBINE_1(BufferSubDataTest,
2341*8975f5c5SAndroid Build Coastguard Worker                                  BufferSubDataTestPrint,
2342*8975f5c5SAndroid Build Coastguard Worker                                  testing::Bool(),
2343*8975f5c5SAndroid Build Coastguard Worker                                  ANGLE_ALL_TEST_PLATFORMS_ES3,
2344*8975f5c5SAndroid Build Coastguard Worker                                  ES3_VULKAN().enable(Feature::PreferCPUForBufferSubData));
2345*8975f5c5SAndroid Build Coastguard Worker 
2346*8975f5c5SAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BufferDataTestES3);
2347*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES3_AND(BufferDataTestES3,
2348*8975f5c5SAndroid Build Coastguard Worker                                ES3_VULKAN().enable(Feature::PreferCPUForBufferSubData),
2349*8975f5c5SAndroid Build Coastguard Worker                                ES3_METAL().enable(Feature::ForceBufferGPUStorage));
2350*8975f5c5SAndroid Build Coastguard Worker 
2351*8975f5c5SAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BufferStorageTestES3);
2352*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES3_AND(BufferStorageTestES3,
2353*8975f5c5SAndroid Build Coastguard Worker                                ES3_VULKAN().enable(Feature::AllocateNonZeroMemory));
2354*8975f5c5SAndroid Build Coastguard Worker 
2355*8975f5c5SAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(IndexedBufferCopyTest);
2356*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES3(IndexedBufferCopyTest);
2357*8975f5c5SAndroid Build Coastguard Worker 
2358*8975f5c5SAndroid Build Coastguard Worker GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BufferStorageTestES3Threaded);
2359*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES3(BufferStorageTestES3Threaded);
2360*8975f5c5SAndroid Build Coastguard Worker 
2361*8975f5c5SAndroid Build Coastguard Worker #ifdef _WIN64
2362*8975f5c5SAndroid Build Coastguard Worker 
2363*8975f5c5SAndroid Build Coastguard Worker // Test a bug where an integer overflow bug could trigger a crash in D3D.
2364*8975f5c5SAndroid Build Coastguard Worker // The test uses 8 buffers with a size just under 0x2000000 to overflow max uint
2365*8975f5c5SAndroid Build Coastguard Worker // (with the internal D3D rounding to 16-byte values) and trigger the bug.
2366*8975f5c5SAndroid Build Coastguard Worker // Only handle this bug on 64-bit Windows for now. Harder to repro on 32-bit.
2367*8975f5c5SAndroid Build Coastguard Worker class BufferDataOverflowTest : public ANGLETest<>
2368*8975f5c5SAndroid Build Coastguard Worker {
2369*8975f5c5SAndroid Build Coastguard Worker   protected:
BufferDataOverflowTest()2370*8975f5c5SAndroid Build Coastguard Worker     BufferDataOverflowTest() {}
2371*8975f5c5SAndroid Build Coastguard Worker };
2372*8975f5c5SAndroid Build Coastguard Worker 
2373*8975f5c5SAndroid Build Coastguard Worker // See description above.
TEST_P(BufferDataOverflowTest,VertexBufferIntegerOverflow)2374*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataOverflowTest, VertexBufferIntegerOverflow)
2375*8975f5c5SAndroid Build Coastguard Worker {
2376*8975f5c5SAndroid Build Coastguard Worker     // These values are special, to trigger the rounding bug.
2377*8975f5c5SAndroid Build Coastguard Worker     unsigned int numItems       = 0x7FFFFFE;
2378*8975f5c5SAndroid Build Coastguard Worker     constexpr GLsizei bufferCnt = 8;
2379*8975f5c5SAndroid Build Coastguard Worker 
2380*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLBuffer> buffers(bufferCnt);
2381*8975f5c5SAndroid Build Coastguard Worker 
2382*8975f5c5SAndroid Build Coastguard Worker     std::stringstream vertexShaderStr;
2383*8975f5c5SAndroid Build Coastguard Worker 
2384*8975f5c5SAndroid Build Coastguard Worker     for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
2385*8975f5c5SAndroid Build Coastguard Worker     {
2386*8975f5c5SAndroid Build Coastguard Worker         vertexShaderStr << "attribute float attrib" << bufferIndex << ";\n";
2387*8975f5c5SAndroid Build Coastguard Worker     }
2388*8975f5c5SAndroid Build Coastguard Worker 
2389*8975f5c5SAndroid Build Coastguard Worker     vertexShaderStr << "attribute vec2 position;\n"
2390*8975f5c5SAndroid Build Coastguard Worker                        "varying float v_attrib;\n"
2391*8975f5c5SAndroid Build Coastguard Worker                        "void main() {\n"
2392*8975f5c5SAndroid Build Coastguard Worker                        "  gl_Position = vec4(position, 0, 1);\n"
2393*8975f5c5SAndroid Build Coastguard Worker                        "  v_attrib = 0.0;\n";
2394*8975f5c5SAndroid Build Coastguard Worker 
2395*8975f5c5SAndroid Build Coastguard Worker     for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
2396*8975f5c5SAndroid Build Coastguard Worker     {
2397*8975f5c5SAndroid Build Coastguard Worker         vertexShaderStr << "v_attrib += attrib" << bufferIndex << ";\n";
2398*8975f5c5SAndroid Build Coastguard Worker     }
2399*8975f5c5SAndroid Build Coastguard Worker 
2400*8975f5c5SAndroid Build Coastguard Worker     vertexShaderStr << "}";
2401*8975f5c5SAndroid Build Coastguard Worker 
2402*8975f5c5SAndroid Build Coastguard Worker     constexpr char kFS[] =
2403*8975f5c5SAndroid Build Coastguard Worker         "varying highp float v_attrib;\n"
2404*8975f5c5SAndroid Build Coastguard Worker         "void main() {\n"
2405*8975f5c5SAndroid Build Coastguard Worker         "  gl_FragColor = vec4(v_attrib, 0, 0, 1);\n"
2406*8975f5c5SAndroid Build Coastguard Worker         "}";
2407*8975f5c5SAndroid Build Coastguard Worker 
2408*8975f5c5SAndroid Build Coastguard Worker     ANGLE_GL_PROGRAM(program, vertexShaderStr.str().c_str(), kFS);
2409*8975f5c5SAndroid Build Coastguard Worker     glUseProgram(program);
2410*8975f5c5SAndroid Build Coastguard Worker 
2411*8975f5c5SAndroid Build Coastguard Worker     std::vector<GLfloat> data(numItems, 1.0f);
2412*8975f5c5SAndroid Build Coastguard Worker 
2413*8975f5c5SAndroid Build Coastguard Worker     for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
2414*8975f5c5SAndroid Build Coastguard Worker     {
2415*8975f5c5SAndroid Build Coastguard Worker         glBindBuffer(GL_ARRAY_BUFFER, buffers[bufferIndex]);
2416*8975f5c5SAndroid Build Coastguard Worker         glBufferData(GL_ARRAY_BUFFER, numItems * sizeof(float), &data[0], GL_DYNAMIC_DRAW);
2417*8975f5c5SAndroid Build Coastguard Worker 
2418*8975f5c5SAndroid Build Coastguard Worker         std::stringstream attribNameStr;
2419*8975f5c5SAndroid Build Coastguard Worker         attribNameStr << "attrib" << bufferIndex;
2420*8975f5c5SAndroid Build Coastguard Worker 
2421*8975f5c5SAndroid Build Coastguard Worker         GLint attribLocation = glGetAttribLocation(program, attribNameStr.str().c_str());
2422*8975f5c5SAndroid Build Coastguard Worker         ASSERT_NE(-1, attribLocation);
2423*8975f5c5SAndroid Build Coastguard Worker 
2424*8975f5c5SAndroid Build Coastguard Worker         glVertexAttribPointer(attribLocation, 1, GL_FLOAT, GL_FALSE, 4, nullptr);
2425*8975f5c5SAndroid Build Coastguard Worker         glEnableVertexAttribArray(attribLocation);
2426*8975f5c5SAndroid Build Coastguard Worker     }
2427*8975f5c5SAndroid Build Coastguard Worker 
2428*8975f5c5SAndroid Build Coastguard Worker     GLint positionLocation = glGetAttribLocation(program, "position");
2429*8975f5c5SAndroid Build Coastguard Worker     ASSERT_NE(-1, positionLocation);
2430*8975f5c5SAndroid Build Coastguard Worker     glDisableVertexAttribArray(positionLocation);
2431*8975f5c5SAndroid Build Coastguard Worker     glVertexAttrib2f(positionLocation, 1.0f, 1.0f);
2432*8975f5c5SAndroid Build Coastguard Worker 
2433*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_NO_ERROR();
2434*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, numItems);
2435*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_OUT_OF_MEMORY);
2436*8975f5c5SAndroid Build Coastguard Worker 
2437*8975f5c5SAndroid Build Coastguard Worker     // Test that a small draw still works.
2438*8975f5c5SAndroid Build Coastguard Worker     for (GLsizei bufferIndex = 0; bufferIndex < bufferCnt; ++bufferIndex)
2439*8975f5c5SAndroid Build Coastguard Worker     {
2440*8975f5c5SAndroid Build Coastguard Worker         std::stringstream attribNameStr;
2441*8975f5c5SAndroid Build Coastguard Worker         attribNameStr << "attrib" << bufferIndex;
2442*8975f5c5SAndroid Build Coastguard Worker         GLint attribLocation = glGetAttribLocation(program, attribNameStr.str().c_str());
2443*8975f5c5SAndroid Build Coastguard Worker         ASSERT_NE(-1, attribLocation);
2444*8975f5c5SAndroid Build Coastguard Worker         glDisableVertexAttribArray(attribLocation);
2445*8975f5c5SAndroid Build Coastguard Worker     }
2446*8975f5c5SAndroid Build Coastguard Worker 
2447*8975f5c5SAndroid Build Coastguard Worker     glDrawArrays(GL_TRIANGLES, 0, 3);
2448*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_NO_ERROR);
2449*8975f5c5SAndroid Build Coastguard Worker }
2450*8975f5c5SAndroid Build Coastguard Worker 
2451*8975f5c5SAndroid Build Coastguard Worker // Tests a security bug in our CopyBufferSubData validation (integer overflow).
TEST_P(BufferDataOverflowTest,CopySubDataValidation)2452*8975f5c5SAndroid Build Coastguard Worker TEST_P(BufferDataOverflowTest, CopySubDataValidation)
2453*8975f5c5SAndroid Build Coastguard Worker {
2454*8975f5c5SAndroid Build Coastguard Worker     GLBuffer readBuffer, writeBuffer;
2455*8975f5c5SAndroid Build Coastguard Worker 
2456*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_COPY_READ_BUFFER, readBuffer);
2457*8975f5c5SAndroid Build Coastguard Worker     glBindBuffer(GL_COPY_WRITE_BUFFER, writeBuffer);
2458*8975f5c5SAndroid Build Coastguard Worker 
2459*8975f5c5SAndroid Build Coastguard Worker     constexpr int bufSize = 100;
2460*8975f5c5SAndroid Build Coastguard Worker 
2461*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_COPY_READ_BUFFER, bufSize, nullptr, GL_STATIC_DRAW);
2462*8975f5c5SAndroid Build Coastguard Worker     glBufferData(GL_COPY_WRITE_BUFFER, bufSize, nullptr, GL_STATIC_DRAW);
2463*8975f5c5SAndroid Build Coastguard Worker 
2464*8975f5c5SAndroid Build Coastguard Worker     GLintptr big = std::numeric_limits<GLintptr>::max() - bufSize + 90;
2465*8975f5c5SAndroid Build Coastguard Worker 
2466*8975f5c5SAndroid Build Coastguard Worker     glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, big, 0, 50);
2467*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_VALUE);
2468*8975f5c5SAndroid Build Coastguard Worker 
2469*8975f5c5SAndroid Build Coastguard Worker     glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, big, 50);
2470*8975f5c5SAndroid Build Coastguard Worker     EXPECT_GL_ERROR(GL_INVALID_VALUE);
2471*8975f5c5SAndroid Build Coastguard Worker }
2472*8975f5c5SAndroid Build Coastguard Worker 
2473*8975f5c5SAndroid Build Coastguard Worker ANGLE_INSTANTIATE_TEST_ES3(BufferDataOverflowTest);
2474*8975f5c5SAndroid Build Coastguard Worker 
2475*8975f5c5SAndroid Build Coastguard Worker #endif  // _WIN64
2476