| Name | 
 |  | 
 |     EXT_external_objects | 
 |  | 
 | Name Strings | 
 |  | 
 |     GL_EXT_memory_object | 
 |     GL_EXT_semaphore | 
 |  | 
 | Contributors | 
 |  | 
 |     Carsten Rohde, NVIDIA | 
 |     Dave Airlie, Red Hat | 
 |     James Jones, NVIDIA | 
 |     Jan-Harald Fredriksen, ARM | 
 |     Jeff Juliano, NVIDIA | 
 |     Michael Worcester, Imagination Technologies | 
 |  | 
 | Contact | 
 |  | 
 |     James Jones, NVIDIA (jajones 'at' nvidia.com) | 
 |  | 
 | Status | 
 |  | 
 |     Complete | 
 |  | 
 | Version | 
 |  | 
 |     Last Modified Date: June 28, 2017 | 
 |     Revision: 12 | 
 |  | 
 | Number | 
 |  | 
 |     503 | 
 |     OpenGL ES Extension #280 | 
 |  | 
 | Dependencies | 
 |  | 
 |     Written against the OpenGL 4.5 and OpenGL ES 3.2 specifications. | 
 |  | 
 |     GL_EXT_memory_object requires ARB_texture_storage or a version of | 
 |     OpenGL or OpenGL ES that incorporates it. | 
 |  | 
 |     GL_EXT_semaphore requires OpenGL 1.0. | 
 |  | 
 |     ARB_direct_state_access (OpenGL) interacts with GL_EXT_memory_object | 
 |     when OpenGL < 4.5 is used. | 
 |  | 
 |     ARB_sparse_texture (OpenGL) interacts with GL_EXT_memory_object | 
 |  | 
 |     EXT_sparse_texture (OpenGL ES) interacts with GL_EXT_memory_object | 
 |  | 
 |     EXT_protected_textures (OpenGL ES) interacts with GL_EXT_memory_object | 
 |  | 
 | Overview | 
 |  | 
 |     The Vulkan API introduces the concept of explicit memory objects and | 
 |     reusable synchronization objects.  This extension brings those | 
 |     concepts to the OpenGL API via two new object types: | 
 |  | 
 |        Memory objects | 
 |        Semaphores | 
 |  | 
 |     Rather than allocating memory as a response to object allocation, | 
 |     memory allocation and binding are two separate operations in Vulkan. | 
 |     This extension allows an OpenGL application to import a Vulkan | 
 |     memory object, and to bind textures and/or buffer objects to it. | 
 |  | 
 |     No methods to import memory objects are defined here.  Separate | 
 |     platform-specific extensions are defined for this purpose. | 
 |  | 
 |     Semaphores are synchronization primitives that can be waited on and | 
 |     signaled only by the GPU, or in GL terms, in the GL server.  They | 
 |     are similar in concept to GL's "sync" objects and EGL's "EGLSync" | 
 |     objects, but different enough that compatibilities between the two | 
 |     are difficult to derive. | 
 |  | 
 |     Rather than attempt to map Vulkan semaphores on to GL/EGL sync | 
 |     objects to achieve interoperability, this extension introduces a new | 
 |     object, GL semaphores, that map directly to the semantics of Vulkan | 
 |     semaphores.  To achieve full image and buffer memory coherence with | 
 |     a Vulkan driver, the commands that manipulate semaphores also allow | 
 |     external usage information to be imported and exported. | 
 |  | 
 | New Procedures and Functions | 
 |  | 
 |     The following commands are added if either of the GL_EXT_memory_object | 
 |     or GL_EXT_semaphore strings are reported: | 
 |  | 
 |         void GetUnsignedBytevEXT(enum pname, | 
 |                                  ubyte *data); | 
 |  | 
 |         void GetUnsignedBytei_vEXT(enum target, | 
 |                                    uint index, | 
 |                                    ubyte *data); | 
 |  | 
 |     If the GL_EXT_memory_object string is reported, the following | 
 |     commands are added: | 
 |  | 
 |         void DeleteMemoryObjectsEXT(sizei n, | 
 |                                     const uint *memoryObjects); | 
 |  | 
 |         boolean IsMemoryObjectEXT(uint memoryObject); | 
 |  | 
 |         void CreateMemoryObjectsEXT(sizei n, | 
 |                                     uint *memoryObjects); | 
 |  | 
 |         void MemoryObjectParameterivEXT(uint memoryObject, | 
 |                                         enum pname, | 
 |                                         const int *params); | 
 |  | 
 |         void GetMemoryObjectParameterivEXT(uint memoryObject | 
 |                                            enum pname, | 
 |                                            int *params); | 
 |  | 
 |         void TexStorageMem2DEXT(enum target, | 
 |                                 sizei levels, | 
 |                                 enum internalFormat, | 
 |                                 sizei width, | 
 |                                 sizei height, | 
 |                                 uint memory, | 
 |                                 uint64 offset); | 
 |  | 
 |         void TexStorageMem2DMultisampleEXT(enum target, | 
 |                                            sizei samples, | 
 |                                            enum internalFormat, | 
 |                                            sizei width, | 
 |                                            sizei height, | 
 |                                            boolean fixedSampleLocations, | 
 |                                            uint memory, | 
 |                                            uint64 offset); | 
 |  | 
 |         void TexStorageMem3DEXT(enum target, | 
 |                                 sizei levels, | 
 |                                 enum internalFormat, | 
 |                                 sizei width, | 
 |                                 sizei height, | 
 |                                 sizei depth, | 
 |                                 uint memory, | 
 |                                 uint64 offset); | 
 |  | 
 |         void TexStorageMem3DMultisampleEXT(enum target, | 
 |                                            sizei samples, | 
 |                                            enum internalFormat, | 
 |                                            sizei width, | 
 |                                            sizei height, | 
 |                                            sizei depth, | 
 |                                            boolean fixedSampleLocations, | 
 |                                            uint memory, | 
 |                                            uint64 offset); | 
 |  | 
 |         void BufferStorageMemEXT(enum target, | 
 |                                  sizeiptr size, | 
 |                                  uint memory, | 
 |                                  uint64 offset); | 
 |  | 
 |         [[ The following are added if direct state access is supported ]] | 
 |  | 
 |         void TextureStorageMem2DEXT(uint texture, | 
 |                                     sizei levels, | 
 |                                     enum internalFormat, | 
 |                                     sizei width, | 
 |                                     sizei height, | 
 |                                     uint memory, | 
 |                                     uint64 offset); | 
 |  | 
 |         void TextureStorageMem2DMultisampleEXT(uint texture, | 
 |                                                sizei samples, | 
 |                                                enum internalFormat, | 
 |                                                sizei width, | 
 |                                                sizei height, | 
 |                                                boolean fixedSampleLocations, | 
 |                                                uint memory, | 
 |                                                uint64 offset); | 
 |  | 
 |         void TextureStorageMem3DEXT(uint texture, | 
 |                                     sizei levels, | 
 |                                     enum internalFormat, | 
 |                                     sizei width, | 
 |                                     sizei height, | 
 |                                     sizei depth, | 
 |                                     uint memory, | 
 |                                     uint64 offset); | 
 |  | 
 |         void TextureStorageMem3DMultisampleEXT(uint texture, | 
 |                                                sizei samples, | 
 |                                                enum internalFormat, | 
 |                                                sizei width, | 
 |                                                sizei height, | 
 |                                                sizei depth, | 
 |                                                boolean fixedSampleLocations, | 
 |                                                uint memory, | 
 |                                                uint64 offset); | 
 |  | 
 |         void NamedBufferStorageMemEXT(uint buffer, | 
 |                                       sizeiptr size, | 
 |                                       uint memory, | 
 |                                       uint64 offset); | 
 |  | 
 |         [[ The following are available in OpenGL only ]] | 
 |  | 
 |         void TexStorageMem1DEXT(enum target, | 
 |                                 sizei levels, | 
 |                                 enum internalFormat, | 
 |                                 sizei width, | 
 |                                 uint memory, | 
 |                                 uint64 offset); | 
 |  | 
 |         [[ The following are availble in OpenGL only, and only when | 
 |            direct state access is available ]] | 
 |  | 
 |         void TextureStorageMem1DEXT(uint texture, | 
 |                                     sizei levels, | 
 |                                     enum internalFormat, | 
 |                                     sizei width, | 
 |                                     uint memory, | 
 |                                     uint64 offset); | 
 |  | 
 |     If the GL_EXT_semaphore string is reported, the following | 
 |     commands are added: | 
 |  | 
 |         void GenSemaphoresEXT(sizei n, | 
 |                               uint *semaphores); | 
 |  | 
 |         void DeleteSemaphoresEXT(sizei n, | 
 |                                  const uint *semaphores); | 
 |  | 
 |         boolean IsSemaphoreEXT(uint semaphore); | 
 |  | 
 |         void SemaphoreParameterui64vEXT(uint semaphore, | 
 |                                         enum pname, | 
 |                                         const uint64 *params); | 
 |  | 
 |         void GetSemaphoreParameterui64vEXT(uint semaphore, | 
 |                                            enum pname, | 
 |                                            uint64 *params); | 
 |  | 
 |         void WaitSemaphoreEXT(uint semaphore, | 
 |                               uint numBufferBarriers, | 
 |                               const uint *buffers, | 
 |                               uint numTextureBarriers, | 
 |                               const uint *textures, | 
 |                               const GLenum *srcLayouts); | 
 |  | 
 |         void SignalSemaphoreEXT(uint semaphore, | 
 |                                 uint numBufferBarriers, | 
 |                                 const uint *buffers, | 
 |                                 uint numTextureBarriers, | 
 |                                 const uint *textures, | 
 |                                 const GLenum *dstLayouts); | 
 |  | 
 | New Tokens | 
 |  | 
 |     If the GL_EXT_memory_object 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, | 
 |     and GetTextureParameterI{i ui}v: | 
 |  | 
 |         TEXTURE_TILING_EXT                         0x9580 | 
 |  | 
 |     Accepted by the <pname> parameter of MemoryObjectParameterivEXT, and | 
 |     GetMemoryObjectParameterivEXT: | 
 |  | 
 |         DEDICATED_MEMORY_OBJECT_EXT                0x9581 | 
 |  | 
 |         [[ The following are available when GL_EXT_protected_textures is | 
 |            available ]] | 
 |  | 
 | 	PROTECTED_MEMORY_OBJECT_EXT                0x959B | 
 |  | 
 |     Accepted by the <pname> parameter of GetInternalFormativ or | 
 |     GetInternalFormati64v: | 
 |  | 
 |         NUM_TILING_TYPES_EXT                       0x9582 | 
 |         TILING_TYPES_EXT                           0x9583 | 
 |  | 
 |     Returned in the <params> parameter of GetInternalFormativ or | 
 |     GetInternalFormati64v when the <pname> parameter is TILING_TYPES_EXT, | 
 |     returned in the <params> parameter of GetTexParameter{if}v, | 
 |     GetTexParameterI{i ui}v, GetTextureParameter{if}v, and | 
 |     GetTextureParameterI{i ui}v when the <pname> parameter is | 
 |     TEXTURE_TILING_EXT, and accepted by the <params> parameter of | 
 |     TexParameter{ifx}{v}, TexParameterI{i ui}v, TextureParameter{if}{v}, | 
 |     TextureParameterI{i ui}v when the <pname> parameter is | 
 |     TEXTURE_TILING_EXT: | 
 |  | 
 |         OPTIMAL_TILING_EXT                         0x9584 | 
 |         LINEAR_TILING_EXT                          0x9585 | 
 |  | 
 |     The following tokens are added if either of the GL_EXT_memory_object or | 
 |     GL_EXT_semaphore strings are reported: | 
 |  | 
 |     Accepted by the <pname> parameter of GetBooleanv, GetDoublev, GetFloatv, | 
 |     GetIntegerv, GetInteger64v, GetUnsignedBytevEXT, and the <target> | 
 |     parameter of GetBooleani_v, GetIntegeri_v,GetFloati_v, GetDoublei_v, | 
 |     GetInteger64i_v, and GetUnsignedBytei_vEXT: | 
 |  | 
 |         NUM_DEVICE_UUIDS_EXT                       0x9596 | 
 |         DEVICE_UUID_EXT                            0x9597 | 
 |         DRIVER_UUID_EXT                            0x9598 | 
 |  | 
 |     Constant values: | 
 |  | 
 |         UUID_SIZE_EXT                              16 | 
 |  | 
 |     If the GL_EXT_semaphore string is reported, the following tokens are | 
 |     added: | 
 |  | 
 |     Accepted by the <dstLayouts> parameter of SignalSemaphoreEXT and the | 
 |     <srcLayouts> parameter of WaitSemaphoreEXT: | 
 |  | 
 |         LAYOUT_GENERAL_EXT                         0x958D | 
 |         LAYOUT_COLOR_ATTACHMENT_EXT                0x958E | 
 |         LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT        0x958F | 
 |         LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT         0x9590 | 
 |         LAYOUT_SHADER_READ_ONLY_EXT                0x9591 | 
 |         LAYOUT_TRANSFER_SRC_EXT                    0x9592 | 
 |         LAYOUT_TRANSFER_DST_EXT                    0x9593 | 
 |  | 
 | Additions to Chapter 2 of the OpenGL 4.5 Specification (OpenGL | 
 | Fundamentals) | 
 |  | 
 |     Add two new sections after 2.6.13 (Sync Objects) | 
 |  | 
 |         2.6.14 Semaphore Objects | 
 |  | 
 |         A /semaphore object/ is a synchronization primitive similar to a | 
 |         /sync object/, but with semantics based on Vulkan semaphores. | 
 |  | 
 |         Semaphore objects may be shared.  They are described in detail in | 
 |         section XXX. | 
 |  | 
 |         2.6.15 Memory Objects | 
 |  | 
 |         Many GL objects have some associated data stored in GL server | 
 |         memory.  /Memory objects/ are an abstract representation of GL | 
 |         server memory suitable for use as the backing store of a | 
 |         /buffer object/, a /texture object/, or both, depending on how | 
 |         the memory referred to by the object was allocated.  Memory | 
 |         objects can not be created directly within the GL.  They must be | 
 |         imported from an API capable of allocating abstract memory, such | 
 |         as Vulkan. | 
 |  | 
 |         Memory objects may be shared.  They are described in detail in | 
 |         Chapter 6 (Memory Objects). | 
 |  | 
 | Additions to Chapter 4 of the OpenGL 4.5 Specification (Event Model) | 
 |  | 
 |     Add a new section between sections 4.1, "Sync Objects and Fences" | 
 |     and section 4.2, "Query Objects and Asynchronous Queries" | 
 |  | 
 |         4.2 Semaphore Objects | 
 |  | 
 |         Like sync objects, a semaphore object acts as a /synchronization | 
 |         primitive/.  However, semaphore objects differ from sync objects | 
 |         in several ways: | 
 |  | 
 |         * They may only be created by importing an external semaphore | 
 |           handle into the GL. | 
 |  | 
 |         * They are reusable. | 
 |  | 
 |         * As a corollary to the above behavior, separate commands are | 
 |           provided to create and signal semaphore objects. | 
 |  | 
 |         * Their state is reset upon completion of a wait operation. | 
 |  | 
 |         * As a corollary to the above behavior, only a single waiter may | 
 |           be associated with a unique signal command. | 
 |  | 
 |         * There is no way to wait for a semaphore to become signaled in | 
 |           the GL client.  All waits operations execute in the GL server, | 
 |           and semaphores have no queryable state. | 
 |  | 
 |         The command | 
 |  | 
 |             void GenSemaphoresEXT(sizei n, | 
 |                                   uint *semaphores); | 
 |  | 
 |         returns <n> previous unused semaphore names in <semaphores>. | 
 |         These names are marked as used, for the purposes of | 
 |         GenSemaphoresEXT only, but they are associated with semaphore | 
 |         state only when an external semaphore handle is imported to | 
 |         them. | 
 |  | 
 |         Semaphore objects are deleted by calling | 
 |  | 
 |             void DeleteSemaphoresEXT(sizei n, | 
 |                                      const uint *semaphores); | 
 |  | 
 |         <semaphores> contains <n> names of semaphores to be deleted. | 
 |         After a semaphore is deleted, it unreferences any external | 
 |         semaphore state it referenced, and its name is again unused. | 
 |         Unused names in <semaphores> are silently ignored, as is the | 
 |         value zero. | 
 |  | 
 |         The command | 
 |  | 
 |             boolean IsSemaphoreEXT(uint semaphore); | 
 |  | 
 |         returns TRUE if <semaphore> is the name of a semaphore.  If | 
 |         <semaphore> is zero, or if <semaphore> is a non-zero value that | 
 |         is not the name of a semaphore, IsSemaphore returns FALSE. | 
 |  | 
 |         4.2.1 Importing External Semaphore Handles into Semaphores | 
 |  | 
 |         A semaphore is created by importing an external semaphore object | 
 |         via a reference to its associated external handle.  The | 
 |         supported set of external handle types and associated import | 
 |         functions are listed in table 4.2. | 
 |  | 
 |         Table 4.2: Commands for importing external semaphore handles. | 
 |  | 
 |         | Handle Type | Import command | | 
 |         +-------------+----------------+ | 
 |         +-------------+----------------+ | 
 |  | 
 |         Applications must only import external semaphore handles exported | 
 |         from the same device or set of devices used by the current context, | 
 |         and from compatible driver versions.  To determine which devices are | 
 |         used by the current context, first call GetIntegerv with <pname> set | 
 |         to NUM_DEVICE_UUIDS_EXT, then call GetUnsignedBytei_vEXT with <target> | 
 |         set to DEVICE_UUID_EXT, <index> set to a value in the range [0, | 
 |         <number of device UUIDs>), and <data> set to point to an array of | 
 |         UUID_SIZE_EXT unsigned bytes.  To determine the driver ID of the | 
 |         current context, call GetUnsignedBytevEXT with <pname> set to | 
 |         DRIVER_UUID_EXT and <data> set to point to an array of UUID_SIZE_EXT | 
 |         unsigned bytes. | 
 |  | 
 |         These device and driver ID values can be used to correlate devices | 
 |         and determine driver compatibility across process and API boundaries. | 
 |  | 
 |         External handles are often defined using platform-specific | 
 |         types.  Therefore, the base GL specification defines no methods | 
 |         to import an external handle. | 
 |  | 
 |         4.2.2 Semaphore Parameters | 
 |  | 
 |         Semaphore parameters control how semaphore wait and signal | 
 |         operations behave.  Table 4.3 defines which parameters are available | 
 |         for a semaphore based on the external handle type from which it was | 
 |         imported.  Semaphore parameters are set using the command | 
 |  | 
 |             void SemaphoreParameterui64vEXT(uint semaphore, | 
 |                                             enum pname, | 
 |                                             const uint64 *params); | 
 |  | 
 |         <semaphore> is the name of the semaphore object on which the | 
 |         parameter <pname> will be set to the value(s) in <pname>. | 
 |  | 
 |         Table 4.3: Semaphore parameters | 
 |  | 
 |         | Name | External Handle Types | Legal Values | | 
 |         +------+-----------------------+--------------+ | 
 |         +------+-----------------------+--------------+ | 
 |  | 
 |         Parameters of a semaphore object may be queried with the command | 
 |  | 
 |             void GetSemaphoreParameterui64EXT(uint semaphore, | 
 |                                               enum pname, | 
 |                                               uint64 *params); | 
 |  | 
 |         <semaphore> is the semaphore object from with the parameter <pname> | 
 |         is queried.  The value(s) of the parameter are returned in <params>. | 
 |         <pname> may be any value in table 4.3. | 
 |  | 
 |         4.2.3 Waiting for Semaphores | 
 |  | 
 |         The command | 
 |  | 
 |             void WaitSemaphoreEXT(uint semaphore, | 
 |                                   uint numBufferBarriers, | 
 |                                   const uint *buffers, | 
 |                                   uint numTextureBarriers, | 
 |                                   const uint *textures, | 
 |                                   const GLenum *srcLayouts); | 
 |  | 
 |         Returns immediately but causes GL server to block until | 
 |         <semaphore> is signaled.  If an error occurs, WaitSemaphore | 
 |         generates a GL error as specified below, and does not cause the | 
 |         GL server to block. | 
 |  | 
 |         After completion of the semaphore wait operation, the semaphore | 
 |         will be returned to the unsignaled state.  Calling WaitSemaphore on | 
 |         a semaphore that has not previously had a signal operation flushed | 
 |         to the GL server or submitted by an external semaphore signaler | 
 |         since the semaphore was created or last waited on results in | 
 |         undefined behavior. | 
 |  | 
 |         Following completion of the semaphore wait operation, memory will | 
 |         also be made visible in the specified buffer and texture objects. | 
 |         Since texture layout state is managed internally by the GL, but may | 
 |         have been modified by an external API, the current layout of the | 
 |         textures must be specified to initialize internal GL state prior to | 
 |         using the textures after an external access.  The valid layouts | 
 |         correspond to those specified by the Vulkan API, as described in | 
 |         table 4.3.  However, the layouts do not necessarily correspond to an | 
 |         optimal state for any particular GL operation.  The GL will simply | 
 |         perform appropriate transitions internally as necessary based on the | 
 |         specified current layout of the texture. | 
 |  | 
 |         Table 4.4: Texture layouts and corresponding Vulkan Image Layouts | 
 |  | 
 |         | Texture Layout                         | Equivalent Vulkan Image Layout                  | | 
 |         +----------------------------------------+-------------------------------------------------+ | 
 |         | GL_NONE                                | VK_IMAGE_LAYOUT_UNDEFINED                       | | 
 |         | GL_LAYOUT_GENERAL_EXT                  | VK_IMAGE_LAYOUT_GENERAL                         | | 
 |         | GL_LAYOUT_COLOR_ATTACHMENT_EXT         | VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        | | 
 |         | GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT | VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT        | | 
 |         | GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT  | VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL | | 
 |         | GL_LAYOUT_SHADER_READ_ONLY_EXT         | VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL        | | 
 |         | GL_LAYOUT_TRANSFER_SRC_EXT             | VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL            | | 
 |         | GL_LAYOUT_TRANSFER_DST_EXT             | VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL            | | 
 |         +------------------------------------------------------------------------------------------+ | 
 |  | 
 |         4.2.4 Signaling Semaphores | 
 |  | 
 |         The command | 
 |  | 
 |             void SignalSemaphoreEXT(uint semaphore, | 
 |                                     uint numBufferBarriers, | 
 |                                     const uint *buffers, | 
 |                                     uint numTextureBarriers, | 
 |                                     const uint *textures, | 
 |                                     const GLenum *dstLayouts); | 
 |  | 
 |         will insert a semaphore signaling operation in the GL command | 
 |         stream. | 
 |  | 
 |         Prior to signaling the semaphore, memory used by the specified | 
 |         buffer objects and textures will be made visible, and textures | 
 |         can be transitioned to a specified internal layout to allow | 
 |         applications to access the textures using a consistent layout in | 
 |         an external API or process.  Possible layouts are specified in | 
 |         table 4.3, along with their corresponding layout in the Vulkan | 
 |         API. | 
 |  | 
 | Add a new Chapter, "Memory Objects", between Chapter 5 (Shared Objects | 
 | and Multiple Contexts) and Chapter 6 (Buffer Objects) | 
 |  | 
 |     Memory objects reference a fixed-size allocation of abstract server | 
 |     memory.  The memory may not be accessed directly, but may be bound | 
 |     to other objects that require a data store in server memory.  The | 
 |     memory itself is allocated outside the scope of the GL, and is | 
 |     merely referenced by a memory object. | 
 |  | 
 |     The command | 
 |  | 
 |        void CreateMemoryObjectsEXT(sizei n, uint *memoryObjects); | 
 |  | 
 |     returns <n> previously unused memory object names in <memoryObjects>. | 
 |     The memory objects named contain default state, but initially have no | 
 |     external memory associated with them. | 
 |  | 
 |     Memory objects are deleted by calling | 
 |  | 
 |         void DeleteMemoryObjectsEXT(sizei n, const uint *memoryObjects); | 
 |  | 
 |     <memoryObjects> contains <n> names of memory objects to be deleted. | 
 |     After a memory object is deleted, it references no server memory, | 
 |     and its name is again unused. | 
 |  | 
 |     Unused names in <memoryObjects> are silently ignored, as is the | 
 |     value zero. | 
 |  | 
 |     The command | 
 |  | 
 |         boolean IsMemoryObjectEXT(uint memoryObject); | 
 |  | 
 |     returns TRUE if <memoryObject> is the name of a memory object.  If | 
 |     <memoryObject> is zero, or if <memoryObject> is a non-zero value | 
 |     that is not the name of a memory object, IsMemoryObjectEXT returns | 
 |     FALSE. | 
 |  | 
 |     6.1 Importing Abstract Memory into a Memory Object | 
 |  | 
 |     A memory object is associated with external memory by importing an | 
 |     externally-allocated abstract memory region via a reference to an | 
 |     associated external handle.  The supported set of external handle types | 
 |     and their corresponding import functions are listed in table 6.1. | 
 |  | 
 |         Table 6.1: Commands for importing external memory handles. | 
 |  | 
 |         | Handle Type | Import command | | 
 |         +-------------+----------------+ | 
 |         +-------------+----------------+ | 
 |  | 
 |     Applications must only import external semaphore handles exported | 
 |     from the same device or set of devices used by the current context. | 
 |     Refer to section 4.2.1 for methods to determine which devices are | 
 |     used by the current context. | 
 |  | 
 |     External handles are often defined using platform-specific types. | 
 |     Therefore, the base GL specification defines no methods to import an | 
 |     external handle. | 
 |  | 
 |     6.2 Memory object parameters | 
 |  | 
 |     Memory object parameters are set using the command | 
 |  | 
 |         void MemoryObjectParameterivEXT(uint memoryObject, | 
 |                                         enum pname, | 
 |                                         const int *params); | 
 |  | 
 |     <memoryObject> is the name of the memory object on which the parameter | 
 |     <pname> will be set to the value(s) in <params>.  The possible values for | 
 |     <pname> are specified in table 6.2. | 
 |  | 
 |         Table 6.2: Memory Object Parameters. | 
 |  | 
 |         | Name                        | Legal Values | | 
 |         +-----------------------------+--------------+ | 
 |         | DEDICATED_MEMORY_OBJECT_EXT | FALSE, TRUE  | | 
 |         | PROTECTED_MEMORY_OBJECT_EXT | FALSE, TRUE  | | 
 |         +-----------------------------+--------------+ | 
 |  | 
 |     The parameter DEDICATED_MEMORY_OBJECT_EXT must be set to TRUE when the | 
 |     external memory handle from which the object's memory will be imported | 
 |     was created as a dedicated allocation. | 
 |  | 
 |     The parameter PROTECTED_MEMORY_OBJECT_EXT must be set to TRUE when the | 
 |     external memory handle from which the object's memory will be imported | 
 |     refers to a protected resource.  The definition of a protected resource | 
 |     is outside the scope of this extension. | 
 |  | 
 |     Memory object parameters become immutable once the object is associated | 
 |     with external memory by an import operation.  An INVALID_OPERATION error | 
 |     is generated if <memoryObject> is immutable. | 
 |  | 
 |     The parameters of a memory object may be queried with the command: | 
 |  | 
 |         void GetMemoryObjectParameterivEXT(uint memoryObject | 
 |                                            enum pname, | 
 |                                            int *params); | 
 |  | 
 |     The value(s) of the parameter <pname> from the memory object | 
 |     <memoryObject> are returned in <params>. | 
 |  | 
 | Additions to Chapter 6 of the OpenGL 4.5 Specification (Buffer Objects) | 
 |  | 
 |     Modify the list of commands described in 6.2 "Creating and Modifying | 
 |     Buffer Object Data Stores" to add the following: | 
 |  | 
 |         void BufferStorageMemEXT(enum target, | 
 |                                  sizeiptr size, | 
 |                                  uint memory, | 
 |                                  uint64 offset); | 
 |  | 
 |         void NamedBufferStorageMemEXT(uint buffer, | 
 |                                       sizeiptr size, | 
 |                                       uint memory, | 
 |                                       uint64 offset); | 
 |  | 
 |     Replace the two paragraphs after the above list of commands with the | 
 |     following: | 
 |  | 
 |         "For BufferStorage and BufferStorageMemEXT, the buffer object is | 
 |         that bound to <target>, which must be one of the values listed | 
 |         in table 6.1.  For NamedBufferStroage and | 
 |         NamedBufferStorageMemEXT, <buffer> is the name of the buffer | 
 |         object.  For all the above commands, <size> is the size of the | 
 |         data store in basic machine units.  For BufferStorageMemEXT and | 
 |         NamedBufferStorageMemEXT, <memory> and <offset> define a region | 
 |         of abstract memory that will be used as the data store for | 
 |         <buffer>.  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. | 
 |  | 
 |         "The data store of the buffer object is allocated or referenced | 
 |         as a result of these commands, and cannot be de-allocated or | 
 |         unreferenced until the buffer is deleted with a call to | 
 |         DeleteBuffers." | 
 |  | 
 |     Replace the paragraph that beings "BufferStorage and | 
 |     NamedBufferStorage delete..." with the following: | 
 |  | 
 |         "BufferStorage, BufferStorageMemEXT, NamedBufferStorage, and | 
 |         NamedBufferStorageMemEXT delete any existing data store, and set | 
 |         the values of the buffer object's state variables as shown in | 
 |         table 6.3." | 
 |  | 
 |     Add the following to the list of errors for the BufferStorage | 
 |     functions" | 
 |  | 
 |         "An INVALID_VALUE error is generated by BufferStorageMemEXT and | 
 |         NamedBufferStorageMemEXT if <memory> is 0, or if <offset> + | 
 |         <size> is greater than the size of the specified | 
 |         memory object. | 
 |  | 
 |         "An INVALID_VALUE error is generated if <offset> is not a valid | 
 |         value for <memory> or the texture." | 
 |  | 
 |         "An INVALID_OPERATION error is generated if <memory> names a valid | 
 |         memory object which has no associated memory." | 
 |  | 
 |     Modify the header for the third column in table 6.2 to read | 
 |     "Value for *BufferStorage*", and update the table description to | 
 |     include the new memory object buffer storage commands. | 
 |  | 
 |     Modify the first sentence of section 6.3, "Mapping and Unmapping | 
 |     Buffer Data", to read as follows: | 
 |  | 
 |         "If the data store for a buffer object is not a reference to a | 
 |         memory object, all or part of the data store may be mapped into | 
 |         the client's address space with the commands:" | 
 |  | 
 |     Add the following to the list of errors for the MapBufferRange and | 
 |     MapNamedBufferRange commands: | 
 |  | 
 |         An INVALID_OPERATION error is generated by Map*BufferRange if | 
 |         the specified buffer is referencing a memory object as its data | 
 |         store. | 
 |  | 
 | Additions to Chapter 8 of the OpenGL 4.5 Specification (Textures and | 
 | Samplers) | 
 |  | 
 |     For each list of TexStorage* commands in the 1D, 2D, 3D, | 
 |     2DMultisample, and 3DMultisample families, add the following | 
 |     variants: | 
 |  | 
 |         void TexStorageMem*EXT(<existing parameters>, | 
 |                                uint memory, | 
 |                                uint64 offset); | 
 |  | 
 |         void TextureStorageMem*EXT(<existing parameters>, | 
 |                                    uint memory, | 
 |                                    uint64 offset); | 
 |  | 
 |     For each family of TexStorage* commands, add appropriate language to | 
 |     the description based on the following template: | 
 |  | 
 |         "Calling TexStorageMem*EXT or TextureStorageMem*EXT is | 
 |         equivalent to calling TexStorage* or TextureStorage* | 
 |         except that rather than allocating new memory for the texture's | 
 |         image data, the memory at <offset> in the memory object | 
 |         specified by <memory> will be used.  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." | 
 |  | 
 |     Add errors based on the following template for each family of | 
 |     TexStorage* commands: | 
 |  | 
 |         "An INVALID_VALUE error is generated if <memory> is 0, or if | 
 |         the memory object is not large enough to contain the specified | 
 |         texture's image data." | 
 |  | 
 |         "An INVALID_VALUE error is generated if <offset> is not a valid | 
 |         value for <memory> or the texture." | 
 |  | 
 |         "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 <memory> is a protected | 
 |         memory object and the texture parameter TEXTURE_PROTECTED_EXT is not | 
 |         TRUE." | 
 |  | 
 |     Insert the following before Table 8.17: | 
 |  | 
 |         "If <pname> is TEXTURE_TILING_EXT then the state is stored in the | 
 |         texture, but only takes effect the next time storage is allocated | 
 |         from a memory object for the texture object using TexStorageMem*EXT | 
 |         or TextureStorageMem*EXT.  If the value of TEXTURE_IMMUTABLE_FORMAT | 
 |         is TRUE, then TEXTURE_TILING_EXT cannot be changed and an | 
 |         INVALID_OPERATION error is generated." | 
 |  | 
 |     Add the following to table 8.17: Texture parameters and their values. | 
 |  | 
 |         | Name               | Type    | Legal values                          | | 
 |         +--------------------+---------+---------------------------------------+ | 
 |         | TEXTURE_TILING_EXT | enum    | OPTIMAL_TILING_EXT, LINEAR_TILING_EXT | | 
 |         +--------------------+---------+---------------------------------------+ | 
 |  | 
 | Additions to Chapter 22 of the OpenGL 4.5 Specification (Context state | 
 | Queries) | 
 |  | 
 |     Add the following to the end of the first list of functions in section | 
 |     22.1, Simple Queries: | 
 |  | 
 |         void GetUnsignedBytevEXT(enum pname, | 
 |                                  ubyte *data); | 
 |  | 
 |     Replace the sentence following that list with: | 
 |  | 
 |         The commands obtain boolean, integer, 64-bit integer, floating- | 
 |         point, double-precision, or unsigned byte state variables. | 
 |  | 
 |     Add the following to the end of the list of indexed simple state query | 
 |     commands: | 
 |  | 
 |         void GetUnsignedBytei_vEXT(enum target, | 
 |                                    uint index, | 
 |                                    ubyte *data); | 
 |  | 
 |  | 
 |  | 
 |     Add the following to section 22.3.2, Other Internal Format Queries: | 
 |  | 
 |         NUM_TILING_TYPES_EXT: The number of tiling types that would be | 
 |         returned by querying TILING_TYPES_EXT is returned in <params>. | 
 |  | 
 |         TILING_TYPES_EXT: The tiling type supported when using memory | 
 |         objects to create textures with <internalFormat> and <target> | 
 |         are written to <params>, in the order in which they occur in | 
 |         table 22.3.  Possible values are those listed in table 22.3. | 
 |  | 
 |         Table 22.3: Possible tiling types supported by textures using | 
 |         memory objects. | 
 |  | 
 |         | Tiling Type        | | 
 |         +--------------------+ | 
 |         | OPTIMAL_TILING_EXT | | 
 |         | LINEAR_TILING_EXT  | | 
 |         +--------------------+ | 
 |  | 
 | Errors | 
 |  | 
 | New State | 
 |  | 
 | Issues | 
 |  | 
 |     1)  Should only DSA-style texture and buffer object binding | 
 |         functions be added to keep the number of new functions | 
 |         to a minimum? | 
 |  | 
 |         RESOLVED: No.  Both DSA and traditional entry points will be added. | 
 |  | 
 |     2)  Should the type of the memory <size> and <offset> parameters be | 
 |         GLsizeiptr, GLintptr, GLint64, or GLuint64? | 
 |  | 
 |         RESOLVED: GLuint64.  This matches the VkDeviceSize semantics. | 
 |  | 
 |     3)  Should there be a way to allocate memory within OpenGL in | 
 |         addition to importing it? | 
 |  | 
 |         RESOLVED: No.  This could be covered in a separate extension, but | 
 |         this would involve building up all the memory property | 
 |         infrastructure Vulkan already has.  Applications wishing to use | 
 |         memory objects in OpenGL will need to leverage the allocation and | 
 |         memory capability querying mechanisms present in Vulkan to perform | 
 |         the actual allocations, and then map the capabilities to GL | 
 |         equivalents when using them. | 
 |  | 
 |     4)  How are sparse textures handled? | 
 |  | 
 |         RESOLVED: Sparse texture support is deferred to a later extension. | 
 |         Late in the development of this specification, it was discovered | 
 |         that naively extending TexPageCommitmentARB to accept an offset | 
 |         and memory object parameter results in a subtly awkward interface | 
 |         when used to build GL sparse textures equivalent to those of Vulkan | 
 |         sparse images, due to the lack of a defined memory layout ordering | 
 |         for array textures.  Developing a better interface would have | 
 |         further delayed release of the basic functionality defined here, | 
 |         which is in higher demand. | 
 |  | 
 |     5)  Do memory objects created as dedicated allocations need special | 
 |         handling? | 
 |  | 
 |         RESOLVED: No.  Like other memory regions, these allocations must be | 
 |         bound to GL objects compatible with those they are bound to in | 
 |         Vulkan to avoid aliasing issues, but otherwise no special handling | 
 |         is required. | 
 |  | 
 |     6)  Should the BufferStorage functions still take a flags parameter? | 
 |  | 
 |         RESOLVED: No.  The flags are not relevant when the memory has | 
 |         already been allocated externally. | 
 |  | 
 |     7)  Should the Buffer commands be called BufferStorage or BufferData? | 
 |  | 
 |         RESOLVED: BufferStorage.  GL has both commands, while GL ES has only | 
 |         BufferData.  The difference between the two GL commands is | 
 |         immutability.  The naming of the BufferStorage seems more consistent | 
 |         with the usage, since data is not specified with these commands, but | 
 |         a backing store is, and immutability for Vulkan memory-backed buffer | 
 |         objects seems desirable.  However, if GLES implementations can not | 
 |         support immutable buffers, BufferData() support can be added in a | 
 |         future extension with some added driver complexity. | 
 |  | 
 |     8)  Can semaphore commands be issued inside of Begin/End, or be | 
 |         included in display lists? | 
 |  | 
 |         RESOLVED: No. | 
 |  | 
 |     9)  Do ownership transfer and memory barrier commands need to be | 
 |         included in the semaphore operations? | 
 |  | 
 |         RESOLVED: Yes, these are needed for proper synchronization on some | 
 |         implementations.  Presumably only the source side of the barriers | 
 |         needs to be specified when transitioning from external to GL usage, | 
 |         and only the destination side needs to be specified when | 
 |         transitioning from GL to external usage.  That should give the | 
 |         OpenGL driver sufficient knowledge to perform any needed automatic | 
 |         transitions based on subsequent usage within the GL API. | 
 |  | 
 |         Still, it is unclear how much of the Vulkan pipeline barrier API | 
 |         should be explicitly exposed in the GL API: | 
 |  | 
 |         * Should queue ownership be included?  There is no equivalent | 
 |           idiom to define this on top of in GL.  However, since the | 
 |           external side is the only portion specified by the | 
 |           application, it could be described in Vulkan terms. | 
 |  | 
 |         * Should image layout be included?  Similar to the above, there | 
 |           is no GL concept of this, but Vulkan terms could be leveraged. | 
 |  | 
 |         * Should access type be included?  This maps relatively well to | 
 |           OpenGL memory barrier bits, but there is not a 1-1 | 
 |           correspondence. | 
 |  | 
 |         * Should the pipeline stage be included?  This could be mapped | 
 |           to stages defined in the GL state machine, but such explicit | 
 |           references to the stages are not thus far included in GL | 
 |           language or tokens. | 
 |  | 
 |         Another option is to require the Vulkan driver to put images, | 
 |         buffers, and their memory in a particular state before sharing | 
 |         them with OpenGL.  For example, require applications to | 
 |         transition to the GENERAL image layout, dstStageMask of | 
 |         TOP_OF_PIPE or ALL_COMMANDS, dstAccessMask will include | 
 |         MEMORY_WRITE_BIT | MEMORY_READ_BIT or some new "more external" | 
 |         version of these, and the dstQueueFamilyIndex must be IGNORED | 
 |         while srcQueueFamilyIndex must be a valid queue family (a | 
 |         currently illegal situation). | 
 |  | 
 |     10) Should the barrier functionality be included in the semaphore | 
 |         operation commands? | 
 |  | 
 |         RESOLVED: Yes.  The only time such barriers are required in GL is | 
 |         when synchronizing with external memory accesses, which is also the | 
 |         only time semaphores should be used.  For internal synchronization, | 
 |         existing GL and EGL commands should be used.  Since the use cases | 
 |         align, it makes sense to make them a single command to cut down on | 
 |         the potential for misuse and keep the API footprint as small as | 
 |         possible. | 
 |  | 
 |     11) Must both Gen[MemoryObjects,Semaphores]EXT commands and | 
 |         Create[MemoryObjects,Semaphores]EXT commands be defined, or is | 
 |         one or the other sufficient? | 
 |  | 
 |         RESOLVED: One variant is sufficient for each object type. | 
 |  | 
 |     12) Should buffer objects backed by memory objects be mappable? | 
 |  | 
 |         RESOLVED: No.  This would complicate the API as interactions between | 
 |         GL and Vulkan cache flushing semantics would need to be defined. | 
 |  | 
 |     13) Does the usage information provided when creating Vulkan images | 
 |         need to be specified when creating textures on memory objects? | 
 |         If so, how is it specified? | 
 |  | 
 |         RESOLVED: There are a few options for specifying the usage in | 
 |         OpenGL: | 
 |  | 
 |         * Have some sort of GLX/EGL-like attrib list that allows users | 
 |           to specify an arbitrary set of usage parameters. | 
 |  | 
 |         * Allow applications to re-use the Vulkan usage flags directly | 
 |           in GL. | 
 |  | 
 |         * Re-define all the Vulkan image usage flags in GL, and update | 
 |           the list via new GL interop extensions as new Vulkan usage | 
 |           flags are added by Vulkan extensions. | 
 |  | 
 |         None of these are very compelling.  They all complicate the OpenGL | 
 |         API significantly and have a high spec maintenance burden as new | 
 |         extensions are added. | 
 |  | 
 |         Other options for resolving the overall issue of GL knowing the | 
 |         usage include: | 
 |  | 
 |         * Disallow Vulkan implementations from utilizing the usage | 
 |           information as input when determining the internal parameters of a | 
 |           Vulkan image used with eternal memory. | 
 |  | 
 |         * Only allow Vulkan implementations to utilize the usage information | 
 |           when using the dedicated allocation path where it can be stored as | 
 |           a form of metadata along with the memory. | 
 |  | 
 |         * Require applications to specify all supported usage flags at image | 
 |           creation time on the Vulkan side for images that are intended to | 
 |           alias with OpenGL textures. | 
 |  | 
 |         The first two options have the downside of potentially limiting the | 
 |         ability of implementations to fully optimize external images | 
 |         regardless of their use case.  The last option constrains the | 
 |         limitations to the case of interoperation with OpenGL, making it a | 
 |         less onerous requirement for implementations while still keeping the | 
 |         OpenGL side of the API relatively simple compared to the options | 
 |         involving re-specification of image usage on the OpenGL side. | 
 |  | 
 |         The agreed resolution is to use the final option: Require all | 
 |         supported usage flags be specified by the application on the Vulkan | 
 |         side if the image is intended to alias with an OpenGL texture. | 
 |  | 
 |     14) Are memory barriers for textures and buffer objects needed with | 
 |         semaphore signal/wait operations, or should a blanket availability/ | 
 |         visibility rule be applied like in Vulkan<->Vulkan semaphore | 
 |         synchronization? | 
 |  | 
 |         RESOLVED: Perhaps extra availability/visibility operations need to | 
 |         be performed to enable external accesses, so it is safest to require | 
 |         explicit specification of the resources that need to be made | 
 |         available and visible as part of a semaphore synchronization | 
 |         operation. | 
 |  | 
 |     15) Are OpenGL equivalents of the Vulkan image creation flags related to | 
 |         sparse properties needed? | 
 |  | 
 |         RESOLVED: Sparse support is not included in this extension. | 
 |  | 
 |         Prior to this resolution, the proposed resolution was as follows: | 
 |  | 
 |         No.  For the purposes of OpenGL, the functionality of all the Vulkan | 
 |         sparse image creation flags is contained in the existing | 
 |         TEXTURE_SPARSE texture parameter.  Because OpenGL does not have the | 
 |         same sparse feature granularity as Vulkan, applications wishing to | 
 |         create a sparse image that will alias with an OpenGL sparse texture | 
 |         will be required to set all of the sparse bits.  Images not intended | 
 |         to alias with an OpenGL texture without the TEXTURE_SPARSE flag set | 
 |         must have none of the Vulkan sparse bits set. | 
 |  | 
 |     16) How do Vulkan sparse block sizes and OpenGL virtual page sizes | 
 |         interact? | 
 |  | 
 |         RESOLVED: Sparse support is not included in this extension. | 
 |  | 
 |         Prior to this resolution, the proposed resolution was as follows: | 
 |  | 
 |         The application must use an OpenGL virtual page size with dimensions | 
 |         matching those of the Vulkan sparse block size for any Vulkan images | 
 |         aliasing OpenGL sparse textures.  If no such virtual page size exists, | 
 |         such aliasing is not supported. | 
 |  | 
 |     17) Is an OpenGL equivalent of the mutable format Vulkan image creation | 
 |         parameter needed? | 
 |  | 
 |         RESOLVED: No.  However, Vulkan applications will be required to set | 
 |         the mutable format bit when creating an  image that will alias with | 
 |         an OpenGL texture on an OpenGL implementation that supports | 
 |         ARB_texture_view, OES_texture_view, EXT_texture_view, or OpenGL 4.3 | 
 |         and above. | 
 |  | 
 |     18) Is an OpenGL equivalent of the tiling Vulkan image creation | 
 |         parameter needed? | 
 |  | 
 |         RESOLVED: Yes.  Further, OpenGL implementations may not support | 
 |         creating textures from Vulkan images using certain tiling types, so | 
 |         a query is needed to determine the types supported. | 
 |  | 
 |     19) Is a way to specify dedicated allocation semantics needed? | 
 |  | 
 |         RESOLVED: Yes.  Importing dedicated allocation-style memory may | 
 |         require the driver to use different paths than importing purely | 
 |         abstract memory.  Additionally, textures and buffer objects may need to derive meta-data from their associated memory object if | 
 |         it is a dedicated allocation.  Therefore, a dedicated allocation | 
 |         parameter should be added to the memory objects.  Additional | 
 |         parameters for textures and buffer objects are not required because | 
 |         unlike Vulkan, OpenGL exposes no application-visible texture or | 
 |         buffer state that would vary depending on whether a dedicated | 
 |         allocation will be used for their storage.  Therefore, they can | 
 |         inherit the state from the memory object associated with them at | 
 |         storage specification time.  Note that allowing parameters to be | 
 |         specified on a memory object prior to the import operation requires | 
 |         separate memory import from memory object instantiation commands. | 
 |  | 
 |     20) How should devices be correlated between OpenGL Vulkan, and other | 
 |         APIs? | 
 |  | 
 |         RESOLVED: Device UUID, LUID, and node mask queries are introduced, | 
 |         corresponding to those added to the Vulkan API for external memory/ | 
 |         semaphore purposes.  Because contexts may be associated with | 
 |         multiple physical GPUs in some cases, multiple values are returned | 
 |         for device UUIDs and multiple bits are set in the device node masks. | 
 |         It is not expected that a single context will be associated with | 
 |         multiple DXGI adapters, so only one LUID is returned. | 
 |  | 
 |         When sharing with Vulkan device groups, the device UUIDs used by the | 
 |         context must match those of the Vulkan physical devices in the | 
 |         Vulkan device group.  Future extensions could relax this | 
 |         requirement. | 
 |  | 
 |     21) How do applications determine valid values for the <offset> | 
 |         parameter of the new storage allocation/binding functions? | 
 |  | 
 |         RESOLVED: This is outside the scope of this extension.  The API or | 
 |         mechanism which allocated the memory must provide this information. | 
 |         However, the GL will generate an error if an invalid offset is used. | 
 |  | 
 |     22) Are there any interactions with the EXT_protected_textures | 
 |         extension? | 
 |  | 
 |         RESOLVED: Yes.  Memory objects can be marked as protected or not | 
 |         protected before import.  This state must match that of the | 
 |         imported resource.  For all textures bound to a given memory object, | 
 |         the value of the TEXTURE_PROTECTED_EXT parameter of the textures | 
 |         must match the PROTECTED_MEMORY_OBJECT_EXT parameter of the memory | 
 |         object. | 
 |  | 
 | Revision History | 
 |  | 
 |     Revision 12, 2017-06-08 (Andres Rodriguez) | 
 |         - Fixed parameter name in MemoryObjectParameterivEXT's description. | 
 |         - Fixed missing EXT suffix in some mentions of GetUnsignedByte* | 
 |  | 
 |     Revision 11, 2017-06-02 (James Jones) | 
 |         - Added extension numbers. | 
 |         - Fixed the name of GetSemaphoreParameterui64vEXT. | 
 |         - Clarified which extensions each command and token belongs to. | 
 |         - Marked complete. | 
 |  | 
 |     Revision 10, 2017-05-24 (James Jones) | 
 |         - Added issue 21 and resolution. | 
 |         - Added issue 22 and resolution. | 
 |         - Removed sparse texture support. | 
 |         - Filled in real token values | 
 |         - Further documented the new LAYOUT tokens. | 
 |  | 
 |     Revision 9, 2017-04-05 (James Jones) | 
 |         - Added context device UUID queries. | 
 |  | 
 |     Revision 8, 2017-04-04 (James Jones) | 
 |         - Clarified semaphore semantics | 
 |  | 
 |     Revision 7, 2017-03-28 (James Jones) | 
 |         - Fixed various typos. | 
 |  | 
 |     Revision 6, 2017-03-17 (James Jones) | 
 |         - Renamed from KHR to EXT. | 
 |         - Added texture tiling parameters. | 
 |         - Added semaphore parameter manipulation functions. | 
 |         - Replaced GenMemoryObjectsEXT with CreateMemoryObjectsEXT | 
 |         - Added memory object parameter manipulation functions. | 
 |         - Updated issue 13 with a proposed resolution. | 
 |         - Added issues 15-19 and proposed resolutions. | 
 |  | 
 |     Revision 5, 2016-10-22 (James Jones) | 
 |         - Added proposed memory barrier semantics to the semaphore commands. | 
 |         - Added issue 14. | 
 |         - Added some clarifications to issue 13 | 
 |  | 
 |     Revision 4, 2016-09-28 (James Jones) | 
 |         - Merged in GL_KHR_semaphore to reduce number of specs. | 
 |         - Added spec body describing the new commands. | 
 |         - Added issues 9-13. | 
 |  | 
 |     Revision 3, 2016-08-15 (James Jones and Jeff Juliano) | 
 |         - Clarified overview text. | 
 |  | 
 |     Revision 2, 2016-08-07 (James Jones) | 
 |         - Added non-contiguous sparse binding support via | 
 |           TexPageCommitmentMemKHR(). | 
 |  | 
 |     Revision 1, 2016-08-05 (James Jones) | 
 |         - Initial draft. |