mesa: glTexStorage* support sparse texture allocation

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Signed-off-by: Qiang Yu <yuq825@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14223>
This commit is contained in:
Qiang Yu 2021-12-08 16:05:05 +08:00
parent 482fe76300
commit 34e5c14f70
6 changed files with 106 additions and 10 deletions

View file

@ -384,6 +384,87 @@ tex_storage_error_check(struct gl_context *ctx,
return GL_FALSE;
}
static GLboolean
sparse_texture_error_check(struct gl_context *ctx, GLuint dims,
struct gl_texture_object *texObj,
mesa_format format, GLenum target, GLsizei levels,
GLsizei width, GLsizei height, GLsizei depth,
bool dsa)
{
const char* suffix = dsa ? "ture" : "";
int px, py, pz;
int index = texObj->VirtualPageSizeIndex;
if (!st_GetSparseTextureVirtualPageSize(ctx, target, format, index,
&px, &py, &pz)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(sparse index = %d)",
suffix, dims, index);
return GL_TRUE;
}
if (target == GL_TEXTURE_3D) {
if (width > ctx->Const.MaxSparse3DTextureSize ||
height > ctx->Const.MaxSparse3DTextureSize ||
depth > ctx->Const.MaxSparse3DTextureSize)
goto exceed_max_size;
} else {
if (width > ctx->Const.MaxSparseTextureSize ||
height > ctx->Const.MaxSparseTextureSize)
goto exceed_max_size;
if (target == GL_TEXTURE_2D_ARRAY ||
target == GL_TEXTURE_CUBE_MAP_ARRAY) {
if (depth > ctx->Const.MaxSparseArrayTextureLayers)
goto exceed_max_size;
} else if (target == GL_TEXTURE_1D_ARRAY) {
if (height > ctx->Const.MaxSparseArrayTextureLayers)
goto exceed_max_size;
}
}
if (width % px || height % py || depth % pz) {
_mesa_error(ctx, GL_INVALID_VALUE, "glTex%sStorage%uD(sparse page size)",
suffix, dims);
return GL_TRUE;
}
/* ARB_sparse_texture spec:
*
* If the value of SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB is FALSE,
* then TexStorage* will generate an INVALID_OPERATION error if
* * the texture's TEXTURE_SPARSE_ARB parameter is TRUE,
* * <target> is one of TEXTURE_1D_ARRAY, TEXTURE_2D_ARRAY,
* TEXTURE_CUBE_MAP, or TEXTURE_CUBE_MAP_ARRAY, and
* * for the virtual page size corresponding to the
* VIRTUAL_PAGE_SIZE_INDEX_ARB parameter, either of the following is
* true:
* - <width> is not a multiple of VIRTUAL_PAGE_SIZE_X_ARB *
* 2^(<levels>-1), or
* - <height> is not a multiple of VIRTUAL_PAGE_SIZE_Y_ARB *
* 2^(<levels>-1).
*
* This make sure all allocated mipmap level size is multiple of virtual
* page size when SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB is FALSE.
*/
if (!ctx->Const.SparseTextureFullArrayCubeMipmaps &&
(target == GL_TEXTURE_1D_ARRAY ||
target == GL_TEXTURE_2D_ARRAY ||
target == GL_TEXTURE_CUBE_MAP ||
target == GL_TEXTURE_CUBE_MAP_ARRAY) &&
(width % (px << (levels - 1)) ||
height % (py << (levels - 1)))) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(sparse array align)",
suffix, dims);
return GL_TRUE;
}
return GL_FALSE;
exceed_max_size:
_mesa_error(ctx, GL_INVALID_VALUE, "glTex%sStorage%uD(exceed max sparse size)",
suffix, dims);
return GL_TRUE;
}
/**
* Helper that does the storage allocation for _mesa_TexStorage1/2/3D()
@ -448,6 +529,11 @@ texture_storage(struct gl_context *ctx, GLuint dims,
suffix, dims);
return;
}
if (texObj->IsSparse &&
sparse_texture_error_check(ctx, dims, texObj, texFormat, target, levels,
width, height, depth, dsa))
return; /* error was recorded */
}
assert(levels > 0);

View file

@ -137,7 +137,7 @@ make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
*/
pt = st_texture_create(st, st->internal_target, st->bitmap.tex_format,
0, width, height, 1, 1, 0,
PIPE_BIND_SAMPLER_VIEW);
PIPE_BIND_SAMPLER_VIEW, false);
if (!pt) {
_mesa_unmap_pbo_source(ctx, unpack);
return NULL;
@ -363,7 +363,8 @@ reset_cache(struct st_context *st)
st->bitmap.tex_format, 0,
BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
1, 1, 0,
PIPE_BIND_SAMPLER_VIEW);
PIPE_BIND_SAMPLER_VIEW,
false);
}

View file

@ -473,7 +473,7 @@ alloc_texture(struct st_context *st, GLsizei width, GLsizei height,
struct pipe_resource *pt;
pt = st_texture_create(st, st->internal_target, texFormat, 0,
width, height, 1, 1, 0, bind);
width, height, 1, 1, 0, bind, false);
return pt;
}

View file

@ -985,7 +985,8 @@ guess_and_alloc_texture(struct st_context *st,
ptHeight,
ptDepth,
ptLayers, 0,
bindings);
bindings,
false);
stObj->lastLevel = lastLevel;
@ -1080,7 +1081,8 @@ st_AllocTextureImageBuffer(struct gl_context *ctx,
ptHeight,
ptDepth,
ptLayers, 0,
bindings);
bindings,
false);
return stImage->pt != NULL;
}
}
@ -3126,7 +3128,8 @@ st_finalize_texture(struct gl_context *ctx,
ptHeight,
ptDepth,
ptLayers, ptNumSamples,
bindings);
bindings,
false);
if (!stObj->pt) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
@ -3337,7 +3340,8 @@ st_texture_storage(struct gl_context *ctx,
ptHeight,
ptDepth,
ptLayers, num_samples,
bindings);
bindings,
texObj->IsSparse);
}
if (!stObj->pt)

View file

@ -63,7 +63,8 @@ st_texture_create(struct st_context *st,
GLuint depth0,
GLuint layers,
GLuint nr_samples,
GLuint bind)
GLuint bind,
bool sparse)
{
struct pipe_resource pt, *newtex;
struct pipe_screen *screen = st->screen;
@ -97,6 +98,9 @@ st_texture_create(struct st_context *st,
pt.nr_samples = nr_samples;
pt.nr_storage_samples = nr_samples;
if (sparse)
pt.flags |= PIPE_RESOURCE_FLAG_SPARSE;
newtex = screen->resource_create(screen, &pt);
assert(!newtex || pipe_is_referenced(&newtex->reference));
@ -422,7 +426,7 @@ st_create_color_map_texture(struct gl_context *ctx)
/* create texture for color map/table */
pt = st_texture_create(st, PIPE_TEXTURE_2D, format, 0,
texSize, texSize, 1, 1, 0, PIPE_BIND_SAMPLER_VIEW);
texSize, texSize, 1, 1, 0, PIPE_BIND_SAMPLER_VIEW, false);
return pt;
}

View file

@ -287,7 +287,8 @@ st_texture_create(struct st_context *st,
GLuint depth0,
GLuint layers,
GLuint nr_samples,
GLuint tex_usage );
GLuint tex_usage,
bool sparse);
extern void