1 //
2 // Copyright 2020 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // ExternalBufferTest:
7 // Tests the correctness of external buffer ext extension.
8 //
9
10 #include "test_utils/ANGLETest.h"
11 #include "test_utils/gl_raii.h"
12 #include "util/EGLWindow.h"
13
14 #include "common/android_util.h"
15
16 #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 26
17 # define ANGLE_AHARDWARE_BUFFER_SUPPORT
18 // NDK header file for access to Android Hardware Buffers
19 # include <android/hardware_buffer.h>
20 #endif
21
22 namespace angle
23 {
24
25 class ExternalBufferTestES31 : public ANGLETest<>
26 {
27 protected:
ExternalBufferTestES31()28 ExternalBufferTestES31()
29 {
30 setWindowWidth(16);
31 setWindowHeight(16);
32 setConfigRedBits(8);
33 setConfigGreenBits(8);
34 setConfigBlueBits(8);
35 setConfigAlphaBits(8);
36 setConfigDepthBits(24);
37 }
38
createAndroidHardwareBuffer(size_t size,const GLubyte * data)39 AHardwareBuffer *createAndroidHardwareBuffer(size_t size, const GLubyte *data)
40 {
41 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
42 // The height and width are number of pixels of size format
43 AHardwareBuffer_Desc aHardwareBufferDescription = {};
44 aHardwareBufferDescription.width = size;
45 aHardwareBufferDescription.height = 1;
46 aHardwareBufferDescription.layers = 1;
47 aHardwareBufferDescription.format = AHARDWAREBUFFER_FORMAT_BLOB;
48 aHardwareBufferDescription.usage =
49 AHARDWAREBUFFER_USAGE_CPU_READ_RARELY | AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
50 aHardwareBufferDescription.stride = 0;
51
52 // Allocate memory from Android Hardware Buffer
53 AHardwareBuffer *aHardwareBuffer = nullptr;
54 EXPECT_EQ(0, AHardwareBuffer_allocate(&aHardwareBufferDescription, &aHardwareBuffer));
55
56 void *mappedMemory = nullptr;
57 EXPECT_EQ(0, AHardwareBuffer_lock(aHardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY,
58 -1, nullptr, &mappedMemory));
59
60 // Need to grab the stride the implementation might have enforced
61 AHardwareBuffer_describe(aHardwareBuffer, &aHardwareBufferDescription);
62
63 if (data)
64 {
65 memcpy(mappedMemory, data, size);
66 }
67
68 EXPECT_EQ(0, AHardwareBuffer_unlock(aHardwareBuffer, nullptr));
69 return aHardwareBuffer;
70 #else
71 return nullptr;
72 #endif // ANGLE_PLATFORM_ANDROID
73 }
74
destroyAndroidHardwareBuffer(AHardwareBuffer * aHardwareBuffer)75 void destroyAndroidHardwareBuffer(AHardwareBuffer *aHardwareBuffer)
76 {
77 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
78 AHardwareBuffer_release(aHardwareBuffer);
79 #endif
80 }
81
lockAndroidHardwareBuffer(AHardwareBuffer * aHardwareBuffer)82 void *lockAndroidHardwareBuffer(AHardwareBuffer *aHardwareBuffer)
83 {
84 void *data = nullptr;
85 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
86 EXPECT_EQ(0, AHardwareBuffer_lock(aHardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY,
87 -1, nullptr, &data));
88 #endif
89 return data;
90 }
91
unlockAndroidHardwareBuffer(AHardwareBuffer * aHardwareBuffer)92 void unlockAndroidHardwareBuffer(AHardwareBuffer *aHardwareBuffer)
93 {
94 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
95 AHardwareBuffer_unlock(aHardwareBuffer, nullptr);
96 #endif
97 }
98 };
99
100 // Testing subdata update with external buffer from AHB
TEST_P(ExternalBufferTestES31,BufferSubData)101 TEST_P(ExternalBufferTestES31, BufferSubData)
102 {
103 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
104 !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
105 constexpr uint8_t kBufferSize = 16;
106 std::vector<GLubyte> initData(kBufferSize, 0xA);
107
108 // Create the Image
109 AHardwareBuffer *aHardwareBuffer;
110 constexpr GLbitfield kFlags = GL_DYNAMIC_STORAGE_BIT_EXT;
111 aHardwareBuffer = createAndroidHardwareBuffer(kBufferSize, initData.data());
112
113 GLBuffer buffer;
114 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
115 glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
116 eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);
117 ASSERT_GL_NO_ERROR();
118
119 std::vector<GLubyte> expectedData(kBufferSize, 0xFF);
120
121 glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, expectedData.data());
122 glFinish();
123
124 ASSERT_GL_NO_ERROR();
125
126 // Inspect the data written into the buffer using CPU access.
127 uint8_t *data = static_cast<uint8_t *>(lockAndroidHardwareBuffer(aHardwareBuffer));
128
129 for (uint32_t i = 0; i < kBufferSize; ++i)
130 {
131 EXPECT_EQ(data[i], 0xFF);
132 }
133
134 unlockAndroidHardwareBuffer(aHardwareBuffer);
135
136 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
137 // Delete the source AHB
138 destroyAndroidHardwareBuffer(aHardwareBuffer);
139 }
140
141 // Verify that subdata updates to an external buffer backed by an AHB doesn't orphan the AHB
TEST_P(ExternalBufferTestES31,SubDataDoesNotCauseOrphaning)142 TEST_P(ExternalBufferTestES31, SubDataDoesNotCauseOrphaning)
143 {
144 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
145 !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
146 constexpr uint8_t kBufferSize = 16;
147 std::vector<GLubyte> initData(kBufferSize, 0xA);
148
149 // Create the AHB
150 AHardwareBuffer *aHardwareBuffer;
151 constexpr GLbitfield kFlags = GL_DYNAMIC_STORAGE_BIT_EXT;
152 aHardwareBuffer = createAndroidHardwareBuffer(kBufferSize, initData.data());
153
154 // Create externalBuffer
155 GLBuffer externalBuffer;
156 glBindBuffer(GL_SHADER_STORAGE_BUFFER, externalBuffer);
157 glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
158 eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);
159 ASSERT_GL_NO_ERROR();
160
161 // Create a copy read buffer
162 std::vector<GLubyte> copyReadBufferData(kBufferSize, 0xB);
163 GLBuffer copyReadBuffer;
164 glBindBuffer(GL_COPY_READ_BUFFER, copyReadBuffer);
165 glBufferData(GL_COPY_READ_BUFFER, kBufferSize, copyReadBufferData.data(), GL_STATIC_READ);
166 ASSERT_GL_NO_ERROR();
167
168 // Copy from copyReadBuffer to externalBuffer
169 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, kBufferSize);
170 ASSERT_GL_NO_ERROR();
171
172 // Update externalBuffer
173 std::vector<GLubyte> expectedData(kBufferSize, 0xFF);
174 glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, expectedData.data());
175 glFinish();
176 ASSERT_GL_NO_ERROR();
177
178 // Inspect the data written into the AHB, through externalBuffer, using CPU access.
179 uint8_t *data = static_cast<uint8_t *>(lockAndroidHardwareBuffer(aHardwareBuffer));
180
181 for (uint32_t i = 0; i < kBufferSize; ++i)
182 {
183 EXPECT_EQ(data[i], 0xFF);
184 }
185
186 unlockAndroidHardwareBuffer(aHardwareBuffer);
187
188 glBindBuffer(GL_COPY_READ_BUFFER, 0);
189 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
190 // Delete the source AHB
191 destroyAndroidHardwareBuffer(aHardwareBuffer);
192 }
193
194 // Testing dispatch compute shader external from source AHB
TEST_P(ExternalBufferTestES31,DispatchCompute)195 TEST_P(ExternalBufferTestES31, DispatchCompute)
196 {
197 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
198 !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
199 constexpr char kCS[] = R"(#version 310 es
200 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
201 layout(std430, binding=0) buffer Output {
202 uint data[];
203 } bOutput;
204 void main() {
205 bOutput.data[gl_GlobalInvocationID.x] =
206 gl_GlobalInvocationID.x * 3u;
207 }
208 )";
209
210 constexpr uint8_t kBufferSize = 16 * 4;
211 std::vector<GLubyte> initData(kBufferSize, 0xA);
212
213 // Create the Image
214 AHardwareBuffer *aHardwareBuffer;
215 constexpr GLbitfield kFlags = GL_MAP_READ_BIT;
216 aHardwareBuffer = createAndroidHardwareBuffer(kBufferSize, initData.data());
217
218 GLBuffer buffer;
219 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
220 glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
221 eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);
222
223 ASSERT_GL_NO_ERROR();
224
225 GLProgram program;
226 program.makeCompute(kCS);
227 ASSERT_NE(program, 0U);
228 ASSERT_GL_NO_ERROR();
229
230 glUseProgram(program);
231 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
232 glDispatchCompute(kBufferSize, 1, 1);
233 glFinish();
234 ASSERT_GL_NO_ERROR();
235
236 // Inspect the data written into the buffer using CPU access.
237 uint32_t *data = static_cast<uint32_t *>(lockAndroidHardwareBuffer(aHardwareBuffer));
238
239 for (uint32_t i = 0; i < (kBufferSize / sizeof(uint32_t)); ++i)
240 {
241 EXPECT_EQ(data[i], static_cast<uint32_t>(i * 3));
242 }
243
244 unlockAndroidHardwareBuffer(aHardwareBuffer);
245
246 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
247 // Delete the source AHB
248 destroyAndroidHardwareBuffer(aHardwareBuffer);
249 }
250
251 // Test interaction between GL_OES_mapbuffer and GL_EXT_external_buffer extensions.
TEST_P(ExternalBufferTestES31,MapBuffer)252 TEST_P(ExternalBufferTestES31, MapBuffer)
253 {
254 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
255 !IsGLExtensionEnabled("GL_EXT_buffer_storage") ||
256 !IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
257 constexpr uint8_t kBufferSize = 16;
258 std::vector<GLubyte> initData(kBufferSize, 0xFF);
259
260 // Create the AHB
261 AHardwareBuffer *aHardwareBuffer;
262 constexpr GLbitfield kFlags = (GL_MAP_READ_BIT_EXT | GL_MAP_WRITE_BIT_EXT);
263 aHardwareBuffer = createAndroidHardwareBuffer(kBufferSize, initData.data());
264
265 GLBuffer buffer;
266 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
267 glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
268 eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);
269
270 ASSERT_GL_NO_ERROR();
271
272 // Inspect the data written into the buffer using CPU access.
273 uint8_t *data = static_cast<uint8_t *>(
274 glMapBufferRangeEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT_EXT));
275 ASSERT_GL_NO_ERROR();
276
277 for (uint32_t i = 0; i < kBufferSize; ++i)
278 {
279 EXPECT_EQ(data[i], 0xFF);
280 }
281
282 glUnmapBufferOES(GL_SHADER_STORAGE_BUFFER);
283
284 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
285 // Delete the source AHB
286 destroyAndroidHardwareBuffer(aHardwareBuffer);
287 }
288
289 // Verify that mapping an external buffer backed by an AHB doesn't orphan the AHB
TEST_P(ExternalBufferTestES31,MapBufferDoesNotCauseOrphaning)290 TEST_P(ExternalBufferTestES31, MapBufferDoesNotCauseOrphaning)
291 {
292 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
293 !IsGLExtensionEnabled("GL_EXT_buffer_storage") ||
294 !IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
295 constexpr uint8_t kBufferSize = 16;
296 std::vector<GLubyte> initData(kBufferSize, 0xA);
297
298 // Create the AHB
299 AHardwareBuffer *aHardwareBuffer;
300 constexpr GLbitfield kFlags =
301 (GL_MAP_READ_BIT_EXT | GL_MAP_WRITE_BIT_EXT | GL_DYNAMIC_STORAGE_BIT_EXT);
302 aHardwareBuffer = createAndroidHardwareBuffer(kBufferSize, initData.data());
303
304 GLBuffer buffer;
305 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
306 glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
307 eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);
308 ASSERT_GL_NO_ERROR();
309
310 // Create a copy read buffer
311 std::vector<GLubyte> copyReadBufferData(kBufferSize, 0xB);
312 GLBuffer copyReadBuffer;
313 glBindBuffer(GL_COPY_READ_BUFFER, copyReadBuffer);
314 glBufferData(GL_COPY_READ_BUFFER, kBufferSize, copyReadBufferData.data(), GL_STATIC_READ);
315 ASSERT_GL_NO_ERROR();
316
317 // Copy from copyReadBuffer to externalBuffer
318 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, kBufferSize);
319 ASSERT_GL_NO_ERROR();
320
321 // Inspect the data written into the buffer using map buffer API.
322 constexpr GLbitfield kMapFlags = (GL_MAP_WRITE_BIT_EXT | GL_MAP_INVALIDATE_BUFFER_BIT);
323 uint8_t *mapData = static_cast<uint8_t *>(
324 glMapBufferRangeEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, kMapFlags));
325 ASSERT_GL_NO_ERROR();
326 EXPECT_NE(mapData, nullptr);
327 glUnmapBufferOES(GL_SHADER_STORAGE_BUFFER);
328
329 // Update externalBuffer
330 std::vector<GLubyte> expectedData(kBufferSize, 0xFF);
331 glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, expectedData.data());
332 glFinish();
333 ASSERT_GL_NO_ERROR();
334
335 // Inspect the data written into the AHB, through externalBuffer, using CPU access.
336 uint8_t *data = static_cast<uint8_t *>(lockAndroidHardwareBuffer(aHardwareBuffer));
337
338 for (uint32_t i = 0; i < kBufferSize; ++i)
339 {
340 EXPECT_EQ(data[i], 0xFF);
341 }
342
343 unlockAndroidHardwareBuffer(aHardwareBuffer);
344
345 glBindBuffer(GL_COPY_READ_BUFFER, 0);
346 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
347 // Delete the source AHB
348 destroyAndroidHardwareBuffer(aHardwareBuffer);
349 }
350
351 // Verify that create and destroy external buffer backed by an AHB doesn't leak AHB
TEST_P(ExternalBufferTestES31,BufferDoesNotLeakAHB)352 TEST_P(ExternalBufferTestES31, BufferDoesNotLeakAHB)
353 {
354 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
355 !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
356
357 // Create and destroy 128M AHB backed buffer in a loop. If we leak AHB, it will fail due to AHB
358 // allocation failure before loop ends.
359 constexpr size_t kBufferSize = 128 * 1024 * 1024;
360 for (int loop = 0; loop < 1000; loop++)
361 {
362 // Create the AHB
363 AHardwareBuffer *aHardwareBuffer;
364 constexpr GLbitfield kFlags = GL_DYNAMIC_STORAGE_BIT_EXT;
365 aHardwareBuffer = createAndroidHardwareBuffer(kBufferSize, nullptr);
366 GLBuffer buffer;
367 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
368 glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
369 eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);
370 ASSERT_GL_NO_ERROR();
371 // Delete the source AHB
372 destroyAndroidHardwareBuffer(aHardwareBuffer);
373 }
374 }
375
376 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ExternalBufferTestES31);
377 ANGLE_INSTANTIATE_TEST_ES31(ExternalBufferTestES31);
378 } // namespace angle
379