[Mesa-dev] [RFC PATCH] st/mesa: skip texture validation logic when nothing has changed

Timothy Arceri tarceri at itsqueeze.com
Sat Jun 10 04:52:46 UTC 2017


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



More information about the mesa-dev mailing list