Commit 37d2e606 by Shahbaz Youssefi Committed by Commit Bot

Make BlobCache use independent from ANGLE_program_cache_control

The decision to enable caching or not was based on the size of the cache as directed by eglProgramCacheResizeANGLE, which is incorrect for applications that only use the ANDROID_blob_cache extension. The new behavior is as follows: - If EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE is specifically requested and set to true, but the size of the cache is 0, caching is disabled for the context. - If EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE is specifically requested and set to false, caching is disabled for the context. - Otherwise, caching is left enabled for the context, although the cache possibly has a size of zero, which effectively disables it. During application execution, if the blob cache callbacks are set, the application cache will be used. Bug: 896406, angleproject:2516 Change-Id: Ic0cabda03fb6bf53994e86e3ede30afc8021d67e Reviewed-on: https://chromium-review.googlesource.com/c/1405708 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent bf433727
...@@ -64,11 +64,7 @@ void BlobCache::populate(const BlobCache::Key &key, angle::MemoryBuffer &&value, ...@@ -64,11 +64,7 @@ void BlobCache::populate(const BlobCache::Key &key, angle::MemoryBuffer &&value,
newEntry.second = source; newEntry.second = source;
// Cache it inside blob cache only if caching inside the application is not possible. // Cache it inside blob cache only if caching inside the application is not possible.
const CacheEntry *result = mBlobCache.put(key, std::move(newEntry), newEntry.first.size()); mBlobCache.put(key, std::move(newEntry), newEntry.first.size());
if (!result)
{
ERR() << "Failed to store binary blob in memory cache, blob is too large.";
}
} }
bool BlobCache::get(angle::ScratchBuffer *scratchBuffer, bool BlobCache::get(angle::ScratchBuffer *scratchBuffer,
...@@ -92,11 +88,12 @@ bool BlobCache::get(angle::ScratchBuffer *scratchBuffer, ...@@ -92,11 +88,12 @@ bool BlobCache::get(angle::ScratchBuffer *scratchBuffer,
return false; return false;
} }
EGLsizeiANDROID originalValueSize = valueSize;
valueSize = mGetBlobFunc(key.data(), key.size(), scratchMemory->data(), valueSize); valueSize = mGetBlobFunc(key.data(), key.size(), scratchMemory->data(), valueSize);
// Make sure the key/value pair still exists/is unchanged after the second call // Make sure the key/value pair still exists/is unchanged after the second call
// (modifications to the application cache by another thread are a possibility) // (modifications to the application cache by another thread are a possibility)
if (static_cast<size_t>(valueSize) != scratchMemory->size()) if (valueSize != originalValueSize)
{ {
// This warning serves to find issues with the application cache, none of which are // This warning serves to find issues with the application cache, none of which are
// currently known to be thread-safe. If such a use ever arises, this WARN can be // currently known to be thread-safe. If such a use ever arises, this WARN can be
......
...@@ -137,6 +137,8 @@ class BlobCache final : angle::NonCopyable ...@@ -137,6 +137,8 @@ class BlobCache final : angle::NonCopyable
bool areBlobCacheFuncsSet() const; bool areBlobCacheFuncsSet() const;
bool isCachingEnabled() const { return areBlobCacheFuncsSet() || maxSize() > 0; }
private: private:
// This internal cache is used only if the application is not providing caching callbacks // This internal cache is used only if the application is not providing caching callbacks
using CacheEntry = std::pair<angle::MemoryBuffer, CacheSource>; using CacheEntry = std::pair<angle::MemoryBuffer, CacheSource>;
......
...@@ -786,16 +786,20 @@ Error Display::createContext(const Config *configuration, ...@@ -786,16 +786,20 @@ Error Display::createContext(const Config *configuration,
gl::MemoryProgramCache *cachePointer = &mMemoryProgramCache; gl::MemoryProgramCache *cachePointer = &mMemoryProgramCache;
// Check context creation attributes to see if we should enable the cache. // Check context creation attributes to see if we are using EGL_ANGLE_program_cache_control.
if (mAttributeMap.get(EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE, EGL_TRUE) == EGL_FALSE) // If not, keep caching enabled for EGL_ANDROID_blob_cache, which can have its callbacks set
// at any time.
bool usesProgramCacheControl =
mAttributeMap.contains(EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE);
if (usesProgramCacheControl)
{ {
cachePointer = nullptr; bool programCacheControlEnabled =
} mAttributeMap.get(EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE, GL_FALSE);
// A program cache size of zero indicates it should be disabled.
// A program cache size of zero indicates it should be disabled. if (!programCacheControlEnabled || mMemoryProgramCache.maxSize() == 0)
if (mMemoryProgramCache.maxSize() == 0) {
{ cachePointer = nullptr;
cachePointer = nullptr; }
} }
gl::Context *context = gl::Context *context =
......
...@@ -123,6 +123,12 @@ angle::Result MemoryProgramCache::getProgram(const Context *context, ...@@ -123,6 +123,12 @@ angle::Result MemoryProgramCache::getProgram(const Context *context,
Program *program, Program *program,
egl::BlobCache::Key *hashOut) egl::BlobCache::Key *hashOut)
{ {
// If caching is effectively disabled, don't bother calculating the hash.
if (!mBlobCache.isCachingEnabled())
{
return angle::Result::Incomplete;
}
ComputeHash(context, program, hashOut); ComputeHash(context, program, hashOut);
egl::BlobCache::Value binaryProgram; egl::BlobCache::Value binaryProgram;
if (get(context, *hashOut, &binaryProgram)) if (get(context, *hashOut, &binaryProgram))
...@@ -176,6 +182,12 @@ void MemoryProgramCache::putProgram(const egl::BlobCache::Key &programHash, ...@@ -176,6 +182,12 @@ void MemoryProgramCache::putProgram(const egl::BlobCache::Key &programHash,
const Context *context, const Context *context,
const Program *program) const Program *program)
{ {
// If caching is effectively disabled, don't bother serializing the program.
if (!mBlobCache.isCachingEnabled())
{
return;
}
angle::MemoryBuffer serializedProgram; angle::MemoryBuffer serializedProgram;
program->serialize(context, &serializedProgram); program->serialize(context, &serializedProgram);
......
...@@ -78,39 +78,24 @@ EGLsizeiANDROID GetBlob(const void *key, ...@@ -78,39 +78,24 @@ EGLsizeiANDROID GetBlob(const void *key,
class EGLBlobCacheTest : public ANGLETest class EGLBlobCacheTest : public ANGLETest
{ {
protected: protected:
EGLBlobCacheTest() : mHasProgramCache(false) { setDeferContextInit(true); } EGLBlobCacheTest() : mHasBlobCache(false) {}
void SetUp() override void SetUp() override
{ {
ANGLETest::SetUp(); ANGLETest::SetUp();
// Enable the program cache so that angle would do caching, which eventually lands in the
// BlobCache
EGLDisplay display = getEGLWindow()->getDisplay(); EGLDisplay display = getEGLWindow()->getDisplay();
if (eglDisplayExtensionEnabled(display, "EGL_ANGLE_program_cache_control")) mHasBlobCache = eglDisplayExtensionEnabled(display, kEGLExtName);
{
mHasProgramCache = true;
setContextProgramCacheEnabled(true);
eglProgramCacheResizeANGLE(display, 0x10000, EGL_PROGRAM_CACHE_RESIZE_ANGLE);
}
getEGLWindow()->initializeContext();
} }
void TearDown() override { ANGLETest::TearDown(); } void TearDown() override { ANGLETest::TearDown(); }
bool extensionAvailable()
{
EGLDisplay display = getEGLWindow()->getDisplay();
return eglDisplayExtensionEnabled(display, kEGLExtName);
}
bool programBinaryAvailable() bool programBinaryAvailable()
{ {
return (getClientMajorVersion() >= 3 || extensionEnabled("GL_OES_get_program_binary")); return (getClientMajorVersion() >= 3 || extensionEnabled("GL_OES_get_program_binary"));
} }
bool mHasProgramCache; bool mHasBlobCache;
}; };
// Makes sure the extension exists and works // Makes sure the extension exists and works
...@@ -118,7 +103,7 @@ TEST_P(EGLBlobCacheTest, Functional) ...@@ -118,7 +103,7 @@ TEST_P(EGLBlobCacheTest, Functional)
{ {
EGLDisplay display = getEGLWindow()->getDisplay(); EGLDisplay display = getEGLWindow()->getDisplay();
EXPECT_EQ(true, extensionAvailable()); EXPECT_EQ(true, mHasBlobCache);
eglSetBlobCacheFuncsANDROID(display, SetBlob, GetBlob); eglSetBlobCacheFuncsANDROID(display, SetBlob, GetBlob);
ASSERT_EGL_SUCCESS(); ASSERT_EGL_SUCCESS();
...@@ -157,7 +142,7 @@ void main() ...@@ -157,7 +142,7 @@ void main()
})"; })";
// Compile a shader so it puts something in the cache // Compile a shader so it puts something in the cache
if (mHasProgramCache && programBinaryAvailable()) if (programBinaryAvailable())
{ {
GLuint program = CompileProgram(kVertexShaderSrc, kFragmentShaderSrc); GLuint program = CompileProgram(kVertexShaderSrc, kFragmentShaderSrc);
ASSERT_NE(0u, program); ASSERT_NE(0u, program);
...@@ -187,7 +172,7 @@ void main() ...@@ -187,7 +172,7 @@ void main()
// Tests error conditions of the APIs. // Tests error conditions of the APIs.
TEST_P(EGLBlobCacheTest, NegativeAPI) TEST_P(EGLBlobCacheTest, NegativeAPI)
{ {
EXPECT_EQ(true, extensionAvailable()); EXPECT_EQ(true, mHasBlobCache);
// Test bad display // Test bad display
eglSetBlobCacheFuncsANDROID(EGL_NO_DISPLAY, nullptr, nullptr); eglSetBlobCacheFuncsANDROID(EGL_NO_DISPLAY, nullptr, nullptr);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment