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