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> ¶msInfo)
210*8975f5c5SAndroid Build Coastguard Worker {
211*8975f5c5SAndroid Build Coastguard Worker const BufferSubDataTestParams ¶ms = 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