[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