xref: /aosp_15_r20/external/angle/src/tests/gl_tests/ExternalBufferTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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