| // |
| // Copyright 2024 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. |
| // |
| // EGLMemoryUsageReportTest: |
| // Tests pertaining to EGL_ANGLE_memory_usage_report extension. |
| // |
| |
| #include <gtest/gtest.h> |
| |
| #include "test_utils/ANGLETest.h" |
| #include "test_utils/gl_raii.h" |
| #include "util/EGLWindow.h" |
| |
| using namespace angle; |
| |
| class EGLMemoryUsageReportTest : public ANGLETest<> |
| { |
| protected: |
| bool hasEGLDisplayExtension(const char *extname) const |
| { |
| return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), extname); |
| } |
| |
| bool hasMemoryUsageReportExtension() const |
| { |
| return hasEGLDisplayExtension("EGL_ANGLE_memory_usage_report"); |
| } |
| |
| uint64_t getMemoryUsage(EGLDisplay display, EGLContext context) |
| { |
| GLint parts[2]; |
| EXPECT_EGL_TRUE(eglQueryContext(display, context, EGL_CONTEXT_MEMORY_USAGE_ANGLE, parts)); |
| |
| return (static_cast<uint64_t>(parts[0]) & 0xffffffff) | |
| ((static_cast<uint64_t>(parts[1]) & 0xffffffff) << 32); |
| } |
| }; |
| |
| // Basic memory usage queries |
| TEST_P(EGLMemoryUsageReportTest, BasicQuery) |
| { |
| ANGLE_SKIP_TEST_IF(!hasMemoryUsageReportExtension()); |
| |
| constexpr GLint kTextureDim = 1024; |
| constexpr GLuint kTextureSize = kTextureDim * kTextureDim * 4; |
| constexpr GLuint kBufferSize = 4096; |
| constexpr GLint kRenderbufferDim = 512; |
| constexpr GLuint kRenderbufferSize = kRenderbufferDim * kRenderbufferDim * 4; |
| constexpr GLuint kTotalObjectsMemorySize = kBufferSize + kRenderbufferSize + kTextureSize; |
| |
| EGLDisplay display = getEGLWindow()->getDisplay(); |
| EGLContext context = getEGLWindow()->getContext(); |
| |
| uint64_t memorySize1 = getMemoryUsage(display, context); |
| uint64_t memorySize2; |
| |
| { |
| GLBuffer buffer; |
| glBindBuffer(GL_ARRAY_BUFFER, buffer); |
| glBufferData(GL_ARRAY_BUFFER, kBufferSize, nullptr, GL_STATIC_DRAW); |
| |
| GLTexture texture; |
| glBindTexture(GL_TEXTURE_2D, texture); |
| glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kTextureDim, kTextureDim); |
| |
| GLRenderbuffer rbo; |
| glBindRenderbuffer(GL_RENDERBUFFER, rbo); |
| glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, kRenderbufferDim, kRenderbufferDim); |
| |
| memorySize2 = getMemoryUsage(display, context); |
| |
| EXPECT_EQ(memorySize2 - memorySize1, kTotalObjectsMemorySize); |
| } |
| |
| uint64_t memorySize3 = getMemoryUsage(display, context); |
| EXPECT_EQ(memorySize2 - memorySize3, kTotalObjectsMemorySize); |
| } |
| |
| // Test that querying memory usage of a context that is not current works. |
| TEST_P(EGLMemoryUsageReportTest, QueryNonCurrentContext) |
| { |
| ANGLE_SKIP_TEST_IF(!hasMemoryUsageReportExtension()); |
| |
| constexpr GLint kTextureDim = 1024; |
| constexpr GLuint kTextureSize = kTextureDim * kTextureDim * 4; |
| |
| EGLWindow *window = getEGLWindow(); |
| EGLDisplay display = window->getDisplay(); |
| |
| // Create a 2nd context. |
| EGLContext context2 = window->createContext(EGL_NO_CONTEXT, nullptr); |
| |
| uint64_t context2MemorySize1 = getMemoryUsage(display, context2); |
| |
| { |
| EXPECT_EGL_TRUE(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context2)); |
| GLTexture texture; |
| glBindTexture(GL_TEXTURE_2D, texture); |
| glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kTextureDim, kTextureDim); |
| |
| // Make default context current. |
| EXPECT_TRUE(window->makeCurrent()); |
| EXPECT_NE(eglGetCurrentContext(), context2); |
| |
| // Query 2nd context's memory size |
| uint64_t context2MemorySize2 = getMemoryUsage(display, context2); |
| |
| EXPECT_EQ(context2MemorySize2 - context2MemorySize1, kTextureSize); |
| } |
| |
| EXPECT_EGL_TRUE(eglDestroyContext(display, context2)); |
| } |
| |
| GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EGLMemoryUsageReportTest); |
| ANGLE_INSTANTIATE_TEST_ES3(EGLMemoryUsageReportTest); |