iris: Add fence support using drm_syncobj
This commit is contained in:
parent
db199d9d07
commit
f459c56be6
|
@ -34,23 +34,6 @@
|
|||
#include "iris_screen.h"
|
||||
#include "common/gen_sample_positions.h"
|
||||
|
||||
static void
|
||||
iris_flush(struct pipe_context *ctx,
|
||||
struct pipe_fence_handle **fence,
|
||||
unsigned flags)
|
||||
{
|
||||
struct iris_context *ice = (struct iris_context *)ctx;
|
||||
|
||||
iris_batch_flush(&ice->render_batch);
|
||||
|
||||
if (ice->compute_batch.contains_draw)
|
||||
iris_batch_flush(&ice->compute_batch);
|
||||
|
||||
// XXX: bogus!!!
|
||||
if (fence)
|
||||
*fence = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* For debugging purposes, this returns a time in seconds.
|
||||
*/
|
||||
|
@ -182,12 +165,12 @@ iris_create_context(struct pipe_screen *pscreen, void *priv, unsigned flags)
|
|||
ctx->const_uploader = ctx->stream_uploader;
|
||||
|
||||
ctx->destroy = iris_destroy_context;
|
||||
ctx->flush = iris_flush;
|
||||
ctx->set_debug_callback = iris_set_debug_callback;
|
||||
ctx->get_sample_position = iris_get_sample_position;
|
||||
|
||||
ice->shaders.urb_size = devinfo->urb.size;
|
||||
|
||||
iris_init_context_fence_functions(ctx);
|
||||
iris_init_blit_functions(ctx);
|
||||
iris_init_clear_functions(ctx);
|
||||
iris_init_program_functions(ctx);
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "intel/compiler/brw_compiler.h"
|
||||
#include "iris_batch.h"
|
||||
#include "iris_binder.h"
|
||||
#include "iris_fence.h"
|
||||
#include "iris_resource.h"
|
||||
#include "iris_screen.h"
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "iris_batch.h"
|
||||
#include "iris_bufmgr.h"
|
||||
#include "iris_context.h"
|
||||
#include "iris_fence.h"
|
||||
#include "iris_screen.h"
|
||||
|
||||
|
@ -105,3 +106,254 @@ iris_batch_add_syncpt(struct iris_batch *batch,
|
|||
*store = NULL;
|
||||
iris_syncpt_reference(batch->screen, store, syncpt);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
struct pipe_fence_handle {
|
||||
struct pipe_reference ref;
|
||||
struct iris_syncpt *syncpt[IRIS_BATCH_COUNT];
|
||||
unsigned count;
|
||||
};
|
||||
|
||||
static void
|
||||
iris_fence_destroy(struct pipe_screen *p_screen,
|
||||
struct pipe_fence_handle *fence)
|
||||
{
|
||||
struct iris_screen *screen = (struct iris_screen *)p_screen;
|
||||
|
||||
for (unsigned i = 0; i < fence->count; i++)
|
||||
iris_syncpt_reference(screen, &fence->syncpt[i], NULL);
|
||||
|
||||
free(fence);
|
||||
}
|
||||
|
||||
static void
|
||||
iris_fence_reference(struct pipe_screen *p_screen,
|
||||
struct pipe_fence_handle **dst,
|
||||
struct pipe_fence_handle *src)
|
||||
{
|
||||
if (pipe_reference(&(*dst)->ref, &src->ref))
|
||||
iris_fence_destroy(p_screen, *dst);
|
||||
|
||||
*dst = src;
|
||||
}
|
||||
|
||||
static bool
|
||||
check_syncpt(struct pipe_screen *p_screen,
|
||||
struct iris_syncpt *syncpt)
|
||||
{
|
||||
if (!syncpt)
|
||||
return false;
|
||||
|
||||
struct iris_screen *screen = (struct iris_screen *)p_screen;
|
||||
struct drm_syncobj_wait args = {
|
||||
.handles = (uintptr_t)&syncpt->handle,
|
||||
.count_handles = 1,
|
||||
};
|
||||
return drm_ioctl(screen->fd, DRM_IOCTL_SYNCOBJ_WAIT, &args);
|
||||
}
|
||||
|
||||
static void
|
||||
iris_fence_flush(struct pipe_context *ctx,
|
||||
struct pipe_fence_handle **out_fence,
|
||||
unsigned flags)
|
||||
{
|
||||
struct iris_screen *screen = (void *) ctx->screen;
|
||||
struct iris_context *ice = (struct iris_context *)ctx;
|
||||
struct iris_batch *batch[IRIS_BATCH_COUNT] = {
|
||||
&ice->compute_batch,
|
||||
&ice->render_batch
|
||||
};
|
||||
|
||||
/* XXX PIPE_FLUSH_DEFERRED */
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(batch); i++)
|
||||
iris_batch_flush(batch[i]);
|
||||
|
||||
if (!out_fence)
|
||||
return;
|
||||
|
||||
struct pipe_fence_handle *fence = calloc(1, sizeof(*fence));
|
||||
if (!fence)
|
||||
return;
|
||||
|
||||
pipe_reference_init(&fence->ref, 1);
|
||||
|
||||
for (unsigned b = 0; b < ARRAY_SIZE(batch); b++) {
|
||||
if (!check_syncpt(ctx->screen, batch[b]->last_syncpt))
|
||||
continue;
|
||||
|
||||
iris_syncpt_reference(screen, &fence->syncpt[fence->count++],
|
||||
batch[b]->last_syncpt);
|
||||
}
|
||||
*out_fence = fence;
|
||||
}
|
||||
|
||||
static void
|
||||
iris_fence_await(struct pipe_context *ctx,
|
||||
struct pipe_fence_handle *fence)
|
||||
{
|
||||
struct iris_context *ice = (struct iris_context *)ctx;
|
||||
struct iris_batch *batch[IRIS_BATCH_COUNT] = {
|
||||
&ice->compute_batch,
|
||||
&ice->render_batch
|
||||
};
|
||||
for (unsigned b = 0; b < ARRAY_SIZE(batch); b++) {
|
||||
for (unsigned i = 0; i < fence->count; i++) {
|
||||
iris_batch_add_syncpt(batch[b], fence->syncpt[i],
|
||||
I915_EXEC_FENCE_WAIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define NSEC_PER_SEC (1000 * USEC_PER_SEC)
|
||||
#define USEC_PER_SEC (1000 * MSEC_PER_SEC)
|
||||
#define MSEC_PER_SEC (1000)
|
||||
|
||||
static uint64_t
|
||||
rel2abs(uint64_t timeout)
|
||||
{
|
||||
struct timespec ts;
|
||||
uint64_t now;
|
||||
|
||||
if (!timeout)
|
||||
return 0;
|
||||
|
||||
if (timeout == PIPE_TIMEOUT_INFINITE)
|
||||
return INT64_MAX;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
now = ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec;
|
||||
|
||||
if (now > INT64_MAX - timeout)
|
||||
return INT64_MAX;
|
||||
|
||||
return now + timeout;
|
||||
}
|
||||
|
||||
static boolean
|
||||
iris_fence_finish(struct pipe_screen *p_screen,
|
||||
struct pipe_context *ctx,
|
||||
struct pipe_fence_handle *fence,
|
||||
uint64_t timeout)
|
||||
{
|
||||
struct iris_screen *screen = (struct iris_screen *)p_screen;
|
||||
|
||||
if (!fence->count)
|
||||
return true;
|
||||
|
||||
uint32_t handles[ARRAY_SIZE(fence->syncpt)];
|
||||
for (unsigned i = 0; i < fence->count; i++)
|
||||
handles[i] = fence->syncpt[i]->handle;
|
||||
|
||||
struct drm_syncobj_wait args = {
|
||||
.handles = (uintptr_t)handles,
|
||||
.count_handles = fence->count,
|
||||
.timeout_nsec = rel2abs(timeout), /* XXX */
|
||||
.flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL
|
||||
};
|
||||
return drm_ioctl(screen->fd, DRM_IOCTL_SYNCOBJ_WAIT, &args) == 0;
|
||||
}
|
||||
|
||||
#ifndef SYNC_IOC_MAGIC
|
||||
/* duplicated from linux/sync_file.h to avoid build-time dependency
|
||||
* on new (v4.7) kernel headers. Once distro's are mostly using
|
||||
* something newer than v4.7 drop this and #include <linux/sync_file.h>
|
||||
* instead.
|
||||
*/
|
||||
struct sync_merge_data {
|
||||
char name[32];
|
||||
__s32 fd2;
|
||||
__s32 fence;
|
||||
__u32 flags;
|
||||
__u32 pad;
|
||||
};
|
||||
|
||||
#define SYNC_IOC_MAGIC '>'
|
||||
#define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 3, struct sync_merge_data)
|
||||
#endif
|
||||
|
||||
static int
|
||||
sync_merge_fd(int sync_fd, int new_fd)
|
||||
{
|
||||
if (sync_fd == -1)
|
||||
return new_fd;
|
||||
|
||||
if (new_fd == -1)
|
||||
return sync_fd;
|
||||
|
||||
struct sync_merge_data args = {
|
||||
.name = "iris fence",
|
||||
.fd2 = new_fd,
|
||||
.fence = -1,
|
||||
};
|
||||
|
||||
drm_ioctl(sync_fd, SYNC_IOC_MERGE, &args);
|
||||
close(new_fd);
|
||||
close(sync_fd);
|
||||
|
||||
return args.fence;
|
||||
}
|
||||
|
||||
static int
|
||||
iris_fence_get_fd(struct pipe_screen *p_screen,
|
||||
struct pipe_fence_handle *fence)
|
||||
{
|
||||
struct iris_screen *screen = (struct iris_screen *)p_screen;
|
||||
int fd = -1;
|
||||
|
||||
for (unsigned i = 0; i < fence->count; i++) {
|
||||
struct drm_syncobj_handle args = {
|
||||
.handle = fence->syncpt[i]->handle,
|
||||
.flags = DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE,
|
||||
.fd = -1,
|
||||
};
|
||||
|
||||
drm_ioctl(screen->fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &args);
|
||||
fd = sync_merge_fd(fd, args.fd);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void
|
||||
iris_fence_create_fd(struct pipe_context *ctx,
|
||||
struct pipe_fence_handle **out,
|
||||
int fd,
|
||||
enum pipe_fd_type type)
|
||||
{
|
||||
assert(type == PIPE_FD_TYPE_NATIVE_SYNC);
|
||||
|
||||
struct iris_screen *screen = (struct iris_screen *)ctx->screen;
|
||||
struct drm_syncobj_handle args = {
|
||||
.flags = DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE,
|
||||
.fd = fd,
|
||||
};
|
||||
drm_ioctl(screen->fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &args);
|
||||
|
||||
struct iris_syncpt *syncpt = malloc(sizeof(*syncpt));
|
||||
syncpt->handle = args.handle;
|
||||
pipe_reference_init(&syncpt->ref, 1);
|
||||
|
||||
struct pipe_fence_handle *fence = malloc(sizeof(*fence));
|
||||
pipe_reference_init(&fence->ref, 1);
|
||||
fence->syncpt[0] = syncpt;
|
||||
fence->count = 1;
|
||||
|
||||
*out = fence;
|
||||
}
|
||||
|
||||
void
|
||||
iris_init_screen_fence_functions(struct pipe_screen *screen)
|
||||
{
|
||||
screen->fence_reference = iris_fence_reference;
|
||||
screen->fence_finish = iris_fence_finish;
|
||||
screen->fence_get_fd = iris_fence_get_fd;
|
||||
}
|
||||
|
||||
void
|
||||
iris_init_context_fence_functions(struct pipe_context *ctx)
|
||||
{
|
||||
ctx->flush = iris_fence_flush;
|
||||
ctx->create_fence_fd = iris_fence_create_fd;
|
||||
ctx->fence_server_sync = iris_fence_await;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,9 @@ struct iris_syncpt {
|
|||
uint32_t handle;
|
||||
};
|
||||
|
||||
void iris_init_context_fence_functions(struct pipe_context *ctx);
|
||||
void iris_init_screen_fence_functions(struct pipe_screen *screen);
|
||||
|
||||
struct iris_syncpt *iris_create_syncpt(struct iris_screen *screen);
|
||||
void iris_syncpt_destroy(struct iris_screen *, struct iris_syncpt *);
|
||||
void iris_batch_add_syncpt(struct iris_batch *batch,
|
||||
|
|
|
@ -459,22 +459,6 @@ iris_destroy_screen(struct pipe_screen *pscreen)
|
|||
ralloc_free(screen);
|
||||
}
|
||||
|
||||
static void
|
||||
iris_fence_reference(struct pipe_screen *screen,
|
||||
struct pipe_fence_handle **ptr,
|
||||
struct pipe_fence_handle *fence)
|
||||
{
|
||||
}
|
||||
|
||||
static boolean
|
||||
iris_fence_finish(struct pipe_screen *screen,
|
||||
struct pipe_context *ctx,
|
||||
struct pipe_fence_handle *fence,
|
||||
uint64_t timeout)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
iris_query_memory_info(struct pipe_screen *pscreen,
|
||||
struct pipe_memory_info *info)
|
||||
|
@ -596,6 +580,7 @@ iris_screen_create(int fd)
|
|||
|
||||
struct pipe_screen *pscreen = &screen->base;
|
||||
|
||||
iris_init_screen_fence_functions(pscreen);
|
||||
iris_init_screen_resource_functions(pscreen);
|
||||
|
||||
pscreen->destroy = iris_destroy_screen;
|
||||
|
@ -611,8 +596,6 @@ iris_screen_create(int fd)
|
|||
pscreen->context_create = iris_create_context;
|
||||
pscreen->flush_frontbuffer = iris_flush_frontbuffer;
|
||||
pscreen->get_timestamp = iris_get_timestamp;
|
||||
pscreen->fence_reference = iris_fence_reference;
|
||||
pscreen->fence_finish = iris_fence_finish;
|
||||
pscreen->query_memory_info = iris_query_memory_info;
|
||||
|
||||
return pscreen;
|
||||
|
|
Loading…
Reference in New Issue