| 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 <count> 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 <texture>, including any embedded sampler state. |
| GetTextureSamplerHandleIMG will create a texture handle using the current |
| non-sampler state from the texture named <texture> and the sampler state |
| from the sampler object <sampler>. 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 <texture> is zero or is not the |
| name of an existing texture object or if <sampler> 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 <texture>'s |
| TEXTURE_IMMUTABLE_FORMAT is FALSE (section 8.17), or if <texture> 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 <texture>'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 <sampler> 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 : <behavior> |
| |
| where <behavior> 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 <sampler> |
| identifies a sampler object referenced by one or more texture handles. |
| |
| The error INVALID_OPERATION is generated by TexParameter* if <target> |
| 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 <target> |
| identifies a texture object referenced by one or more texture handles. |
| |
| The error INVALID_OPERATION is generated by MapBuffer* if <target> |
| 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 <u>. The shader itself |
| // needs no special #extension directive as long as <u> is a uniform in |
| // the default partition, and doesn't declare an explicit binding point. |
| // Link the program, and query the location of <u>, which we will store |
| // in <location>. |
| |
| // 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 <u> 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 |