Edit

kc3-lang/angle/src/tests/gl_tests/ExternalBufferTest.cpp

Branch :

  • Show log

    Commit

  • Author : Yuly Novikov
    Date : 2021-03-02 19:04:57
    Hash : a6b16d29
    Message : Suppress UNINSTANTIATED_PARAMETERIZED_TEST failures on Ozone We only support ES2 on Ozone, so tests that depend on ES3 or ES31 support are not instantiated there. Bug: chromium:1183147 Change-Id: Id58bcd9b44a5b9a70b5ae8115e27c44f5dc81226 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2726550 Reviewed-by: Jonah Ryan-Davis <jonahr@google.com> Commit-Queue: Yuly Novikov <ynovikov@chromium.org>

  • src/tests/gl_tests/ExternalBufferTest.cpp
  • //
    // Copyright 2020 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    // ExternalBufferTest:
    //   Tests the correctness of external buffer ext extension.
    //
    
    #include "test_utils/ANGLETest.h"
    #include "test_utils/gl_raii.h"
    #include "util/EGLWindow.h"
    
    #include "common/android_util.h"
    
    #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 26
    #    define ANGLE_AHARDWARE_BUFFER_SUPPORT
    // NDK header file for access to Android Hardware Buffers
    #    include <android/hardware_buffer.h>
    #endif
    
    namespace angle
    {
    
    class ExternalBufferTestES31 : public ANGLETest
    {
      protected:
        ExternalBufferTestES31()
        {
            setWindowWidth(16);
            setWindowHeight(16);
            setConfigRedBits(8);
            setConfigGreenBits(8);
            setConfigBlueBits(8);
            setConfigAlphaBits(8);
            setConfigDepthBits(24);
        }
    
        AHardwareBuffer *createAndroidHardwareBuffer(size_t size, const GLubyte *data)
        {
    #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
            // The height and width are number of pixels of size format
            AHardwareBuffer_Desc aHardwareBufferDescription = {};
            aHardwareBufferDescription.width                = size;
            aHardwareBufferDescription.height               = 1;
            aHardwareBufferDescription.layers               = 1;
            aHardwareBufferDescription.format               = AHARDWAREBUFFER_FORMAT_BLOB;
            aHardwareBufferDescription.usage =
                AHARDWAREBUFFER_USAGE_CPU_READ_RARELY | AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
            aHardwareBufferDescription.stride = 0;
    
            // Allocate memory from Android Hardware Buffer
            AHardwareBuffer *aHardwareBuffer = nullptr;
            EXPECT_EQ(0, AHardwareBuffer_allocate(&aHardwareBufferDescription, &aHardwareBuffer));
    
            void *mappedMemory = nullptr;
            EXPECT_EQ(0, AHardwareBuffer_lock(aHardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY,
                                              -1, nullptr, &mappedMemory));
    
            // Need to grab the stride the implementation might have enforced
            AHardwareBuffer_describe(aHardwareBuffer, &aHardwareBufferDescription);
    
            memcpy(mappedMemory, data, size);
    
            EXPECT_EQ(0, AHardwareBuffer_unlock(aHardwareBuffer, nullptr));
            return aHardwareBuffer;
    #else
            return nullptr;
    #endif  // ANGLE_PLATFORM_ANDROID
        }
    
        void destroyAndroidHardwareBuffer(AHardwareBuffer *aHardwareBuffer)
        {
    #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
            AHardwareBuffer_release(aHardwareBuffer);
    #endif
        }
    
        void *lockAndroidHardwareBuffer(AHardwareBuffer *aHardwareBuffer)
        {
            void *data = nullptr;
    #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
            EXPECT_EQ(0, AHardwareBuffer_lock(aHardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY,
                                              -1, nullptr, &data));
    #endif
            return data;
        }
    
        void unlockAndroidHardwareBuffer(AHardwareBuffer *aHardwareBuffer)
        {
    #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
            AHardwareBuffer_unlock(aHardwareBuffer, nullptr);
    #endif
        }
    };
    
    // Testing subdata update with external buffer from AHB
    TEST_P(ExternalBufferTestES31, BufferSubData)
    {
        ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
                           !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
        constexpr uint8_t kBufferSize = 16;
        std::vector<GLubyte> initData(kBufferSize, 0xA);
    
        // Create the Image
        AHardwareBuffer *aHardwareBuffer;
        constexpr GLbitfield kFlags = GL_DYNAMIC_STORAGE_BIT_EXT;
        aHardwareBuffer             = createAndroidHardwareBuffer(kBufferSize, initData.data());
    
        GLBuffer buffer;
        glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
        glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
                                   eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);
        ASSERT_GL_NO_ERROR();
    
        std::vector<GLubyte> expectedData(kBufferSize, 0xFF);
    
        glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, expectedData.data());
        glFinish();
    
        ASSERT_GL_NO_ERROR();
    
        // Inspect the data written into the buffer using CPU access.
        uint8_t *data = static_cast<uint8_t *>(lockAndroidHardwareBuffer(aHardwareBuffer));
    
        for (uint32_t i = 0; i < kBufferSize; ++i)
        {
            EXPECT_EQ(data[i], 0xFF);
        }
    
        unlockAndroidHardwareBuffer(aHardwareBuffer);
        // Delete the source AHB when in use
        destroyAndroidHardwareBuffer(aHardwareBuffer);
    }
    
    // Testing dispatch compute shader external from source AHB
    TEST_P(ExternalBufferTestES31, DispatchCompute)
    {
        ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
                           !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
        constexpr char kCS[] = R"(#version 310 es
        layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
        layout(std430, binding=0) buffer Output {
            uint data[];
        } bOutput;
        void main() {
            bOutput.data[gl_GlobalInvocationID.x] =
                gl_GlobalInvocationID.x * 3u;
        }
    )";
    
        constexpr uint8_t kBufferSize = 16 * 4;
        std::vector<GLubyte> initData(kBufferSize, 0xA);
    
        // Create the Image
        AHardwareBuffer *aHardwareBuffer;
        constexpr GLbitfield kFlags = GL_MAP_READ_BIT;
        aHardwareBuffer             = createAndroidHardwareBuffer(kBufferSize, initData.data());
    
        GLBuffer buffer;
        glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
        glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
                                   eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);
    
        ASSERT_GL_NO_ERROR();
    
        GLProgram program;
        program.makeCompute(kCS);
        ASSERT_NE(program.get(), 0U);
        ASSERT_GL_NO_ERROR();
    
        glUseProgram(program);
        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
        glDispatchCompute(kBufferSize, 1, 1);
        glFinish();
        ASSERT_GL_NO_ERROR();
    
        // Inspect the data written into the buffer using CPU access.
        uint32_t *data = static_cast<uint32_t *>(lockAndroidHardwareBuffer(aHardwareBuffer));
    
        for (uint32_t i = 0; i < (kBufferSize / sizeof(uint32_t)); ++i)
        {
            EXPECT_EQ(data[i], static_cast<uint32_t>(i * 3));
        }
    
        unlockAndroidHardwareBuffer(aHardwareBuffer);
        // Delete the source AHB when in use
        destroyAndroidHardwareBuffer(aHardwareBuffer);
    }
    
    // Test interaction between GL_OES_mapbuffer and GL_EXT_external_buffer extensions.
    TEST_P(ExternalBufferTestES31, MapBuffer)
    {
        ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
                           !IsGLExtensionEnabled("GL_EXT_buffer_storage") ||
                           !IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
        constexpr uint8_t kBufferSize = 16;
        std::vector<GLubyte> initData(kBufferSize, 0xFF);
    
        // Create the Image
        AHardwareBuffer *aHardwareBuffer;
        constexpr GLbitfield kFlags = (GL_MAP_READ_BIT_EXT | GL_MAP_WRITE_BIT_EXT);
        aHardwareBuffer             = createAndroidHardwareBuffer(kBufferSize, initData.data());
    
        GLBuffer buffer;
        glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
        glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
                                   eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);
    
        ASSERT_GL_NO_ERROR();
    
        // Inspect the data written into the buffer using CPU access.
        uint8_t *data = static_cast<uint8_t *>(
            glMapBufferRangeEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT_EXT));
        ASSERT_GL_NO_ERROR();
    
        for (uint32_t i = 0; i < kBufferSize; ++i)
        {
            EXPECT_EQ(data[i], 0xFF);
        }
    
        glUnmapBufferOES(GL_SHADER_STORAGE_BUFFER);
        // Delete the source AHB when in use
        destroyAndroidHardwareBuffer(aHardwareBuffer);
    }
    
    GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ExternalBufferTestES31);
    ANGLE_INSTANTIATE_TEST_ES31(ExternalBufferTestES31);
    }  // namespace angle