Name IMG_bindless_texture Name Strings GL_IMG_bindless_texture Contact Tobias Hector (tobias.hector 'at' imgtec.com) Contributors Contributors to the original ARB_bindless_texture Notice Copyright (c) 2013 The Khronos Group Inc. Copyright terms at http://www.khronos.org/registry/speccopyright.html Status Draft Version Last Modified Date: May 23, 2016 Author Revision: 4 Number OpenGL ES Extension #270 Dependencies OpenGL ES 3.1 is required. This extension is written against the OpenGL ES Shading Language specification, Language Version 3.10, Document Revision 3 and the OpenGL ES 3.1 API specification. This extension interacts with EXT/OES_gpu_shader5. This extension interacts with EXT/OES_texture_buffer and EXT_buffer_storage. This extension interacts with OpenGL ES 3.2 Overview This extension allows OpenGL ES applications to access texture objects in shaders without first binding each texture to one of a limited number of texture image units. Using this extension, an application can query a 64-bit unsigned integer texture handle for each texture that it wants to access and then use that handle directly in GLSL ES. This extensions significantly reduces the amount of API and internal GL driver overhead needed to manage resource bindings. This extension adds no new data types to GLSL. Instead, it uses existing sampler data types and allows them to be populated with texture handles. This extension also permits sampler types to be used as uniform block members as well as default uniforms. Additionally, new APIs are provided to load values for sampler uniforms with 64-bit handle inputs. The use of existing integer-based Uniform* APIs is still permitted, in which case the integer specified will identify a texture image. For samplers with values specified as texture image units, the GL implementation will translate the unit number to an internal handle as required. New Procedures and Functions uint64 GetTextureHandleIMG(uint texture); uint64 GetTextureSamplerHandleIMG(uint texture, uint sampler); void UniformHandleui64IMG(int location, uint64 value); void UniformHandleui64vIMG(int location, sizei count, const uint64 *value); void ProgramUniformHandleui64IMG(uint program, int location, uint64 value); void ProgramUniformHandleui64vIMG(uint program, int location, sizei count, const uint64 *values); New Tokens None Additions to Chapter 5 of the OpenGL ES 3.1 API Specification, "Shared Objects and Multiple Contexts" Insert a new section 5.4, "Object use by GPU Handles" GPU handles to objects are valid in all contexts in the share group that the originating object belongs to, irrespective of whether the object itself is shared. If the originating object for a handle is deleted or becomes otherwise invalid, the handle becomes immediately invalid in all contexts. Using an invalid handle can lead to undefined results, including program termination. Additions to Chapter 7 of the OpenGL ES 3.1 API Specification, "Variables and Types" Add the following sentence to Section 7.6, Uniform Variables, immediately before the error block on page 97: A sampler uniform will consume no more than 2 components. Add the following commands to the list of Uniform* functions in section 7.6.1, Loading Uniform Variables in the Default Uniform Block: void UniformHandleui64IMG(int location, uint64 value); void UniformHandleui64vIMG(int location, sizei count, const uint64 *value); Delete the sentence "Only the Uniform1i{v} commands can be used to load sampler values (see section 7.9)", and add the following paragraph: The UniformHandleui64{v}IMG commands will load 64-bit unsigned integer handles into a uniform location corresponding to sampler types. Only the UniformHandleui64{v}IMG and Uniform1i{v} commands can be used to load sampler values (see section 7.9). Add the following error condition to the list of errors for Uniform* functions: An INVALID_OPERATION error is generated if the UniformHandleui64{v}IMG commands are used on a sampler variable with the "bound_sampler" layout qualifier (see the Language specification, section 4.4.5bindless). Add the following commands to the list of ProgramUniform* functions in section 7.6.1, Loading Uniform Variables in the Default Uniform Block: void ProgramUniformHandleui64IMG(uint program, int location, uint64 value); void ProgramUniformHandleui64vIMG(uint program, int location, sizei count, const uint64 *values); Edit section 7.6.2.1, "Uniform Buffer Object Storage", to add the following rules for sampler types to the list at the beginning of p105: * Members of sampler types are extracted from a buffer object by reading a single 64-bit value at the specified offset. Replace Section 7.9, Samplers, with the following, adding the ability to use samplers in new places as well as describing the behavior of the new UniformHandleui64{v}IMG APIs: Samplers are special data types used by the OpenGL ES Shading Language to identify the texture object used for each texture lookup. Sampler variables may be used as uniforms in the default block or in user-defined blocks. When used as uniforms in the default block, the value of sampler variables may be specified with either Uniform1i{v} or UniformHandleui64{v}IMG. If a sampler uniform value is specified by Uniform1i{v}, the value passed to Uniform1i{v} indicates a texture image unit that will be accessed, and the value must be in the range from zero to the implementation-dependent maximum supported number of texture image units. If a sampler uniform value is specified by UniformHandleui64{v}IMG, the value passed to UniformHandleui64{v}IMG directly specifies a texture object by handle, as defined in Section 8.2bindless (Bindless Textures). When a program is linked, all sampler uniforms are initialized to zero and considered to be references to texture image units. When used as uniform block members, the value of the sampler is a 64-bit unsigned integer handle and never refers to a texture image unit. When the value of a sampler indicates a texture image unit, the type of the sampler identifies the target on the texture image unit. The texture object bound to that texture image unit's target is used for any texture accesses using that sampler. For example, a variable of type sampler2D selects the target TEXTURE_2D on its texture image unit. Binding of texture objects to targets is done as usual with BindTexture. Selecting the texture image unit to bind to is done as usual with ActiveTexture. When the value of a sampler indicates a texture handle, the target of the texture referred to by the handle must match the type of the sampler. For example, a variable of type sampler2D must be used in conjunction with a handle of a texture of target TEXTURE_2D. If the value of a sampler variable is not a valid texture handle, the results of using that sampler during shader execution are undefined and may lead to program termination. If the value of a sampler variable is a valid handle of a texture with a target different from the variable type, the results of using that handle are undefined but may not include program termination. Sampler uniforms specified using handles do not count as using any texture image unit, even if a texture referred to by a handle is currently bound to one or more texture image units. Errors The error INVALID_VALUE is generated if a Uniform1i{v} call is used to set a sampler uniform to a value less than zero or greater than or equal to the value of MAX_TEXTURE_IMAGE_UNITS. It is not allowed to have uniform variables of different sampler types pointing to the same texture image unit within a program object. This situation can only be detected at the next rendering command issued, and an INVALID_OPERATION error will then be generated. Active samplers are those samplers actually being used in a program object. When a program is linked by LinkProgram, the GL determines whether each sampler is active or not. There is no limit on the number of active sampler variables that may be used by a program or by any particular shader. However, restrictions on the use of texture image units imposes an effective limit on the number of non-handle sampler uniforms. Active samplers used uniforms in the default uniform block are counted toward implementation-dependent limits on the total number of uniform components supported by the program. Each active sampler variable may count as two components against such limits. Additions to Chapter 8 of the OpenGL ES 3.1 API Specification, "Textures and Samplers" Insert a new section 8.2bindless, Bindless Textures, after Section 8.2, Sampler Objects: The previous sections describe mechanisms to make texture and sampler objects available to shaders or fixed-function fragment processing by binding the objects to texture image units. Additionally, texture objects may be accessed by shader using texture handles, which are 64-bit unsigned integers identifying the state of a texture and/or sampler object. The handle zero is reserved and will never be assigned to a valid texture handle. To obtain a texture handle, use the commands: uint64 GetTextureHandleIMG(uint texture); uint64 GetTextureSamplerHandleIMG(uint texture, uint sampler); GetTextureHandleIMG will create a texture handle using the current state of the texture named , including any embedded sampler state. GetTextureSamplerHandleIMG will create a texture handle using the current non-sampler state from the texture named and the sampler state from the sampler object . In both cases, a 64-bit unsigned integer handle is returned. If an error occurs, a handle of zero is returned. The handle for each texture or texture/sampler pair is unique; the same handle will be returned if GetTextureHandleIMG is called multiple times for the same texture or if GetTextureSamplerHandleIMG is called multiple times for the same texture/sampler pair. When a texture object is referenced by one or more texture handles, the texture parameters of the object (Section 8.9) may not be changed. The contents of the images in a texture object may still be updated via commands such as TexSubImage*, CopyTexSubImage*, and CompressedTexSubImage*, and by rendering to a framebuffer object, even if the texture object is referenced by one or more texture handles. However, once a handle references a texture object, texel updates via API commands are no longer implicitly synchronised by the API. Updates to the texture will become visible to the server after an unspecified period of time, and may occur during other server operations - though they are guaranteed to be visible to subsequently issued GL commands with no further action. Applications are responsible for synchronizing access, to ensure operations have completed in the desired order - for instance by using FenceSync (see Chapter 4 - Event Model). [[ If EXT/OES_texture_buffer or OpenGL ES 3.2, and EXT_buffer_storage are supported ]] If the texture object is a buffer texture, the contents of the buffer object may still be updated by using MapBuffer* commands with the MAP_PERSISTENT_BIT_EXT, or via the texture update commands in the same way as other bindless textures, even if the buffer is bound to a texture while that buffer texture object is referenced by one or more texture handles. When a sampler object is referenced by one or more texture handles, the sampler parameters of the object may not be changed. Errors An INVALID_VALUE error is generated if is zero or is not the name of an existing texture object or if is zero or is not the name of an existing sampler object. [[ If EXT/OES_texture_buffer or OpenGL ES 3.2, and EXT_buffer_storage are supported ]] An INVALID_OPERATION error is generated if the value of 's TEXTURE_IMMUTABLE_FORMAT is FALSE (section 8.17), or if is a texture buffer and the values of the backing buffer's BUFFER_- IMMUTABLE_STORAGE_EXT is FALSE, BUFFER_ACCESS_FLAGS includes DYNAMIC_STORAGE_BIT or does not include MAP_PERSISTENT_BIT_EXT. [[ Else ]] An INVALID_OPERATION error is generated if the value of 's TEXTURE_IMMUTABLE_FORMAT is FALSE (section 8.17). [[ If EXT/OES_texture_border_clamp or OpenGL ES 3.2 are supported ]] An INVALID_OPERATION error is generated if the border color (taken from the embedded sampler for GetTextureHandleIMG or from the for GetTextureSamplerHandleIMG) is not one of the following allowed values. If the texture's base internal format is signed or unsigned integer, allowed values are (0,0,0,0), (0,0,0,1), (1,1,1,0), and (1,1,1,1). If the base internal format is not integer, allowed values are (0.0,0.0,0.0,0.0), (0.0,0.0,0.0,1.0), (1.0,1.0,1.0,0.0), and (1.0,1.0,1.0,1.0). Additions to Chapter 11 of the OpenGL ES 3.1 API Specification, "Programmable Vertex Processing" Add the following sentence to the end of the paragraph in Section 11.1.3.5, Texture Access, beginning "All active shaders combined cannot use more than the value of MAX_COMBINED_TEXTURE_IMAGE_UNITS...": Samplers accessed using texture handles (section 3.9.X) are not counted against this limit. Modifications to The OpenGL ES 3.10 Shading Language Specification Including the following line in a shader can be used to control the language features described in this extension: #extension GL_IMG_bindless_texture : where is as specified in section 3.4. New preprocessor #defines are added to the OpenGL ES Shading Language: #define GL_IMG_bindless_texture 1 Additions to Chapter 4 of the OpenGL ES 3.1 Language Specification, "Variables and Types" Add the following paragraph to the end of section 4.1.7.1, Samplers: The OpenGL ES API allows default block sampler uniforms to be assigned values referencing either a texture image unit number or a bindless texture handle, depending on the API function used. All other sampler variables must be assigned a texture handle. A layout qualifier specifies which of these is used in the program. Remove the bullet point "sampler types are not allowed" Section 4.3.7, Interface Blocks. Add the following paragraph to the end of section 4.4.5, "Opaque Uniform Layout Qualifiers": Sampler variables declared in uniform blocks may not be qualified with a binding, and a compile-time error will be generated if a shader specifies this. Insert a new section 4.4.5bindless, "Bindless Sampler Layout Qualifiers", after section 4.4.5, "Opaque Uniform Layout Qualifiers": Sampler types accept a uniform layout qualifier identifier controlling whether the uniform may be used with a bindless handle: layout-qualifier-id bindless_sampler bound_sampler These modifiers control whether default-block uniforms of the corresponding types may have their values set via both UniformHandle* and Uniform1i (bindless_sampler) or only via Uniform1i (bound_sampler). These layouts may be specified at global scope to control the default behavior of uniforms of the corresponding types, e.g. layout (bindless_sampler) uniform; They may also be specified on a uniform variable declaration of a corresponding type, e.g. layout (bindless_sampler) uniform sampler2D mySampler; If both bindless_sampler and bound_sampler are declared at global scope in any compilation unit, a link- time error will be generated. If these layout qualifiers are applied to other types of default block uniforms, a compile-time error will be generated. In the absence of these qualifiers, sampler uniforms are considered "bound". Additionally, if GL_IMG_bindless_texture is not enabled, these uniforms are considered "bound". Declaring a sampler in the uniform default-block with a binding point qualifier implicitly also declares it with "bound_sampler". Errors The error INVALID_OPERATION is generated by SamplerParameter* if identifies a sampler object referenced by one or more texture handles. The error INVALID_OPERATION is generated by TexParameter* if identifies a texture object referenced by one or more texture handles. The error INVALID_OPERATION is generated by {Program}UniformHandleui64{v}IMG if the sampler or image uniform being updated has the "bound_sampler" layout qualifier, or an explicit binding qualifier. [[ If EXT/OES_texture_buffer or OpenGL ES 3.2, and EXT_buffer_storage are supported ]] The error INVALID_OPERATION is generated by TexBuffer*EXT if identifies a texture object referenced by one or more texture handles. The error INVALID_OPERATION is generated by MapBuffer* if identifies a buffer object bound to a texture that is referenced by one or more texture handles, and access does not include MAP_PERSISTENT_BIT_EXT. Examples To loop through a collection of 256 textures in the OpenGL API using a conventional GLSL shader and without calling glBindTexture, one might do: #define NUM_TEXTURES 256 GLuint textures[NUM_TEXTURES]; GLuint64 texHandles[NUM_TEXTURES]; // Initialize the texture objects and handles. glGenTextures(NUM_TEXTURES, textures); for (int i = 0; i < NUM_TEXTURES; i++) { // Initialize the texture images with glTexStorage. // Initialize the texture parameters as required. // Get a handle for the texture. texHandles[i] = glGetTextureHandleIMG(textures[i]); // At this point, it's no longer possible to modify texture parameters // for "textures[i]". However, it's still possible to update texture // data via glTexSubImage. } // Compile GLSL shader using sampler uniform . The shader itself // needs no special #extension directive as long as is a uniform in // the default partition, and doesn't declare an explicit binding point. // Link the program, and query the location of , which we will store // in . // Render a little bit using each of the texture handles in turn. for (int i = 0; i < NUM_TEXTURES; i++) { // Update the single sampler uniform to point at "texHandles[i]". glUniformHandleui64IMG(location, texHandles[i]); drawStuff(); } The GLSL portion of this extension removes the restriction that sampler variables must be uniforms in the default block. You can store a large collection of samplers in a uniform block. To use a "dictionary" of samplers in a uniform block (in combination with either EXT_gpu_shader5, or OpenGL ES 3.2), you could use a shader like: #version 310 es #extension GL_IMG_bindless_texture : require #extension GL_EXT_gpu_shader5 : require #define NUM_TEXTURES 256 uniform int whichSampler; in highp vec2 texCoord; out lowp vec4 finalColor; uniform Samplers { sampler2D allTheSamplers[NUM_TEXTURES]; }; void main() { finalColor = texture(allTheSamplers[whichSampler], texCoord); } New State Add new table, Bindless Texture Handles Initial Get Value Type Get Command Value Description Sec. Attribute ------------ ---- -------------------- ------- ------------------------- ----------- ------- - Z64 GetTextureHandleIMG n/a texture handle 8.2bindless - or GetTextureSampler- HandleIMG - Z+ - n/a texture object used 8.2bindless - - Z+ - n/a sampler object used 8.2bindless - Issues See original issues in ARB_bindless_texture. (1) How does IMG_bindless_texture differ from ARB_bindless_texture? RESOLVED: - Bindless images are not supported. - Bindless samplers are only supported via uniforms/uniform buffers. - No constructors between opaque and integer types - No residency functions - This extension does not add dynamic indexing, as it is introduced by EXT/OES_shader_gpu5 (or OpenGL ES 3.2) - Only immutable textures and buffers (for buffer textures) are usable with bindless handles. - Texture uploads are considered asynchronous to usage, and must be manually synchronized with fences in order to avoid race conditions - For buffer texture objects, the only allowed buffer update mechanism is persistent mapping (2) Should texture uploads/copies still be allowed? RESOLVED: The original ARB_bindless_texture allows texture uploads, with the expectation that the commands are still serialized relative to surrounding draw calls. Such an implementation would prove difficult for a tile-based architecture; attempting to serialize resource updates between draw calls requires significant amounts of additional overhead. Without bindless, the driver is able to track resources to make it work as expected - which is impossible with bindless textures. So we've decided to remove this particular requirement, instead saying that texture uploads and copies occur asynchronously to other commands, and require explicit synchronisation, in order to be completed at predictable times. (2) Should buffer uploads/copies for buffer texture objects still be allowed? RESOLVED: Only persistent mapping is allowed. Revision History Rev. Date Author Changes ---- ---------- -------- ----------------------------------------- 1 2015-08-21 thector Initial revision 2 2015-08-24 thector Fixed references to "EXT_buffer_storage", added error for TexBuffer*EXT functions 3 2015-12-04 thector Texture data uploads are now entirely asynchronous 4 2016-05-23 thector Ensured that example in spec is actually compilable