| Name |
| |
| NV_memory_attachment |
| |
| Name Strings |
| |
| GL_NV_memory_attachment |
| |
| Contributors |
| |
| Carsten Rohde, NVIDIA |
| Christoph Kubisch, NVIDIA |
| James Jones, NVIDIA |
| |
| Contact |
| |
| Carsten Rohde, NVIDIA (crohde 'at' nvidia.com) |
| |
| Status |
| |
| Complete |
| |
| Version |
| |
| Last Modified Date: Aug 27, 2018 |
| Revision: 2 |
| |
| Number |
| |
| 524 |
| OpenGL ES Extension #305 |
| |
| Dependencies |
| |
| Requires GL_EXT_memory_object and ARB_texture_storage or a version of |
| OpenGL or OpenGL ES that incorporates it. |
| |
| Written against the OpenGL 4.6 and OpenGL ES 3.2 specifications. |
| |
| Interacts with ARB_direct_state_access (OpenGL) when OpenGL < 4.5 is used. |
| |
| Interacts with NV_shader_buffer_load. |
| |
| Interacts with NV_bindless_texture and ARB_bindless_texture. |
| |
| Overview |
| |
| This extension extends the memory objects introduced with EXT_memory_object |
| to allow existing textures and buffers to be migrated to an imported memory |
| allocation. The primary use-case of this extension is plug-in development |
| where resource management (creation, deletion, sizing etc.) is handled by |
| inaccessible host application code. |
| |
| New Procedures and Functions |
| |
| If the GL_NV_memory_attachment string is reported, the following |
| commands are added: |
| |
| void GetMemoryObjectDetachedResourcesuivNV(uint memory, |
| enum pname, |
| int first, |
| sizei count, |
| uint *params) |
| |
| void ResetMemoryObjectParameterNV(uint memory, |
| enum pname); |
| |
| void TexAttachMemoryNV(enum target, |
| uint memory, |
| uint64 offset); |
| |
| void BufferAttachMemoryNV(enum target, |
| uint memory, |
| uint64 offset); |
| |
| [[ The following are added if direct state access is supported ]] |
| |
| void TextureAttachMemoryNV(uint texture, |
| uint memory, |
| uint64 offset); |
| |
| void NamedBufferAttachMemoryNV(uint buffer, |
| uint memory, |
| uint64 offset); |
| |
| New Tokens |
| |
| If the GL_NV_memory_attachment string is reported, the following tokens |
| are added: |
| |
| Accepted by the <pname> parameter of TexParameter{ifx}{v}, |
| TexParameterI{i ui}v, TextureParameter{if}{v}, TextureParameterI{i ui}v, |
| GetTexParameter{if}v, GetTexParameterI{i ui}v, GetTextureParameter{if}v, |
| GetTextureParameterI{i ui}v, GetBufferParameter{i|i64}v and |
| GetNamedBufferParameter{i|i64}v: |
| |
| ATTACHED_MEMORY_OBJECT_NV 0x95A4 |
| ATTACHED_MEMORY_OFFSET_NV 0x95A5 |
| MEMORY_ATTACHABLE_ALIGNMENT_NV 0x95A6 |
| MEMORY_ATTACHABLE_SIZE_NV 0x95A7 |
| MEMORY_ATTACHABLE_NV 0x95A8 |
| |
| Accepted by the <pname> parameter of GetBooleanv, GetDoublev, GetFloatv, |
| GetIntegerv, GetInteger64v, GetUnsignedBytevEXT, |
| GetMemoryObjectParameterivEXT, and the <target> parameter of GetBooleani_v, |
| GetIntegeri_v,GetFloati_v, GetDoublei_v, GetInteger64i_v and |
| GetUnsignedBytei_vEXT: |
| |
| DETACHED_MEMORY_INCARNATION_NV 0x95A9 |
| |
| Accepted by the <pname> parameter of GetMemoryObjectParameterivEXT, |
| GetMemoryObjectDetachedResourcesuivNV and ResetMemoryObjectParameterNV: |
| |
| DETACHED_TEXTURES_NV 0x95AA |
| DETACHED_BUFFERS_NV 0x95AB |
| |
| Accepted by the <pname> parameter of MemoryObjectParameterivEXT, |
| GetMemoryObjectParameterivEXT: |
| |
| MAX_DETACHED_TEXTURES_NV 0x95AC |
| MAX_DETACHED_BUFFERS_NV 0x95AD |
| |
| |
| Additions to Chapter 6 of the EXT_external_objects Specification |
| (Memory Objects) |
| |
| Add a new sections after 6.2 (Memory object parameters) |
| |
| 6.3 Attaching memory to existing resources |
| |
| MEMORY_ATTACHABLE_NV should be used to query if it is valid to attach |
| a memory object to an existing resource (buffer or texture). The |
| memory region size and offset alignment required by a resource can be |
| queried using MEMORY_ATTACHABLE_SIZE_NV and |
| MEMORY_ATTACHABLE_ALIGNMENT_NV respectively. The current attached |
| memory object and the used offset for a resource can be queried by |
| ATTACHED_MEMORY_OBJECT_NV and ATTACHED_MEMORY_OFFSET_NV. |
| |
| If a resource which has memory attached is resized, the attached memory |
| will be detached and a new data store will be allocated. If a resource |
| which has memory attached is deleted, the attached memory will first be |
| detached. If any such detachment occurs, a global incarnation counter |
| will be increased and the current value will be stored in the detached |
| memory object. The incarnation counter can be queried by |
| DETACHED_MEMORY_INCARNATION_EXT either globally or for a specific |
| memory object. |
| |
| The command |
| |
| void GetMemoryObjectDetachedResourcesuivNV(uint memory, |
| enum pname, |
| int first, |
| sizei count, |
| uint *params) |
| |
| will return a list of detached buffers (if <pname> is |
| DETACHED_BUFFERS_NV) or textures (if <pname> is DETACHED_TEXTURES_NV) |
| in <params> for memory object <memory>. It will return <count> items |
| beginning with <first> item. The number of available items can be |
| queried by calling GetMemoryObjectParameterivEXT with <pname> set to |
| DETACHED_TEXTURES_NV or DETACHED_BUFFERS_NV. An INVALID_VALUE error is |
| generated by GetMemoryObjectDetachedResourcesuivNV if <memory> is 0. |
| An INVALID_OPERATION error is generated if <memory> names a valid |
| memory object which has no associated memory. An INVALID_VALUE error |
| is generated if <pname> is neither DETACHED_BUFFERS_NV nor |
| DETACHED_TEXTURES_NV. An INVALID_VALUE error is generated if |
| <first> + <count> is greater than the number of available items in the |
| list. An INVALID_VALUE error is generated if <params> is NULL. |
| MemoryObjectParameterivEXT must be called with <pname> set to |
| MAX_DETACHED_TEXTURES_NV or MAX_DETACHED_BUFFERS_NV before calling |
| GetMemoryObjectDetachedResourcesuivNV to set the maximum number of |
| items in the list of detached textures or buffers. The default values |
| are 0 which means that tracking of detached textures and buffers is |
| disabled by default. |
| |
| The command |
| |
| void ResetMemoryObjectParameterNV(uint memory, |
| enum pname); |
| |
| will reset the list of detached buffers (if <pname> is |
| DETACHED_BUFFERS_NV) or textures (if <pname> is DETACHED_TEXTURES_NV) |
| for memory object <memory>. An INVALID_VALUE error is generated by |
| ResetMemoryObjectParameterNV if <memory> is 0. An INVALID_OPERATION |
| error is generated if <memory> names a valid memory object which has |
| no associated memory. An INVALID_VALUE error is generated if <pname> |
| is neither DETACHED_BUFFERS_NV nor DETACHED_TEXTURES_NV. |
| |
| |
| Additions to Chapter 6 of the OpenGL 4.6 Specification (Buffer Objects) |
| |
| Add a new section after 6.2.1 (Clearing Buffer Object Data Stores) |
| |
| 6.2.2 Attaching a memory object to a buffer object |
| |
| The commands |
| |
| void BufferAttachMemoryNV(enum target, |
| uint memory, |
| uint64 offset); |
| |
| void NamedBufferAttachMemoryNV(uint buffer, |
| uint memory, |
| uint64 offset); |
| |
| will attach a region of a memory object to a buffer object. For |
| BufferAttachMemoryNV, the buffer object is that bound to <target>, |
| which must be one of the values listed in table 6.1. For |
| NamedBufferAttachMemoryNV, <buffer> is the name of the buffer |
| object. <memory> and <offset> define a region of memory that will |
| replace the data store for <buffer>. The content of the original data |
| store will be preserved by a server side copy and the original data |
| store will be deleted after that copy. The implementation may restrict |
| which values of <offset> are valid for a given memory object and buffer |
| parameter combination. These restrictions are outside the scope of |
| this extension and must be determined by querying the API or mechanism |
| which created the resource which <memory> refers to. If an invalid |
| offset is specified an INVALID_VALUE error is generated. An |
| INVALID_VALUE error is generated by BufferAttachMemoryNV and |
| NamedBufferAttachMemoryNV if <memory> is 0. An INVALID_OPERATION error |
| is generated if <memory> names a valid memory object which has no |
| associated memory. An INVALID_OPERATION error is generated if the |
| specified buffer was created with MAP_PERSISTENT_BIT flag. An |
| INVALID_OPERATION error is generated if the specified buffer is |
| currently mapped by client. |
| |
| Additions to Chapter 8 of the OpenGL 4.6 Specification (Textures and |
| Samplers) |
| |
| Add a new section between sections 8.19, "Immutable-Format Texture Images" |
| and section 8.20, "Invalidating Texture Image Data" |
| |
| 8.20 Attaching a memory object to a texture image |
| |
| The commands |
| |
| void TexAttachMemoryNV(enum target, |
| uint memory, |
| uint64 offset); |
| |
| void TextureAttachMemoryNV(uint texture, |
| uint memory, |
| uint64 offset); |
| |
| will attach a region of a memory object to a texture. For |
| TexAttachMemoryNV, the texture is that bound to <target>, which must be |
| one of TEXTURE_1D, TEXTURE_2D, TEXTURE_3D, TEXTURE_1D_ARRAY, |
| TEXTURE_2D_ARRAY, TEXTURE_RECTANGLE, TEXTURE_CUBE_MAP, |
| TEXTURE_CUBE_MAP_ARRAY, TEXTURE_2D_MULTISAMPLE, or |
| TEXTURE_2D_MULTISAMPLE_ARRAY. For TextureAttachMemoryNV, <texture> is |
| the name of the texture. <memory> and <offset> define a region of |
| memory that will replace the data store for <texture>. The content of |
| the original data store will be preserved by a server side copy and the |
| original data store will be deleted after that copy. The |
| implementation may restrict which values of <offset> are valid for a |
| given memory object and texture parameter combination. These |
| restrictions are outside the scope of this extension and must be |
| determined by querying the API or mechanism which created the resource |
| which <memory> refers to. If an invalid offset is specified an |
| INVALID_VALUE error is generated. An INVALID_VALUE error is generated |
| by TexAttachMemoryNV and TextureAttachMemoryNV if <memory> is 0. An |
| INVALID_OPERATION error is generated if <memory> names a valid memory |
| object which has no associated memory. |
| |
| Errors |
| |
| New State |
| |
| Sample |
| |
| // host: code not visible to the plug-in developer |
| // plug-in: code written by plug-in developer |
| |
| uint tex0; |
| uint tex1; |
| |
| // host |
| { |
| // sets up textures as usual |
| } |
| |
| // plug-in |
| { |
| int attachable0; |
| int attachable1; |
| GetTextureParameteriv(tex0, MEMORY_ATTACHABLE_NV, &attachable0); |
| GetTextureParameteriv(tex1, MEMORY_ATTACHABLE_NV, &attachable1); |
| |
| if (attachable0 && attachable1){ |
| |
| // allocate memory within vulkan and import it as specified in |
| // EXT_memory_object |
| |
| // attach imported vulkan memory |
| TextureAttachMemoryNV(tex0, memobj, memoffset0); |
| |
| // ... do same for tex1 |
| TextureAttachMemoryNV(tex1, memobj, memoffset1); |
| } |
| } |
| |
| /////////////////////////////// |
| // Querying mutations by host |
| |
| int incarnationExpected; |
| |
| // plug-in |
| { |
| // global query |
| GetIntegerv(DETACHED_MEMORY_INCARNATION_NV, &incarnationExpected); |
| |
| // if we have multiple memory objects |
| for each memobj { |
| GetMemoryObjectParameterivEXT(memobj.id, |
| DETACHED_MEMORY_INCARNATION_NV, |
| &memobj.incarnation); |
| GLint maxDetachedTextures = 64; |
| MemoryObjectParameterivEXT(memobj.id, |
| MAX_DETACHED_TEXTURES_NV, |
| &maxDetachedTextures); |
| } |
| } |
| |
| // host |
| { |
| // deletion triggers a detach |
| glDeleteTextures(1, &tex1); |
| } |
| |
| // plug-in |
| { |
| // global query if resources of context were affected |
| int incarnation; |
| GetIntegerv(DETACHED_MEMORY_INCARNATION_NV, &incarnation); |
| |
| if (incarnation != incarnationExpected) { |
| incarnationExpected = incarnation; |
| |
| // narrow down search which memory object was affected |
| for each memobj { |
| GetMemoryObjectParameterivEXT(memobj.id, |
| DETACHED_MEMORY_INCARNATION_NV, |
| &incarnation); |
| |
| if (incarnation != memobj.incarnation) { |
| memobj.incarnation = incarnation; |
| |
| int removedTexCount; |
| GetMemoryObjectParameterivEXT(memobj.id, |
| DETACHED_TEXTURES_NV, |
| &removedTexCount); |
| |
| std::vector<uint> removedTexs(removedTexCount); |
| |
| GetMemoryObjectDetachedResourcesuivNV( |
| memobj.id, |
| DETACHED_TEXTURES_NV, |
| 0, removedTexCount, |
| removedTexs.data()); |
| |
| for (int i = 0; i < removedTexCount; i++) { |
| uint tex = removedTexs[i]; |
| // look up tex in custom allocator and |
| // mark its memory as available again |
| } |
| |
| ResetMemoryObjectParameter(memobj.id, |
| DETACHED_TEXTURES_NV); |
| } |
| } |
| } |
| } |
| |
| Issues |
| |
| 1) Do we need to introduce allocation done within OpenGL |
| or is attaching existing resources to imported allocation |
| sufficient? |
| |
| RESOLVED: No. No need to duplicate work which has already been done |
| in Vulkan. |
| |
| 2) Should binding memory only work on immutable resources? |
| |
| RESOLVED: No. To improve compatibility with existing GL resources, |
| allow mutable resources as well. A global and local incarnation counter |
| was introduced to test against changes, as well as detecting the |
| detached resources. |
| |
| 3) Do we support client-mappable resources? |
| |
| RESOLVED: Yes. Client-mappable resources are supported but not |
| when they are persistent. When memory is attached resource must be |
| unmapped. |
| |
| 4) What are the affects on TextureViews? |
| |
| RESOLVED: TextureViews inherit the memory state. |
| |
| 5) Do bindless resources change? |
| |
| RESOLVED: Yes. The existing handles and GPU addresses become invalid |
| when memory is attached and must be queried afterwards. |
| |
| 6) Should we support resources that were migrated to host memory by driver? |
| |
| RESOLVED: Yes, but the attached memory is independ from this state. |
| |
| 7) Do we need an "attachable" per-resource state? |
| |
| RESOLVED: Yes. |
| |
| 8) How is bindless residency affected? |
| |
| RESOLVED: A memory object becomes resident if at least one attached |
| resource is resident. |
| |
| |
| Revision History |
| |
| Revision 2, 2018-08-20 (Carsten Rohde, Christoph Kubisch) |
| - Added spec body describing new commands. |
| - Added non-DSA functions |
| - Resolve issues |
| |
| Revision 1, 2018-05-07 (Carsten Rohde, Christoph Kubisch) |
| - Initial draft. |