gallium: add pipe_context::callback
authorNicolai Hähnle <nicolai.haehnle@amd.com>
Sun, 22 Oct 2017 15:38:53 +0000 (17:38 +0200)
committerNicolai Hähnle <nicolai.haehnle@amd.com>
Thu, 9 Nov 2017 13:00:50 +0000 (14:00 +0100)
For running post-draw operations inside the driver thread. ddebug will
use it.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
src/gallium/auxiliary/util/u_threaded_context.c
src/gallium/auxiliary/util/u_threaded_context_calls.h
src/gallium/include/pipe/p_context.h

index 7db9005452f951d7f0308c18589e8781f9576d2f..e1ec47e4e0c6a14f6780adad0bdef79a432339f8 100644 (file)
@@ -169,6 +169,16 @@ 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)
 {
@@ -2373,6 +2383,41 @@ tc_resource_commit(struct pipe_context *_pipe, struct pipe_resource *res,
 }
 
 
+/********************************************************************
+ * 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
  */
@@ -2470,6 +2515,7 @@ threaded_context_create(struct pipe_context *pipe,
    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)
index 1356c54baf2027d0075a3339b1a25259d42f6593..0d2fd183680a4677e1f89007647c7cd965a95f17 100644 (file)
@@ -1,4 +1,5 @@
 CALL(flush)
+CALL(callback)
 CALL(destroy_query)
 CALL(begin_query)
 CALL(end_query)
index d9228e4fc92874ac698ae962741802240d44aa90..0dd4ad12424f219b593bd17d06f89fa75cb8488a 100644 (file)
@@ -855,6 +855,17 @@ struct pipe_context {
     */
    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);
 };