renderengine: use std::unordered_map in ProgramCache
Replace DefaultKeyedVector by std::unordered_map for
ProgramCache::mCache. Dump cache size in dumpsys.
Bug: 115738279
Test: boots
Change-Id: I28428e32866e6d4e78df4b569e476b33be31c091
diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
index 1b0a539..b94cdca 100644
--- a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
@@ -35,6 +35,7 @@
#include <ui/DebugUtils.h>
#include <ui/Rect.h>
#include <ui/Region.h>
+#include <utils/KeyedVector.h>
#include <utils/String8.h>
#include <utils/Trace.h>
#include "GLExtensions.h"
@@ -883,6 +884,10 @@
result.appendFormat("GLES: %s, %s, %s\n", extensions.getVendor(), extensions.getRenderer(),
extensions.getVersion());
result.appendFormat("%s\n", extensions.getExtensions());
+
+ result.appendFormat("RenderEngine program cache size: %zu\n",
+ ProgramCache::getInstance().getSize());
+
result.appendFormat("RenderEngine last dataspace conversion: (%s) to (%s)\n",
dataspaceDetails(static_cast<android_dataspace>(mDataSpace)).c_str(),
dataspaceDetails(static_cast<android_dataspace>(mOutputDataSpace)).c_str());
diff --git a/services/surfaceflinger/RenderEngine/gl/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/gl/ProgramCache.cpp
index c118248..1e7e93c 100644
--- a/services/surfaceflinger/RenderEngine/gl/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/gl/ProgramCache.cpp
@@ -20,6 +20,7 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
+#include <log/log.h>
#include <renderengine/private/Description.h>
#include <utils/String8.h>
#include <utils/Trace.h>
@@ -94,10 +95,8 @@
if (tex != Key::TEXTURE_OFF && tex != Key::TEXTURE_EXT && tex != Key::TEXTURE_2D) {
continue;
}
- Program* program = mCache.valueFor(shaderKey);
- if (program == nullptr) {
- program = generateProgram(shaderKey);
- mCache.add(shaderKey, program);
+ if (mCache.count(shaderKey) == 0) {
+ mCache.emplace(shaderKey, generateProgram(shaderKey));
shaderCount++;
}
}
@@ -113,10 +112,8 @@
shaderKey.set(Key::OPACITY_MASK,
(i & 1) ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT);
shaderKey.set(Key::ALPHA_MASK, (i & 2) ? Key::ALPHA_LT_ONE : Key::ALPHA_EQ_ONE);
- Program* program = mCache.valueFor(shaderKey);
- if (program == nullptr) {
- program = generateProgram(shaderKey);
- mCache.add(shaderKey, program);
+ if (mCache.count(shaderKey) == 0) {
+ mCache.emplace(shaderKey, generateProgram(shaderKey));
shaderCount++;
}
}
@@ -667,19 +664,19 @@
Key needs(computeKey(description));
// look-up the program in the cache
- Program* program = mCache.valueFor(needs);
- if (program == nullptr) {
+ auto it = mCache.find(needs);
+ if (it == mCache.end()) {
// we didn't find our program, so generate one...
- nsecs_t time = -systemTime();
- program = generateProgram(needs);
- mCache.add(needs, program);
- time += systemTime();
+ nsecs_t time = systemTime();
+ it = mCache.emplace(needs, generateProgram(needs)).first;
+ time = systemTime() - time;
ALOGV(">>> generated new program: needs=%08X, time=%u ms (%zu programs)", needs.mKey,
uint32_t(ns2ms(time)), mCache.size());
}
// here we have a suitable program for this description
+ Program* program = it->second;
if (program->isValid()) {
program->use();
program->setUniforms(description);
diff --git a/services/surfaceflinger/RenderEngine/gl/ProgramCache.h b/services/surfaceflinger/RenderEngine/gl/ProgramCache.h
index 47963eb..bf5e434 100644
--- a/services/surfaceflinger/RenderEngine/gl/ProgramCache.h
+++ b/services/surfaceflinger/RenderEngine/gl/ProgramCache.h
@@ -17,9 +17,10 @@
#ifndef SF_RENDER_ENGINE_PROGRAMCACHE_H
#define SF_RENDER_ENGINE_PROGRAMCACHE_H
+#include <unordered_map>
+
#include <GLES2/gl2.h>
#include <renderengine/private/Description.h>
-#include <utils/KeyedVector.h>
#include <utils/Singleton.h>
#include <utils/TypeHelpers.h>
@@ -155,10 +156,17 @@
}
inline bool isY410BT2020() const { return (mKey & Y410_BT2020_MASK) == Y410_BT2020_ON; }
- // this is the definition of a friend function -- not a method of class Needs
- friend inline int strictly_order_type(const Key& lhs, const Key& rhs) {
- return (lhs.mKey < rhs.mKey) ? 1 : 0;
+ // for use by std::unordered_map
+
+ bool operator==(const Key& other) const {
+ return mKey == other.mKey;
}
+
+ struct Hash {
+ size_t operator()(const Key& key) const {
+ return static_cast<size_t>(key.mKey);
+ }
+ };
};
ProgramCache();
@@ -167,6 +175,8 @@
// Generate shaders to populate the cache
void primeCache(bool useColorManagement);
+ size_t getSize() const { return mCache.size(); }
+
// useProgram lookup a suitable program in the cache or generates one
// if none can be found.
void useProgram(const Description& description);
@@ -191,7 +201,7 @@
// Key/Value map used for caching Programs. Currently the cache
// is never shrunk.
- DefaultKeyedVector<Key, Program*> mCache;
+ std::unordered_map<Key, Program*, Key::Hash> mCache;
};
} // namespace gl