[Mesa-dev] [RFC PATCH 02/65] mesa: implement ARB_bindless_texture

Samuel Pitoiset samuel.pitoiset at gmail.com
Tue May 23 12:03:52 UTC 2017



On 05/22/2017 12:43 PM, Nicolai Hähnle wrote:
> On 19.05.2017 18:52, Samuel Pitoiset wrote:
>> Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
>> ---
>>  src/mesa/main/context.c         |   3 +
>>  src/mesa/main/dd.h              |  17 +
>>  src/mesa/main/mtypes.h          |  34 ++
>>  src/mesa/main/samplerobj.c      |   6 +
>>  src/mesa/main/shared.c          |  12 +
>>  src/mesa/main/texobj.c          |  12 +
>>  src/mesa/main/texturebindless.c | 827 
>> +++++++++++++++++++++++++++++++++++++++-
>>  src/mesa/main/texturebindless.h |  28 ++
>>  8 files changed, 934 insertions(+), 5 deletions(-)
>>
>> diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
>> index 3570f94f5a..5321886a95 100644
>> --- a/src/mesa/main/context.c
>> +++ b/src/mesa/main/context.c
>> @@ -133,6 +133,7 @@
>>  #include "varray.h"
>>  #include "version.h"
>>  #include "viewport.h"
>> +#include "texturebindless.h"
>>  #include "program/program.h"
>>  #include "math/m_matrix.h"
>>  #include "main/dispatch.h" /* for _gloffset_COUNT */
>> @@ -855,6 +856,7 @@ init_attrib_groups(struct gl_context *ctx)
>>     _mesa_init_transform_feedback( ctx );
>>     _mesa_init_varray( ctx );
>>     _mesa_init_viewport( ctx );
>> +   _mesa_init_resident_handles( ctx );
>>
>>     if (!_mesa_init_texture( ctx ))
>>        return GL_FALSE;
>> @@ -1339,6 +1341,7 @@ _mesa_free_context_data( struct gl_context *ctx )
>>     _mesa_free_transform_feedback(ctx);
>>     _mesa_free_performance_monitors(ctx);
>>     _mesa_free_performance_queries(ctx);
>> +   _mesa_free_resident_handles(ctx);
>>
>>     _mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj, NULL);
>>     _mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj, NULL);
>> diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
>> index a9ca43d69e..d830f5184d 100644
>> --- a/src/mesa/main/dd.h
>> +++ b/src/mesa/main/dd.h
>> @@ -1050,6 +1050,23 @@ struct dd_function_table {
>>                                  GLintptr offset, GLsizeiptr size,
>>                                  GLboolean commit);
>>     /*@}*/
>> +
>> +   /**
>> +    * \name GL_ARB_bindless_texture interface
>> +    */
>> +   /*@{*/
>> +   GLuint64 (*NewTextureHandle)(struct gl_context *ctx,
>> +                                struct gl_texture_object *texObj,
>> +                                struct gl_sampler_object *sampObj);
>> +   void (*DeleteTextureHandle)(struct gl_context *ctx, GLuint64 handle);
>> +   void (*MakeTextureHandleResident)(struct gl_context *ctx, GLuint64 
>> handle,
>> +                                     bool resident);
>> +   GLuint64 (*NewImageHandle)(struct gl_context *ctx,
>> +                              struct gl_image_unit *imgObj);
>> +   void (*DeleteImageHandle)(struct gl_context *ctx, GLuint64 handle);
>> +   void (*MakeImageHandleResident)(struct gl_context *ctx, GLuint64 
>> handle,
>> +                                   GLenum access, bool resident);
>> +   /*@}*/
>>  };
>>
>>
>> diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
>> index efc6920254..70865b373d 100644
>> --- a/src/mesa/main/mtypes.h
>> +++ b/src/mesa/main/mtypes.h
>> @@ -987,6 +987,9 @@ struct gl_sampler_object
>>     GLenum CompareFunc;        /**< GL_ARB_shadow */
>>     GLenum sRGBDecode;           /**< GL_DECODE_EXT or 
>> GL_SKIP_DECODE_EXT */
>>     GLboolean CubeMapSeamless;   /**< 
>> GL_AMD_seamless_cubemap_per_texture */
>> +   bool HandleAllocated;        /**< GL_ARB_bindless_texture */
>> +
>> +   struct hash_table *Handles;
>>  };
>>
>>
>> @@ -1034,6 +1037,8 @@ struct gl_texture_object
>>     GLuint NumLevels;           /**< GL_ARB_texture_view */
>>     GLuint NumLayers;           /**< GL_ARB_texture_view */
>>
>> +   GLboolean HandleAllocated;  /**< GL_ARB_bindless_texture */
>> +
>>     /** Actual texture images, indexed by [cube face] and [mipmap 
>> level] */
>>     struct gl_texture_image *Image[MAX_FACES][MAX_TEXTURE_LEVELS];
>>
>> @@ -1051,6 +1056,10 @@ struct gl_texture_object
>>
>>     /** GL_ARB_shader_image_load_store */
>>     GLenum ImageFormatCompatibilityType;
>> +
>> +   /** GL_ARB_bindless_texture */
>> +   struct hash_table *SamplerHandles;
>> +   struct hash_table *ImageHandles;
>>  };
>>
>>
>> @@ -1390,6 +1399,7 @@ struct gl_buffer_object
>>     GLboolean Written;   /**< Ever written to? (for debugging) */
>>     GLboolean Purgeable; /**< Is the buffer purgeable under memory 
>> pressure? */
>>     GLboolean Immutable; /**< GL_ARB_buffer_storage */
>> +   GLboolean HandleAllocated; /**< GL_ARB_bindless_texture */
> 
> Should be consistent with gl_sampler_object in terms of type (and 
> gl_texture_object as well). Which type? Since the state is not 
> API-visible, bool is justifiable.

Correct.

