• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1Name
2
3    OES_get_program_binary
4
5Name Strings
6
7    GL_OES_get_program_binary
8
9Contributors
10
11    Acorn Pooley
12    Aske Simon Christensen
13    David Garcia
14    Georg Kolling
15    Jason Green
16    Jeremy Sandmel
17    Joey Blankenship
18    Mark Callow
19    Robert Simpson
20    Tom Olson
21
22Contact
23
24    Benj Lipchak, AMD (benj.lipchak 'at' amd.com)
25
26Notice
27
28    Copyright (c) 2007-2013 The Khronos Group Inc. Copyright terms at
29        http://www.khronos.org/registry/speccopyright.html
30
31Specification Update Policy
32
33    Khronos-approved extension specifications are updated in response to
34    issues and bugs prioritized by the Khronos OpenGL ES Working Group. For
35    extensions which have been promoted to a core Specification, fixes will
36    first appear in the latest version of that core Specification, and will
37    eventually be backported to the extension document. This policy is
38    described in more detail at
39        https://www.khronos.org/registry/OpenGL/docs/update_policy.php
40
41Status
42
43    Ratified by the Khronos BOP, May 29, 2008.
44
45Version
46
47    Last Modified Date: June 24, 2020
48    Revision: #16
49
50Number
51
52    OpenGL ES Extension #47
53
54Dependencies
55
56    OpenGL ES 2.0 is required.
57
58    Written based on the wording of the OpenGL ES 2.0 specification.
59
60Overview
61
62    This extension introduces two new commands.  GetProgramBinaryOES empowers an
63    application to use the GL itself as an offline compiler.  The resulting
64    program binary can be reloaded into the GL via ProgramBinaryOES.  This is a
65    very useful path for applications that wish to remain portable by shipping
66    pure GLSL source shaders, yet would like to avoid the cost of compiling
67    their shaders at runtime.  Instead an application can supply its GLSL source
68    shaders during first application run, or even during installation.  The
69    application then compiles and links its shaders and reads back the program
70    binaries.  On subsequent runs, only the program binaries need be supplied!
71    Though the level of optimization may not be identical -- the offline shader
72    compiler may have the luxury of more aggressive optimization at its
73    disposal -- program binaries generated online by the GL are interchangeable
74    with those generated offline by an SDK tool.
75
76    Note that an implementation supporting this extension need not include an
77    online compiler.  That is, it is not required to support loading GLSL shader
78    sources via the ShaderSource command.  A query of boolean value
79    SHADER_COMPILER can be used to determine if an implementation supports a
80    shader compiler.  If not, the GetProgramBinaryOES command is rendered
81    virtually useless, but the ProgramBinaryOES command may still be used by
82    vendor extensions as a standard method for loading offline-compiled program
83    binaries.
84
85
86Issues
87
88    1. Why introduce a new entrypoint for loading binaries when ShaderBinary
89       is already part of the core spec and permits loading binary shader pairs?
90
91    RESOLVED: There are several reasons:
92      - Shader objects are taken out of the equation, since they're not
93        relevant to wholesale program object replacement.
94      - Implicit links during retrieval are no longer needed since we don't
95        need to keep shader object state in sync with program object state.
96      - Explicit links during program object reload are no longer needed since
97        the program binary is pre-linked and ready to run.
98      - The number of API calls needed to load program objects is much fewer.
99      - Complex error detection needed by the previous proposal is eliminated.
100      - No change to the retrieval/reload path is needed when new shader stages
101        are introduced by future extensions.
102      - This is a more elegant mapping for what we're trying to achieve!
103
104    2. Do we need to consider state dependencies when using this extension?
105
106    RESOLVED: No more than you do when using GLSL source shaders.  A program
107    binary retrieved with GetProgramBinaryOES can be expected to work regardless
108    of the current GL state in effect at the time it was retrieved with
109    GetProgramBinaryOES, loaded with ProgramBinaryOES, installed as part of
110    render state with UseProgram, or used for drawing with DrawArrays or
111    DrawElements.
112
113    However, some implementations have internal state dependencies that affect
114    both GLSL source shaders and program binaries, causing them to run out of
115    resources when confronted by combinations of certain GL state and certain
116    shader program characteristics.  An application need be concerned no more
117    with these issues when using program binaries than when using GLSL source
118    shaders.
119
120    3. How are shader objects involved, if at all?
121
122    RESOLVED: Any shader objects attached to the program object at the time
123    GetProgramBinaryOES or ProgramBinaryOES is called are ignored.  (See also
124    Issue 4.)
125
126    The program binary retrieved by GetProgramBinaryOES is the one installed
127    during the most recent call to LinkProgram or ProgramBinaryOES, i.e. the one
128    which would go into effect if we were to call UseProgram.  Attaching
129    different shader objects after the most recent call to LinkProgram is
130    inconsequential.
131
132    4. Should we throw an error as a programming aid if there are shader objects
133       attached to the program object when ProgramBinaryOES is called?
134
135    RESOLVED: No, they are irrelevant but harmless, and GL precedent is to throw
136    errors on bad state combinations, not on harmless ones.  Besides, the
137    programmer should discover pretty quickly that they're getting the wrong
138    shader, if they accidentally called ProgramBinaryOES instead of LinkProgram.
139    Also, an app may intentionally leave the attachments in place if it for some
140    reason is switching back and forth between loading a program object with
141    program binaries, and loading it with compiled GLSL shaders.
142
143    5. Where are the binary formats defined and described?
144
145    RESOLVED: This extension provides a common infrastructure for retrieving and
146    loading program binaries.  A vendor extension must also be present in order
147    to define one or more binary formats, thereby populating the list of
148    PROGRAM_BINARY_FORMATS_OES.  The <binaryFormat> returned by
149    GetProgramBinaryOES is always one of the binary formats in this list.  If
150    ProgramBinaryOES is called with a <binaryFormat> not in this list, the
151    implementation will throw an INVALID_ENUM error.
152
153    The beauty of this extension, however, is that an application does not need
154    to be aware of the vendor extension on any given implementation.  It only
155    needs to retrieve a program binary with an anonymous <binaryFormat> and
156    resupply that same <binaryFormat> when loading the program binary.
157
158    6. Under what conditions might a call to ProgramBinaryOES fail?
159
160    RESOLVED: Even if a program binary is successfully retrieved with
161    GetProgramBinaryOES and then in a future run the program binary is
162    resupplied with ProgramBinaryOES, and all of the parameters are correct,
163    the program binary load may still fail.
164
165    This can happen if there has been a change to the hardware or software on
166    the system, such as a hardware upgrade or driver update.  In this case the
167    PROGRAM_BINARY_FORMATS_OES list may no longer contain the binary format
168    associated with the cached program binary, and INVALID_ENUM will be thrown
169    if the cached program binary format is passed into ProgramBinaryOES anyway.
170
171    Even if the cached program binary format is still valid, ProgramBinaryOES
172    may still fail to load the cached binary.  This is the driver's way of
173    signaling to the app that it needs to recompile and recache its program
174    binaries because there has been some important change to the online
175    compiler, such as a bug fix or a significant new optimization.
176
177    7. Can BindAttribLocation be called after ProgramBinaryOES to remap an
178       attribute location used by the program binary?
179
180    RESOLVED: No.  BindAttribLocation only affects the result of a subsequent
181    call to LinkProgram.  LinkProgram operates on the attached shader objects
182    and replaces any program binary loaded prior to LinkProgram.  So there is no
183    mechanism to remap an attribute location after loading a program binary.
184
185    However, an application is free to remap an attribute location prior to
186    retrieving the program binary.  By calling BindAttribLocation followed by
187    LinkProgram, an application can remap the attribute location.  If this is
188    followed by a call to GetProgramBinaryOES, the retrieved program binary will
189    include the desired attribute location assignment.
190
191New Procedures and Functions
192
193    void GetProgramBinaryOES(uint program, sizei bufSize, sizei *length,
194                             enum *binaryFormat, void *binary);
195
196    void ProgramBinaryOES(uint program, enum binaryFormat,
197                          const void *binary, int length);
198
199New Tokens
200
201    Accepted by the <pname> parameter of GetProgramiv:
202
203        PROGRAM_BINARY_LENGTH_OES                   0x8741
204
205    Accepted by the <pname> parameter of GetBooleanv, GetIntegerv, and
206    GetFloatv:
207
208        NUM_PROGRAM_BINARY_FORMATS_OES              0x87FE
209        PROGRAM_BINARY_FORMATS_OES                  0x87FF
210
211Additions to Chapter 2 of the OpenGL ES 2.0 Specification (OpenGL Operation)
212
213    Update section 2.15, replace first sentence of last paragraph with:
214
215    "OpenGL ES 2.0 provides interfaces to directly load pre-compiled shader
216    binaries, to directly load pre-linked program binaries, or to load the
217    shader sources and compile them."
218
219    Add section 2.15.4, Program Binaries
220
221    "The command
222
223        void GetProgramBinaryOES(uint program, sizei bufSize, sizei *length,
224                                 enum *binaryFormat, void *binary);
225
226    returns the program object's executable, henceforth referred to as its
227    program binary.  The maximum number of bytes that may be written into
228    <binary> is specified by <bufSize>.  If <bufSize> is less than the number of
229    bytes in the program binary, then 0 is returned in <length>, and an
230    INVALID_OPERATION error is thrown.  Otherwise, the actual number of bytes
231    written into <binary> is returned in <length> and its format is returned in
232    <binaryFormat>.  If <length> is NULL, then no length is returned.
233
234    The number of bytes in the program binary can be queried by calling
235    GetProgramiv with <pname> PROGRAM_BINARY_LENGTH_OES.  When a program
236    object's LINK_STATUS is FALSE, its program binary length is zero, and a call
237    to GetProgramBinaryOES will generate an INVALID_OPERATION error.
238
239    The command
240
241        void ProgramBinaryOES(uint program, enum binaryFormat,
242                              const void *binary, int length);
243
244    loads a program object with a program binary previously returned from
245    GetProgramBinaryOES.  This is useful for future instantiations of the GL to
246    avoid online compilation, while still using OpenGL Shading Language source
247    shaders as a portable initial format.  <binaryFormat> and <binary> must be
248    those returned by a previous call to GetProgramBinaryOES, and <length> must
249    be the length of the program binary as returned by GetProgramBinaryOES or
250    GetProgramiv with <pname> PROGRAM_BINARY_LENGTH_OES.  The program binary
251    will fail to load if these conditions are not met.
252
253    An implementation may reject a program binary if it determines the program
254    binary was produced by an incompatible or outdated version of the compiler.
255    In this case the application should fall back to providing the original
256    OpenGL Shading Language source shaders, and perhaps again retrieve the
257    program binary for future use.
258
259    A program object's program binary is replaced by calls to LinkProgram or
260    ProgramBinaryOES.  Either command sets the program object's LINK_STATUS to
261    TRUE or FALSE, as queried with GetProgramiv, to reflect success or failure.
262    Either command also updates its information log, queried with
263    GetProgramInfoLog, to provide details about warnings or errors.
264
265    If ProgramBinaryOES failed, any information about a previous link or load of
266    that program object is lost.  Thus, a failed load does not restore the old
267    state of <program>.
268
269    Note that ProgramBinaryOES disregards any shader objects attached to the
270    program object, as these shader objects are used only by LinkProgram.
271
272    Queries of values NUM_PROGRAM_BINARY_FORMATS and PROGRAM_BINARY_FORMATS
273    return the number of program binary formats and the list of program binary
274    format values supported by an implementation.  The <binaryFormat> returned
275    by GetProgramBinaryOES must be present in this list."
276
277GLX Protocol
278
279    None.
280
281Errors
282
283    INVALID_OPERATION error is generated if GetProgramBinaryOES is called when
284    the program object, <program>, does not contain a valid program binary as
285    reflected by its LINK_STATUS state; if <bufSize> is not big enough to
286    contain the entire program binary; or if the value of
287    NUM_PROGRAM_BINARY_FORMATS is zero.
288
289New State
290
291    (table 6.25, Program Object State) add the following:
292
293    Get Value                  Type  Get Command   Initial Value  Description               Section
294    -------------              ----  -----------   -------------  -----------               -------
295    PROGRAM_BINARY_LENGTH_OES  Z+    GetProgramiv  0              Length of program binary  2.15.4
296
297    (table 6.28, Implementation Dependent Values) add the following:
298
299    Get Value                       Type  Get Command  Minimum Value  Description                        Section
300    -------------                   ----  -----------  -------------  -----------                        -------
301    PROGRAM_BINARY_FORMATS_OES      0+*Z  GetIntegerv  N/A            Enumerated program binary formats  2.15.4
302    NUM_PROGRAM_BINARY_FORMATS_OES  Z     GetIntegerv  0              Number of program binary formats   2.15.4
303
304    (table 6.29, Implementation Dependent Values (cont.)) add the following:
305
306    Get Value      Type  Get Command          Minimum Value  Description             Section
307    -------------  ----  -----------          -------------  -----------             -------
308    Binary format  Z1    GetProgramBinaryOES  N/A            Binary format returned  2.15.2
309
310Sample Usage
311
312    void retrieveProgramBinary(const GLchar* vsSource, const GLchar* fsSource,
313                               const char* myBinaryFileName,
314                               GLenum* binaryFormat)
315    {
316        GLuint  newFS, newVS;
317        GLuint  newProgram;
318        GLchar* sources[1];
319        GLint   success;
320
321        //
322        //  Create new shader/program objects and attach them together.
323        //
324        newVS = glCreateShader(GL_VERTEX_SHADER);
325        newFS = glCreateShader(GL_FRAGMENT_SHADER);
326        newProgram = glCreateProgram();
327        glAttachShader(newProgram, newVS);
328        glAttachShader(newProgram, newFS);
329
330        //
331        //  Supply GLSL source shaders, compile, and link them
332        //
333        sources[0] = vsSource;
334        glShaderSource(newVS, 1, sources, NULL);
335        glCompileShader(newVS);
336
337        sources[0] = fsSource;
338        glShaderSource(newFS, 1, sources, NULL);
339        glCompileShader(newFS);
340
341        glLinkProgram(newProgram);
342        glGetProgramiv(newProgram, GL_LINK_STATUS, &success);
343
344        if (success)
345        {
346            GLint   binaryLength;
347            void*   binary;
348            FILE*   outfile;
349
350            //
351            //  Retrieve the binary from the program object
352            //
353            glGetProgramiv(newProgram, GL_PROGRAM_BINARY_LENGTH_OES, &binaryLength);
354            binary = (void*)malloc(binaryLength);
355            glGetProgramBinaryOES(newProgram, binaryLength, NULL, binaryFormat, binary);
356
357            //
358            //  Cache the program binary for future runs
359            //
360            outfile = fopen(myBinaryFileName, "wb");
361            fwrite(binary, binaryLength, 1, outfile);
362            fclose(outfile);
363            free(binary);
364        }
365        else
366        {
367            //
368            // Fallback to simpler source shaders?  Take my toys and go home?
369            //
370        }
371
372        //
373        // Clean up
374        //
375        glDeleteShader(newVS);
376        glDeleteShader(newFS);
377        glDeleteProgram(newProgram);
378    }
379
380    void loadProgramBinary(const char* myBinaryFileName, GLenum binaryFormat,
381                           GLuint progObj)
382    {
383        GLint   binaryLength;
384        void*   binary;
385        GLint   success;
386        FILE*   infile;
387
388        //
389        //  Read the program binary
390        //
391        infile = fopen(myBinaryFileName, "rb");
392        fseek(infile, 0, SEEK_END);
393        binaryLength = (GLint)ftell(infile);
394        binary = (void*)malloc(binaryLength);
395        fseek(infile, 0, SEEK_SET);
396        fread(binary, binaryLength, 1, infile);
397        fclose(infile);
398
399        //
400        //  Load the binary into the program object -- no need to link!
401        //
402        glProgramBinaryOES(progObj, binaryFormat, binary, binaryLength);
403        free(binary);
404
405        glGetProgramiv(progObj, GL_LINK_STATUS, &success);
406
407        if (!success)
408        {
409            //
410            // Something must have changed since the program binaries
411            // were cached away.  Fallback to source shader loading path,
412            // and then retrieve and cache new program binaries once again.
413            //
414        }
415    }
416
417Revision History
418
419    #16    24/06/2020    Arthur Tombs    Fix typo: pass binaryLength by value
420                                         instead of by pointer in example code
421    #15    01/11/2019    Jon Leech       Add an error for ProgramBinary if there
422                                         are no binary formats (Bug 16155).
423    #14    10/08/2013    Jon Leech       Change GLvoid -> void (Bug 10412).
424    #13    06/02/2008    Benj Lipchak    Fix typo: GLint -> int, update status.
425    #12    05/07/2008    Benj Lipchak    Add Issue about BindAttribLocation.
426    #11    04/03/2008    Benj Lipchak    Fix memory leaks in sample code.
427    #10    03/27/2008    Benj Lipchak    Mark spec as ratified by the WG, add
428                                         new issues, and update sample code.
429    #09    03/13/2008    Benj Lipchak    Many minor updates!  Most notably,
430                                         introduce PROGRAM_BINARY_FORMATS_OES
431                                         and NUM_PROGRAM_BINARY_FORMATS_OES.
432    #08    03/12/2008    Benj Lipchak    Rewrite as {Get}ProgramBinaryOES.  Add
433                                         issues section.
434    #07    02/27/2008    Benj Lipchak    When <bufSize> is too small, throw
435                                         error and return 0 in <length>.  Limit
436                                         the allowed reasons for subsequent
437                                         binary rejection.  Rename to OES and
438                                         GetShaderBinary.  Add the LinkProgram
439                                         error condition.
440    #06    01/10/2008    Benj Lipchak    Clarify that GetProgramInfoLog may be
441                                         called after an implicit link, and
442                                         clarify that the returned binary pair
443                                         must be loaded with a single call to
444                                         ShaderBinary or an error is thrown.
445    #05    01/08/2008    Benj Lipchak    Clarify program object state after
446                                         GetProgramBinaryEXT, fix example code.
447    #04    01/02/2008    Benj Lipchak    Split GetProgramBinary into its own
448                                         multi-vendor extension proposal.
449    #03    11/26/2007    Benj Lipchak    Add sample usage and define tokens.
450    #02    10/22/2007    Benj Lipchak    Add error conditions.
451    #01    10/14/2007    Benj Lipchak    First draft.
452