2018-01-25 18:02 GMT+01:00 Roland Scheidegger <srol...@vmware.com>:

> Am 25.01.2018 um 16:55 schrieb Brian Paul:
> > The newest version of WSI Fusion makes several glDrawPixels calls
> > per frame.  By caching more than one image, we get better performance
> > when panning/zomming the map.
> Still zooming :-)
>
>
>
>
> >
> > v2: move pixel unpack param checking out of cache search loop, per Roland
> > ---
> >  src/mesa/state_tracker/st_cb_drawpixels.c | 196
> +++++++++++++++++++++---------
> >  src/mesa/state_tracker/st_context.c       |   4 -
> >  src/mesa/state_tracker/st_context.h       |  22 +++-
> >  3 files changed, 154 insertions(+), 68 deletions(-)
> >
> > diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c
> b/src/mesa/state_tracker/st_cb_drawpixels.c
> > index 1d88976..e63f6f7 100644
> > --- a/src/mesa/state_tracker/st_cb_drawpixels.c
> > +++ b/src/mesa/state_tracker/st_cb_drawpixels.c
> > @@ -375,6 +375,131 @@ alloc_texture(struct st_context *st, GLsizei
> width, GLsizei height,
> >
> >
> >  /**
> > + * Search the cache for an image which matches the given parameters.
> > + * \return  pipe_resource pointer if found, NULL if not found.
> > + */
> > +static struct pipe_resource *
> > +search_drawpixels_cache(struct st_context *st,
> > +                        GLsizei width, GLsizei height,
> > +                        GLenum format, GLenum type,
> > +                        const struct gl_pixelstore_attrib *unpack,
> > +                        const void *pixels)
> > +{
> > +   struct pipe_resource *pt = NULL;
> > +   const GLint bpp = _mesa_bytes_per_pixel(format, type);
> > +   unsigned i;
> > +
> > +   if ((unpack->RowLength != 0 && unpack->RowLength != width) ||
> > +       unpack->SkipPixels != 0 ||
> > +       unpack->SkipRows != 0 ||
> > +       unpack->SwapBytes) {
> > +      /* we don't allow non-default pixel unpacking values */
> > +      return NULL;
> > +   }
> > +
> > +   /* Search cache entries for a match */
> > +   for (i = 0; i < ARRAY_SIZE(st->drawpix_cache.entries); i++) {
> > +      struct drawpix_cache_entry *entry = &st->drawpix_cache.entries[i];
> > +
> > +      if (width == entry->width &&
> > +          height == entry->height &&
> > +          format == entry->format &&
> > +          type == entry->type &&
> > +          pixels == entry->user_pointer &&
> > +          !_mesa_is_bufferobj(unpack->BufferObj) &&
> Move this line as well?
>
>
>
> > +          entry->image) {
> > +         assert(entry->texture);
> > +
> > +         /* check if the pixel data is the same */
> > +         if (memcmp(pixels, entry->image, width * height * bpp) == 0) {
> > +            /* Success - found a cache match */
> > +            pipe_resource_reference(&pt, entry->texture);
> > +            /* refcount of returned texture should be at least two
> here.  One
> > +             * reference for the cache to hold on to, one for the
> caller (which
> > +             * it will release), and possibly more held by the driver.
> > +             */
> > +            assert(pt->reference.count >= 2);
> > +
> > +            /* update the age of this entry */
> > +            entry->age = ++st->drawpix_cache.age;
> > +
> > +            return pt;
> > +         }
> > +      }
> > +   }
> > +
> > +   /* no cache match found */
> > +   return NULL;
> > +}
> > +
> > +
> > +/**
> > + * Find the oldest entry in the glDrawPixels cache.  We'll replace this
> > + * one when we need to store a new image.
> > + */
> > +static struct drawpix_cache_entry *
> > +find_oldest_drawpixels_cache_entry(struct st_context *st)
> > +{
> > +   unsigned oldest_age = ~0u, oldest_index = ~0u;
> > +   unsigned i;
> > +
> > +   /* Find entry with oldest (lowest) age */
> > +   for (i = 0; i < ARRAY_SIZE(st->drawpix_cache.entries); i++) {
> > +      const struct drawpix_cache_entry *entry =
> &st->drawpix_cache.entries[i];
> > +      if (entry->age < oldest_age) {
> > +         oldest_age = entry->age;
> > +         oldest_index = i;
> > +      }
> > +   }
> > +
> > +   assert(oldest_age != ~0u);
> Ok, if it takes 2 years to hit it, that's probably ok...
>
> Reviewed-by: Roland Scheidegger <srol...@vmware.com>
>

Note that at 13000fps (maximum I could achieve with glxgears) it would take
less than 4 days. Though I guess if you run glDrawPixels each frame you
couldn't achieve such fps value.

Gustaw Smolarczyk


>
> > +   assert(oldest_index != ~0u);
> > +
> > +   return &st->drawpix_cache.entries[oldest_index];
> > +}
> > +
> > +
> > +/**
> > + * Try to save the given glDrawPixels image in the cache.
> > + */
> > +static void
> > +cache_drawpixels_image(struct st_context *st,
> > +                       GLsizei width, GLsizei height,
> > +                       GLenum format, GLenum type,
> > +                       const struct gl_pixelstore_attrib *unpack,
> > +                       const void *pixels,
> > +                       struct pipe_resource *pt)
> > +{
> > +   if ((unpack->RowLength == 0 || unpack->RowLength == width) &&
> > +       unpack->SkipPixels == 0 &&
> > +       unpack->SkipRows == 0) {
> > +      const GLint bpp = _mesa_bytes_per_pixel(format, type);
> > +      struct drawpix_cache_entry *entry =
> > +         find_oldest_drawpixels_cache_entry(st);
> > +      assert(entry);
> > +      entry->width = width;
> > +      entry->height = height;
> > +      entry->format = format;
> > +      entry->type = type;
> > +      entry->user_pointer = pixels;
> > +      free(entry->image);
> > +      entry->image = malloc(width * height * bpp);
> > +      if (entry->image) {
> > +         memcpy(entry->image, pixels, width * height * bpp);
> > +         pipe_resource_reference(&entry->texture, pt);
> > +         entry->age = ++st->drawpix_cache.age;
> > +      }
> > +      else {
> > +         /* out of memory, free/disable cached texture */
> > +         entry->width = 0;
> > +         entry->height = 0;
> > +         pipe_resource_reference(&entry->texture, NULL);
> > +      }
> > +   }
> > +}
> > +
> > +
> > +/**
> >   * Make texture containing an image for glDrawPixels image.
> >   * If 'pixels' is NULL, leave the texture image data undefined.
> >   */
> > @@ -392,44 +517,11 @@ make_texture(struct st_context *st,
> >     GLenum baseInternalFormat;
> >
> >  #if USE_DRAWPIXELS_CACHE
> > -   const GLint bpp = _mesa_bytes_per_pixel(format, type);
> > -
> > -   /* Check if the glDrawPixels() parameters and state matches the
> cache */
> > -   if (width == st->drawpix_cache.width &&
> > -       height == st->drawpix_cache.height &&
> > -       format == st->drawpix_cache.format &&
> > -       type == st->drawpix_cache.type &&
> > -       pixels == st->drawpix_cache.user_pointer &&
> > -       !_mesa_is_bufferobj(unpack->BufferObj) &&
> > -       (unpack->RowLength == 0 || unpack->RowLength == width) &&
> > -       unpack->SkipPixels == 0 &&
> > -       unpack->SkipRows == 0 &&
> > -       unpack->SwapBytes == GL_FALSE &&
> > -       st->drawpix_cache.image) {
> > -      assert(st->drawpix_cache.texture);
> > -
> > -      /* check if the pixel data is the same */
> > -      if (memcmp(pixels, st->drawpix_cache.image, width * height * bpp)
> == 0) {
> > -         /* OK, re-use the cached texture */
> > -         pipe_resource_reference(&pt, st->drawpix_cache.texture);
> > -         /* refcount of returned texture should be at least two here.
> One
> > -          * reference for the cache to hold on to, one for the caller
> (which
> > -          * it will release), and possibly more held by the driver.
> > -          */
> > -         assert(pt->reference.count >= 2);
> > -         return pt;
> > -      }
> > -   }
> > -
> > -   /* discard the cached image and texture (if there is one) */
> > -   st->drawpix_cache.width = 0;
> > -   st->drawpix_cache.height = 0;
> > -   st->drawpix_cache.user_pointer = NULL;
> > -   if (st->drawpix_cache.image) {
> > -      free(st->drawpix_cache.image);
> > -      st->drawpix_cache.image = NULL;
> > +   pt = search_drawpixels_cache(st, width, height, format, type,
> > +                                unpack, pixels);
> > +   if (pt) {
> > +      return pt;
> >     }
> > -   pipe_resource_reference(&st->drawpix_cache.texture, NULL);
> >  #endif
> >
> >     /* Choose a pixel format for the temp texture which will hold the
> > @@ -522,28 +614,7 @@ make_texture(struct st_context *st,
> >     _mesa_unmap_pbo_source(ctx, unpack);
> >
> >  #if USE_DRAWPIXELS_CACHE
> > -   /* Save the glDrawPixels parameter and image in the cache */
> > -   if ((unpack->RowLength == 0 || unpack->RowLength == width) &&
> > -       unpack->SkipPixels == 0 &&
> > -       unpack->SkipRows == 0) {
> > -      st->drawpix_cache.width = width;
> > -      st->drawpix_cache.height = height;
> > -      st->drawpix_cache.format = format;
> > -      st->drawpix_cache.type = type;
> > -      st->drawpix_cache.user_pointer = pixels;
> > -      assert(!st->drawpix_cache.image);
> > -      st->drawpix_cache.image = malloc(width * height * bpp);
> > -      if (st->drawpix_cache.image) {
> > -         memcpy(st->drawpix_cache.image, pixels, width * height * bpp);
> > -         pipe_resource_reference(&st->drawpix_cache.texture, pt);
> > -      }
> > -      else {
> > -         /* out of memory, free/disable cached texture */
> > -         st->drawpix_cache.width = 0;
> > -         st->drawpix_cache.height = 0;
> > -         pipe_resource_reference(&st->drawpix_cache.texture, NULL);
> > -      }
> > -   }
> > +   cache_drawpixels_image(st, width, height, format, type, unpack,
> pixels, pt);
> >  #endif
> >
> >     return pt;
> > @@ -1658,4 +1729,11 @@ st_destroy_drawpix(struct st_context *st)
> >        cso_delete_vertex_shader(st->cso_context,
> st->drawpix.vert_shaders[0]);
> >     if (st->drawpix.vert_shaders[1])
> >        cso_delete_vertex_shader(st->cso_context,
> st->drawpix.vert_shaders[1]);
> > +
> > +   /* Free cache data */
> > +   for (i = 0; i < ARRAY_SIZE(st->drawpix_cache.entries); i++) {
> > +      struct drawpix_cache_entry *entry = &st->drawpix_cache.entries[i];
> > +      free(entry->image);
> > +      pipe_resource_reference(&entry->texture, NULL);
> > +   }
> >  }
> > diff --git a/src/mesa/state_tracker/st_context.c
> b/src/mesa/state_tracker/st_context.c
> > index 3ba4847..eb6c458 100644
> > --- a/src/mesa/state_tracker/st_context.c
> > +++ b/src/mesa/state_tracker/st_context.c
> > @@ -273,10 +273,6 @@ st_destroy_context_priv(struct st_context *st, bool
> destroy_pipe)
> >        }
> >     }
> >
> > -   /* free glDrawPixels cache data */
> > -   free(st->drawpix_cache.image);
> > -   pipe_resource_reference(&st->drawpix_cache.texture, NULL);
> > -
> >     /* free glReadPixels cache data */
> >     st_invalidate_readpix_cache(st);
> >
> > diff --git a/src/mesa/state_tracker/st_context.h
> b/src/mesa/state_tracker/st_context.h
> > index 0258bed..ae2bdf5 100644
> > --- a/src/mesa/state_tracker/st_context.h
> > +++ b/src/mesa/state_tracker/st_context.h
> > @@ -86,6 +86,20 @@ struct st_bound_handles
> >     uint64_t *handles;
> >  };
> >
> > +
> > +#define NUM_DRAWPIX_CACHE_ENTRIES 4
> > +
> > +struct drawpix_cache_entry
> > +{
> > +   GLsizei width, height;
> > +   GLenum format, type;
> > +   const void *user_pointer;  /**< Last user 'pixels' pointer */
> > +   void *image;               /**< Copy of the glDrawPixels image data
> */
> > +   struct pipe_resource *texture;
> > +   unsigned age;
> > +};
> > +
> > +
> >  struct st_context
> >  {
> >     struct st_context_iface iface;
> > @@ -208,12 +222,10 @@ struct st_context
> >        void *vert_shaders[2];   /**< ureg shaders */
> >     } drawpix;
> >
> > +   /** Cache of glDrawPixels images */
> >     struct {
> > -      GLsizei width, height;
> > -      GLenum format, type;
> > -      const void *user_pointer;  /**< Last user 'pixels' pointer */
> > -      void *image;               /**< Copy of the glDrawPixels image
> data */
> > -      struct pipe_resource *texture;
> > +      struct drawpix_cache_entry entries[NUM_DRAWPIX_CACHE_ENTRIES];
> > +      unsigned age;
> >     } drawpix_cache;
> >
> >     /** for glReadPixels */
> >
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to