mesa: implement ARB_bindless_texture

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
This commit is contained in:
Samuel Pitoiset
2017-04-03 22:06:27 +02:00
parent 6649b840c3
commit 1fe7b1f972
8 changed files with 960 additions and 7 deletions

View File

@@ -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);

View File

@@ -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);
/*@}*/
};

View File

@@ -47,6 +47,7 @@
#include "main/formats.h" /* MESA_FORMAT_COUNT */
#include "compiler/glsl/list.h"
#include "util/bitscan.h"
#include "util/u_dynarray.h"
#ifdef __cplusplus
@@ -988,6 +989,10 @@ 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 */
/** GL_ARB_bindless_texture */
struct util_dynarray Handles;
bool HandleAllocated;
};
@@ -1052,6 +1057,11 @@ struct gl_texture_object
/** GL_ARB_shader_image_load_store */
GLenum ImageFormatCompatibilityType;
/** GL_ARB_bindless_texture */
struct util_dynarray SamplerHandles;
struct util_dynarray ImageHandles;
bool HandleAllocated;
};
@@ -1404,6 +1414,8 @@ struct gl_buffer_object
unsigned MinMaxCacheHitIndices;
unsigned MinMaxCacheMissIndices;
bool MinMaxCacheDirty;
bool HandleAllocated; /**< GL_ARB_bindless_texture */
};
@@ -3212,6 +3224,11 @@ struct gl_shared_state
/** GL_ARB_sampler_objects */
struct _mesa_HashTable *SamplerObjects;
/* GL_ARB_bindless_texture */
struct hash_table_u64 *TextureHandles;
struct hash_table_u64 *ImageHandles;
mtx_t HandlesMutex; /**< For texture/image handles safety */
/**
* Some context in this share group was affected by a GPU reset
*
@@ -4515,6 +4532,19 @@ struct gl_subroutine_index_binding
GLuint *IndexPtr;
};
struct gl_texture_handle_object
{
struct gl_texture_object *texObj;
struct gl_sampler_object *sampObj;
GLuint64 handle;
};
struct gl_image_handle_object
{
struct gl_image_unit imgObj;
GLuint64 handle;
};
/**
* Mesa rendering context.
*
@@ -4869,6 +4899,14 @@ struct gl_context
GLfloat PrimitiveBoundingBox[8];
struct disk_cache *Cache;
/**
* \name GL_ARB_bindless_texture
*/
/*@{*/
struct hash_table_u64 *ResidentTextureHandles;
struct hash_table_u64 *ResidentImageHandles;
/*@}*/
};
/**

View File

@@ -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);
}
/**

View File

@@ -39,6 +39,7 @@
#include "shaderapi.h"
#include "shaderobj.h"
#include "syncobj.h"
#include "texturebindless.h"
#include "util/hash_table.h"
#include "util/set.h"
@@ -84,6 +85,9 @@ _mesa_alloc_shared_state(struct gl_context *ctx)
/* GL_ARB_sampler_objects */
shared->SamplerObjects = _mesa_NewHashTable();
/* GL_ARB_bindless_texture */
_mesa_init_shared_handles(shared);
/* Allocate the default buffer object */
shared->NullBufferObj = ctx->Driver.NewBufferObject(ctx, 0);
@@ -373,6 +377,8 @@ free_shared_state(struct gl_context *ctx, struct gl_shared_state *shared)
_mesa_HashDeleteAll(shared->TexObjects, delete_texture_cb, ctx);
_mesa_DeleteHashTable(shared->TexObjects);
_mesa_free_shared_handles(shared);
mtx_destroy(&shared->Mutex);
mtx_destroy(&shared->TexMutex);

View File

@@ -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,11 @@ _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;

View File

