102f4aeb0Sopenharmony_ciName 202f4aeb0Sopenharmony_ci 302f4aeb0Sopenharmony_ci ANDROID_blob_cache 402f4aeb0Sopenharmony_ci 502f4aeb0Sopenharmony_ciName Strings 602f4aeb0Sopenharmony_ci 702f4aeb0Sopenharmony_ci EGL_ANDROID_blob_cache 802f4aeb0Sopenharmony_ci 902f4aeb0Sopenharmony_ciContributors 1002f4aeb0Sopenharmony_ci 1102f4aeb0Sopenharmony_ci Jamie Gennis 1202f4aeb0Sopenharmony_ci 1302f4aeb0Sopenharmony_ciContact 1402f4aeb0Sopenharmony_ci 1502f4aeb0Sopenharmony_ci Jamie Gennis, Google Inc. (jgennis 'at' google.com) 1602f4aeb0Sopenharmony_ci 1702f4aeb0Sopenharmony_ciStatus 1802f4aeb0Sopenharmony_ci 1902f4aeb0Sopenharmony_ci Complete 2002f4aeb0Sopenharmony_ci 2102f4aeb0Sopenharmony_ciVersion 2202f4aeb0Sopenharmony_ci 2302f4aeb0Sopenharmony_ci Version 3, December 13, 2012 2402f4aeb0Sopenharmony_ci 2502f4aeb0Sopenharmony_ciNumber 2602f4aeb0Sopenharmony_ci 2702f4aeb0Sopenharmony_ci EGL Extension #48 2802f4aeb0Sopenharmony_ci 2902f4aeb0Sopenharmony_ciDependencies 3002f4aeb0Sopenharmony_ci 3102f4aeb0Sopenharmony_ci Requires EGL 1.0 3202f4aeb0Sopenharmony_ci 3302f4aeb0Sopenharmony_ci This extension is written against the wording of the EGL 1.4 Specification 3402f4aeb0Sopenharmony_ci 3502f4aeb0Sopenharmony_ciOverview 3602f4aeb0Sopenharmony_ci 3702f4aeb0Sopenharmony_ci Shader compilation and optimization has been a troublesome aspect of OpenGL 3802f4aeb0Sopenharmony_ci programming for a long time. It can consume seconds of CPU cycles during 3902f4aeb0Sopenharmony_ci application start-up. Additionally, state-based re-compiles done 4002f4aeb0Sopenharmony_ci internally by the drivers add an unpredictable element to application 4102f4aeb0Sopenharmony_ci performance tuning, often leading to occasional pauses in otherwise smooth 4202f4aeb0Sopenharmony_ci animations. 4302f4aeb0Sopenharmony_ci 4402f4aeb0Sopenharmony_ci This extension provides a mechanism through which client API 4502f4aeb0Sopenharmony_ci implementations may cache shader binaries after they are compiled. It may 4602f4aeb0Sopenharmony_ci then retrieve those cached shaders during subsequent executions of the same 4702f4aeb0Sopenharmony_ci program. The management of the cache is handled by the application (or 4802f4aeb0Sopenharmony_ci middleware), allowing it to be tuned to a particular platform or 4902f4aeb0Sopenharmony_ci environment. 5002f4aeb0Sopenharmony_ci 5102f4aeb0Sopenharmony_ci While the focus of this extension is on providing a persistent cache for 5202f4aeb0Sopenharmony_ci shader binaries, it may also be useful for caching other data. This is 5302f4aeb0Sopenharmony_ci perfectly acceptable, but the guarantees provided (or lack thereof) were 5402f4aeb0Sopenharmony_ci designed around the shader use case. 5502f4aeb0Sopenharmony_ci 5602f4aeb0Sopenharmony_ci Note that although this extension is written as if the application 5702f4aeb0Sopenharmony_ci implements the caching functionality, on the Android OS it is implemented 5802f4aeb0Sopenharmony_ci as part of the Android EGL module. This extension is not exposed to 5902f4aeb0Sopenharmony_ci applications on Android, but will be used automatically in every 6002f4aeb0Sopenharmony_ci application that uses EGL if it is supported by the underlying 6102f4aeb0Sopenharmony_ci device-specific EGL implementation. 6202f4aeb0Sopenharmony_ci 6302f4aeb0Sopenharmony_ciNew Types 6402f4aeb0Sopenharmony_ci 6502f4aeb0Sopenharmony_ci /* 6602f4aeb0Sopenharmony_ci * EGLsizeiANDROID is a signed integer type for representing the size of a 6702f4aeb0Sopenharmony_ci * memory buffer. 6802f4aeb0Sopenharmony_ci */ 6902f4aeb0Sopenharmony_ci #include <khrplatform.h> 7002f4aeb0Sopenharmony_ci typedef khronos_ssize_t EGLsizeiANDROID; 7102f4aeb0Sopenharmony_ci 7202f4aeb0Sopenharmony_ci /* 7302f4aeb0Sopenharmony_ci * EGLSetBlobFunc is a pointer to an application-provided function that a 7402f4aeb0Sopenharmony_ci * client API implementation may use to insert a key/value pair into the 7502f4aeb0Sopenharmony_ci * cache. 7602f4aeb0Sopenharmony_ci */ 7702f4aeb0Sopenharmony_ci typedef void (*EGLSetBlobFuncANDROID) (const void* key, 7802f4aeb0Sopenharmony_ci EGLsizeiANDROID keySize, const void* value, EGLsizeiANDROID valueSize) 7902f4aeb0Sopenharmony_ci 8002f4aeb0Sopenharmony_ci /* 8102f4aeb0Sopenharmony_ci * EGLGetBlobFunc is a pointer to an application-provided function that a 8202f4aeb0Sopenharmony_ci * client API implementation may use to retrieve a cached value from the 8302f4aeb0Sopenharmony_ci * cache. 8402f4aeb0Sopenharmony_ci */ 8502f4aeb0Sopenharmony_ci typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void* key, 8602f4aeb0Sopenharmony_ci EGLsizeiANDROID keySize, void* value, EGLsizeiANDROID valueSize) 8702f4aeb0Sopenharmony_ci 8802f4aeb0Sopenharmony_ciNew Procedures and Functions 8902f4aeb0Sopenharmony_ci 9002f4aeb0Sopenharmony_ci void eglSetBlobCacheFuncsANDROID(EGLDisplay dpy, 9102f4aeb0Sopenharmony_ci EGLSetBlobFuncANDROID set, 9202f4aeb0Sopenharmony_ci EGLGetBlobFuncANDROID get); 9302f4aeb0Sopenharmony_ci 9402f4aeb0Sopenharmony_ciNew Tokens 9502f4aeb0Sopenharmony_ci 9602f4aeb0Sopenharmony_ci None. 9702f4aeb0Sopenharmony_ci 9802f4aeb0Sopenharmony_ciChanges to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors) 9902f4aeb0Sopenharmony_ci 10002f4aeb0Sopenharmony_ci Add a new subsection after Section 3.8, page 50 10102f4aeb0Sopenharmony_ci (Synchronization Primitives) 10202f4aeb0Sopenharmony_ci 10302f4aeb0Sopenharmony_ci "3.9 Persistent Caching 10402f4aeb0Sopenharmony_ci 10502f4aeb0Sopenharmony_ci In order to facilitate persistent caching of internal client API state that 10602f4aeb0Sopenharmony_ci is slow to compute or collect, the application may specify callback 10702f4aeb0Sopenharmony_ci function pointers through which the client APIs can request data be cached 10802f4aeb0Sopenharmony_ci and retrieved. The command 10902f4aeb0Sopenharmony_ci 11002f4aeb0Sopenharmony_ci void eglSetBlobCacheFuncsANDROID(EGLDisplay dpy, 11102f4aeb0Sopenharmony_ci EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get); 11202f4aeb0Sopenharmony_ci 11302f4aeb0Sopenharmony_ci sets the callback function pointers that client APIs associated with 11402f4aeb0Sopenharmony_ci display <dpy> can use to interact with caching functionality provided by 11502f4aeb0Sopenharmony_ci the application. <set> points to a function that inserts a new value into 11602f4aeb0Sopenharmony_ci the cache and associates it with the given key. <get> points to a function 11702f4aeb0Sopenharmony_ci that retrieves from the cache the value associated with a given key. The 11802f4aeb0Sopenharmony_ci semantics of these callback functions are described in Section 3.9.1 (Cache 11902f4aeb0Sopenharmony_ci Operations). 12002f4aeb0Sopenharmony_ci 12102f4aeb0Sopenharmony_ci Cache functions may only be specified once during the lifetime of an 12202f4aeb0Sopenharmony_ci EGLDisplay. The <set> and <get> functions may be called at any time and 12302f4aeb0Sopenharmony_ci from any thread from the time at which eglSetBlobCacheFuncsANDROID is 12402f4aeb0Sopenharmony_ci called until the time that the last resource associated with <dpy> is 12502f4aeb0Sopenharmony_ci deleted and <dpy> itself is terminated. Concurrent calls to these 12602f4aeb0Sopenharmony_ci functions from different threads is also allowed. 12702f4aeb0Sopenharmony_ci 12802f4aeb0Sopenharmony_ci If eglSetBlobCacheFuncsANDROID generates an error then all client APIs must 12902f4aeb0Sopenharmony_ci behave as though eglSetBlobCacheFuncsANDROID was not called for the display 13002f4aeb0Sopenharmony_ci <dpy>. If <set> or <get> is NULL then an EGL_BAD_PARAMETER error is 13102f4aeb0Sopenharmony_ci generated. If a successful eglSetBlobCacheFuncsANDROID call was already 13202f4aeb0Sopenharmony_ci made for <dpy> and the display has not since been terminated then an 13302f4aeb0Sopenharmony_ci EGL_BAD_PARAMETER error is generated. 13402f4aeb0Sopenharmony_ci 13502f4aeb0Sopenharmony_ci 3.9.1 Cache Operations 13602f4aeb0Sopenharmony_ci 13702f4aeb0Sopenharmony_ci To insert a new binary value into the cache and associate it with a given 13802f4aeb0Sopenharmony_ci key, a client API implementation can call the application-provided callback 13902f4aeb0Sopenharmony_ci function 14002f4aeb0Sopenharmony_ci 14102f4aeb0Sopenharmony_ci void (*set) (const void* key, EGLsizeiANDROID keySize, 14202f4aeb0Sopenharmony_ci const void* value, EGLsizeiANDROID valueSize) 14302f4aeb0Sopenharmony_ci 14402f4aeb0Sopenharmony_ci <key> and <value> are pointers to the beginning of the key and value, 14502f4aeb0Sopenharmony_ci respectively, that are to be inserted. <keySize> and <valueSize> specify 14602f4aeb0Sopenharmony_ci the size in bytes of the data pointed to by <key> and <value>, 14702f4aeb0Sopenharmony_ci respectively. 14802f4aeb0Sopenharmony_ci 14902f4aeb0Sopenharmony_ci No guarantees are made as to whether a given key/value pair is present in 15002f4aeb0Sopenharmony_ci the cache after the set call. If a different value has been associated 15102f4aeb0Sopenharmony_ci with the given key in the past then it is undefined which value, if any, is 15202f4aeb0Sopenharmony_ci associated with the key after the set call. Note that while there are no 15302f4aeb0Sopenharmony_ci guarantees, the cache implementation should attempt to cache the most 15402f4aeb0Sopenharmony_ci recently set value for a given key. 15502f4aeb0Sopenharmony_ci 15602f4aeb0Sopenharmony_ci To retrieve the binary value associated with a given key from the cache, a 15702f4aeb0Sopenharmony_ci client API implementation can call the application-provided callback 15802f4aeb0Sopenharmony_ci function 15902f4aeb0Sopenharmony_ci 16002f4aeb0Sopenharmony_ci EGLsizeiANDROID (*get) (const void* key, EGLsizeiANDROID keySize, 16102f4aeb0Sopenharmony_ci void* value, EGLsizeiANDROID valueSize) 16202f4aeb0Sopenharmony_ci 16302f4aeb0Sopenharmony_ci <key> is a pointer to the beginning of the key. <keySize> specifies the 16402f4aeb0Sopenharmony_ci size in bytes of the binary key pointed to by <key>. If the cache contains 16502f4aeb0Sopenharmony_ci a value associated with the given key then the size of that binary value in 16602f4aeb0Sopenharmony_ci bytes is returned. Otherwise 0 is returned. 16702f4aeb0Sopenharmony_ci 16802f4aeb0Sopenharmony_ci If the cache contains a value for the given key and its size in bytes is 16902f4aeb0Sopenharmony_ci less than or equal to <valueSize> then the value is written to the memory 17002f4aeb0Sopenharmony_ci pointed to by <value>. Otherwise nothing is written to the memory pointed 17102f4aeb0Sopenharmony_ci to by <value>. 17202f4aeb0Sopenharmony_ci 17302f4aeb0Sopenharmony_ciIssues 17402f4aeb0Sopenharmony_ci 17502f4aeb0Sopenharmony_ci 1. How should errors be handled in the callback functions? 17602f4aeb0Sopenharmony_ci 17702f4aeb0Sopenharmony_ci RESOLVED: No guarantees are made about the presence of values in the cache, 17802f4aeb0Sopenharmony_ci so there should not be a need to return error information to the client API 17902f4aeb0Sopenharmony_ci implementation. The cache implementation can simply drop a value if it 18002f4aeb0Sopenharmony_ci encounters an error during the 'set' callback. Similarly, it can simply 18102f4aeb0Sopenharmony_ci return 0 if it encouters an error in a 'get' callback. 18202f4aeb0Sopenharmony_ci 18302f4aeb0Sopenharmony_ci 2. When a client API driver gets updated, that may need to invalidate 18402f4aeb0Sopenharmony_ci previously cached entries. How can the driver handle this situation? 18502f4aeb0Sopenharmony_ci 18602f4aeb0Sopenharmony_ci RESPONSE: There are a number of ways the driver can handle this situation. 18702f4aeb0Sopenharmony_ci The recommended way is to include the driver version in all cache keys. 18802f4aeb0Sopenharmony_ci That way each driver version will use a set of cache keys that are unique 18902f4aeb0Sopenharmony_ci to that version, and conflicts should never occur. Updating the driver 19002f4aeb0Sopenharmony_ci could then leave a number of values in the cache that will never be 19102f4aeb0Sopenharmony_ci requested again. If needed, the cache implementation can handle those 19202f4aeb0Sopenharmony_ci values in some way, but the driver does not need to take any special 19302f4aeb0Sopenharmony_ci action. 19402f4aeb0Sopenharmony_ci 19502f4aeb0Sopenharmony_ci 3. How much data can be stored in the cache? 19602f4aeb0Sopenharmony_ci 19702f4aeb0Sopenharmony_ci RESPONSE: This is entirely dependent upon the cache implementation. 19802f4aeb0Sopenharmony_ci Presumably it will be tuned to store enough data to be useful, but not 19902f4aeb0Sopenharmony_ci enough to become problematic. :) 20002f4aeb0Sopenharmony_ci 20102f4aeb0Sopenharmony_ciRevision History 20202f4aeb0Sopenharmony_ci 20302f4aeb0Sopenharmony_ci#3 (Jon Leech, December 13, 2012) 20402f4aeb0Sopenharmony_ci - Fix typo in New Functions section & assign extension #. 20502f4aeb0Sopenharmony_ci 20602f4aeb0Sopenharmony_ci#2 (Jamie Gennis, April 25, 2011) 20702f4aeb0Sopenharmony_ci - Swapped the order of the size and pointer arguments to the get and set 20802f4aeb0Sopenharmony_ci functions. 20902f4aeb0Sopenharmony_ci 21002f4aeb0Sopenharmony_ci#1 (Jamie Gennis, April 22, 2011) 21102f4aeb0Sopenharmony_ci - Initial draft. 212