From: Marek Olšák Date: Fri, 1 Sep 2017 22:31:58 +0000 (+0200) Subject: radeonsi: implement pipe_context::fence_server_sync X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=3824ca76108076350f22489a0d73486549ef0168;p=mesa.git radeonsi: implement pipe_context::fence_server_sync This will be more useful once we have sync_file support. Reviewed-by: Nicolai Hähnle --- 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 @@ -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. 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; }