> 
> 
>>     gl_buffer_usage UsageHistory; /**< How has this buffer been used 
>> so far? */
>>
>>     /** Counters used for buffer usage warnings */
>> @@ -3203,6 +3213,11 @@ struct gl_shared_state
>>     /** GL_ARB_sampler_objects */
>>     struct _mesa_HashTable *SamplerObjects;
>>
>> +   /* GL_ARB_bindless_texture */
>> +   struct hash_table *TextureHandles;
>> +   struct hash_table *ImageHandles;
>> +   mtx_t HandlesMutex; /**< For texture/image handles safety */
>> +
>>     /**
>>      * Some context in this share group was affected by a GPU reset
>>      *
>> @@ -4488,6 +4503,17 @@ struct gl_subroutine_index_binding
>>     GLuint *IndexPtr;
>>  };
>>
>> +struct gl_texture_handle_object
>> +{
>> +   struct gl_texture_object *texObj;
>> +   struct gl_sampler_object *sampObj;
>> +};
>> +
>> +struct gl_image_handle_object
>> +{
>> +   struct gl_image_unit imgObj;
>> +};
>> +
>>  /**
>>   * Mesa rendering context.
>>   *
>> @@ -4842,6 +4868,14 @@ struct gl_context
>>     GLfloat PrimitiveBoundingBox[8];
>>
>>     struct disk_cache *Cache;
>> +
>> +   /**
>> +    * \name GL_ARB_bindless_texture
>> +    */
>> +   /*@{*/
>> +   struct hash_table *ResidentTextureHandles;
>> +   struct hash_table *ResidentImageHandles;
>> +   /*@}*/
>>  };
>>
>>  /**
>> diff --git a/src/mesa/main/samplerobj.c b/src/mesa/main/samplerobj.c
>> index 63beaf1abb..ee15c68b4f 100644
>> --- a/src/mesa/main/samplerobj.c
>> +++ b/src/mesa/main/samplerobj.c
>> @@ -38,6 +38,7 @@
>>  #include "main/macros.h"
>>  #include "main/mtypes.h"
>>  #include "main/samplerobj.h"
>> +#include "main/texturebindless.h"
>>
>>
>>  struct gl_sampler_object *
>> @@ -61,6 +62,7 @@ static void
>>  delete_sampler_object(struct gl_context *ctx,
>>                        struct gl_sampler_object *sampObj)
>>  {
>> +   _mesa_delete_sampler_handles(ctx, sampObj);
>>     mtx_destroy(&sampObj->Mutex);
>>     free(sampObj->Label);
>>     free(sampObj);
>> @@ -132,6 +134,10 @@ _mesa_init_sampler_object(struct 
>> gl_sampler_object *sampObj, GLuint name)
>>     sampObj->CompareFunc = GL_LEQUAL;
>>     sampObj->sRGBDecode = GL_DECODE_EXT;
>>     sampObj->CubeMapSeamless = GL_FALSE;
>> +   sampObj->HandleAllocated = GL_FALSE;
>> +
>> +   /* GL_ARB_bindless_texture */
>> +   _mesa_init_sampler_handles(sampObj);
>>  }
>>
>>  /**
>> diff --git a/src/mesa/main/shared.c b/src/mesa/main/shared.c
>> index 5344812738..b188287a08 100644
>> --- a/src/mesa/main/shared.c
>> +++ b/src/mesa/main/shared.c
>> @@ -84,6 +84,13 @@ _mesa_alloc_shared_state(struct gl_context *ctx)
>>     /* GL_ARB_sampler_objects */
>>     shared->SamplerObjects = _mesa_NewHashTable();
>>
>> +   /* GL_ARB_bindless_texture */
>> +   shared->TextureHandles = _mesa_hash_table_create(NULL, 
>> _mesa_hash_pointer,
>> +                                                    
>> _mesa_key_pointer_equal);
>> +   shared->ImageHandles = _mesa_hash_table_create(NULL, 
>> _mesa_hash_pointer,
>> +                                                  
>> _mesa_key_pointer_equal);
>> +   mtx_init(&shared->HandlesMutex, mtx_recursive);
>> +
>>     /* Allocate the default buffer object */
>>     shared->NullBufferObj = ctx->Driver.NewBufferObject(ctx, 0);
>>
>> @@ -373,6 +380,11 @@ free_shared_state(struct gl_context *ctx, struct 
>> gl_shared_state *shared)
>>     _mesa_HashDeleteAll(shared->TexObjects, delete_texture_cb, ctx);
>>     _mesa_DeleteHashTable(shared->TexObjects);
>>
>> +   /* Bindless texture/image handles */
>> +   _mesa_hash_table_destroy(shared->TextureHandles, NULL);
>> +   _mesa_hash_table_destroy(shared->ImageHandles, NULL);
>> +   mtx_destroy(&shared->HandlesMutex);
>> +
>>     mtx_destroy(&shared->Mutex);
>>     mtx_destroy(&shared->TexMutex);
>>
>> diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c
>> index 868e4eb7a2..13a24f6deb 100644
>> --- a/src/mesa/main/texobj.c
>> +++ b/src/mesa/main/texobj.c
>> @@ -43,6 +43,7 @@
>>  #include "texstate.h"
>>  #include "mtypes.h"
>>  #include "program/prog_instruction.h"
>> +#include "texturebindless.h"
>>
>>
>>
>> @@ -311,6 +312,7 @@ _mesa_initialize_texture_object( struct gl_context 
>> *ctx,
>>     obj->DepthMode = ctx->API == API_OPENGL_CORE ? GL_RED : GL_LUMINANCE;
>>     obj->StencilSampling = false;
>>     obj->Sampler.CubeMapSeamless = GL_FALSE;
>> +   obj->Sampler.HandleAllocated = GL_FALSE;
>>     obj->Swizzle[0] = GL_RED;
>>     obj->Swizzle[1] = GL_GREEN;
>>     obj->Swizzle[2] = GL_BLUE;
>> @@ -320,6 +322,9 @@ _mesa_initialize_texture_object( struct gl_context 
>> *ctx,
>>     obj->BufferObjectFormat = GL_R8;
>>     obj->_BufferObjectFormat = MESA_FORMAT_R_UNORM8;
>>     obj->ImageFormatCompatibilityType = 
>> GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE;
>> +
>> +   /* GL_ARB_bindless_texture */
>> +   _mesa_init_texture_handles(obj);
>>  }
>>
>>
>> @@ -397,6 +402,9 @@ _mesa_delete_texture_object(struct gl_context *ctx,
>>        }
>>     }
>>
>> +   /* Delete all texture/image handles. */
>> +   _mesa_delete_texture_handles(ctx, texObj);
>> +
>>     _mesa_reference_buffer_object(ctx, &texObj->BufferObject, NULL);
>>
>>     /* destroy the mutex -- it may have allocated memory (eg on bsd) */
>> @@ -1461,6 +1469,10 @@ _mesa_DeleteTextures( GLsizei n, const GLuint 
>> *textures)
>>               */
>>              unbind_texobj_from_image_units(ctx, delObj);
>>
>> +            /* Make all handles that reference this texture object 
>> non-resident
>> +             * in the current context. */
>> +            _mesa_make_texture_handles_non_resident(ctx, delObj);
>> +
>>              _mesa_unlock_texture(ctx, delObj);
>>
>>              ctx->NewState |= _NEW_TEXTURE_OBJECT;
>> diff --git a/src/mesa/main/texturebindless.c 
>> b/src/mesa/main/texturebindless.c
>> index 4d9c22d428..0c6f9c3fc9 100644
>> --- a/src/mesa/main/texturebindless.c
>> +++ b/src/mesa/main/texturebindless.c
>> @@ -29,57 +29,874 @@
>>  #include "mtypes.h"
>>  #include "texobj.h"
>>  #include "texturebindless.h"
>> +#include "shaderimage.h"
>> +#include "teximage.h"
>> +#include "hash.h"
>>
>>  #include "util/set.h"
>>  #include "util/hash_table.h"
>>
>> +/**
>> + * Return the gl_texture_handle_object for a given 64bit handle.
>> + */
>> +static struct gl_texture_handle_object *
>> +lookup_texture_handle(struct gl_context *ctx, GLuint64 id)
>> +{
>> +   struct hash_entry *entry;
>> +
>> +   mtx_lock(&ctx->Shared->HandlesMutex);
>> +   entry = _mesa_hash_table_search(ctx->Shared->TextureHandles, (void 
>> *)id);
>> +   mtx_unlock(&ctx->Shared->HandlesMutex);
>> +
>> +   return entry ? (struct gl_texture_handle_object *)entry->data : NULL;
>> +}
>> +
>> +/**
>> + * Return the gl_image_handle_object for a given 64bit handle.
>> + */
>> +static struct gl_image_handle_object *
>> +lookup_image_handle(struct gl_context *ctx, GLuint64 id)
>> +{
>> +   struct hash_entry *entry;
>> +
>> +   mtx_lock(&ctx->Shared->HandlesMutex);
>> +   entry = _mesa_hash_table_search(ctx->Shared->ImageHandles, (void 
>> *)id);
>> +   mtx_unlock(&ctx->Shared->HandlesMutex);
>> +
>> +   return entry ? (struct gl_image_handle_object *)entry->data : NULL;
>> +}
>> +
>> +/**
>> + * Delete a texture handle in the shared state.
>> + */
>> +static void
>> +delete_texture_handle(struct gl_context *ctx, GLuint64 id)
>> +{
>> +   struct hash_entry *entry;
>> +
>> +   mtx_lock(&ctx->Shared->HandlesMutex);
>> +   entry = _mesa_hash_table_search(ctx->Shared->TextureHandles, (void 
>> *)id);
>> +   _mesa_hash_table_remove(ctx->Shared->TextureHandles, entry);
>> +   mtx_unlock(&ctx->Shared->HandlesMutex);
>> +}
>> +
>> +/**
>> + * Delete an image handle in the shared state.
>> + */
>> +static void
>> +delete_image_handle(struct gl_context *ctx, GLuint64 id)
>> +{
>> +   struct hash_entry *entry;
>> +
>> +   mtx_lock(&ctx->Shared->HandlesMutex);
>> +   entry = _mesa_hash_table_search(ctx->Shared->ImageHandles, (void 
>> *)id);
>> +   _mesa_hash_table_remove(ctx->Shared->ImageHandles, entry);
>> +   mtx_unlock(&ctx->Shared->HandlesMutex);
>> +}
>> +
>> +/**
>> + * Return TRUE if the texture handle is resident in the current context.
>> + */
>> +static inline bool
>> +is_texture_handle_resident(struct gl_context *ctx, GLuint64 handle)
>> +{
>> +   return _mesa_hash_table_search(ctx->ResidentTextureHandles,
>> +                                  (void *)handle) != NULL;
>> +}
>> +
>> +/**
>> + * Return TRUE if the image handle is resident in the current context.
>> + */
>> +static inline bool
>> +is_image_handle_resident(struct gl_context *ctx, GLuint64 handle)
>> +{
>> +   return _mesa_hash_table_search(ctx->ResidentImageHandles,
>> +                                  (void *)handle) != NULL;
>> +}
>> +
>> +/**
>> + * Set a texture handle resident/non-resident in the current context.
>> + */
>> +static void
>> +make_texture_handle_resident(struct gl_context *ctx,
>> +                            struct gl_texture_handle_object *handleObj,
>> +                            GLuint64 handle, bool resident)
>> +{
>> +   if (resident) {
>> +      struct gl_sampler_object *sampObj = NULL;
>> +      struct gl_texture_object *texObj = NULL;
>> +
>> +      _mesa_hash_table_insert(ctx->ResidentTextureHandles,
>> +                              (void *)handle, handleObj);
>> +
>> +      ctx->Driver.MakeTextureHandleResident(ctx, handle, GL_TRUE);
>> +
>> +      /* Reference the texture object (and the separate sampler if 
>> needed) to
>> +       * be sure it won't be deleted until it is not bound anywhere 
>> and there
>> +       * are no handles using the object that are resident in any 
>> context. */
>> +      _mesa_reference_texobj(&texObj, handleObj->texObj);
>> +      if (handleObj->sampObj)
>> +         _mesa_reference_sampler_object(ctx, &sampObj, 
>> handleObj->sampObj);
>> +   } else {
>> +      struct hash_entry *entry;
>> +
>> +      entry = _mesa_hash_table_search(ctx->ResidentTextureHandles,
>> +                                      (void *)handle);
>> +      _mesa_hash_table_remove(ctx->ResidentTextureHandles, entry);
>> +
>> +      ctx->Driver.MakeTextureHandleResident(ctx, handle, GL_FALSE);
>> +
>> +      /* Unreference the texture object (and the separate sampler if 
>> needed),
>> +       * if refcount hits zero, the texture and all handles will be 
>> deleted. */
>> +      _mesa_reference_texobj(&handleObj->texObj, NULL);
>> +      if (handleObj->sampObj)
>> +         _mesa_reference_sampler_object(ctx, &handleObj->sampObj, NULL);
>> +   }
>> +}
>> +
>> +/**
>> + * Set an image handle resident/non-resident in the current context.
>> + */
>> +static void
>> +make_image_handle_resident(struct gl_context *ctx,
>> +                          struct gl_image_handle_object *handleObj,
>> +                          GLuint64 handle, GLenum access, bool resident)
>> +{
>> +   if (resident) {
>> +      struct gl_texture_object *texObj = NULL;
>> +
>> +      _mesa_hash_table_insert(ctx->ResidentImageHandles,
>> +                              (void *)handle, handleObj);
>> +
>> +      ctx->Driver.MakeImageHandleResident(ctx, handle, access, GL_TRUE);
>> +
>> +      /* Reference the texture object to be sure it won't be deleted 
>> until it
>> +       * is not bound anywhere and there are no handles using the 
>> object that
>> +       * are resident in any context. */
>> +      _mesa_reference_texobj(&texObj, handleObj->imgObj.TexObj);
>> +   } else {
>> +      struct hash_entry *entry;
>> +
>> +      entry = _mesa_hash_table_search(ctx->ResidentImageHandles,
>> +                                      (void *)handle);
>> +      _mesa_hash_table_remove(ctx->ResidentImageHandles, entry);
>> +
>> +      ctx->Driver.MakeImageHandleResident(ctx, handle, access, 
>> GL_FALSE);
>> +
>> +      /* Unreference the texture object, if refcount hits zero, the 
>> texture and
>> +       * all handles will be deleted. */
>> +      _mesa_reference_texobj(&handleObj->imgObj.TexObj, NULL);
>> +   }
>> +}
>> +
>> +static GLuint64
>> +get_texture_handle(struct gl_context *ctx, struct gl_texture_object 
>> *texObj,
>> +                   struct gl_sampler_object *sampObj)
>> +{
>> +   struct gl_texture_handle_object *handleObj;
>> +   struct hash_entry *entry;
>> +   GLuint64 handle;
>> +
>> +   handleObj = CALLOC_STRUCT(gl_texture_handle_object);
>> +   if (!handleObj) {
>> +      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexture*HandleARB()");
>> +      return 0;
>> +   }
>> +
>> +   handleObj->texObj = texObj;
>> +   if (&texObj->Sampler != sampObj)
>> +      handleObj->sampObj = sampObj;
>> +
>> +   /* The ARB_bindless_texture spec says:
>> +    *
>> +    * "The handle for each texture or texture/sampler pair is unique; 
>> the same
>> +    *  handle will be returned if GetTextureHandleARB is called 
>> multiple times
>> +    *  for the same texture or if GetTextureSamplerHandleARB is 
>> called multiple
>> +    *  times for the same texture/sampler pair."
>> +    */
>> +   mtx_lock(&ctx->Shared->HandlesMutex);
>> +   entry = _mesa_hash_table_search(texObj->SamplerHandles, handleObj);
>> +   if (entry) {
>> +      mtx_unlock(&ctx->Shared->HandlesMutex);
>> +      free(handleObj);
>> +      return (uint64_t)entry->data;
>> +   }
>> +
>> +   /* Ask the driver for a new handle and store it. */
>> +   handle = ctx->Driver.NewTextureHandle(ctx, texObj, sampObj);
>> +   if (!handle) {
>> +      mtx_unlock(&ctx->Shared->HandlesMutex);
>> +      free(handleObj);
>> +      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexture*HandleARB()");
>> +      return 0;
>> +   }
>> +
>> +   _mesa_hash_table_insert(texObj->SamplerHandles, handleObj, (void 
>> *)handle);
>> +
>> +   if (&texObj->Sampler != sampObj) {
>> +      _mesa_hash_table_insert(sampObj->Handles, handleObj,
>> +                              (void *)handle);
>> +   }
>> +
>> +   /* When referenced by one or more handles, texture objects are 
>> immutable. */
>> +   texObj->HandleAllocated = true;
>> +   sampObj->HandleAllocated = true;
>> +   if (texObj->Target == GL_TEXTURE_BUFFER)
>> +      texObj->BufferObject->HandleAllocated = true;
>> +
>> +   /* Store the handle in the shared state for all contexts. */
>> +   _mesa_hash_table_insert(ctx->Shared->TextureHandles,
>> +                           (void *)handle, handleObj);
> 
> This won't work on 32-bit systems (same for image handles).

Because the handle is 64-bit? Mmh...

> 
> 
>> +   mtx_unlock(&ctx->Shared->HandlesMutex);
>> +
>> +   return (GLuint64)handle;
>> +}
>> +
>> +static GLuint64
>> +get_image_handle(struct gl_context *ctx, struct gl_texture_object 
>> *texObj,
>> +                 GLint level, GLboolean layered, GLint layer, GLenum 
>> format)
>> +{
>> +   struct gl_image_handle_object *handleObj;
>> +   struct gl_image_unit *imgObj;
>> +   struct hash_entry *entry;
>> +   GLuint64 handle;
>> +
>> +   handleObj = CALLOC_STRUCT(gl_image_handle_object);
>> +   if (!handleObj) {
>> +      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetImageHandleARB()");
>> +      return 0;
>> +   }
>> +
>> +   imgObj = &handleObj->imgObj;
>> +   imgObj->TexObj = texObj; /* weak reference */
>> +   imgObj->Level = level;
>> +   imgObj->Access = GL_READ_WRITE;
>> +   imgObj->Format = format;
>> +   imgObj->_ActualFormat = _mesa_get_shader_image_format(format);
>> +
>> +   if (_mesa_tex_target_is_layered(texObj->Target)) {
>> +      imgObj->Layered = layered;
>> +      imgObj->Layer = layer;
>> +      imgObj->_Layer = (imgObj->Layered ? 0 : imgObj->Layer);
>> +   } else {
>> +      imgObj->Layered = GL_FALSE;
>> +      imgObj->Layer = 0;
>> +   }
>> +
>> +   /* The ARB_bindless_texture spec says:
>> +    *
>> +    * "The handle returned for each combination of <texture>, <level>,
>> +    *  <layered>, <layer>, and <format> is unique; the same handle 
>> will be
>> +    *  returned if GetImageHandleARB is called multiple times with 
>> the same
>> +    *  parameters."
>> +    */
>> +   mtx_lock(&ctx->Shared->HandlesMutex);
>> +   entry = _mesa_hash_table_search(texObj->ImageHandles, handleObj);
>> +   if (entry) {
>> +      mtx_unlock(&ctx->Shared->HandlesMutex);
>> +      free(handleObj);
>> +      return (uint64_t)entry->data;
>> +   }
>> +
>> +   /* Ask the driver for a new handle and store it. */
>> +   handle = ctx->Driver.NewImageHandle(ctx, &handleObj->imgObj);
>> +   if (!handle) {
>> +      mtx_unlock(&ctx->Shared->HandlesMutex);
>> +      free(handleObj);
>> +      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetImageHandleARB()");
>> +      return 0;
>> +   }
>> +
>> +   _mesa_hash_table_insert(texObj->ImageHandles, handleObj, (void 
>> *)handle);
>> +
>> +   /* When referenced by one or more handles, texture objects are 
>> immutable. */
>> +   texObj->HandleAllocated = true;
>> +   if (texObj->Target == GL_TEXTURE_BUFFER)
>> +      texObj->BufferObject->HandleAllocated = true;
>> +   texObj->Sampler.HandleAllocated = true;
>> +
>> +   /* Store the handle in the shared state for all contexts. */
>> +   _mesa_hash_table_insert(ctx->Shared->ImageHandles,
>> +                           (void *)handle, handleObj);
>> +   mtx_unlock(&ctx->Shared->HandlesMutex);
>> +
>> +   return (GLuint64)handle;
>> +}
>> +
>> +void
>> +_mesa_init_resident_handles(struct gl_context *ctx)
>> +{
>> +   ctx->ResidentTextureHandles =
>> +      _mesa_hash_table_create(NULL, _mesa_hash_pointer,
>> +                              _mesa_key_pointer_equal);
>> +   ctx->ResidentImageHandles =
>> +      _mesa_hash_table_create(NULL, _mesa_hash_pointer,
>> +                              _mesa_key_pointer_equal);
>> +}
>> +
>> +void
>> +_mesa_free_resident_handles(struct gl_context *ctx)
>> +{
>> +   _mesa_hash_table_destroy(ctx->ResidentTextureHandles, NULL);
>> +   _mesa_hash_table_destroy(ctx->ResidentImageHandles, NULL);
>> +}
>> +
>> +static uint32_t
>> +texture_handle_key_hash(const void *key)
>> +{
>> +   return _mesa_hash_data(key, sizeof(struct gl_texture_handle_object));
>> +}
>> +
>> +static bool
>> +texture_handle_key_equals(const void *a, const void *b)
>> +{
>> +   struct gl_texture_handle_object *aa = (struct 
>> gl_texture_handle_object *)a;
>> +   struct gl_texture_handle_object *bb = (struct 
>> gl_texture_handle_object *)b;
>> +
>> +   return !memcmp(aa, bb, sizeof(struct gl_texture_handle_object));
>> +}
>> +
>> +static uint32_t
>> +image_handle_key_hash(const void *key)
>> +{
>> +   return _mesa_hash_data(key, sizeof(struct gl_image_handle_object));
>> +}
>> +
>> +static bool
>> +image_handle_key_equals(const void *a, const void *b)
>> +{
>> +   struct gl_image_handle_object *aa = (struct gl_image_handle_object 
>> *)a;
>> +   struct gl_image_handle_object *bb = (struct gl_image_handle_object 
>> *)b;
>> +
>> +   return !memcmp(aa, bb, sizeof(struct gl_image_handle_object));
>> +}
>> +
>> +void
>> +_mesa_init_texture_handles(struct gl_texture_object *texObj)
>> +{
>> +   texObj->SamplerHandles =
>> +      _mesa_hash_table_create(NULL, texture_handle_key_hash,
>> +                              texture_handle_key_equals);
>> +   texObj->ImageHandles =
>> +      _mesa_hash_table_create(NULL, image_handle_key_hash,
>> +                              image_handle_key_equals);
>> +}
>> +
>> +void
>> +_mesa_make_texture_handles_non_resident(struct gl_context *ctx,
>> +                                        struct gl_texture_object 
>> *texObj)
>> +{
>> +   struct hash_entry *entry;
>> +   GLuint64 handle;
>> +
>> +   mtx_lock(&ctx->Shared->HandlesMutex);
>> +
>> +   hash_table_foreach(texObj->SamplerHandles, entry) {
>> +      struct gl_texture_handle_object *handleObj =
>> +         (struct gl_texture_handle_object *)entry->key;
>> +
>> +      handle = (uint64_t)entry->data;
>> +      if (is_texture_handle_resident(ctx, handle))
>> +         make_texture_handle_resident(ctx, handleObj, handle, false);
>> +   }
>> +
>> +   hash_table_foreach(texObj->ImageHandles, entry) {
>> +      struct gl_image_handle_object *handleObj =
>> +         (struct gl_image_handle_object *)entry->key;
>> +
>> +      handle = (uint64_t)entry->data;
>> +      if (is_image_handle_resident(ctx, handle))
>> +         make_image_handle_resident(ctx, handleObj, handle, 
>> GL_READ_ONLY, false);
>> +   }
> 
> So... this also needs to loop through all other contexts and make the 
> handle non-resident in them, right? Otherwise you might end up with 
> dangling pointers (or at least dangling handles).

No. Resident handles are per-context. Though, I'm not very happy myself 
with the way I managed the handles. I'm open to any better suggestions.

> 
> 
>> +
>> +   mtx_unlock(&ctx->Shared->HandlesMutex);
>> +}
>> +
>> +void
>> +_mesa_delete_texture_handles(struct gl_context *ctx,
>> +                             struct gl_texture_object *texObj)
>> +{
>> +   struct hash_entry *entry;
>> +
>> +   hash_table_foreach(texObj->SamplerHandles, entry) {
>> +      struct gl_texture_handle_object *handleObj =
>> +         (struct gl_texture_handle_object *)entry->key;
>> +      GLuint64 handle = (GLuint64)entry->data;
>> +
>> +      ctx->Driver.DeleteTextureHandle(ctx, handle);
>> +
>> +      delete_texture_handle(ctx, handle);
>> +      free(handleObj);
>> +   }
>> +
>> +   hash_table_foreach(texObj->ImageHandles, entry) {
>> +      struct gl_image_handle_object *handleObj =
>> +         (struct gl_image_handle_object *)entry->key;
>> +      GLuint64 handle = (GLuint64)entry->data;
>> +
>> +      ctx->Driver.DeleteImageHandle(ctx, handle);
>> +
>> +      delete_image_handle(ctx, handle);
>> +      free(handleObj);
>> +   }
>> +
>> +   _mesa_hash_table_destroy(texObj->SamplerHandles, NULL);
>> +   _mesa_hash_table_destroy(texObj->ImageHandles, NULL);
>> +}
>> +
>> +void
>> +_mesa_init_sampler_handles(struct gl_sampler_object *sampObj)
>> +{
>> +   sampObj->Handles = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
>> +                                              _mesa_key_pointer_equal);
>> +}
>> +
>> +void
>> +_mesa_delete_sampler_handles(struct gl_context *ctx,
>> +                             struct gl_sampler_object *sampObj)
>> +{
>> +   struct hash_entry *entry;
>> +
>> +   hash_table_foreach(sampObj->Handles, entry) {
>> +      GLuint64 handle = (GLuint64)entry->data;
>> +
>> +      ctx->Driver.DeleteTextureHandle(ctx, handle);
>> +
>> +      delete_texture_handle(ctx, handle);
>> +   }
>> +
>> +   _mesa_hash_table_destroy(sampObj->Handles, NULL);
>> +}
>> +
>> +static GLboolean
>> +is_sampler_border_color_valid(struct gl_sampler_object *samp)
>> +{
>> +   static const GLfloat valid_float_border_colors[4][4] = {
>> +      { 0.0, 0.0, 0.0, 0.0 },
>> +      { 0.0, 0.0, 0.0, 1.0 },
>> +      { 1.0, 1.0, 1.0, 0.0 },
>> +      { 1.0, 1.0, 1.0, 1.0 },
>> +   };
>> +   static const GLint valid_integer_border_colors[4][4] = {
>> +      { 0, 0, 0, 0 },
>> +      { 0, 0, 0, 1 },
>> +      { 1, 1, 1, 0 },
>> +      { 1, 1, 1, 1 },
>> +   };
>> +   size_t size = sizeof(samp->BorderColor.ui);
>> +
>> +   /* The ARB_bindless_texture spec says:
>> +    *
>> +    * "The error INVALID_OPERATION is generated if the border color 
>> (taken from
>> +    *  the embedded sampler for GetTextureHandleARB or from the 
>> <sampler> for
>> +    *  GetTextureSamplerHandleARB) 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)."
>> +    */
>> +   if (!memcmp(samp->BorderColor.f, valid_float_border_colors[0], 
>> size) ||
>> +       !memcmp(samp->BorderColor.f, valid_float_border_colors[1], 
>> size) ||
>> +       !memcmp(samp->BorderColor.f, valid_float_border_colors[2], 
>> size) ||
>> +       !memcmp(samp->BorderColor.f, valid_float_border_colors[3], size))
>> +      return GL_TRUE;
>> +
>> +   if (!memcmp(samp->BorderColor.ui, valid_integer_border_colors[0], 
>> size) ||
>> +       !memcmp(samp->BorderColor.ui, valid_integer_border_colors[1], 
>> size) ||
>> +       !memcmp(samp->BorderColor.ui, valid_integer_border_colors[2], 
>> size) ||
>> +       !memcmp(samp->BorderColor.ui, valid_integer_border_colors[3], 
>> size))
>> +      return GL_TRUE;
>> +
>> +   return GL_FALSE;
>> +}
>> +
>>  GLuint64 GLAPIENTRY
>>  _mesa_GetTextureHandleARB(GLuint texture)
>>  {
>> -   return 0;
>> +   struct gl_texture_object *texObj = NULL;
>> +
>> +   GET_CURRENT_CONTEXT(ctx);
>> +
>> +   if (!_mesa_has_ARB_bindless_texture(ctx)) {
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glGetTextureHandleARB(unsupported)");
>> +      return 0;
>> +   }
>> +
>> +   /* The ARB_bindless_texture spec says:
>> +    *
>> +    * "The error INVALID_VALUE is generated by GetTextureHandleARB or
>> +    *  GetTextureSamplerHandleARB if <texture> is zero or not the 
>> name of an
>> +    *  existing texture object."
>> +    */
>> +   if (texture > 0)
>> +      texObj = _mesa_lookup_texture(ctx, texture);
>> +
>> +   if (!texObj) {
>> +      _mesa_error(ctx, GL_INVALID_VALUE, 
>> "glGetTextureHandleARB(texture)");
>> +      return 0;
>> +   }
>> +
>> +   /* The ARB_bindless_texture spec says:
>> +    *
>> +    * "The error INVALID_OPERATION is generated by 
>> GetTextureHandleARB or
>> +    *  GetTextureSamplerHandleARB if the texture object specified by 
>> <texture>
>> +    *  is not complete."
>> +    */
>> +   if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
>> +      _mesa_test_texobj_completeness(ctx, texObj);
>> +      if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
>> +         _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                     "glGetTextureHandleARB(incomplete texture)");
>> +         return 0;
>> +      }
>> +   }
>> +
>> +   if (!is_sampler_border_color_valid(&texObj->Sampler)) {
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glGetTextureHandleARB(invalid border color)");
>> +      return 0;
>> +   }
>> +
>> +   return get_texture_handle(ctx, texObj, &texObj->Sampler);
>>  }
>>
>>  GLuint64 GLAPIENTRY
>>  _mesa_GetTextureSamplerHandleARB(GLuint texture, GLuint sampler)
>>  {
>> -   return 0;
>> +   struct gl_texture_object *texObj = NULL;
>> +   struct gl_sampler_object *sampObj;
>> +
>> +   GET_CURRENT_CONTEXT(ctx);
>> +
>> +   if (!_mesa_has_ARB_bindless_texture(ctx)) {
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glGetTextureSamplerHandleARB(unsupported)");
>> +      return 0;
>> +   }
>> +
>> +   /* The ARB_bindless_texture spec says:
>> +    *
>> +    * "The error INVALID_VALUE is generated by GetTextureHandleARB or
>> +    *  GetTextureSamplerHandleARB if <texture> is zero or not the 
>> name of an
>> +    *  existing texture object."
>> +    */
>> +   if (texture > 0)
>> +      texObj = _mesa_lookup_texture(ctx, texture);
>> +
>> +   if (!texObj) {
>> +      _mesa_error(ctx, GL_INVALID_VALUE,
>> +                  "glGetTextureSamplerHandleARB(texture)");
>> +      return 0;
>> +   }
>> +
>> +   /* The ARB_bindless_texture spec says:
>> +    *
>> +    * "The error INVALID_VALUE is generated by 
>> GetTextureSamplerHandleARB if
>> +    *  <sampler> is zero or is not the name of an existing sampler 
>> object."
>> +    */
>> +   sampObj = _mesa_lookup_samplerobj(ctx, sampler);
>> +   if (!sampObj) {
>> +      _mesa_error(ctx, GL_INVALID_VALUE,
>> +                  "glGetTextureSamplerHandleARB(sampler)");
>> +      return 0;
>> +   }
>> +
>> +   /* The ARB_bindless_texture spec says:
>> +    *
>> +    * "The error INVALID_OPERATION is generated by 
>> GetTextureHandleARB or
>> +    *  GetTextureSamplerHandleARB if the texture object specified by 
>> <texture>
>> +    *  is not complete."
>> +    */
>> +   if (!_mesa_is_texture_complete(texObj, sampObj)) {
>> +      _mesa_test_texobj_completeness(ctx, texObj);
>> +      if (!_mesa_is_texture_complete(texObj, sampObj)) {
>> +         _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                     "glGetTextureSamplerHandleARB(incomplete 
>> texture)");
>> +         return 0;
>> +      }
>> +   }
>> +
>> +   if (!is_sampler_border_color_valid(sampObj)) {
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glGetTextureSamplerHandleARB(invalid border color)");
>> +      return 0;
>> +   }
>> +
>> +   return get_texture_handle(ctx, texObj, sampObj);
>>  }
>>
>>  void GLAPIENTRY
>>  _mesa_MakeTextureHandleResidentARB(GLuint64 handle)
>>  {
>> +   struct gl_texture_handle_object *handleObj;
>> +
>> +   GET_CURRENT_CONTEXT(ctx);
>> +
>> +   if (!_mesa_has_ARB_bindless_texture(ctx)) {
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glMakeTextureHandleResidentARB(unsupported)");
>> +      return;
>> +   }
>> +
>> +   /* The ARB_bindless_texture spec says:
>> +    *
>> +    * "The error INVALID_OPERATION is generated by 
>> MakeTextureHandleResidentARB
>> +    *  if <handle> is not a valid texture handle, or if <handle> is 
>> already
>> +    *  resident in the current GL context."
>> +    */
>> +   handleObj = lookup_texture_handle(ctx, handle);
>> +   if (!handleObj) {
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glMakeTextureHandleResidentARB(handle)");
>> +      return;
>> +   }
>> +
>> +   if (is_texture_handle_resident(ctx, handle)) {
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glMakeTextureHandleResidentARB(already resident)");
>> +      return;
>> +   }
>> +
>> +   make_texture_handle_resident(ctx, handleObj, handle, true);
>>  }
>>
>>  void GLAPIENTRY
>>  _mesa_MakeTextureHandleNonResidentARB(GLuint64 handle)
>>  {
>> +   struct gl_texture_handle_object *handleObj;
>> +
>> +   GET_CURRENT_CONTEXT(ctx);
>> +
>> +   if (!_mesa_has_ARB_bindless_texture(ctx)) {
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glMakeTextureHandleNonResidentARB(unsupported)");
>> +      return;
>> +   }
>> +
>> +   /* The ARB_bindless_texture spec says:
>> +    *
>> +    * "The error INVALID_OPERATION is generated by
>> +    *  MakeTextureHandleNonResidentARB if <handle> is not a valid 
>> texture
>> +    *  handle, or if <handle> is not resident in the current GL 
>> context."
>> +    */
>> +   handleObj = lookup_texture_handle(ctx, handle);
>> +   if (!handleObj) {
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glMakeTextureHandleNonResidentARB(handle)");
>> +      return;
>> +   }
>> +
>> +   if (!is_texture_handle_resident(ctx, handle)) {
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glMakeTextureHandleNonResidentARB(not resident)");
>> +      return;
>> +   }
>> +
>> +   make_texture_handle_resident(ctx, handleObj, handle, false);
>>  }
>>
>>  GLuint64 GLAPIENTRY
>>  _mesa_GetImageHandleARB(GLuint texture, GLint level, GLboolean layered,
>>                          GLint layer, GLenum format)
>>  {
>> -   return 0;
>> +   struct gl_texture_object *texObj = NULL;
>> +
>> +   GET_CURRENT_CONTEXT(ctx);
>> +
>> +   if (!_mesa_has_ARB_bindless_texture(ctx) &&
>> +       !_mesa_has_ARB_shader_image_load_store(ctx)) {
> 
> || instead of &&

Right.

> 
> 
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glGetImageHandleARB(unsupported)");
>> +      return 0;
>> +   }
>> +
>> +   /* The ARB_bindless_texture spec says:
>> +    *
>> +    * "The error INVALID_VALUE is generated by GetImageHandleARB if 
>> <texture>
>> +    *  is zero or not the name of an existing texture object, if the 
>> image for
>> +    *  <level> does not existing in <texture>, or if <layered> is 
>> FALSE and
>> +    *  <layer> is greater than or equal to the number of layers in 
>> the image at
>> +    *  <level>."
>> +    */
>> +   if (texture > 0)
>> +      texObj = _mesa_lookup_texture(ctx, texture);
>> +
>> +   if (!texObj) {
>> +      _mesa_error(ctx, GL_INVALID_VALUE, 
>> "glGetImageHandleARB(texture)");
>> +      return 0;
>> +   }
>> +
>> +   if (level < 0 || level >= _mesa_max_texture_levels(ctx, 
>> texObj->Target)) {
>> +      _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(level)");
>> +      return 0;
>> +   }
>> +
>> +   if (!layered && layer > _mesa_get_texture_layers(texObj, level)) {
>> +      _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(layer)");
>> +      return 0;
>> +   }
>> +
>> +   if (!_mesa_is_shader_image_format_supported(ctx, format)) {
>> +      _mesa_error(ctx, GL_INVALID_VALUE, "glGetImageHandleARB(format)");
>> +      return 0;
>> +   }
>> +
>> +   /* The ARB_bindless_texture spec says:
>> +    *
>> +    * "The error INVALID_OPERATION is generated by GetImageHandleARB 
>> if the
>> +    *  texture object <texture> is not complete or if <layered> is 
>> TRUE and
>> +    *  <texture> is not a three-dimensional, one-dimensional array, two
>> +    *  dimensional array, cube map, or cube map array texture."
>> +    */
>> +   if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
>> +      _mesa_test_texobj_completeness(ctx, texObj);
>> +      if (!_mesa_is_texture_complete(texObj, &texObj->Sampler)) {
>> +         _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                     "glGetImageHandleARB(incomplete texture)");
>> +         return 0;
>> +      }
>> +   }
>> +
>> +   if (layered && !_mesa_tex_target_is_layered(texObj->Target)) {
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glGetImageHandleARB(not layered)");
>> +      return 0;
>> +   }
>> +
>> +   return get_image_handle(ctx, texObj, level, layered, layer, format);
>>  }
>>
>>  void GLAPIENTRY
>>  _mesa_MakeImageHandleResidentARB(GLuint64 handle, GLenum access)
>>  {
>> +   struct gl_image_handle_object *handleObj;
>> +
>> +   GET_CURRENT_CONTEXT(ctx);
>> +
>> +   if (!_mesa_has_ARB_bindless_texture(ctx) &&
>> +       !_mesa_has_ARB_shader_image_load_store(ctx)) {
> 
> || instead of &&
> 
> 
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glMakeImageHandleResidentARB(unsupported)");
>> +      return;
>> +   }
>> +
>> +   if (access != GL_READ_ONLY &&
>> +       access != GL_WRITE_ONLY &&
>> +       access != GL_READ_WRITE) {
>> +      _mesa_error(ctx, GL_INVALID_ENUM,
>> +                  "glMakeImageHandleResidentARB(access)");
>> +      return;
>> +   }
>> +
>> +   /* The ARB_bindless_texture spec says:
>> +    *
>> +    * "The error INVALID_OPERATION is generated by 
>> MakeImageHandleResidentARB
>> +    *  if <handle> is not a valid image handle, or if <handle> is 
>> already
>> +    *  resident in the current GL context."
>> +    */
>> +   handleObj = lookup_image_handle(ctx, handle);
>> +   if (!handleObj) {
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glMakeImageHandleResidentARB(handle)");
>> +      return;
>> +   }
>> +
>> +   if (is_image_handle_resident(ctx, handle)) {
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glMakeImageHandleResidentARB(already resident)");
>> +      return;
>> +   }
>> +
>> +   make_image_handle_resident(ctx, handleObj, handle, access, true);
>>  }
>>
>>  void GLAPIENTRY
>>  _mesa_MakeImageHandleNonResidentARB(GLuint64 handle)
>>  {
>> +   struct gl_image_handle_object *handleObj;
>> +
>> +   GET_CURRENT_CONTEXT(ctx);
>> +
>> +   if (!_mesa_has_ARB_bindless_texture(ctx) &&
>> +       !_mesa_has_ARB_shader_image_load_store(ctx)) {
> 
> || vs. &&
> 
> 
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glMakeImageHandleNonResidentARB(unsupported)");
>> +      return;
>> +   }
>> +
>> +   /* The ARB_bindless_texture spec says:
>> +    *
>> +    * "The error INVALID_OPERATION is generated by
>> +    *  MakeImageHandleNonResidentARB if <handle> is not a valid image 
>> handle,
>> +    *  or if <handle> is not resident in the current GL context."
>> +    */
>> +   handleObj = lookup_image_handle(ctx, handle);
>> +   if (!handleObj) {
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glMakeImageHandleNonResidentARB(handle)");
>> +      return;
>> +   }
>> +
>> +   if (!is_image_handle_resident(ctx, handle)) {
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glMakeImageHandleNonResidentARB(not resident)");
>> +      return;
>> +   }
>> +
>> +   make_image_handle_resident(ctx, handleObj, handle, GL_READ_ONLY, 
>> false);
>>  }
>>
>>  GLboolean GLAPIENTRY
>>  _mesa_IsTextureHandleResidentARB(GLuint64 handle)
>>  {
>> -   return GL_FALSE;
>> +   GET_CURRENT_CONTEXT(ctx);
>> +
>> +   if (!_mesa_has_ARB_bindless_texture(ctx)) {
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glIsTextureHandleResidentARB(unsupported)");
>> +      return GL_FALSE;
>> +   }
>> +
>> +   /* The ARB_bindless_texture spec says:
>> +    *
>> +    * "The error INVALID_OPERATION will be generated by
>> +    *  IsTextureHandleResidentARB and IsImageHandleResidentARB if 
>> <handle> is
>> +    *  not a valid texture or image handle, respectively."
>> +    */
>> +   if (!lookup_texture_handle(ctx, handle)) {
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glIsTextureHandleResidentARB(handle)");
>> +      return GL_FALSE;
>> +   }
>> +
>> +   return is_texture_handle_resident(ctx, handle);
>>  }
>>
>>  GLboolean GLAPIENTRY
>>  _mesa_IsImageHandleResidentARB(GLuint64 handle)
>>  {
>> -   return GL_FALSE;
>> +   GET_CURRENT_CONTEXT(ctx);
>> +
>> +   if (!_mesa_has_ARB_bindless_texture(ctx) &&
>> +       !_mesa_has_ARB_shader_image_load_store(ctx)) {
> 
> || instead of &&
> 
> Cheers,
> Nicolai
> 
> 
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glIsImageHandleResidentARB(unsupported)");
>> +      return GL_FALSE;
>> +   }
>> +
>> +   /* The ARB_bindless_texture spec says:
>> +    *
>> +    * "The error INVALID_OPERATION will be generated by
>> +    *  IsTextureHandleResidentARB and IsImageHandleResidentARB if 
>> <handle> is
>> +    *  not a valid texture or image handle, respectively."
>> +    */
>> +   if (!lookup_image_handle(ctx, handle)) {
>> +      _mesa_error(ctx, GL_INVALID_OPERATION,
>> +                  "glIsImageHandleResidentARB(handle)");
>> +      return GL_FALSE;
>> +   }
>> +
>> +   return is_image_handle_resident(ctx, handle);
>>  }
>> diff --git a/src/mesa/main/texturebindless.h 
>> b/src/mesa/main/texturebindless.h
>> index 88b84ce275..bdee74121e 100644
>> --- a/src/mesa/main/texturebindless.h
>> +++ b/src/mesa/main/texturebindless.h
>> @@ -31,6 +31,34 @@ extern "C" {
>>  #endif
>>
>>  /**
>> + * \name Internal functions
>> + */
>> +/*@{*/
>> +
>> +void
>> +_mesa_init_resident_handles(struct gl_context *ctx);
>> +
>> +void
>> +_mesa_free_resident_handles(struct gl_context *ctx);
>> +
>> +void
>> +_mesa_init_texture_handles(struct gl_texture_object *texObj);
>> +void
>> +_mesa_make_texture_handles_non_resident(struct gl_context *ctx,
>> +                                        struct gl_texture_object 
>> *texObj);
>> +void
>> +_mesa_delete_texture_handles(struct gl_context *ctx,
>> +                             struct gl_texture_object *texObj);
>> +
>> +void
>> +_mesa_init_sampler_handles(struct gl_sampler_object *sampObj);
>> +void
>> +_mesa_delete_sampler_handles(struct gl_context *ctx,
>> +                             struct gl_sampler_object *sampObj);
>> +
>> +/*@}*/
>> +
>> +/**
>>   * \name API functions
>>   */
>>  /*@{*/
>>
> 
> 


More information about the mesa-dev mailing list