1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
|
Name
ANDROID_blob_cache
Name Strings
EGL_ANDROID_blob_cache
Contributors
Jamie Gennis
Contact
Jamie Gennis, Google Inc. (jgennis 'at' google.com)
Status
Draft.
Version
Version 1, April 22, 2011
Number
EGL Extension #XXX
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
/*
* EGLsizei is a signed integer type for representing the size of a memory
* buffer.
*/
#include <khrplatform.h>
typedef khronos_ssize_t EGLsizei;
/*
* 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 (*EGLSetBlobFunc) (const void* key, EGLsizei keySize,
const void* value, EGLsizei 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 EGLsizei (*EGLGetBlobFunc) (const void* key, EGLsizei keySize,
void* value, EGLsizei valueSize)
New Procedures and Functions
void eglSetBlobCacheFuncs(EGLDisplay dpy,
EGLSetBlobFunc set,
EGLGetBlobFunc 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 eglSetBlobCacheFuncs(EGLDisplay dpy,
EGLSetBlobFunc set, EGLGetBlobFunc 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 eglSetBlobCacheFuncs 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 eglSetBlobCacheFuncs generates an error then all client APIs must behave
as though eglSetBlobCacheFuncs was not called for the display <dpy>. If
<set> or <get> is NULL then an EGL_BAD_PARAMETER error is generated. If a
successful eglSetBlobCacheFuncs 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, EGLsizei keySize, const void* value,
EGLsizei 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
EGLsizei (*get) (const void* key, EGLsizei keySize, void* value,
EGLsizei 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
#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.
|