radeonsi: implement pipe_context::fence_server_sync
authorMarek Olšák <marek.olsak@amd.com>
Fri, 1 Sep 2017 22:31:58 +0000 (00:31 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Mon, 11 Sep 2017 14:29:52 +0000 (16:29 +0200)
This will be more useful once we have sync_file support.

Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
src/gallium/drivers/radeon/r600_pipe_common.c
src/gallium/drivers/radeon/radeon_winsys.h
src/gallium/winsys/amdgpu/drm/amdgpu_cs.c

index b17bf80bf50f1e03cc0d04ad5773fb66a24a7531..fc27b4c218bcad71ebe8c9cf84ede953dcf31f6c 100644 (file)
@@ -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.
index f0a0a922a10c6d16b9188eb91daed04ca35e498c..99e22e06857b5b221716fb0345eaf32835813298 100644 (file)
@@ -573,6 +573,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.
index ca6021cc02c0234b8ba7d85d38b3f1abe7246838..1d7ea347bc2cd99ce64bebdc9e8ba38210252aa2 100644 (file)
@@ -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;
 }