diff options
Diffstat (limited to 'src/radeon_ctx.c')
| -rw-r--r-- | src/radeon_ctx.c | 436 |
1 files changed, 220 insertions, 216 deletions
diff --git a/src/radeon_ctx.c b/src/radeon_ctx.c index 4e0ba56..1188b09 100644 --- a/src/radeon_ctx.c +++ b/src/radeon_ctx.c @@ -24,56 +24,33 @@ * Jerome Glisse */ #include <stdlib.h> +#include <string.h> #include "radeon_priv.h" +#include "radeon_drm.h" -#pragma pack(1) -struct cs_reloc_gem { - uint32_t handle; - uint32_t read_domain; - uint32_t write_domain; - uint32_t flags; -}; -#pragma pack() - -int radeon_ctx_set_object_new(struct radeon_ctx *ctx, - struct radeon_object *bo, - int id) +int radeon_ctx_set_bo_new(struct radeon_ctx *ctx, struct radeon_bo *bo) { void *ptr; - ptr = realloc(ctx->bo, sizeof(struct radeon_ctx_bo) * (ctx->nbo + 1)); + ptr = realloc(ctx->bo, sizeof(struct radeon_bo) * (ctx->nbo + 1)); if (ptr == NULL) { return -ENOMEM; } ctx->bo = ptr; - ctx->bo[ctx->nbo].bo = bo; - ctx->bo[ctx->nbo].id = id; + ctx->bo[ctx->nbo] = bo; ctx->nbo++; return 0; } -struct radeon_object *radeon_ctx_get_object(struct radeon_ctx *ctx, unsigned handle) -{ - unsigned i; - - for (i = 0; i < ctx->nbo; i++) { - if (ctx->bo[i].bo->handle == handle) { - return radeon_object_incref(ctx->bo[i].bo); - } - } - return NULL; -} - -struct radeon_object *radeon_ctx_get_bo(struct radeon_ctx *ctx, unsigned reloc) +struct radeon_bo *radeon_ctx_get_bo(struct radeon_ctx *ctx, unsigned reloc) { - struct cs_reloc_gem *greloc; + struct radeon_cs_reloc *greloc; unsigned i; - greloc = (struct cs_reloc_gem *)&ctx->reloc[reloc]; + greloc = (void *)(((u8 *)ctx->reloc) + reloc * 4); for (i = 0; i < ctx->nbo; i++) { - if (ctx->bo[i].bo->handle == greloc->handle) { - ctx->bo[i].id = reloc; - return radeon_object_incref(ctx->bo[i].bo); + if (ctx->bo[i]->handle == greloc->handle) { + return radeon_bo_incref(ctx->radeon, ctx->bo[i]); } } fprintf(stderr, "%s no bo for reloc[%d 0x%08X] %d\n", __func__, reloc, greloc->handle, ctx->nbo); @@ -82,14 +59,14 @@ struct radeon_object *radeon_ctx_get_bo(struct radeon_ctx *ctx, unsigned reloc) void radeon_ctx_get_placement(struct radeon_ctx *ctx, unsigned reloc, u32 *placement) { - struct cs_reloc_gem *greloc; + struct radeon_cs_reloc *greloc; unsigned i; placement[0] = 0; placement[1] = 0; - greloc = (struct cs_reloc_gem *)&ctx->reloc[reloc]; + greloc = (void *)(((u8 *)ctx->reloc) + reloc * 4); for (i = 0; i < ctx->nbo; i++) { - if (ctx->bo[i].bo->handle == greloc->handle) { + if (ctx->bo[i]->handle == greloc->handle) { placement[0] = greloc->read_domain | greloc->write_domain; placement[1] = placement[0]; return; @@ -97,45 +74,52 @@ void radeon_ctx_get_placement(struct radeon_ctx *ctx, unsigned reloc, u32 *place } } -struct radeon_ctx *radeon_ctx(struct radeon *radeon, unsigned device) +struct radeon_ctx *radeon_ctx(struct radeon *radeon) { struct radeon_ctx *ctx; + if (radeon == NULL) + return NULL; ctx = calloc(1, sizeof(*ctx)); if (ctx == NULL) return NULL; ctx->radeon = radeon_incref(radeon); - if (radeon == NULL) { - ctx->radeon = radeon_new(-1, device); - if (ctx->radeon == NULL) { - free(ctx); - return NULL; - } - } return ctx; } -void radeon_ctx_destroy(struct radeon_ctx *ctx) +struct radeon_ctx *radeon_ctx_incref(struct radeon_ctx *ctx) +{ + ctx->refcount++; + return ctx; +} + +struct radeon_ctx *radeon_ctx_decref(struct radeon_ctx *ctx) { unsigned i; + if (ctx == NULL) + return NULL; + if (--ctx->refcount > 0) { + return NULL; + } + for (i = 0; i < ctx->ndraw; i++) { ctx->draw[i] = radeon_draw_decref(ctx->draw[i]); } for (i = 0; i < ctx->nbo; i++) { - ctx->bo[i].bo = radeon_object_decref(ctx->bo[i].bo); + ctx->bo[i] = radeon_bo_decref(ctx->radeon, ctx->bo[i]); } - radeon_decref(ctx->radeon); + ctx->radeon = radeon_decref(ctx->radeon); free(ctx->draw); free(ctx->bo); free(ctx->pm4); free(ctx->reloc); memset(ctx, 0, sizeof(*ctx)); free(ctx); + return NULL; } -static int radeon_ctx_state_bo(struct radeon_ctx *ctx, - struct radeon_state *state) +static int radeon_ctx_state_bo(struct radeon_ctx *ctx, struct radeon_state *state) { unsigned i, j; int r; @@ -144,12 +128,12 @@ static int radeon_ctx_state_bo(struct radeon_ctx *ctx, return 0; for (i = 0; i < state->nbo; i++) { for (j = 0; j < ctx->nbo; j++) { - if (state->bo[i] == ctx->bo[j].bo) + if (state->bo[i] == ctx->bo[j]) break; } if (j == ctx->nbo) { - radeon_object_incref(state->bo[i]); - r = radeon_ctx_set_object_new(ctx, state->bo[i], -1); + radeon_bo_incref(ctx->radeon, state->bo[i]); + r = radeon_ctx_set_bo_new(ctx, state->bo[i]); if (r) return r; } @@ -157,95 +141,87 @@ static int radeon_ctx_state_bo(struct radeon_ctx *ctx, return 0; } -int radeon_ctx_set_draw_new(struct radeon_ctx *ctx, struct radeon_draw *draw) -{ - struct radeon_draw **ndraw; - unsigned i; - int r; - - ndraw = realloc(ctx->draw, sizeof(void*) * (ctx->ndraw + 1)); - if (ndraw == NULL) - return -ENOMEM; - ctx->draw = ndraw; - for (i = 0; i < draw->nstate; i++) { - r = radeon_ctx_state_bo(ctx, draw->state[i]); - if (r) - return r; - } - ctx->draw[ctx->ndraw++] = draw; - ctx->cdraw = draw; - return 0; -} - -struct radeon_object *radeon_object(struct radeon_bo *bo, unsigned handle, - unsigned size, void *ptr) -{ - struct radeon_object *object; - - object = calloc(1, sizeof(*object)); - if (object == NULL) - return NULL; - object->data = calloc(1, size); - if (object->data == NULL) { - return NULL; - } - object->size = size; - object->handle = handle; - object->bo = bo; - object->refcount = 1; - if (ptr) - memcpy(object->data, ptr, size); - return object; -} - -struct radeon_object *radeon_object_incref(struct radeon_object *object) -{ - object->refcount++; - return object; -} - -struct radeon_object *radeon_object_decref(struct radeon_object *object) +static void radeon_ctx_dump_bof(struct radeon_ctx *ctx) { - if (object == NULL) - return NULL; - if (--object->refcount > 0) { - return NULL; - } - free(object->data); - object->data = NULL; - object->bo = radeon_bo_unref(object->bo); - free(object); - return NULL; -} - -int radeon_ctx_allocate_bo(struct radeon_ctx *ctx) -{ - struct radeon *radeon = ctx->radeon; - struct radeon_object *bo; - struct cs_reloc_gem *greloc; + bof_t *bcs, *blob, *array, *bo, *size, *handle, *device_id, *root; + char tmp[256]; unsigned i; + root = device_id = bcs = blob = array = bo = size = handle = NULL; + root = bof_object(); + if (root == NULL) + goto out_err; + device_id = bof_int32(ctx->radeon->device); + if (device_id == NULL) + return; + if (bof_object_set(root, "device_id", device_id)) + goto out_err; + bof_decref(device_id); + device_id = NULL; + /* dump relocs */ + blob = bof_blob(ctx->nreloc * 16, ctx->reloc); + if (blob == NULL) + goto out_err; + if (bof_object_set(root, "reloc", blob)) + goto out_err; + bof_decref(blob); + blob = NULL; + /* dump cs */ + blob = bof_blob(ctx->cpm4 * 4, ctx->pm4); + if (blob == NULL) + goto out_err; + if (bof_object_set(root, "pm4", blob)) + goto out_err; + bof_decref(blob); + blob = NULL; + /* dump bo */ + array = bof_array(); + if (array == NULL) + goto out_err; for (i = 0; i < ctx->nbo; i++) { - bo = ctx->bo[i].bo; - bo->bo = radeon_bo_open(radeon->bom, 0, bo->size, 0, - RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0); - if (bo->bo == NULL) { - return -ENOMEM; - } - radeon_bo_map(bo->bo, 1); - memcpy(bo->bo->ptr, bo->data, bo->size); - radeon_bo_unmap(bo->bo); - } - for (i = 0; i < ctx->nbo; i++) { - if (ctx->bo[i].id >= 0) { - greloc = (struct cs_reloc_gem *)&ctx->reloc[ctx->bo[i].id]; - greloc->handle = ctx->bo[i].bo->bo->handle; - } - } - for (i = 0; i < ctx->nbo; i++) { - ctx->bo[i].bo->handle = ctx->bo[i].bo->bo->handle; + bo = bof_object(); + if (bo == NULL) + goto out_err; + size = bof_int32(ctx->bo[i]->size); + if (size == NULL) + goto out_err; + if (bof_object_set(bo, "size", size)) + goto out_err; + bof_decref(size); + size = NULL; + handle = bof_int32(ctx->bo[i]->handle); + if (handle == NULL) + goto out_err; + if (bof_object_set(bo, "handle", handle)) + goto out_err; + bof_decref(handle); + handle = NULL; + radeon_bo_map(ctx->radeon, ctx->bo[i]); + blob = bof_blob(ctx->bo[i]->size, ctx->bo[i]->data); + radeon_bo_unmap(ctx->radeon, ctx->bo[i]); + if (blob == NULL) + goto out_err; + if (bof_object_set(bo, "data", blob)) + goto out_err; + bof_decref(blob); + blob = NULL; + if (bof_array_append(array, bo)) + goto out_err; + bof_decref(bo); + bo = NULL; } - return 0; + if (bof_object_set(root, "bo", array)) + goto out_err; + sprintf(tmp, "d-0x%04X.bof", ctx->radeon->device); + bof_dump_file(root, tmp); +out_err: + bof_decref(blob); + bof_decref(array); + bof_decref(bo); + bof_decref(size); + bof_decref(handle); + bof_decref(device_id); + bof_decref(root); } int radeon_ctx_submit(struct radeon_ctx *ctx) @@ -256,7 +232,6 @@ int radeon_ctx_submit(struct radeon_ctx *ctx) int r = 0; #if 0 - printf("reloc %d %d %d pm4 %d\n", ctx->reloc_ndw, ctx->reloc_ndw / 4, ctx->nbo, ctx->cpm4); for (r = 0; r < ctx->cpm4; r++) { fprintf(stderr, "0x%08X\n", ctx->pm4[r]); } @@ -267,7 +242,7 @@ int radeon_ctx_submit(struct radeon_ctx *ctx) chunks[0].length_dw = ctx->cpm4; chunks[0].chunk_data = (uint64_t)(uintptr_t)ctx->pm4; chunks[1].chunk_id = RADEON_CHUNK_ID_RELOCS; - chunks[1].length_dw = ctx->reloc_ndw; + chunks[1].length_dw = ctx->nreloc * sizeof(struct radeon_cs_reloc) / 4; chunks[1].chunk_data = (uint64_t)(uintptr_t)ctx->reloc; chunk_array[0] = (uint64_t)(uintptr_t)&chunks[0]; chunk_array[1] = (uint64_t)(uintptr_t)&chunks[1]; @@ -283,39 +258,28 @@ int radeon_ctx_draw(struct radeon_ctx *ctx) return ctx->radeon->asic->ctx_draw(ctx); } -int radeon_ctx_reloc(struct radeon_ctx *ctx, struct radeon_object *bo, +int radeon_ctx_reloc(struct radeon_ctx *ctx, struct radeon_bo *bo, unsigned id, unsigned *placement) { unsigned i; - void *ptr; - struct cs_reloc_gem *greloc; + struct radeon_cs_reloc *ptr; - for (i = 0; i < ctx->nbo; i++) { - if (ctx->bo[i].bo == bo) { - if (ctx->bo[i].id >= 0) { - ctx->pm4[id] = ctx->bo[i].id; - return 0; - } - break; + for (i = 0; i < ctx->nreloc; i++) { + if (ctx->reloc[i].handle == bo->handle) { + ctx->pm4[id] = i * sizeof(struct radeon_cs_reloc) / 4; + return 0; } } - if (i == ctx->nbo) { - fprintf(stderr, "%s bo %p 0x%08X unknown to context\n", - __func__, bo, bo->handle); - return -EINVAL; - } - ptr = realloc(ctx->reloc, sizeof(struct cs_reloc_gem) + ctx->reloc_ndw *4); + ptr = realloc(ctx->reloc, sizeof(struct radeon_cs_reloc) * (ctx->nreloc + 1)); if (ptr == NULL) return -ENOMEM; ctx->reloc = ptr; - greloc = (struct cs_reloc_gem *)&ctx->reloc[ctx->reloc_ndw]; - greloc->handle = bo->bo->handle; - greloc->read_domain = placement[0] | placement [1]; - greloc->write_domain = placement[0] | placement [1]; - greloc->flags = 0; - ctx->bo[i].id = ctx->reloc_ndw; - ctx->pm4[id] = ctx->bo[i].id; - ctx->reloc_ndw += sizeof(struct cs_reloc_gem) / 4; + ptr[ctx->nreloc].handle = bo->handle; + ptr[ctx->nreloc].read_domain = placement[0] | placement [1]; + ptr[ctx->nreloc].write_domain = placement[0] | placement [1]; + ptr[ctx->nreloc].flags = 0; + ctx->pm4[id] = ctx->nreloc * sizeof(struct radeon_cs_reloc) / 4; + ctx->nreloc++; return 0; } @@ -341,73 +305,113 @@ int radeon_ctx_state_schedule(struct radeon_ctx *ctx, struct radeon_state *state ctx->id += state->cpm4; return 0; } -#if 0 -int radeon_ctx_draw_schedule(struct radeon_ctx *ctx, unsigned id) + +void *copy_object(void *ptr, unsigned size) { - struct radeon_draw *draw; - unsigned i; - int r; + void *copy; - draw = ctx->draw[id]; - for (i = 0; i < draw->nstate; i++) { - r = radeon_ctx_state_schedule(ctx, draw->state[i]); - if (r) - return r; - } - return 0; + copy = calloc(1, size); + if (copy == NULL) + return NULL; + memcpy(copy, ptr, size); + return copy; } -#endif -int radeon_ctx_draw_set_reg(struct radeon_ctx *ctx, unsigned offset, u32 value) + +int radeon_ctx_set_draw_new(struct radeon_ctx *ctx, struct radeon_draw *draw) { - struct radeon_draw *draw; - struct radeon *radeon = ctx->radeon; - struct radeon_object *bo; - unsigned id, stateid, typeid, boid, reloc; - int r; + struct radeon_draw *pdraw = NULL; + struct radeon_draw **ndraw; + struct radeon_state *nstate, *ostate; + unsigned cpm4, i, cstate; + void *tmp; + int r = 0; - draw = ctx->cdraw; - if (draw == NULL) { - draw = radeon_draw(ctx->radeon); - if (draw == NULL) - return -ENOMEM; - r = radeon_ctx_set_draw_new(ctx, draw); - if (r) { - radeon_draw_decref(draw); + ndraw = realloc(ctx->draw, sizeof(void*) * (ctx->ndraw + 1)); + if (ndraw == NULL) + return -ENOMEM; + ctx->draw = ndraw; + for (i = 0; i < draw->nstate; i++) { + r = radeon_ctx_state_bo(ctx, draw->state[i]); + if (r) return r; - } } - r = radeon_reg_id(radeon, offset, &typeid, &stateid, &id); - if (r) { + r = radeon_draw_check(draw); + if (r) return r; + if (draw->cpm4 >= RADEON_CTX_MAX_PM4) { + fprintf(stderr, "%s single draw too big %d, max %d\n", + __func__, draw->cpm4, RADEON_CTX_MAX_PM4); + return -EINVAL; } - if (draw->state[stateid] == NULL) { - draw->state[stateid] = radeon_state(radeon, typeid, stateid); - if (draw->state[stateid] == NULL) - return -ENOMEM; - }; - draw->state[stateid]->states[id] = value; - if (radeon->type[typeid].regs[id].need_reloc) { - r = radeon_ctx_next_reloc(ctx, &reloc); - if (r) - return r; - bo = radeon_ctx_get_bo(ctx, reloc); - if (bo == NULL) - return -ENOMEM; - boid = radeon->type[typeid].regs[id].bo_id; - radeon_object_decref(draw->state[stateid]->bo[boid]); - draw->state[stateid]->bo[boid] = bo; - radeon_ctx_get_placement(ctx, reloc, &draw->state[stateid]->placement[boid * 2]); + tmp = realloc(ctx->state, (ctx->nstate + draw->nstate) * sizeof(void*)); + if (tmp == NULL) + return -ENOMEM; + ctx->state = tmp; + pdraw = ctx->cdraw; + for (i = 0, cpm4 = 0, cstate = ctx->nstate; i < draw->nstate - 1; i++) { + nstate = draw->state[i]; + if (nstate) { + if (pdraw && pdraw->state[i]) { + ostate = pdraw->state[i]; + if (ostate->pm4_crc != nstate->pm4_crc) { + ctx->state[cstate++] = nstate; + cpm4 += nstate->cpm4; + } + } else { + ctx->state[cstate++] = nstate; + cpm4 += nstate->cpm4; + } + } + } + /* The last state is the draw state always add it */ + if (draw->state[i] == NULL) { + fprintf(stderr, "%s no draw command\n", __func__); + return -EINVAL; + } + ctx->state[cstate++] = draw->state[i]; + cpm4 += draw->state[i]->cpm4; + if ((ctx->draw_cpm4 + cpm4) > RADEON_CTX_MAX_PM4) { + /* need to flush */ + return -EBUSY; } + ctx->draw_cpm4 += cpm4; + ctx->nstate = cstate; + ctx->draw[ctx->ndraw++] = draw; + ctx->cdraw = draw; return 0; } -void *copy_object(void *ptr, unsigned size) +int radeon_ctx_set_draw(struct radeon_ctx *ctx, struct radeon_draw *draw) { - void *copy; + int r; - copy = calloc(1, size); - if (copy == NULL) - return NULL; - memcpy(copy, ptr, size); - return copy; + radeon_draw_incref(draw); + r = radeon_ctx_set_draw_new(ctx, draw); + if (r) + radeon_draw_decref(draw); + return r; +} + +int radeon_ctx_pm4(struct radeon_ctx *ctx) +{ + unsigned i; + int r; + + free(ctx->pm4); + ctx->cpm4 = 0; + ctx->pm4 = malloc(ctx->draw_cpm4 * 4); + if (ctx->pm4 == NULL) + return -EINVAL; + for (i = 0, ctx->id = 0; i < ctx->nstate; i++) { + r = radeon_ctx_state_schedule(ctx, ctx->state[i]); + if (r) + return r; + } + if (ctx->id != ctx->draw_cpm4) { + fprintf(stderr, "%s miss predicted pm4 size %d for %d\n", + __func__, ctx->draw_cpm4, ctx->id); + return -EINVAL; + } + ctx->cpm4 = ctx->draw_cpm4; + return 0; } |