@@ -25,61 +25,899 @@
#include "context.h"
#include "enums.h"
#include "imports.h"
#include "macros.h"
#include "hash.h"
#include "mtypes.h"
#include "shaderimage.h"
#include "teximage.h"
#include "texobj.h"
#include "texturebindless.h"
#include "util/set.h"
#include "util/hash_table.h"
/**
* Return the gl_texture_handle_object for a given 64-bit handle.
*/
static struct gl_texture_handle_object *
lookup_texture_handle(struct gl_context *ctx, GLuint64 id)
{
struct gl_texture_handle_object *texHandleObj;
mtx_lock(&ctx->Shared->HandlesMutex);
texHandleObj = (struct gl_texture_handle_object *)
_mesa_hash_table_u64_search(ctx->Shared->TextureHandles, id);
mtx_unlock(&ctx->Shared->HandlesMutex);
return texHandleObj;
}
/**
* Return the gl_image_handle_object for a given 64-bit handle.
*/
static struct gl_image_handle_object *
lookup_image_handle(struct gl_context *ctx, GLuint64 id)
{
struct gl_image_handle_object *imgHandleObj;
mtx_lock(&ctx->Shared->HandlesMutex);
imgHandleObj = (struct gl_image_handle_object *)
_mesa_hash_table_u64_search(ctx->Shared->ImageHandles, id);
mtx_unlock(&ctx->Shared->HandlesMutex);
return imgHandleObj;
}
/**
* Delete a texture handle in the shared state.
*/
static void
delete_texture_handle(struct gl_context *ctx, GLuint64 id)
{
mtx_lock(&ctx->Shared->HandlesMutex);
_mesa_hash_table_u64_remove(ctx->Shared->TextureHandles, id);
mtx_unlock(&ctx->Shared->HandlesMutex);
ctx->Driver.DeleteTextureHandle(ctx, id);
}
/**
* Delete an image handle in the shared state.
*/
static void
delete_image_handle(struct gl_context *ctx, GLuint64 id)
{
mtx_lock(&ctx->Shared->HandlesMutex);
_mesa_hash_table_u64_remove(ctx->Shared->ImageHandles, id);
mtx_unlock(&ctx->Shared->HandlesMutex);
ctx->Driver.DeleteImageHandle(ctx, id);
}
/**
* 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_u64_search(ctx->ResidentTextureHandles,
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_u64_search(ctx->ResidentImageHandles,
handle) != NULL;
}
/**
* Make 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 *texHandleObj,
bool resident)
{
struct gl_sampler_object *sampObj = NULL;
struct gl_texture_object *texObj = NULL;
GLuint64 handle = texHandleObj->handle;
if (resident) {
assert(!is_texture_handle_resident(ctx, handle));
_mesa_hash_table_u64_insert(ctx->ResidentTextureHandles, handle,
texHandleObj);
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, texHandleObj->texObj);
if (texHandleObj->sampObj)
_mesa_reference_sampler_object(ctx, &sampObj, texHandleObj->sampObj);
} else {
assert(is_texture_handle_resident(ctx, handle));
_mesa_hash_table_u64_remove(ctx->ResidentTextureHandles, handle);
ctx->Driver.MakeTextureHandleResident(ctx, handle, GL_FALSE);
/* Unreference the texture object but keep the pointer intact, if
* refcount hits zero, the texture and all handles will be deleted.
*/
texObj = texHandleObj->texObj;
_mesa_reference_texobj(&texObj, NULL);
/* Unreference the separate sampler object but keep the pointer intact,
* if refcount hits zero, the sampler and all handles will be deleted.
*/
if (texHandleObj->sampObj) {
sampObj = texHandleObj->sampObj;
_mesa_reference_sampler_object(ctx, &sampObj, NULL);
}
}
}
/**
* Make 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 *imgHandleObj,
GLenum access, bool resident)
{
struct gl_texture_object *texObj = NULL;
GLuint64 handle = imgHandleObj->handle;
if (resident) {
assert(!is_image_handle_resident(ctx, handle));
_mesa_hash_table_u64_insert(ctx->ResidentImageHandles, handle,
imgHandleObj);
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, imgHandleObj->imgObj.TexObj);
} else {
assert(is_image_handle_resident(ctx, handle));
_mesa_hash_table_u64_remove(ctx->ResidentImageHandles, handle);
ctx->Driver.MakeImageHandleResident(ctx, handle, access, GL_FALSE);
/* Unreference the texture object but keep the pointer intact, if
* refcount hits zero, the texture and all handles will be deleted.
*/
texObj = imgHandleObj->imgObj.TexObj;
_mesa_reference_texobj(&texObj, NULL);
}
}
static struct gl_texture_handle_object *
find_texhandleobj(struct gl_texture_object *texObj,
struct gl_sampler_object *sampObj)
{
util_dynarray_foreach(&texObj->SamplerHandles,
struct gl_texture_handle_object *, texHandleObj) {
if ((*texHandleObj)->sampObj == sampObj)
return *texHandleObj;
}
return NULL;
}
static GLuint64
get_texture_handle(struct gl_context *ctx, struct gl_texture_object *texObj,
struct gl_sampler_object *sampObj)
{
bool separate_sampler = &texObj->Sampler != sampObj;
struct gl_texture_handle_object *texHandleObj;
GLuint64 handle;
/* 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);
texHandleObj = find_texhandleobj(texObj, separate_sampler ? sampObj : NULL);
if (texHandleObj) {
mtx_unlock(&ctx->Shared->HandlesMutex);
return texHandleObj->handle;
}
/* Request a new texture handle from the driver. */
handle = ctx->Driver.NewTextureHandle(ctx, texObj, sampObj);
if (!handle) {
mtx_unlock(&ctx->Shared->HandlesMutex);
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexture*HandleARB()");
return 0;
}
texHandleObj = CALLOC_STRUCT(gl_texture_handle_object);
if (!texHandleObj) {
mtx_unlock(&ctx->Shared->HandlesMutex);
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexture*HandleARB()");
return 0;
}
/* Store the handle into the texture object. */
texHandleObj->texObj = texObj;
texHandleObj->sampObj = separate_sampler ? sampObj : NULL;
texHandleObj->handle = handle;
util_dynarray_append(&texObj->SamplerHandles,
struct gl_texture_handle_object *, texHandleObj);
if (separate_sampler) {
/* Store the handle into the separate sampler if needed. */
util_dynarray_append(&sampObj->Handles,
struct gl_texture_handle_object *, texHandleObj);
}
/* When referenced by one or more handles, texture objects are immutable. */
texObj->HandleAllocated = true;
if (texObj->Target == GL_TEXTURE_BUFFER)
texObj->BufferObject->HandleAllocated = true;
sampObj->HandleAllocated = true;
/* Store the handle in the shared state for all contexts. */
_mesa_hash_table_u64_insert(ctx->Shared->TextureHandles, handle,
texHandleObj);
mtx_unlock(&ctx->Shared->HandlesMutex);
return handle;
}
static struct gl_image_handle_object *
find_imghandleobj(struct gl_texture_object *texObj, GLint level,
GLboolean layered, GLint layer, GLenum format)
{
util_dynarray_foreach(&texObj->ImageHandles,
struct gl_image_handle_object *, imgHandleObj) {
struct gl_image_unit *u = &(*imgHandleObj)->imgObj;
if (u->TexObj == texObj && u->Level == level && u->Layered == layered &&
u->Layer == layer && u->Format == format)
return *imgHandleObj;
}
return NULL;
}
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 *imgHandleObj;
struct gl_image_unit imgObj;
GLuint64 handle;
/* 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);
imgHandleObj = find_imghandleobj(texObj, level, layered, layer, format);
if (imgHandleObj) {
mtx_unlock(&ctx->Shared->HandlesMutex);
return imgHandleObj->handle;
}
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;
}
/* Request a new image handle from the driver. */
handle = ctx->Driver.NewImageHandle(ctx, &imgObj);
if (!handle) {
mtx_unlock(&ctx->Shared->HandlesMutex);
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetImageHandleARB()");
return 0;
}
imgHandleObj = CALLOC_STRUCT(gl_image_handle_object);
if (!imgHandleObj) {
mtx_unlock(&ctx->Shared->HandlesMutex);
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetImageHandleARB()");
return 0;
}
/* Store the handle into the texture object. */
memcpy(&imgHandleObj->imgObj, &imgObj, sizeof(struct gl_image_unit));
imgHandleObj->handle = handle;
util_dynarray_append(&texObj->ImageHandles,
struct gl_image_handle_object *, imgHandleObj);
/* 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_u64_insert(ctx->Shared->ImageHandles, handle, imgHandleObj);
mtx_unlock(&ctx->Shared->HandlesMutex);
return handle;
}
/**
* Init/free per-context resident handles.
*/
void
_mesa_init_resident_handles(struct gl_context *ctx)
{
ctx->ResidentTextureHandles = _mesa_hash_table_u64_create(NULL);
ctx->ResidentImageHandles = _mesa_hash_table_u64_create(NULL);
}
void
_mesa_free_resident_handles(struct gl_context *ctx)
{
_mesa_hash_table_u64_destroy(ctx->ResidentTextureHandles, NULL);
_mesa_hash_table_u64_destroy(ctx->ResidentImageHandles, NULL);
}
/**
* Init/free shared allocated handles.
*/
void
_mesa_init_shared_handles(struct gl_shared_state *shared)
{
shared->TextureHandles = _mesa_hash_table_u64_create(NULL);
shared->ImageHandles = _mesa_hash_table_u64_create(NULL);
mtx_init(&shared->HandlesMutex, mtx_recursive);
}
void
_mesa_free_shared_handles(struct gl_shared_state *shared)
{
_mesa_hash_table_u64_destroy(shared->TextureHandles, NULL);
_mesa_hash_table_u64_destroy(shared->ImageHandles, NULL);
mtx_destroy(&shared->HandlesMutex);
}
/**
* Init/free texture/image handles per-texture object.
*/
void
_mesa_init_texture_handles(struct gl_texture_object *texObj)
{
util_dynarray_init(&texObj->SamplerHandles, NULL);
util_dynarray_init(&texObj->ImageHandles, NULL);
}
void
_mesa_make_texture_handles_non_resident(struct gl_context *ctx,
struct gl_texture_object *texObj)
{
mtx_lock(&ctx->Shared->HandlesMutex);
/* Texture handles */
util_dynarray_foreach(&texObj->SamplerHandles,
struct gl_texture_handle_object *, texHandleObj) {
if (is_texture_handle_resident(ctx, (*texHandleObj)->handle))
make_texture_handle_resident(ctx, *texHandleObj, false);
}
/* Image handles */
util_dynarray_foreach(&texObj->ImageHandles,
struct gl_image_handle_object *, imgHandleObj) {
if (is_image_handle_resident(ctx, (*imgHandleObj)->handle))
make_image_handle_resident(ctx, *imgHandleObj, GL_READ_ONLY, false);
}
mtx_unlock(&ctx->Shared->HandlesMutex);
}
void
_mesa_delete_texture_handles(struct gl_context *ctx,
struct gl_texture_object *texObj)
{
/* Texture handles */
util_dynarray_foreach(&texObj->SamplerHandles,
struct gl_texture_handle_object *, texHandleObj) {
struct gl_sampler_object *sampObj = (*texHandleObj)->sampObj;
if (sampObj) {
/* Delete the handle in the separate sampler object. */
util_dynarray_delete_unordered(&sampObj->Handles,
struct gl_texture_handle_object *,
*texHandleObj);
}
delete_texture_handle(ctx, (*texHandleObj)->handle);
free(*texHandleObj);
}
util_dynarray_fini(&texObj->SamplerHandles);
/* Image handles */
util_dynarray_foreach(&texObj->ImageHandles,
struct gl_image_handle_object *, imgHandleObj) {
delete_image_handle(ctx, (*imgHandleObj)->handle);
free(*imgHandleObj);
}
util_dynarray_fini(&texObj->ImageHandles);
}
/**
* Init/free texture handles per-sampler object.
*/
void
_mesa_init_sampler_handles(struct gl_sampler_object *sampObj)
{
util_dynarray_init(&sampObj->Handles, NULL);
}
void
_mesa_delete_sampler_handles(struct gl_context *ctx,
struct gl_sampler_object *sampObj)
{
util_dynarray_foreach(&sampObj->Handles,
struct gl_texture_handle_object *, texHandleObj) {
struct gl_texture_object *texObj = (*texHandleObj)->texObj;
/* Delete the handle in the texture object. */
util_dynarray_delete_unordered(&texObj->SamplerHandles,
struct gl_texture_handle_object *,
*texHandleObj);
delete_texture_handle(ctx, (*texHandleObj)->handle);
free(*texHandleObj);
}
util_dynarray_fini(&sampObj->Handles);
}
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 *texHandleObj;
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."
*/
texHandleObj = lookup_texture_handle(ctx, handle);
if (!texHandleObj) {
_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, texHandleObj, true);
}
void GLAPIENTRY
_mesa_MakeTextureHandleNonResidentARB(GLuint64 handle)
{
struct gl_texture_handle_object *texHandleObj;
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."
*/
texHandleObj = lookup_texture_handle(ctx, handle);
if (!texHandleObj) {
_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, texHandleObj, 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)) {
_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 *imgHandleObj;
GET_CURRENT_CONTEXT(ctx);
if (!_mesa_has_ARB_bindless_texture(ctx) ||
!_mesa_has_ARB_shader_image_load_store(ctx)) {
_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."
*/
imgHandleObj = lookup_image_handle(ctx, handle);
if (!imgHandleObj) {
_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, imgHandleObj, access, true);
}
void GLAPIENTRY
_mesa_MakeImageHandleNonResidentARB(GLuint64 handle)
{
struct gl_image_handle_object *imgHandleObj;
GET_CURRENT_CONTEXT(ctx);
if (!_mesa_has_ARB_bindless_texture(ctx) ||
!_mesa_has_ARB_shader_image_load_store(ctx)) {
_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."
*/
imgHandleObj = lookup_image_handle(ctx, handle);
if (!imgHandleObj) {
_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, imgHandleObj, 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)) {
_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);
}

View File

@@ -30,6 +30,38 @@
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_shared_handles(struct gl_shared_state *shared);
void
_mesa_free_shared_handles(struct gl_shared_state *shared);
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
*/