Name
ANDROID_blob_cache
Name Strings
EGL_ANDROID_blob_cache
Contributors
Jamie Gennis
Contact
Jamie Gennis, Google Inc. (jgennis 'at' google.com)
Status
Complete
Version
Version 3, December 13, 2012
Number
EGL Extension #48
Dependencies
Requires EGL 1.0
This extension is written against the wording of the EGL 1.4 Specification
Overview
Shader compilation and optimization has been a troublesome aspect of OpenGL
programming for a long time. It can consume seconds of CPU cycles during
application start-up. Additionally, state-based re-compiles done
internally by the drivers add an unpredictable element to application
performance tuning, often leading to occasional pauses in otherwise smooth
animations.
This extension provides a mechanism through which client API
implementations may cache shader binaries after they are compiled. It may
then retrieve those cached shaders during subsequent executions of the same
program. The management of the cache is handled by the application (or
middleware), allowing it to be tuned to a particular platform or
environment.
While the focus of this extension is on providing a persistent cache for
shader binaries, it may also be useful for caching other data. This is
perfectly acceptable, but the guarantees provided (or lack thereof) were
designed around the shader use case.
Note that although this extension is written as if the application
implements the caching functionality, on the Android OS it is implemented
as part of the Android EGL module. This extension is not exposed to
applications on Android, but will be used automatically in every
application that uses EGL if it is supported by the underlying
device-specific EGL implementation.
New Types
/*
* EGLsizeiANDROID is a signed integer type for representing the size of a
* memory buffer.
*/
#include <khrplatform.h>
typedef khronos_ssize_t EGLsizeiANDROID;
/*
* EGLSetBlobFunc is a pointer to an application-provided function that a
* client API implementation may use to insert a key/value pair into the
* cache.
*/
typedef void (*EGLSetBlobFuncANDROID) (const void* key,
EGLsizeiANDROID keySize, const void* value, EGLsizeiANDROID valueSize)
/*
* EGLGetBlobFunc is a pointer to an application-provided function that a
* client API implementation may use to retrieve a cached value from the
* cache.
*/
typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void* key,
EGLsizeiANDROID keySize, void* value, EGLsizeiANDROID valueSize)
New Procedures and Functions
void eglSetBlobCacheFuncsANDROID(EGLDisplay dpy,
EGLSetBlobFuncANDROID set,
EGLGetBlobFuncANDROID get);
New Tokens
None.
Changes to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
Add a new subsection after Section 3.8, page 50
(Synchronization Primitives)
"3.9 Persistent Caching
In order to facilitate persistent caching of internal client API state that
is slow to compute or collect, the application may specify callback
function pointers through which the client APIs can request data be cached
and retrieved. The command
void eglSetBlobCacheFuncsANDROID(EGLDisplay dpy,
EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
sets the callback function pointers that client APIs associated with
display <dpy> can use to interact with caching functionality provided by
the application. <set> points to a function that inserts a new value into
the cache and associates it with the given key. <get> points to a function
that retrieves from the cache the value associated with a given key. The
semantics of these callback functions are described in Section 3.9.1 (Cache
Operations).
Cache functions may only be specified once during the lifetime of an
EGLDisplay. The <set> and <get> functions may be called at any time and
from any thread from the time at which eglSetBlobCacheFuncsANDROID is
called until the time that the last resource associated with <dpy> is
deleted and <dpy> itself is terminated. Concurrent calls to these
functions from different threads is also allowed.
If eglSetBlobCacheFuncsANDROID generates an error then all client APIs must
behave as though eglSetBlobCacheFuncsANDROID was not called for the display
<dpy>. If <set> or <get> is NULL then an EGL_BAD_PARAMETER error is
generated. If a successful eglSetBlobCacheFuncsANDROID call was already
made for <dpy> and the display has not since been terminated then an
EGL_BAD_PARAMETER error is generated.
3.9.1 Cache Operations
To insert a new binary value into the cache and associate it with a given
key, a client API implementation can call the application-provided callback
function
void (*set) (const void* key, EGLsizeiANDROID keySize,
const void* value, EGLsizeiANDROID valueSize)
<key> and <value> are pointers to the beginning of the key and value,
respectively, that are to be inserted. <keySize> and <valueSize> specify
the size in bytes of the data pointed to by <key> and <value>,
respectively.
No guarantees are made as to whether a given key/value pair is present in
the cache after the set call. If a different value has been associated
with the given key in the past then it is undefined which value, if any, is
associated with the key after the set call. Note that while there are no
guarantees, the cache implementation should attempt to cache the most
recently set value for a given key.
To retrieve the binary value associated with a given key from the cache, a
client API implementation can call the application-provided callback
function
EGLsizeiANDROID (*get) (const void* key, EGLsizeiANDROID keySize,
void* value, EGLsizeiANDROID valueSize)
<key> is a pointer to the beginning of the key. <keySize> specifies the
size in bytes of the binary key pointed to by <key>. If the cache contains
a value associated with the given key then the size of that binary value in
bytes is returned. Otherwise 0 is returned.
If the cache contains a value for the given key and its size in bytes is
less than or equal to <valueSize> then the value is written to the memory
pointed to by <value>. Otherwise nothing is written to the memory pointed
to by <value>.
Issues
1. How should errors be handled in the callback functions?
RESOLVED: No guarantees are made about the presence of values in the cache,
so there should not be a need to return error information to the client API
implementation. The cache implementation can simply drop a value if it
encounters an error during the 'set' callback. Similarly, it can simply
return 0 if it encouters an error in a 'get' callback.
2. When a client API driver gets updated, that may need to invalidate
previously cached entries. How can the driver handle this situation?
RESPONSE: There are a number of ways the driver can handle this situation.
The recommended way is to include the driver version in all cache keys.
That way each driver version will use a set of cache keys that are unique
to that version, and conflicts should never occur. Updating the driver
could then leave a number of values in the cache that will never be
requested again. If needed, the cache implementation can handle those
values in some way, but the driver does not need to take any special
action.
3. How much data can be stored in the cache?
RESPONSE: This is entirely dependent upon the cache implementation.
Presumably it will be tuned to store enough data to be useful, but not
enough to become problematic. :)
Revision History
#3 (Jon Leech, December 13, 2012)
- Fix typo in New Functions section & assign extension #.
#2 (Jamie Gennis, April 25, 2011)
- Swapped the order of the size and pointer arguments to the get and set
functions.
#1 (Jamie Gennis, April 22, 2011)
- Initial draft.