212 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			212 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| 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.
 |