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 memcpy(mappedMemory, data, size);
64
65 EXPECT_EQ(0, AHardwareBuffer_unlock(aHardwareBuffer, nullptr));
66 return aHardwareBuffer;
67 #else
68 return nullptr;
69 #endif // ANGLE_PLATFORM_ANDROID
70 }
71
destroyAndroidHardwareBuffer(AHardwareBuffer * aHardwareBuffer)72 void destroyAndroidHardwareBuffer(AHardwareBuffer *aHardwareBuffer)
73 {
74 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
75 AHardwareBuffer_release(aHardwareBuffer);
76 #endif
77 }
78
lockAndroidHardwareBuffer(AHardwareBuffer * aHardwareBuffer)79 void *lockAndroidHardwareBuffer(AHardwareBuffer *aHardwareBuffer)
80 {
81 void *data = nullptr;
82 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
83 EXPECT_EQ(0, AHardwareBuffer_lock(aHardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY,
84 -1, nullptr, &data));
85 #endif
86 return data;
87 }
88
unlockAndroidHardwareBuffer(AHardwareBuffer * aHardwareBuffer)89 void unlockAndroidHardwareBuffer(AHardwareBuffer *aHardwareBuffer)
90 {
91 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
92 AHardwareBuffer_unlock(aHardwareBuffer, nullptr);
93 #endif
94 }
95 };
96
97 // Testing subdata update with external buffer from AHB
TEST_P(ExternalBufferTestES31,BufferSubData)98 TEST_P(ExternalBufferTestES31, BufferSubData)
99 {
100 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
101 !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
102 constexpr uint8_t kBufferSize = 16;
103 std::vector<GLubyte> initData(kBufferSize, 0xA);
104
105 // Create the Image
106 AHardwareBuffer *aHardwareBuffer;
107 constexpr GLbitfield kFlags = GL_DYNAMIC_STORAGE_BIT_EXT;
108 aHardwareBuffer = createAndroidHardwareBuffer(kBufferSize, initData.data());
109
110 GLBuffer buffer;
111 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
112 glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
113 eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);
114 ASSERT_GL_NO_ERROR();
115
116 std::vector<GLubyte> expectedData(kBufferSize, 0xFF);
117
118 glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, expectedData.data());
119 glFinish();
120
121 ASSERT_GL_NO_ERROR();
122
123 // Inspect the data written into the buffer using CPU access.
124 uint8_t *data = static_cast<uint8_t *>(lockAndroidHardwareBuffer(aHardwareBuffer));
125
126 for (uint32_t i = 0; i < kBufferSize; ++i)
127 {
128 EXPECT_EQ(data[i], 0xFF);
129 }
130
131 unlockAndroidHardwareBuffer(aHardwareBuffer);
132
133 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
134 // Delete the source AHB
135 destroyAndroidHardwareBuffer(aHardwareBuffer);
136 }
137
138 // Verify that subdata updates to an external buffer backed by an AHB doesn't orphan the AHB
TEST_P(ExternalBufferTestES31,SubDataDoesNotCauseOrphaning)139 TEST_P(ExternalBufferTestES31, SubDataDoesNotCauseOrphaning)
140 {
141 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
142 !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
143 constexpr uint8_t kBufferSize = 16;
144 std::vector<GLubyte> initData(kBufferSize, 0xA);
145
146 // Create the AHB
147 AHardwareBuffer *aHardwareBuffer;
148 constexpr GLbitfield kFlags = GL_DYNAMIC_STORAGE_BIT_EXT;
149 aHardwareBuffer = createAndroidHardwareBuffer(kBufferSize, initData.data());
150
151 // Create externalBuffer
152 GLBuffer externalBuffer;
153 glBindBuffer(GL_SHADER_STORAGE_BUFFER, externalBuffer);
154 glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
155 eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);
156 ASSERT_GL_NO_ERROR();
157
158 // Create a copy read buffer
159 std::vector<GLubyte> copyReadBufferData(kBufferSize, 0xB);
160 GLBuffer copyReadBuffer;
161 glBindBuffer(GL_COPY_READ_BUFFER, copyReadBuffer);
162 glBufferData(GL_COPY_READ_BUFFER, kBufferSize, copyReadBufferData.data(), GL_STATIC_READ);
163 ASSERT_GL_NO_ERROR();
164
165 // Copy from copyReadBuffer to externalBuffer
166 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, kBufferSize);
167 ASSERT_GL_NO_ERROR();
168
169 // Update externalBuffer
170 std::vector<GLubyte> expectedData(kBufferSize, 0xFF);
171 glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, expectedData.data());
172 glFinish();
173 ASSERT_GL_NO_ERROR();
174
175 // Inspect the data written into the AHB, through externalBuffer, using CPU access.
176 uint8_t *data = static_cast<uint8_t *>(lockAndroidHardwareBuffer(aHardwareBuffer));
177
178 for (uint32_t i = 0; i < kBufferSize; ++i)
179 {
180 EXPECT_EQ(data[i], 0xFF);
181 }
182
183 unlockAndroidHardwareBuffer(aHardwareBuffer);
184
185 glBindBuffer(GL_COPY_READ_BUFFER, 0);
186 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
187 // Delete the source AHB
188 destroyAndroidHardwareBuffer(aHardwareBuffer);
189 }
190
191 // Testing dispatch compute shader external from source AHB
TEST_P(ExternalBufferTestES31,DispatchCompute)192 TEST_P(ExternalBufferTestES31, DispatchCompute)
193 {
194 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
195 !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
196 constexpr char kCS[] = R"(#version 310 es
197 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
198 layout(std430, binding=0) buffer Output {
199 uint data[];
200 } bOutput;
201 void main() {
202 bOutput.data[gl_GlobalInvocationID.x] =
203 gl_GlobalInvocationID.x * 3u;
204 }
205 )";
206
207 constexpr uint8_t kBufferSize = 16 * 4;
208 std::vector<GLubyte> initData(kBufferSize, 0xA);
209
210 // Create the Image
211 AHardwareBuffer *aHardwareBuffer;
212 constexpr GLbitfield kFlags = GL_MAP_READ_BIT;
213 aHardwareBuffer = createAndroidHardwareBuffer(kBufferSize, initData.data());
214
215 GLBuffer buffer;
216 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
217 glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
218 eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);
219
220 ASSERT_GL_NO_ERROR();
221
222 GLProgram program;
223 program.makeCompute(kCS);
224 ASSERT_NE(program.get(), 0U);
225 ASSERT_GL_NO_ERROR();
226
227 glUseProgram(program);
228 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
229 glDispatchCompute(kBufferSize, 1, 1);
230 glFinish();
231 ASSERT_GL_NO_ERROR();
232
233 // Inspect the data written into the buffer using CPU access.
234 uint32_t *data = static_cast<uint32_t *>(lockAndroidHardwareBuffer(aHardwareBuffer));
235
236 for (uint32_t i = 0; i < (kBufferSize / sizeof(uint32_t)); ++i)
237 {
238 EXPECT_EQ(data[i], static_cast<uint32_t>(i * 3));
239 }
240
241 unlockAndroidHardwareBuffer(aHardwareBuffer);
242
243 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
244 // Delete the source AHB
245 destroyAndroidHardwareBuffer(aHardwareBuffer);
246 }
247
248 // Test interaction between GL_OES_mapbuffer and GL_EXT_external_buffer extensions.
TEST_P(ExternalBufferTestES31,MapBuffer)249 TEST_P(ExternalBufferTestES31, MapBuffer)
250 {
251 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
252 !IsGLExtensionEnabled("GL_EXT_buffer_storage") ||
253 !IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
254 constexpr uint8_t kBufferSize = 16;
255 std::vector<GLubyte> initData(kBufferSize, 0xFF);
256
257 // Create the AHB
258 AHardwareBuffer *aHardwareBuffer;
259 constexpr GLbitfield kFlags = (GL_MAP_READ_BIT_EXT | GL_MAP_WRITE_BIT_EXT);
260 aHardwareBuffer = createAndroidHardwareBuffer(kBufferSize, initData.data());
261
262 GLBuffer buffer;
263 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
264 glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
265 eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);
266
267 ASSERT_GL_NO_ERROR();
268
269 // Inspect the data written into the buffer using CPU access.
270 uint8_t *data = static_cast<uint8_t *>(
271 glMapBufferRangeEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT_EXT));
272 ASSERT_GL_NO_ERROR();
273
274 for (uint32_t i = 0; i < kBufferSize; ++i)
275 {
276 EXPECT_EQ(data[i], 0xFF);
277 }
278
279 glUnmapBufferOES(GL_SHADER_STORAGE_BUFFER);
280
281 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
282 // Delete the source AHB
283 destroyAndroidHardwareBuffer(aHardwareBuffer);
284 }
285
286 // Verify that mapping an external buffer backed by an AHB doesn't orphan the AHB
TEST_P(ExternalBufferTestES31,MapBufferDoesNotCauseOrphaning)287 TEST_P(ExternalBufferTestES31, MapBufferDoesNotCauseOrphaning)
288 {
289 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
290 !IsGLExtensionEnabled("GL_EXT_buffer_storage") ||
291 !IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
292 constexpr uint8_t kBufferSize = 16;
293 std::vector<GLubyte> initData(kBufferSize, 0xA);
294
295 // Create the AHB
296 AHardwareBuffer *aHardwareBuffer;
297 constexpr GLbitfield kFlags =
298 (GL_MAP_READ_BIT_EXT | GL_MAP_WRITE_BIT_EXT | GL_DYNAMIC_STORAGE_BIT_EXT);
299 aHardwareBuffer = createAndroidHardwareBuffer(kBufferSize, initData.data());
300
301 GLBuffer buffer;
302 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
303 glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
304 eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);
305 ASSERT_GL_NO_ERROR();
306
307 // Create a copy read buffer
308 std::vector<GLubyte> copyReadBufferData(kBufferSize, 0xB);
309 GLBuffer copyReadBuffer;
310 glBindBuffer(GL_COPY_READ_BUFFER, copyReadBuffer);
311 glBufferData(GL_COPY_READ_BUFFER, kBufferSize, copyReadBufferData.data(), GL_STATIC_READ);
312 ASSERT_GL_NO_ERROR();
313
314 // Copy from copyReadBuffer to externalBuffer
315 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, kBufferSize);
316 ASSERT_GL_NO_ERROR();
317
318 // Inspect the data written into the buffer using map buffer API.
319 constexpr GLbitfield kMapFlags = (GL_MAP_WRITE_BIT_EXT | GL_MAP_INVALIDATE_BUFFER_BIT);
320 uint8_t *mapData = static_cast<uint8_t *>(
321 glMapBufferRangeEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, kMapFlags));
322 ASSERT_GL_NO_ERROR();
323 EXPECT_NE(mapData, nullptr);
324 glUnmapBufferOES(GL_SHADER_STORAGE_BUFFER);
325
326 // Update externalBuffer
327 std::vector<GLubyte> expectedData(kBufferSize, 0xFF);
328 glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, expectedData.data());
329 glFinish();
330 ASSERT_GL_NO_ERROR();
331
332 // Inspect the data written into the AHB, through externalBuffer, using CPU access.
333 uint8_t *data = static_cast<uint8_t *>(lockAndroidHardwareBuffer(aHardwareBuffer));
334
335 for (uint32_t i = 0; i < kBufferSize; ++i)
336 {
337 EXPECT_EQ(data[i], 0xFF);
338 }
339
340 unlockAndroidHardwareBuffer(aHardwareBuffer);
341
342 glBindBuffer(GL_COPY_READ_BUFFER, 0);
343 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
344 // Delete the source AHB
345 destroyAndroidHardwareBuffer(aHardwareBuffer);
346 }
347
348 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ExternalBufferTestES31);
349 ANGLE_INSTANTIATE_TEST_ES31(ExternalBufferTestES31);
350 } // namespace angle
351