Based on the same logic in the i965 driver 2f225f61451abd51 and 16060c5adcd4.
perf reports st_finalize_texture() going from 0.60% -> 0.16% with this change when running the Xonotic benchmark from PTS. --- A full run of piglit on radeonsi produced no regressions. No other drivers have been tested. src/mesa/state_tracker/st_cb_texture.c | 28 ++++++++++++++++++++++++++++ src/mesa/state_tracker/st_manager.c | 2 ++ src/mesa/state_tracker/st_texture.h | 9 +++++++++ 3 files changed, 39 insertions(+) diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index 99c59f7..443bb7b 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -147,20 +147,22 @@ st_DeleteTextureImage(struct gl_context * ctx, struct gl_texture_image *img) /** called via ctx->Driver.NewTextureObject() */ static struct gl_texture_object * st_NewTextureObject(struct gl_context * ctx, GLuint name, GLenum target) { struct st_texture_object *obj = ST_CALLOC_STRUCT(st_texture_object); DBG("%s\n", __func__); _mesa_initialize_texture_object(ctx, &obj->base, name, target); + obj->needs_validation = true; + return &obj->base; } /** called via ctx->Driver.DeleteTextureObject() */ static void st_DeleteTextureObject(struct gl_context *ctx, struct gl_texture_object *texObj) { struct st_context *st = st_context(ctx); struct st_texture_object *stObj = st_texture_object(texObj); @@ -599,20 +601,22 @@ st_AllocTextureImageBuffer(struct gl_context *ctx, struct st_texture_object *stObj = st_texture_object(texImage->TexObject); const GLuint level = texImage->Level; GLuint width = texImage->Width; GLuint height = texImage->Height; GLuint depth = texImage->Depth; DBG("%s\n", __func__); assert(!stImage->pt); /* xxx this might be wrong */ + stObj->needs_validation = true; + etc_fallback_allocate(st, stImage); /* Look if the parent texture object has space for this image */ if (stObj->pt && level <= stObj->pt->last_level && st_texture_match_image(st, stObj->pt, texImage)) { /* this image will fit in the existing texture object's memory */ pipe_resource_reference(&stImage->pt, stObj->pt); return GL_TRUE; } @@ -2478,20 +2482,30 @@ st_finalize_texture(struct gl_context *ctx, pipe_resource_reference(&stObj->pt, st_obj->buffer); st_texture_release_all_sampler_views(st, stObj); } return GL_TRUE; } firstImage = st_texture_image_const(stObj->base.Image[cubeMapFace][stObj->base.BaseLevel]); assert(firstImage); + /* Skip the loop over images in the common case of no images having + * changed. But if the GL_BASE_LEVEL or GL_MAX_LEVEL change to something we + * haven't looked at, then we do need to look at those new images. + */ + if (!stObj->needs_validation && + stObj->base.BaseLevel >= stObj->validated_first_level && + stObj->lastLevel <= stObj->validated_last_level) { + return GL_TRUE; + } + /* If both firstImage and stObj point to a texture which can contain * all active images, favour firstImage. Note that because of the * completeness requirement, we know that the image dimensions * will match. */ if (firstImage->pt && firstImage->pt != stObj->pt && (!stObj->pt || firstImage->pt->last_level >= stObj->pt->last_level)) { pipe_resource_reference(&stObj->pt, firstImage->pt); st_texture_release_all_sampler_views(st, stObj); @@ -2624,20 +2638,24 @@ st_finalize_texture(struct gl_context *ctx, (stImage->base.Width == u_minify(ptWidth, level) && stImage->base.Height == height && stImage->base.Depth == depth)) { /* src image fits expected dest mipmap level size */ copy_image_data_to_texture(st, stObj, level, stImage); } } } } + stObj->validated_first_level = stObj->base.BaseLevel; + stObj->validated_last_level = stObj->lastLevel; + stObj->needs_validation = false; + return GL_TRUE; } /** * Called via ctx->Driver.AllocTextureStorage() to allocate texture memory * for a whole mipmap stack. */ static GLboolean st_AllocTextureStorage(struct gl_context *ctx, @@ -2705,20 +2723,25 @@ st_AllocTextureStorage(struct gl_context *ctx, GLuint face; for (face = 0; face < numFaces; face++) { struct st_texture_image *stImage = st_texture_image(texObj->Image[face][level]); pipe_resource_reference(&stImage->pt, stObj->pt); etc_fallback_allocate(st, stImage); } } + /* The texture is in a validated state, so no need to check later. */ + stObj->needs_validation = false; + stObj->validated_first_level = 0; + stObj->validated_last_level = levels - 1; + return GL_TRUE; } static GLboolean st_TestProxyTexImage(struct gl_context *ctx, GLenum target, GLuint numLevels, GLint level, mesa_format format, GLuint numSamples, GLint width, GLint height, GLint depth) { @@ -2803,20 +2826,25 @@ st_TextureView(struct gl_context *ctx, tex->surface_format = st_mesa_format_to_pipe_format(st_context(ctx), image->TexFormat); tex->lastLevel = numLevels - 1; /* free texture sampler views. They need to be recreated when we * change the texture view parameters. */ st_texture_release_all_sampler_views(st, tex); + /* The texture is in a validated state, so no need to check later. */ + tex->needs_validation = false; + tex->validated_first_level = 0; + tex->validated_last_level = numLevels - 1; + return GL_TRUE; } static void st_ClearTexSubImage(struct gl_context *ctx, struct gl_texture_image *texImage, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, const void *clearValue) { diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c index f4c78ae..085f54e 100644 --- a/src/mesa/state_tracker/st_manager.c +++ b/src/mesa/state_tracker/st_manager.c @@ -585,20 +585,22 @@ st_context_teximage(struct st_context_iface *stctxi, } } else { _mesa_clear_texture_image(ctx, texImage); width = height = depth = 0; } pipe_resource_reference(&stImage->pt, tex); stObj->surface_format = pipe_format; + stObj->needs_validation = true; + _mesa_dirty_texobj(ctx, texObj); _mesa_unlock_texture(ctx, texObj); return TRUE; } static void st_context_copy(struct st_context_iface *stctxi, struct st_context_iface *stsrci, unsigned mask) { diff --git a/src/mesa/state_tracker/st_texture.h b/src/mesa/state_tracker/st_texture.h index 1b4d1a3..070b593 100644 --- a/src/mesa/state_tracker/st_texture.h +++ b/src/mesa/state_tracker/st_texture.h @@ -77,20 +77,23 @@ struct st_texture_image * Subclass of gl_texure_object. */ struct st_texture_object { struct gl_texture_object base; /* The "parent" object */ /* The texture must include at levels [0..lastLevel] once validated: */ GLuint lastLevel; + unsigned int validated_first_level; + unsigned int validated_last_level; + /* On validation any active images held in main memory or in other * textures will be copied to this texture and the old storage freed. */ struct pipe_resource *pt; /* Number of views in sampler_views array */ GLuint num_sampler_views; /* Array of sampler views (one per context) attached to this texture * object. Created lazily on first binding in context. @@ -114,20 +117,26 @@ struct st_texture_object * This is used for VDPAU interop, where imported pipe_resources may be * array textures (containing layers with different fields) even though the * GL state describes one non-array texture per field. */ uint layer_override; /** The glsl version of the shader seen during the previous validation */ unsigned prev_glsl_version; /** The value of the sampler's sRGBDecode state at the previous validation */ GLenum prev_sRGBDecode; + + /** + * Set when the texture images of this texture object might not all be the + * pipe_resource *pt above. + */ + bool needs_validation; }; static inline struct st_texture_image * st_texture_image(struct gl_texture_image *img) { return (struct st_texture_image *) img; } static inline const struct st_texture_image * -- 2.9.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev