[Mesa-dev] [PATCH] gallium/postprocess: share pipe_context and cso_context with the state tracker

Marek Olšák maraeo at gmail.com
Wed Nov 28 18:35:36 PST 2012


Using one context instead of two is more efficient and
we can skip another context flush.
---
 src/gallium/auxiliary/postprocess/postprocess.h    |    6 ++-
 src/gallium/auxiliary/postprocess/pp_init.c        |   13 ++-----
 src/gallium/auxiliary/postprocess/pp_program.c     |   20 ++++------
 src/gallium/auxiliary/postprocess/pp_run.c         |   41 +++++++++++++++++++-
 src/gallium/include/state_tracker/st_api.h         |   11 ++++++
 .../state_trackers/dri/common/dri_context.c        |    4 +-
 src/mesa/state_tracker/st_manager.c                |    2 +
 7 files changed, 71 insertions(+), 26 deletions(-)

diff --git a/src/gallium/auxiliary/postprocess/postprocess.h b/src/gallium/auxiliary/postprocess/postprocess.h
index dfa15f7..52ebeb9 100644
--- a/src/gallium/auxiliary/postprocess/postprocess.h
+++ b/src/gallium/auxiliary/postprocess/postprocess.h
@@ -65,13 +65,15 @@ struct pp_queue_t
 
 /* Main functions */
 
-struct pp_queue_t *pp_init(struct pipe_screen *, const unsigned int *);
+struct pp_queue_t *pp_init(struct pipe_context *pipe, const unsigned int *,
+                           struct cso_context *);
 void pp_run(struct pp_queue_t *, struct pipe_resource *,
             struct pipe_resource *, struct pipe_resource *);
 void pp_free(struct pp_queue_t *);
 void pp_free_fbos(struct pp_queue_t *);
 void pp_debug(const char *, ...);
-struct program *pp_init_prog(struct pp_queue_t *, struct pipe_screen *);
+struct program *pp_init_prog(struct pp_queue_t *, struct pipe_context *pipe,
+                             struct cso_context *);
 void pp_init_fbos(struct pp_queue_t *, unsigned int, unsigned int);
 
 /* The filters */
diff --git a/src/gallium/auxiliary/postprocess/pp_init.c b/src/gallium/auxiliary/postprocess/pp_init.c
index 2dc29ac..e059be6 100644
--- a/src/gallium/auxiliary/postprocess/pp_init.c
+++ b/src/gallium/auxiliary/postprocess/pp_init.c
@@ -39,7 +39,8 @@
 
 /** Initialize the post-processing queue. */
 struct pp_queue_t *
-pp_init(struct pipe_screen *pscreen, const unsigned int *enabled)
+pp_init(struct pipe_context *pipe, const unsigned int *enabled,
+        struct cso_context *cso)
 {
 
    unsigned int curpos = 0, i, tmp_req = 0;
@@ -64,7 +65,7 @@ pp_init(struct pipe_screen *pscreen, const unsigned int *enabled)
    if (!tmp_q || !ppq || !ppq->shaders || !ppq->verts)
       goto error;
 
-   ppq->p = pp_init_prog(ppq, pscreen);
+   ppq->p = pp_init_prog(ppq, pipe, cso);
    if (!ppq->p)
       goto error;
 
@@ -89,7 +90,7 @@ pp_init(struct pipe_screen *pscreen, const unsigned int *enabled)
       }
    }
 
-   ppq->p->blitctx = util_create_blit(ppq->p->pipe, ppq->p->cso);
+   ppq->p->blitctx = util_create_blit(ppq->p->pipe, cso);
    if (!ppq->p->blitctx)
       goto error;
 
@@ -152,9 +153,6 @@ pp_free(struct pp_queue_t *ppq)
 
    util_destroy_blit(ppq->p->blitctx);
 
-   cso_set_sampler_views(ppq->p->cso, PIPE_SHADER_FRAGMENT, 0, NULL);
-   cso_release_all(ppq->p->cso);
-
    for (i = 0; i < ppq->n_filters; i++) {
       for (j = 0; j < PP_MAX_PASSES && ppq->shaders[i][j]; j++) {
          if (j >= ppq->verts[i]) {
@@ -168,9 +166,6 @@ pp_free(struct pp_queue_t *ppq)
       }
    }
 
-   cso_destroy_context(ppq->p->cso);
-   ppq->p->pipe->destroy(ppq->p->pipe);
-
    FREE(ppq->p);
    FREE(ppq->pp_queue);
    FREE(ppq);
diff --git a/src/gallium/auxiliary/postprocess/pp_program.c b/src/gallium/auxiliary/postprocess/pp_program.c
index 31e2bee..c25078d 100644
--- a/src/gallium/auxiliary/postprocess/pp_program.c
+++ b/src/gallium/auxiliary/postprocess/pp_program.c
@@ -38,26 +38,22 @@
 
 /** Initialize the internal details */
 struct program *
-pp_init_prog(struct pp_queue_t *ppq, struct pipe_screen *pscreen)
+pp_init_prog(struct pp_queue_t *ppq, struct pipe_context *pipe,
+             struct cso_context *cso)
 {
-
    struct program *p;
 
    pp_debug("Initializing program\n");
-   if (!pscreen)
+   if (!pipe)
       return NULL;
 
    p = CALLOC(1, sizeof(struct program));
    if (!p)
       return NULL;
 
-   p->screen = pscreen;
-   p->pipe = pscreen->context_create(pscreen, NULL);
-
-   /* XXX this doesn't use the cso_context of the state tracker, but creates
-    * its own. Having 2 existing cso_contexts use 1 pipe_context may cause
-    * undefined behavior! */
-   p->cso = cso_create_context(p->pipe);
+   p->screen = pipe->screen;
+   p->pipe = pipe;
+   p->cso = cso;
 
    {
       static const float verts[4][2][4] = {
@@ -79,7 +75,7 @@ pp_init_prog(struct pp_queue_t *ppq, struct pipe_screen *pscreen)
           }
       };
 
-      p->vbuf = pipe_buffer_create(pscreen, PIPE_BIND_VERTEX_BUFFER,
+      p->vbuf = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER,
                                    PIPE_USAGE_STATIC, sizeof(verts));
       pipe_buffer_write(p->pipe, p->vbuf, 0, sizeof(verts), verts);
    }
@@ -140,7 +136,5 @@ pp_init_prog(struct pp_queue_t *ppq, struct pipe_screen *pscreen)
    p->surf.usage = PIPE_BIND_RENDER_TARGET;
    p->surf.format = PIPE_FORMAT_B8G8R8A8_UNORM;
 
-   p->pipe->set_sample_mask(p->pipe, ~0);
-
    return p;
 }
diff --git a/src/gallium/auxiliary/postprocess/pp_run.c b/src/gallium/auxiliary/postprocess/pp_run.c
index 4e6d675..6f06324 100644
--- a/src/gallium/auxiliary/postprocess/pp_run.c
+++ b/src/gallium/auxiliary/postprocess/pp_run.c
@@ -44,6 +44,7 @@ pp_run(struct pp_queue_t *ppq, struct pipe_resource *in,
 {
    struct pipe_resource *refin = NULL, *refout = NULL;
    unsigned int i;
+   struct cso_context *cso = ppq->p->cso;
 
    if (in->width0 != ppq->p->framebuffer.width ||
        in->height0 != ppq->p->framebuffer.height) {
@@ -65,6 +66,28 @@ pp_run(struct pp_queue_t *ppq, struct pipe_resource *in,
       in = ppq->tmp[0];
    }
 
+   /* save state (restored below) */
+   cso_save_blend(cso);
+   cso_save_depth_stencil_alpha(cso);
+   cso_save_fragment_shader(cso);
+   cso_save_framebuffer(cso);
+   cso_save_geometry_shader(cso);
+   cso_save_rasterizer(cso);
+   cso_save_sample_mask(cso);
+   cso_save_samplers(cso, PIPE_SHADER_FRAGMENT);
+   cso_save_sampler_views(cso, PIPE_SHADER_FRAGMENT);
+   cso_save_stencil_ref(cso);
+   cso_save_stream_outputs(cso);
+   cso_save_vertex_elements(cso);
+   cso_save_vertex_shader(cso);
+   cso_save_viewport(cso);
+   cso_save_aux_vertex_buffer_slot(cso);
+
+   /* set default state */
+   cso_set_sample_mask(cso, ~0);
+   cso_set_stream_outputs(cso, 0, NULL, 0);
+   cso_set_geometry_shader_handle(cso, NULL);
+
    // Kept only for this frame.
    pipe_resource_reference(&ppq->depth, indepth);
    pipe_resource_reference(&refin, in);
@@ -100,6 +123,23 @@ pp_run(struct pp_queue_t *ppq, struct pipe_resource *in,
       break;
    }
 
+   /* restore state we changed */
+   cso_restore_blend(cso);
+   cso_restore_depth_stencil_alpha(cso);
+   cso_restore_fragment_shader(cso);
+   cso_restore_framebuffer(cso);
+   cso_restore_geometry_shader(cso);
+   cso_restore_rasterizer(cso);
+   cso_restore_sample_mask(cso);
+   cso_restore_samplers(cso, PIPE_SHADER_FRAGMENT);
+   cso_restore_sampler_views(cso, PIPE_SHADER_FRAGMENT);
+   cso_restore_stencil_ref(cso);
+   cso_restore_stream_outputs(cso);
+   cso_restore_vertex_elements(cso);
+   cso_restore_vertex_shader(cso);
+   cso_restore_viewport(cso);
+   cso_restore_aux_vertex_buffer_slot(cso);
+
    pipe_resource_reference(&ppq->depth, NULL);
    pipe_resource_reference(&refin, NULL);
    pipe_resource_reference(&refout, NULL);
@@ -180,7 +220,6 @@ pp_filter_draw(struct program *p)
 {
    util_draw_vertex_buffer(p->pipe, p->cso, p->vbuf, 0, 0,
                            PIPE_PRIM_QUADS, 4, 2);
-   p->pipe->flush(p->pipe, NULL);
 }
 
 /** Set the framebuffer as active. */
diff --git a/src/gallium/include/state_tracker/st_api.h b/src/gallium/include/state_tracker/st_api.h
index 85de1c2..91c5529 100644
--- a/src/gallium/include/state_tracker/st_api.h
+++ b/src/gallium/include/state_tracker/st_api.h
@@ -353,6 +353,17 @@ struct st_context_iface
    void *st_manager_private;
 
    /**
+    * The CSO context associated with this context in case we need to draw
+    * something before swap buffers.
+    */
+   struct cso_context *cso_context;
+
+   /**
+    * The gallium context.
+    */
+   struct pipe_context *pipe;
+
+   /**
     * Destroy the context.
     */
    void (*destroy)(struct st_context_iface *stctxi);
diff --git a/src/gallium/state_trackers/dri/common/dri_context.c b/src/gallium/state_trackers/dri/common/dri_context.c
index 360174b..e77c43f 100644
--- a/src/gallium/state_trackers/dri/common/dri_context.c
+++ b/src/gallium/state_trackers/dri/common/dri_context.c
@@ -152,7 +152,9 @@ dri_create_context(gl_api api, const struct gl_config * visual,
    // Context successfully created. See if post-processing is requested.
    dri_pp_query(ctx);
 
-   ctx->pp = pp_init(screen->base.screen, ctx->pp_enabled);
+   if (ctx->st->cso_context) {
+      ctx->pp = pp_init(ctx->st->pipe, ctx->pp_enabled, ctx->st->cso_context);
+   }
 
    *error = __DRI_CTX_ERROR_SUCCESS;
    return GL_TRUE;
diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c
index 5576a0d..b58c1a3 100644
--- a/src/mesa/state_tracker/st_manager.c
+++ b/src/mesa/state_tracker/st_manager.c
@@ -673,6 +673,8 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
    st->iface.copy = st_context_copy;
    st->iface.share = st_context_share;
    st->iface.st_context_private = (void *) smapi;
+   st->iface.cso_context = st->cso_context;
+   st->iface.pipe = st->pipe;
 
    *error = ST_CONTEXT_SUCCESS;
    return &st->iface;
-- 
1.7.10.4



More information about the mesa-dev mailing list