[Mesa-dev] [PATCH v2 13/26] gallium: add pipe_context::callback

Nicolai Hähnle nhaehnle at gmail.com
Mon Nov 6 10:23:44 UTC 2017


From: Nicolai Hähnle <nicolai.haehnle at amd.com>

For running post-draw operations inside the driver thread. ddebug will
use it.

Reviewed-by: Marek Olšák <marek.olsak at amd.com>
---
 src/gallium/auxiliary/util/u_threaded_context.c    | 46 ++++++++++++++++++++++
 .../auxiliary/util/u_threaded_context_calls.h      |  1 +
 src/gallium/include/pipe/p_context.h               | 11 ++++++
 3 files changed, 58 insertions(+)

diff --git a/src/gallium/auxiliary/util/u_threaded_context.c b/src/gallium/auxiliary/util/u_threaded_context.c
index 1f8a9d5088b..d4ec24e614b 100644
--- a/src/gallium/auxiliary/util/u_threaded_context.c
+++ b/src/gallium/auxiliary/util/u_threaded_context.c
@@ -162,20 +162,30 @@ tc_add_sized_call(struct threaded_context *tc, enum tc_call_id id,
                                     sizeof(struct type) + \
                                     sizeof(((struct type*)NULL)->slot[0]) * \
                                     (num_slots)))
 
 static union tc_payload *
 tc_add_small_call(struct threaded_context *tc, enum tc_call_id id)
 {
    return tc_add_sized_call(tc, id, 0);
 }
 
+static bool
+tc_is_sync(struct threaded_context *tc)
+{
+   struct tc_batch *last = &tc->batch_slots[tc->last];
+   struct tc_batch *next = &tc->batch_slots[tc->next];
+
+   return util_queue_fence_is_signalled(&last->fence) &&
+          !next->num_total_call_slots;
+}
+
 static void
 _tc_sync(struct threaded_context *tc, const char *info, const char *func)
 {
    struct tc_batch *last = &tc->batch_slots[tc->last];
    struct tc_batch *next = &tc->batch_slots[tc->next];
    bool synced = false;
 
    tc_debug_check(tc);
 
    /* Only wait for queued calls... */
@@ -2348,20 +2358,55 @@ tc_resource_commit(struct pipe_context *_pipe, struct pipe_resource *res,
 
    tc_set_resource_reference(&p->res, res);
    p->level = level;
    p->box = *box;
    p->commit = commit;
    return true; /* we don't care about the return value for this call */
 }
 
 
 /********************************************************************
+ * callback
+ */
+
+struct tc_callback_payload {
+   void (*fn)(void *data);
+   void *data;
+};
+
+static void
+tc_call_callback(struct pipe_context *pipe, union tc_payload *payload)
+{
+   struct tc_callback_payload *p = (struct tc_callback_payload *)payload;
+
+   p->fn(p->data);
+}
+
+static void
+tc_callback(struct pipe_context *_pipe, void (*fn)(void *), void *data,
+            bool asap)
+{
+   struct threaded_context *tc = threaded_context(_pipe);
+
+   if (asap && tc_is_sync(tc)) {
+      fn(data);
+      return;
+   }
+
+   struct tc_callback_payload *p =
+      tc_add_struct_typed_call(tc, TC_CALL_callback, tc_callback_payload);
+   p->fn = fn;
+   p->data = data;
+}
+
+
+/********************************************************************
  * create & destroy
  */
 
 static void
 tc_destroy(struct pipe_context *_pipe)
 {
    struct threaded_context *tc = threaded_context(_pipe);
    struct pipe_context *pipe = tc->pipe;
 
    if (tc->base.const_uploader &&
@@ -2444,20 +2489,21 @@ threaded_context_create(struct pipe_context *pipe,
    pipe->priv = NULL;
 
    tc->pipe = pipe;
    tc->replace_buffer_storage = replace_buffer;
    tc->create_fence = create_fence;
    tc->map_buffer_alignment =
       pipe->screen->get_param(pipe->screen, PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT);
    tc->base.priv = pipe; /* priv points to the wrapped driver context */
    tc->base.screen = pipe->screen;
    tc->base.destroy = tc_destroy;
+   tc->base.callback = tc_callback;
 
    tc->base.stream_uploader = u_upload_clone(&tc->base, pipe->stream_uploader);
    if (pipe->stream_uploader == pipe->const_uploader)
       tc->base.const_uploader = tc->base.stream_uploader;
    else
       tc->base.const_uploader = u_upload_clone(&tc->base, pipe->const_uploader);
 
    if (!tc->base.stream_uploader || !tc->base.const_uploader)
       goto fail;
 
diff --git a/src/gallium/auxiliary/util/u_threaded_context_calls.h b/src/gallium/auxiliary/util/u_threaded_context_calls.h
index 1356c54baf2..0d2fd183680 100644
--- a/src/gallium/auxiliary/util/u_threaded_context_calls.h
+++ b/src/gallium/auxiliary/util/u_threaded_context_calls.h
@@ -1,11 +1,12 @@
 CALL(flush)
+CALL(callback)
 CALL(destroy_query)
 CALL(begin_query)
 CALL(end_query)
 CALL(get_query_result_resource)
 CALL(render_condition)
 CALL(bind_sampler_states)
 CALL(set_framebuffer_state)
 CALL(set_tess_state)
 CALL(set_constant_buffer)
 CALL(set_scissor_states)
diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
index d9228e4fc92..0dd4ad12424 100644
--- a/src/gallium/include/pipe/p_context.h
+++ b/src/gallium/include/pipe/p_context.h
@@ -848,18 +848,29 @@ struct pipe_context {
    /**
     * Make an image handle resident.
     *
     * \param ctx        pipe context
     * \param handle     64-bit image handle
     * \param access     GL_READ_ONLY, GL_WRITE_ONLY or GL_READ_WRITE
     * \param resident   TRUE for resident, FALSE otherwise
     */
    void (*make_image_handle_resident)(struct pipe_context *ctx, uint64_t handle,
                                       unsigned access, bool resident);
+
+   /**
+    * Call the given function from the driver thread.
+    *
+    * This is set by threaded contexts for use by debugging wrappers.
+    *
+    * \param asap if true, run the callback immediately if there are no pending
+    *             commands to be processed by the driver thread
+    */
+   void (*callback)(struct pipe_context *ctx, void (*fn)(void *), void *data,
+                    bool asap);
 };
 
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif /* PIPE_CONTEXT_H */
-- 
2.11.0



More information about the mesa-dev mailing list