summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2017-09-02 00:31:58 +0200
committerMarek Olšák <[email protected]>2017-09-11 16:29:52 +0200
commit3824ca76108076350f22489a0d73486549ef0168 (patch)
tree4542d9a3d28ab15dfa863b9f63999b8c6cf3536b
parent8843bf6dfd4bcca7bcb6dfa64cd959ba7bdb0931 (diff)
radeonsi: implement pipe_context::fence_server_sync
This will be more useful once we have sync_file support. Reviewed-by: Nicolai Hähnle <[email protected]>
-rw-r--r--src/gallium/drivers/radeon/r600_pipe_common.c45
-rw-r--r--src/gallium/drivers/radeon/radeon_winsys.h7
-rw-r--r--src/gallium/winsys/amdgpu/drm/amdgpu_cs.c16
3 files changed, 68 insertions, 0 deletions
diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c
index b17bf80bf50..fc27b4c218b 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.c
+++ b/src/gallium/drivers/radeon/r600_pipe_common.c
@@ -411,6 +411,50 @@ void r600_postflush_resume_features(struct r600_common_context *ctx)
r600_resume_queries(ctx);
}
+static void r600_add_fence_dependency(struct r600_common_context *rctx,
+ struct pipe_fence_handle *fence)
+{
+ struct radeon_winsys *ws = rctx->ws;
+
+ if (rctx->dma.cs)
+ ws->cs_add_fence_dependency(rctx->dma.cs, fence);
+ ws->cs_add_fence_dependency(rctx->gfx.cs, fence);
+}
+
+static void r600_fence_server_sync(struct pipe_context *ctx,
+ struct pipe_fence_handle *fence)
+{
+ struct r600_common_context *rctx = (struct r600_common_context *)ctx;
+ struct r600_multi_fence *rfence = (struct r600_multi_fence *)fence;
+
+ /* Only amdgpu needs to handle fence dependencies (for fence imports).
+ * radeon synchronizes all rings by default and will not implement
+ * fence imports.
+ */
+ if (rctx->screen->info.drm_major == 2)
+ return;
+
+ /* Only imported fences need to be handled by fence_server_sync,
+ * because the winsys handles synchronizations automatically for BOs
+ * within the process.
+ *
+ * Simply skip unflushed fences here, and the winsys will drop no-op
+ * dependencies (i.e. dependencies within the same ring).
+ */
+ if (rfence->gfx_unflushed.ctx)
+ return;
+
+ /* All unflushed commands will not start execution before
+ * this fence dependency is signalled.
+ *
+ * Should we flush the context to allow more GPU parallelism?
+ */
+ if (rfence->sdma)
+ r600_add_fence_dependency(rctx, rfence->sdma);
+ if (rfence->gfx)
+ r600_add_fence_dependency(rctx, rfence->gfx);
+}
+
static void r600_flush_from_st(struct pipe_context *ctx,
struct pipe_fence_handle **fence,
unsigned flags)
@@ -684,6 +728,7 @@ bool r600_common_context_init(struct r600_common_context *rctx,
rctx->b.memory_barrier = r600_memory_barrier;
rctx->b.flush = r600_flush_from_st;
rctx->b.set_debug_callback = r600_set_debug_callback;
+ rctx->b.fence_server_sync = r600_fence_server_sync;
rctx->dma_clear_buffer = r600_dma_clear_buffer_fallback;
/* evergreen_compute.c has a special codepath for global buffers.
diff --git a/src/gallium/drivers/radeon/radeon_winsys.h b/src/gallium/drivers/radeon/radeon_winsys.h
index f0a0a922a10..99e22e06857 100644
--- a/src/gallium/drivers/radeon/radeon_winsys.h
+++ b/src/gallium/drivers/radeon/radeon_winsys.h
@@ -574,6 +574,13 @@ struct radeon_winsys {
void (*cs_sync_flush)(struct radeon_winsys_cs *cs);
/**
+ * Add a fence dependency to the CS, so that the CS will wait for
+ * the fence before execution.
+ */
+ void (*cs_add_fence_dependency)(struct radeon_winsys_cs *cs,
+ struct pipe_fence_handle *fence);
+
+ /**
* Wait for the fence and return true if the fence has been signalled.
* The timeout of 0 will only return the status.
* The timeout of PIPE_TIMEOUT_INFINITE will always wait until the fence
diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_cs.c b/src/gallium/winsys/amdgpu/drm/amdgpu_cs.c
index ca6021cc02c..1d7ea347bc2 100644
--- a/src/gallium/winsys/amdgpu/drm/amdgpu_cs.c
+++ b/src/gallium/winsys/amdgpu/drm/amdgpu_cs.c
@@ -936,6 +936,21 @@ static bool is_noop_fence_dependency(struct amdgpu_cs *acs,
return amdgpu_fence_wait((void *)fence, 0, false);
}
+static void amdgpu_cs_add_fence_dependency(struct radeon_winsys_cs *rws,
+ struct pipe_fence_handle *pfence)
+{
+ struct amdgpu_cs *acs = amdgpu_cs(rws);
+ struct amdgpu_cs_context *cs = acs->csc;
+ struct amdgpu_fence *fence = (struct amdgpu_fence*)pfence;
+
+ if (is_noop_fence_dependency(acs, fence))
+ return;
+
+ unsigned idx = add_fence_dependency_entry(cs);
+ amdgpu_fence_reference(&cs->fence_dependencies[idx],
+ (struct pipe_fence_handle*)fence);
+}
+
static void amdgpu_add_bo_fence_dependencies(struct amdgpu_cs *acs,
struct amdgpu_cs_buffer *buffer)
{
@@ -1397,6 +1412,7 @@ void amdgpu_cs_init_functions(struct amdgpu_winsys *ws)
ws->base.cs_get_next_fence = amdgpu_cs_get_next_fence;
ws->base.cs_is_buffer_referenced = amdgpu_bo_is_referenced;
ws->base.cs_sync_flush = amdgpu_cs_sync_flush;
+ ws->base.cs_add_fence_dependency = amdgpu_cs_add_fence_dependency;
ws->base.fence_wait = amdgpu_fence_wait_rel_timeout;
ws->base.fence_reference = amdgpu_fence_reference;
}