#define GROUP_FORCE_NEW_BLOCK 0
+int r600_context_init_fence(struct r600_context *ctx)
+{
+ ctx->fence = 1;
+ ctx->fence_bo = r600_bo(ctx->radeon, 4096, 0, 0);
+ if (ctx->fence_bo == NULL) {
+ return -ENOMEM;
+ }
+ ctx->cfence = r600_bo_map(ctx->radeon, ctx->fence_bo, PB_USAGE_UNSYNCHRONIZED, NULL);
+ *ctx->cfence = 0;
+ LIST_INITHEAD(&ctx->fenced_bo);
+ return 0;
+}
+
+static void INLINE r600_context_update_fenced_list(struct r600_context *ctx)
+{
+ for (int i = 0; i < ctx->creloc; i++) {
+ if (!LIST_IS_EMPTY(&ctx->bo[i]->fencedlist))
+ LIST_DELINIT(&ctx->bo[i]->fencedlist);
+ LIST_ADDTAIL(&ctx->bo[i]->fencedlist, &ctx->fenced_bo);
+ ctx->bo[i]->fence = ctx->fence;
+ ctx->bo[i]->ctx = ctx;
+ }
+}
+
+static void INLINE r600_context_fence_wraparound(struct r600_context *ctx, unsigned fence)
+{
+ struct radeon_bo *bo, *tmp;
+
+ LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &ctx->fenced_bo, fencedlist) {
+ if (bo->fence <= *ctx->cfence) {
+ LIST_DELINIT(&bo->fencedlist);
+ bo->fence = 0;
+ } else {
+ bo->fence = fence;
+ }
+ }
+}
+
int r600_context_add_block(struct r600_context *ctx, const struct r600_reg *reg, unsigned nreg)
{
struct r600_block *block;
}
free(ctx->reloc);
free(ctx->pm4);
+ if (ctx->fence_bo) {
+ r600_bo_reference(ctx->radeon, &ctx->fence_bo, NULL);
+ }
memset(ctx, 0, sizeof(struct r600_context));
}
r = -ENOMEM;
goto out_err;
}
+ /* save 16dwords space for fence mecanism */
+ ctx->pm4_ndwords -= 16;
+
+ r = r600_context_init_fence(ctx);
+ if (r) {
+ goto out_err;
+ }
/* init dirty list */
LIST_INITHEAD(&ctx->dirty);
struct drm_radeon_cs drmib;
struct drm_radeon_cs_chunk chunks[2];
uint64_t chunk_array[2];
+ unsigned fence;
int r;
if (!ctx->pm4_cdwords)
r600_context_queries_suspend(ctx);
radeon_bo_pbmgr_flush_maps(ctx->radeon->kman);
+
+ /* emit fence */
+ ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE_EOP, 4);
+ ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE_CACHE_FLUSH_AND_INV_TS_EVENT | (5 << 8);
+ ctx->pm4[ctx->pm4_cdwords++] = 0;
+ ctx->pm4[ctx->pm4_cdwords++] = (1 << 29) | (0 << 24);
+ ctx->pm4[ctx->pm4_cdwords++] = ctx->fence;
+ ctx->pm4[ctx->pm4_cdwords++] = 0;
+ ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_NOP, 0);
+ ctx->pm4[ctx->pm4_cdwords++] = 0;
+ r600_context_bo_reloc(ctx, &ctx->pm4[ctx->pm4_cdwords - 1], ctx->fence_bo);
+
#if 1
/* emit cs */
drmib.num_chunks = 2;
r = drmCommandWriteRead(ctx->radeon->fd, DRM_RADEON_CS, &drmib,
sizeof(struct drm_radeon_cs));
#endif
+
+ r600_context_update_fenced_list(ctx);
+
+ fence = ctx->fence + 1;
+ if (fence < ctx->fence) {
+ /* wrap around */
+ fence = 1;
+ r600_context_fence_wraparound(ctx, fence);
+ }
+ ctx->fence = fence;
+
/* restart */
- radeon_bo_fencelist(ctx->radeon, ctx->bo, ctx->creloc);
for (int i = 0; i < ctx->creloc; i++) {
ctx->bo[i]->reloc = NULL;
ctx->bo[i]->last_flush = 0;
return bo;
}
-
static void radeon_bo_destroy(struct radeon *radeon, struct radeon_bo *bo)
{
struct drm_gem_close args;
struct drm_radeon_gem_wait_idle args;
int ret;
- if (LIST_IS_EMPTY(&bo->fencedlist) && !bo->shared)
+ if (!bo->fence && !bo->shared)
+ return 0;
+
+ if (bo->fence <= *bo->ctx->cfence) {
+ LIST_DELINIT(&bo->fencedlist);
+ bo->fence = 0;
return 0;
+ }
/* Zero out args to make valgrind happy */
memset(&args, 0, sizeof(args));
return ret;
}
-#define BO_BUSY_BACKOFF 10000
-
int radeon_bo_busy(struct radeon *radeon, struct radeon_bo *bo, uint32_t *domain)
{
struct drm_radeon_gem_busy args;
int ret;
- int64_t now;
-
- now = os_time_get();
- if (LIST_IS_EMPTY(&bo->fencedlist) && !bo->shared)
- return 0;
-
- if (bo->set_busy && (now - bo->last_busy < BO_BUSY_BACKOFF))
- return -EBUSY;
- bo->set_busy = FALSE;
+ if (!bo->shared) {
+ if (!bo->fence)
+ return 0;
+ if (bo->fence <= *bo->ctx->cfence) {
+ LIST_DELINIT(&bo->fencedlist);
+ bo->fence = 0;
+ return 0;
+ }
+ }
memset(&args, 0, sizeof(args));
args.handle = bo->handle;
ret = drmCommandWriteRead(radeon->fd, DRM_RADEON_GEM_BUSY,
&args, sizeof(args));
- if (ret == 0) {
- struct radeon_bo *entry, *tent;
- LIST_FOR_EACH_ENTRY_SAFE(entry, tent, &bo->fencedlist, fencedlist) {
- LIST_DELINIT(&entry->fencedlist);
- }
- } else {
- bo->set_busy = TRUE;
- bo->last_busy = now;
- }
*domain = args.domain;
return ret;
}
-
-int radeon_bo_fencelist(struct radeon *radeon, struct radeon_bo **bolist,
- uint32_t num_bo)
-{
- struct radeon_bo *first;
- int i;
-
- first = bolist[0];
-
- if (!LIST_IS_EMPTY(&first->fencedlist))
- LIST_DELINIT(&first->fencedlist);
-
- LIST_INITHEAD(&first->fencedlist);
-
- for (i = 1; i < num_bo; i++) {
- if (!LIST_IS_EMPTY(&bolist[i]->fencedlist))
- LIST_DELINIT(&bolist[i]->fencedlist);
-
- LIST_ADDTAIL(&bolist[i]->fencedlist, &first->fencedlist);
- }
- return 0;
-}