[Mesa-dev] [RFC PATCH 02/65] mesa: implement ARB_bindless_texture
Nicolai Hähnle
nhaehnle at gmail.com
Fri May 26 14:32:24 UTC 2017
On 26.05.2017 14:09, Samuel Pitoiset wrote:
>
>
> On 05/24/2017 12:10 PM, Nicolai Hähnle wrote:
>> [snip]
>>>>> +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...
>>
>> Right.
>>
>>
>> [snip]
>>>>> +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.
>>
>> Right, resident handles are per-context, but the handles of a texture
>> might be resident in multiple contexts simultaneously. What happens if
>> they are, and then the texture object is deleted?
>
> The ARB_bindless_texture spec says:
>
> (7) What happens if you try to delete a texture or sampler object with a
> handle that is resident in another context?
>
> RESOLVED: Deleting the texture will remove the texture from the name
> space and make all handles using the texture non-resident in the current
> context. However, texture or image handles for a deleted texture are
> not deleted until the underlying texture or sampler object itself is
> deleted. That deletion won't happen until the object is not bound
> anywhere and there are no handles using the object that are resident in
> any context.
>
> Currently, my implementation does exactly this. I think the app should
> handle this.
You're right, I missed that. This part is fine.
Cheers,
Nicolai
>
>>
>> It seems to me that right now, you end up with dangling resident
>> handles in the "other" contexts. At the very least, this can cause
>> incorrect errors when the handle is re-used by the driver for another
>> texture, so *something* needs to loop over all contexts, it seems...
>>
>> Cheers,
>> Nicolai
--
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.
More information about the mesa-dev
mailing list