diff --git a/src/mesa/main/texstorage.c b/src/mesa/main/texstorage.c index 8fe9a46603b..e7f871a71d5 100644 --- a/src/mesa/main/texstorage.c +++ b/src/mesa/main/texstorage.c @@ -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, + * * 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: + * - is not a multiple of VIRTUAL_PAGE_SIZE_X_ARB * + * 2^(-1), or + * - is not a multiple of VIRTUAL_PAGE_SIZE_Y_ARB * + * 2^(-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); diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c index b4b038c3bc9..d1a2e482ade 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.c +++ b/src/mesa/state_tracker/st_cb_bitmap.c @@ -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); } diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index 3635d266e62..b7037e1a3ba 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -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; } diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index 1a5c14cbc7c..6c2ba9f26b8 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -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) diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c index e0bed2ded3d..5155364038e 100644 --- a/src/mesa/state_tracker/st_texture.c +++ b/src/mesa/state_tracker/st_texture.c @@ -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; } diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h index c9d670f8576..7806631c292 100644 --- a/src/mesa/state_tracker/st_texture.h +++ b/src/mesa/state_tracker/st_texture.h @@ -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