[Mesa-dev] [PATCH 1/2] swr: Handle resource across context changes

Cherniak, Bruce bruce.cherniak at intel.com
Tue Sep 26 18:03:00 UTC 2017


Reviewed-by: Bruce Cherniak <bruce.cherniak at intel.com> 

> On Sep 25, 2017, at 5:28 PM, George Kyriazis <george.kyriazis at intel.com> wrote:
> 
> Swr caches fb contents in tiles.  Those tiles are stored on a per-context
> basis.
> 
> When switching contexts that share resources we need to make sure that
> the tiles of the old context are being stored and the tiles of the new
> context are being invalidated (marked as invalid, hence contents need
> to be reloaded).
> 
> The context does not get any dirty bits to identify this case.  This has
> to be, then, coordinated by the resources that are being shared between
> the contexts.
> 
> Add a "curr_pipe" hook in swr_resource that will allow us to identify a
> MakeCurrent of the above form during swr_update_derived().  At that time,
> we invalidate the tiles of the new context.  The old context, will need to
> have already store its tiles by that time, which happens during glFlush().
> glFlush() is being called at the beginning of MakeCurrent.
> 
> So, the sequence of operations is:
> - At the beginning of glXMakeCurrent(), glFlush() will store the tiles
>  of all bound surfaces of the old context.
> - After the store, a fence will guarantee that the all tile store make
>  it to the surface
> - During swr_update_derived(), when we validate the new context, we check
>  all resources to see what changed, and if so, we invalidate the
>  current tiles.
> 
> Fixes rendering problems with CEI/Ensight.
> ---
> src/gallium/drivers/swr/swr_context.cpp | 14 +++++++++--
> src/gallium/drivers/swr/swr_draw.cpp    | 19 ++++++++------
> src/gallium/drivers/swr/swr_resource.h  |  3 +++
> src/gallium/drivers/swr/swr_state.cpp   | 44 +++++++++++++++++++++++++++++++++
> 4 files changed, 70 insertions(+), 10 deletions(-)
> 
> diff --git a/src/gallium/drivers/swr/swr_context.cpp b/src/gallium/drivers/swr/swr_context.cpp
> index e95bd3b..34d9a25 100644
> --- a/src/gallium/drivers/swr/swr_context.cpp
> +++ b/src/gallium/drivers/swr/swr_context.cpp
> @@ -365,10 +365,20 @@ swr_destroy(struct pipe_context *pipe)
>       util_blitter_destroy(ctx->blitter);
> 
>    for (unsigned i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
> -      pipe_surface_reference(&ctx->framebuffer.cbufs[i], NULL);
> +      if (ctx->framebuffer.cbufs[i]) {
> +         struct swr_resource *res = swr_resource(ctx->framebuffer.cbufs[i]->texture);
> +         /* NULL curr_pipe, so we don't have a reference to a deleted pipe */
> +         res->curr_pipe = NULL;
> +         pipe_surface_reference(&ctx->framebuffer.cbufs[i], NULL);
> +      }
>    }
> 
> -   pipe_surface_reference(&ctx->framebuffer.zsbuf, NULL);
> +   if (ctx->framebuffer.zsbuf) {
> +      struct swr_resource *res = swr_resource(ctx->framebuffer.zsbuf->texture);
> +      /* NULL curr_pipe, so we don't have a reference to a deleted pipe */
> +      res->curr_pipe = NULL;
> +      pipe_surface_reference(&ctx->framebuffer.zsbuf, NULL);
> +   }
> 
>    for (unsigned i = 0; i < ARRAY_SIZE(ctx->sampler_views[0]); i++) {
>       pipe_sampler_view_reference(&ctx->sampler_views[PIPE_SHADER_FRAGMENT][i], NULL);
> diff --git a/src/gallium/drivers/swr/swr_draw.cpp b/src/gallium/drivers/swr/swr_draw.cpp
> index d7f24d6..57660c7 100644
> --- a/src/gallium/drivers/swr/swr_draw.cpp
> +++ b/src/gallium/drivers/swr/swr_draw.cpp
> @@ -239,14 +239,17 @@ swr_flush(struct pipe_context *pipe,
> {
>    struct swr_context *ctx = swr_context(pipe);
>    struct swr_screen *screen = swr_screen(pipe->screen);
> -   struct pipe_surface *cb = ctx->framebuffer.cbufs[0];
> -
> -   /* If the current renderTarget is the display surface, store tiles back to
> -    * the surface, in preparation for present (swr_flush_frontbuffer).
> -    * Other renderTargets get stored back when attachment changes or
> -    * swr_surface_destroy */
> -   if (cb && swr_resource(cb->texture)->display_target)
> -      swr_store_dirty_resource(pipe, cb->texture, SWR_TILE_RESOLVED);
> +
> +   for (int i=0; i < ctx->framebuffer.nr_cbufs; i++) {
> +      struct pipe_surface *cb = ctx->framebuffer.cbufs[i];
> +      if (cb) {
> +         swr_store_dirty_resource(pipe, cb->texture, SWR_TILE_RESOLVED);
> +      }
> +   }
> +   if (ctx->framebuffer.zsbuf) {
> +      swr_store_dirty_resource(pipe, ctx->framebuffer.zsbuf->texture,
> +                               SWR_TILE_RESOLVED);
> +   }
> 
>    if (fence)
>       swr_fence_reference(pipe->screen, fence, screen->flush_fence);
> diff --git a/src/gallium/drivers/swr/swr_resource.h b/src/gallium/drivers/swr/swr_resource.h
> index 4a2d669..1269433 100644
> --- a/src/gallium/drivers/swr/swr_resource.h
> +++ b/src/gallium/drivers/swr/swr_resource.h
> @@ -54,6 +54,9 @@ struct swr_resource {
>    size_t secondary_mip_offsets[PIPE_MAX_TEXTURE_LEVELS];
> 
>    enum swr_resource_status status;
> +
> +   /* last pipe that used (validated) this resource */
> +   struct pipe_context *curr_pipe;
> };
> 
> 
> diff --git a/src/gallium/drivers/swr/swr_state.cpp b/src/gallium/drivers/swr/swr_state.cpp
> index 93108de..893bd6e 100644
> --- a/src/gallium/drivers/swr/swr_state.cpp
> +++ b/src/gallium/drivers/swr/swr_state.cpp
> @@ -953,6 +953,47 @@ swr_change_rt(struct swr_context *ctx,
>    return need_fence;
> }
> 
> +/*
> + * for cases where resources are shared between contexts, invalidate
> + * this ctx's resource. so it can be fetched fresh.  Old ctx's resource
> + * is already stored during a flush
> + */
> +static inline void
> +swr_invalidate_buffers_after_ctx_change(struct pipe_context *pipe)
> +{
> +   struct swr_context *ctx = swr_context(pipe);
> +
> +   for (uint32_t i = 0; i < ctx->framebuffer.nr_cbufs; i++) {
> +      struct pipe_surface *cb = ctx->framebuffer.cbufs[i];
> +      if (cb) {
> +         struct swr_resource *res = swr_resource(cb->texture);
> +         if (res->curr_pipe != pipe) {
> +            /* if curr_pipe is NULL (first use), status should not be WRITE */
> +            assert(res->curr_pipe || !(res->status & SWR_RESOURCE_WRITE));
> +            if (res->status & SWR_RESOURCE_WRITE) {
> +               swr_invalidate_render_target(pipe, i, cb->width, cb->height);
> +            }
> +         }
> +         res->curr_pipe = pipe;
> +      }
> +   }
> +   if (ctx->framebuffer.zsbuf) {
> +      struct pipe_surface *zb = ctx->framebuffer.zsbuf;
> +      if (zb) {
> +         struct swr_resource *res = swr_resource(zb->texture);
> +         if (res->curr_pipe != pipe) {
> +            /* if curr_pipe is NULL (first use), status should not be WRITE */
> +            assert(res->curr_pipe || !(res->status & SWR_RESOURCE_WRITE));
> +            if (res->status & SWR_RESOURCE_WRITE) {
> +               swr_invalidate_render_target(pipe, SWR_ATTACHMENT_DEPTH, zb->width, zb->height);
> +               swr_invalidate_render_target(pipe, SWR_ATTACHMENT_STENCIL, zb->width, zb->height);
> +            }
> +         }
> +         res->curr_pipe = pipe;
> +      }
> +   }
> +}
> +
> static inline void
> swr_user_vbuf_range(const struct pipe_draw_info *info,
>                     const struct swr_vertex_element_state *velems,
> @@ -1040,6 +1081,9 @@ swr_update_derived(struct pipe_context *pipe,
>    /* For example, user_buffer vertex and index buffers. */
>    unsigned post_update_dirty_flags = 0;
> 
> +   /* bring resources that changed context up-to-date */
> +   swr_invalidate_buffers_after_ctx_change(pipe);
> +
>    /* Render Targets */
>    if (ctx->dirty & SWR_NEW_FRAMEBUFFER) {
>       struct pipe_framebuffer_state *fb = &ctx->framebuffer;
> -- 
> 2.7.4
> 
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev



More information about the mesa-dev mailing list