[Mesa-dev] [PATCH 3/3] radeonsi: implement sync_file import/export

Nicolai Hähnle nhaehnle at gmail.com
Wed Sep 13 15:39:50 UTC 2017


On 12.09.2017 22:50, Marek Olšák wrote:
> From: Marek Olšák <marek.olsak at amd.com>
> 
> ---
>   src/gallium/drivers/radeon/r600_pipe_common.c | 77 ++++++++++++++++++++++++++-
>   src/gallium/drivers/radeonsi/si_pipe.c        |  4 +-
>   2 files changed, 79 insertions(+), 2 deletions(-)
> 
> diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c
> index 48fda7b..b66acf7 100644
> --- a/src/gallium/drivers/radeon/r600_pipe_common.c
> +++ b/src/gallium/drivers/radeon/r600_pipe_common.c
> @@ -31,20 +31,21 @@
>   #include "util/u_draw_quad.h"
>   #include "util/u_memory.h"
>   #include "util/u_format_s3tc.h"
>   #include "util/u_upload_mgr.h"
>   #include "os/os_time.h"
>   #include "vl/vl_decoder.h"
>   #include "vl/vl_video_buffer.h"
>   #include "radeon/radeon_video.h"
>   #include <inttypes.h>
>   #include <sys/utsname.h>
> +#include <libsync.h>
>   
>   #ifndef HAVE_LLVM
>   #define HAVE_LLVM 0
>   #endif
>   
>   #if HAVE_LLVM
>   #include <llvm-c/TargetMachine.h>
>   #endif
>   
>   #ifndef MESA_LLVM_VERSION_PATCH
> @@ -448,20 +449,89 @@ static void r600_fence_server_sync(struct pipe_context *ctx,
>   	 * 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_create_fence_fd(struct pipe_context *ctx,
> +				 struct pipe_fence_handle **pfence, int fd)
> +{
> +	struct r600_common_screen *rscreen = (struct r600_common_screen*)ctx->screen;
> +	struct radeon_winsys *ws = rscreen->ws;
> +	struct r600_multi_fence *rfence;
> +
> +	*pfence = NULL;
> +
> +	if (!rscreen->info.has_sync_file)
> +		return;
> +
> +	rfence = CALLOC_STRUCT(r600_multi_fence);
> +	if (!rfence)
> +		return;
> +
> +	pipe_reference_init(&rfence->reference, 1);
> +	rfence->gfx = ws->fence_import_sync_file(ws, fd);
> +	if (!rfence->gfx) {
> +		FREE(rfence);
> +		return;
> +	}
> +
> +	*pfence = (struct pipe_fence_handle*)rfence;
> +}
> +
> +static int r600_fence_get_fd(struct pipe_screen *screen,
> +			     struct pipe_fence_handle *fence)
> +{
> +	struct r600_common_screen *rscreen = (struct r600_common_screen*)screen;
> +	struct radeon_winsys *ws = rscreen->ws;
> +	struct r600_multi_fence *rfence = (struct r600_multi_fence *)fence;
> +	int gfx_fd = -1, sdma_fd = -1;
> +
> +	if (!rscreen->info.has_sync_file)
> +		return -1;
> +
> +	/* Deferred fences aren't supported. */
> +	assert(!rfence->gfx_unflushed.ctx);
> +	if (rfence->gfx_unflushed.ctx)
> +		return -1;
> +
> +	if (rfence->sdma) {
> +		sdma_fd = ws->fence_export_sync_file(ws, rfence->sdma);
> +		if (sdma_fd == -1)
> +			return -1;
> +	}
> +	if (rfence->gfx) {
> +		gfx_fd = ws->fence_export_sync_file(ws, rfence->gfx);
> +		if (gfx_fd == -1) {
> +			if (sdma_fd != -1)
> +				close(sdma_fd);
> +			return -1;
> +		}
> +	}
> +
> +	/* If we don't have FDs at this point, it means we don't have fences
> +	 * either. */
> +	if (sdma_fd == -1)
> +		return gfx_fd;
> +	if (gfx_fd == -1)
> +		return sdma_fd;
> +
> +	/* Get a fence that will be a combination of both fences. */
> +	sync_accumulate("radeonsi", &gfx_fd, sdma_fd);

What happens if this fails?

Cheers,
Nicolai


> +	close(sdma_fd);
> +	return gfx_fd;
> +}
> +
>   static void r600_flush_from_st(struct pipe_context *ctx,
>   			       struct pipe_fence_handle **fence,
>   			       unsigned flags)
>   {
>   	struct pipe_screen *screen = ctx->screen;
>   	struct r600_common_context *rctx = (struct r600_common_context *)ctx;
>   	struct radeon_winsys *ws = rctx->ws;
>   	struct pipe_fence_handle *gfx_fence = NULL;
>   	struct pipe_fence_handle *sdma_fence = NULL;
>   	bool deferred_fence = false;
> @@ -476,23 +546,26 @@ static void r600_flush_from_st(struct pipe_context *ctx,
>   
>   	if (!radeon_emitted(rctx->gfx.cs, rctx->initial_gfx_cs_size)) {
>   		if (fence)
>   			ws->fence_reference(&gfx_fence, rctx->last_gfx_fence);
>   		if (!(flags & PIPE_FLUSH_DEFERRED))
>   			ws->cs_sync_flush(rctx->gfx.cs);
>   	} else {
>   		/* Instead of flushing, create a deferred fence. Constraints:
>   		 * - The state tracker must allow a deferred flush.
>   		 * - The state tracker must request a fence.
> +		 * - fence_get_fd is not allowed.
>   		 * Thread safety in fence_finish must be ensured by the state tracker.
>   		 */
> -		if (flags & PIPE_FLUSH_DEFERRED && fence) {
> +		if (flags & PIPE_FLUSH_DEFERRED &&
> +		    !(flags & PIPE_FLUSH_FENCE_FD) &&
> +		    fence) {
>   			gfx_fence = rctx->ws->cs_get_next_fence(rctx->gfx.cs);
>   			deferred_fence = true;
>   		} else {
>   			rctx->gfx.flush(rctx, rflags, fence ? &gfx_fence : NULL);
>   		}
>   	}
>   
>   	/* Both engines can signal out of order, so we need to keep both fences. */
>   	if (fence) {
>   		struct r600_multi_fence *multi_fence =
> @@ -721,20 +794,21 @@ bool r600_common_context_init(struct r600_common_context *rctx,
>   
>   	rctx->b.invalidate_resource = r600_invalidate_resource;
>   	rctx->b.resource_commit = r600_resource_commit;
>   	rctx->b.transfer_map = u_transfer_map_vtbl;
>   	rctx->b.transfer_flush_region = u_transfer_flush_region_vtbl;
>   	rctx->b.transfer_unmap = u_transfer_unmap_vtbl;
>   	rctx->b.texture_subdata = u_default_texture_subdata;
>   	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.create_fence_fd = r600_create_fence_fd;
>   	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.
>   	 * Everything else can use the direct path.
>   	 */
>   	if ((rscreen->chip_class == EVERGREEN || rscreen->chip_class == CAYMAN) &&
>   	    (context_flags & PIPE_CONTEXT_COMPUTE_ONLY))
>   		rctx->b.buffer_subdata = u_default_buffer_subdata;
>   	else
> @@ -1489,20 +1563,21 @@ bool r600_common_screen_init(struct r600_common_screen *rscreen,
>   	rscreen->b.get_device_vendor = r600_get_device_vendor;
>   	rscreen->b.get_disk_shader_cache = r600_get_disk_shader_cache;
>   	rscreen->b.get_compute_param = r600_get_compute_param;
>   	rscreen->b.get_paramf = r600_get_paramf;
>   	rscreen->b.get_timestamp = r600_get_timestamp;
>   	rscreen->b.fence_finish = r600_fence_finish;
>   	rscreen->b.fence_reference = r600_fence_reference;
>   	rscreen->b.resource_destroy = u_resource_destroy_vtbl;
>   	rscreen->b.resource_from_user_memory = r600_buffer_from_user_memory;
>   	rscreen->b.query_memory_info = r600_query_memory_info;
> +	rscreen->b.fence_get_fd = r600_fence_get_fd;
>   
>   	if (rscreen->info.has_hw_decode) {
>   		rscreen->b.get_video_param = rvid_get_video_param;
>   		rscreen->b.is_video_format_supported = rvid_is_format_supported;
>   	} else {
>   		rscreen->b.get_video_param = r600_get_video_param;
>   		rscreen->b.is_video_format_supported = vl_video_buffer_is_format_supported;
>   	}
>   
>   	r600_init_screen_texture_functions(rscreen);
> diff --git a/src/gallium/drivers/radeonsi/si_pipe.c b/src/gallium/drivers/radeonsi/si_pipe.c
> index ca2e055..e9c95e2 100644
> --- a/src/gallium/drivers/radeonsi/si_pipe.c
> +++ b/src/gallium/drivers/radeonsi/si_pipe.c
> @@ -562,28 +562,30 @@ static int si_get_param(struct pipe_screen* pscreen, enum pipe_cap param)
>   	/* Unsupported features. */
>   	case PIPE_CAP_BUFFER_SAMPLER_VIEW_RGBA_ONLY:
>   	case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
>   	case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
>   	case PIPE_CAP_USER_VERTEX_BUFFERS:
>   	case PIPE_CAP_FAKE_SW_MSAA:
>   	case PIPE_CAP_TEXTURE_GATHER_OFFSETS:
>   	case PIPE_CAP_VERTEXID_NOBASE:
>   	case PIPE_CAP_PRIMITIVE_RESTART_FOR_PATCHES:
>   	case PIPE_CAP_MAX_WINDOW_RECTANGLES:
> -	case PIPE_CAP_NATIVE_FENCE_FD:
>   	case PIPE_CAP_TGSI_FS_FBFETCH:
>   	case PIPE_CAP_TGSI_MUL_ZERO_WINS:
>   	case PIPE_CAP_UMA:
>   	case PIPE_CAP_POLYGON_MODE_FILL_RECTANGLE:
>   	case PIPE_CAP_POST_DEPTH_COVERAGE:
>   		return 0;
>   
> +	case PIPE_CAP_NATIVE_FENCE_FD:
> +		return sscreen->b.info.has_sync_file;
> +
>   	case PIPE_CAP_QUERY_BUFFER_OBJECT:
>   		return si_have_tgsi_compute(sscreen);
>   
>   	case PIPE_CAP_DRAW_PARAMETERS:
>   	case PIPE_CAP_MULTI_DRAW_INDIRECT:
>   	case PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS:
>   		return sscreen->has_draw_indirect_multi;
>   
>   	case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS:
>   		return 30;
> 


-- 
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.


More information about the mesa-dev mailing list