From: Marek Olšák <marek.ol...@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); + 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; -- 2.7.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev