diff --git a/extensions/ANGLE_memory_size.txt b/extensions/ANGLE_memory_size.txt new file mode 100644 index 000000000..d6e824ebf --- /dev/null +++ b/extensions/ANGLE_memory_size.txt @@ -0,0 +1,128 @@ +Name + + ANGLE_memory_size + +Name Strings + + GL_ANGLE_memory_size + +Contributors + + Geoff Lang + +Contact + + Geoff Lang (geofflang 'at' google.com) + +Notice + + Copyright (c) 2018 The Khronos Group Inc. Copyright terms at + http://www.khronos.org/registry/speccopyright.html + +Status + + Draft + +Version + + Version 1, November 1, 2018 + +Number + + OpenGL ES Extension #?? + +Dependencies + + Requires OpenGL ES 2.0 + + Written against the OpenGL ES 3.1 specification. + +Overview + + This extension allows the user to query the estimated memory internally + allocated for an OpenGL resource. This information can be useful for + determining which resources should be deleted under memory pressure. + +New Procedures and Functions + + None + +New Tokens + + Accepted by the parameter of GetTexParameter*, + GetTexLevelParameter*, GetBufferParameter* and GetRenderbufferParameter* + functions: + + GL_MEMORY_SIZE_ANGLE 0x93AD + +Additions to the OpenGL ES 3.1 Specification + + Add an entry to Table 6.2, Buffer object parameters and their values: + + Name Type Initial Value Legal Values + ----------------- ----- ------------- ------------------------ + MEMORY_SIZE_ANGLE int64 0 any non-negative integer + + Change the last sentence of the first paragraph of section 8.10.2, + Texture Parameter Queries: + + - pname must be IMAGE_FORMAT_COMPATIBILITY_TYPE, TEXTURE_- + - IMMUTABLE_FORMAT, TEXTURE_IMMUTABLE_LEVELS, or one of the symbolic + - values in table 8.20. + + pname must be IMAGE_FORMAT_COMPATIBILITY_TYPE, TEXTURE_- + + IMMUTABLE_FORMAT, TEXTURE_IMMUTABLE_LEVELS, MEMORY_SIZE_ANGLE, + + or one of the symbolic values in table 8.20. + + Add to the end of the fifth paragraph of section 8.10.3, Texture Level + Parameter Queries: + + + queries of pname MEMORY_SIZE_ANGLE return the estimated number of bytes + + allocated for level of the texture bound to target. + + Add a new paragraph after paragraph 3 in section 9.2.6, Renderbuffer + Object Queries: + + If pname is MEMORY_SIZE_ANGLE, then params will contain the esimated + number of bytes allocated for the renderbuffer bound to target. + +New State + + Add to Table 20.4: Buffer Object State + + Get value Type Get Cmd Min Value Description Sec. + ------------------- ---- --------------------- --------- ------------------------- ---- + MEMORY_SIZE_ANGLE Z+ GetBufferParameter64v - Estimated bytes allocated 6 + + Add to Table 20.9: Textures (state per texture object) + + Get value Type Get Cmd Min Value Description Sec. + ------------------- ---- -------------------- --------- ------------------------- ----- + MEMORY_SIZE_ANGLE Z+ GetTexParameter - Estimated bytes allocated 6.1.3 + GetTexLevelParameter + + Add to Table 20.16: Renderbuffer (state per renderbuffer object) + + Get value Type Get Cmd Min Value Description Sec. + ------------------- ---- -------------------------- --------- ------------------------- ----- + MEMORY_SIZE_ANGLE Z+ GetRenderbufferParameteriv - Estimated bytes allocated 9.2.6 + + +Interactions with the OpenGL ES 2.0 and 3.0 specifications: + + Remove all references to GetTexLevelParameter and replace references to + GetBufferParameter64v with GetBufferParameteriv. + +Issues + + (1) Could the estimated number of bytes be specified more tightly to an + upper or lower bound? + + RESOLVED: Implementations should attempt to return the lower bound on + the allocated memory if exact numbers are not known. The lower bound is + the most actionable value for making decisions when caching. + +Revision History + + Rev. Date Author Changes + ---- ------------- --------- ---------------------------------------- + 1 Nov 1, 2018 geofflang Initial version diff --git a/src/libANGLE/Buffer.cpp b/src/libANGLE/Buffer.cpp index c506a3418..6999f227d 100644 --- a/src/libANGLE/Buffer.cpp +++ b/src/libANGLE/Buffer.cpp @@ -246,10 +246,10 @@ angle::Result Buffer::getIndexRange(const gl::Context *context, return angle::Result::Continue(); } -GLint Buffer::getMemorySize() const +GLint64 Buffer::getMemorySize() const { - GLint implSize = mImpl->getMemorySize(); - return implSize > 0 ? implSize : clampCast(mState.mSize); + GLint64 implSize = mImpl->getMemorySize(); + return implSize > 0 ? implSize : mState.mSize; } bool Buffer::isBound() const diff --git a/src/libANGLE/Buffer.h b/src/libANGLE/Buffer.h index 6599957a0..eb86a8176 100644 --- a/src/libANGLE/Buffer.h +++ b/src/libANGLE/Buffer.h @@ -117,7 +117,7 @@ class Buffer final : public RefCountObject, GLint64 getMapOffset() const { return mState.mMapOffset; } GLint64 getMapLength() const { return mState.mMapLength; } GLint64 getSize() const { return mState.mSize; } - GLint getMemorySize() const; + GLint64 getMemorySize() const; rx::BufferImpl *getImplementation() const { return mImpl; } diff --git a/src/libANGLE/renderer/BufferImpl.h b/src/libANGLE/renderer/BufferImpl.h index 4e5030b93..ed48bc19e 100644 --- a/src/libANGLE/renderer/BufferImpl.h +++ b/src/libANGLE/renderer/BufferImpl.h @@ -66,7 +66,7 @@ class BufferImpl : public angle::Subject gl::IndexRange *outRange) = 0; // Override if accurate native memory size information is available - virtual GLint getMemorySize() const { return 0; } + virtual GLint64 getMemorySize() const { return 0; } protected: const gl::BufferState &mState; diff --git a/src/tests/angle_end2end_tests.gni b/src/tests/angle_end2end_tests.gni index c47bc11de..c45ceab39 100644 --- a/src/tests/angle_end2end_tests.gni +++ b/src/tests/angle_end2end_tests.gni @@ -72,6 +72,7 @@ angle_end2end_tests_sources = [ "gl_tests/LineLoopTest.cpp", "gl_tests/LinkAndRelinkTest.cpp", "gl_tests/MaxTextureSizeTest.cpp", + "gl_tests/MemorySizeTest.cpp", "gl_tests/MipmapTest.cpp", "gl_tests/MultisampleCompatibilityTest.cpp", "gl_tests/MultithreadingTest.cpp", diff --git a/src/tests/gl_tests/MemorySizeTest.cpp b/src/tests/gl_tests/MemorySizeTest.cpp new file mode 100644 index 000000000..968707f92 --- /dev/null +++ b/src/tests/gl_tests/MemorySizeTest.cpp @@ -0,0 +1,144 @@ +// +// Copyright 2018 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. +// + +// MemorySizeTest.cpp : Tests of the GL_ANGLE_memory_size extension. + +#include "test_utils/ANGLETest.h" + +#include "test_utils/gl_raii.h" + +namespace angle +{ + +class MemorySizeTest : public ANGLETest +{ + protected: + MemorySizeTest() + { + setWindowWidth(128); + setWindowHeight(128); + setConfigRedBits(8); + setConfigGreenBits(8); + setConfigBlueBits(8); + setConfigAlphaBits(8); + } +}; + +// GL_ANGLE_memory_size is implemented in the front-end and should always be exposed. +TEST_P(MemorySizeTest, ExtensionStringExposed) +{ + EXPECT_TRUE(ensureExtensionEnabled("GL_ANGLE_memory_size")); +} + +// Test basic queries of textures +TEST_P(MemorySizeTest, BasicUsageTexture) +{ + ANGLE_SKIP_TEST_IF(!ensureExtensionEnabled("GL_ANGLE_memory_size")); + + GLTexture texture; + glBindTexture(GL_TEXTURE_2D, texture); + + GLint result; + glGetTexParameteriv(GL_TEXTURE_2D, GL_MEMORY_SIZE_ANGLE, &result); + EXPECT_GL_NO_ERROR(); + EXPECT_EQ(0, result); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + glGetTexParameteriv(GL_TEXTURE_2D, GL_MEMORY_SIZE_ANGLE, &result); + EXPECT_GL_NO_ERROR(); + EXPECT_GT(result, 0); + + if (getClientMajorVersion() > 3) + { + glGetTexLevelParameteriv(GL_TEXTURE_2D, 1, GL_MEMORY_SIZE_ANGLE, &result); + EXPECT_GL_NO_ERROR(); + EXPECT_EQ(0, result); + + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_MEMORY_SIZE_ANGLE, &result); + EXPECT_GL_NO_ERROR(); + EXPECT_GT(result, 0); + } +} + +// Test basic queries of buffers +TEST_P(MemorySizeTest, BasicUsageBuffer) +{ + ANGLE_SKIP_TEST_IF(!ensureExtensionEnabled("GL_ANGLE_memory_size")); + + GLBuffer buffer; + glBindBuffer(GL_ARRAY_BUFFER, buffer); + + GLint result; + glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_MEMORY_SIZE_ANGLE, &result); + EXPECT_GL_NO_ERROR(); + EXPECT_EQ(0, result); + + if (getClientMajorVersion() > 3) + { + GLint64 result64; + glGetBufferParameteri64v(GL_ARRAY_BUFFER, GL_MEMORY_SIZE_ANGLE, &result64); + EXPECT_GL_NO_ERROR(); + EXPECT_EQ(0, result64); + } + + constexpr GLsizeiptr kBufSize = 16; + std::array buf; + glBufferData(GL_ARRAY_BUFFER, kBufSize, buf.data(), GL_STATIC_DRAW); + glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_MEMORY_SIZE_ANGLE, &result); + EXPECT_GL_NO_ERROR(); + + // This value may have to be reset to 1 if some backend delays allocations or compresses + // buffers. + constexpr GLint kExpectedMinBufMemorySize = 15; + + EXPECT_GT(result, kExpectedMinBufMemorySize); + + if (getClientMajorVersion() > 3) + { + GLint64 result64; + glGetBufferParameteri64v(GL_ARRAY_BUFFER, GL_MEMORY_SIZE_ANGLE, &result64); + EXPECT_GL_NO_ERROR(); + EXPECT_GT(result64, static_cast(kExpectedMinBufMemorySize)); + } + + // No way to easily test the GLint64 to GLint64 clamping behaviour of glGetBufferParameteriv + // without allocating a buffer >2gb. +} + +// Test basic queries of renderbuffers +TEST_P(MemorySizeTest, BasicUsageRenderbuffer) +{ + ANGLE_SKIP_TEST_IF(!ensureExtensionEnabled("GL_ANGLE_memory_size")); + + GLRenderbuffer renderbuffer; + glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); + + GLint result; + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_MEMORY_SIZE_ANGLE, &result); + EXPECT_GL_NO_ERROR(); + EXPECT_EQ(0, result); + + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 4, 4); + glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_MEMORY_SIZE_ANGLE, &result); + EXPECT_GL_NO_ERROR(); + EXPECT_GT(result, 0); +} + +// No errors specific to GL_ANGLE_memory_size to test for. + +// Use this to select which configurations (e.g. which renderer, which GLES major version) these +// tests should be run against. +ANGLE_INSTANTIATE_TEST(MemorySizeTest, + ES2_D3D9(), + ES2_D3D11(), + ES3_D3D11(), + ES2_D3D11_FL9_3(), + ES2_OPENGL(), + ES3_OPENGL(), + ES2_OPENGLES(), + ES3_OPENGLES(), + ES2_VULKAN()); +} // namespace