static boolean radeon_init_cs_context(struct radeon_cs_context *csc,
struct radeon_drm_winsys *ws)
{
+ int i;
+
+ csc->buf = MALLOC(ws->ib_max_size);
+ if (!csc->buf)
+ return FALSE;
csc->fd = ws->fd;
csc->nrelocs = 512;
csc->relocs_bo = (struct radeon_bo**)
CALLOC(1, csc->nrelocs * sizeof(struct radeon_bo*));
if (!csc->relocs_bo) {
+ FREE(csc->buf);
return FALSE;
}
csc->relocs = (struct drm_radeon_cs_reloc*)
CALLOC(1, csc->nrelocs * sizeof(struct drm_radeon_cs_reloc));
if (!csc->relocs) {
+ FREE(csc->buf);
FREE(csc->relocs_bo);
return FALSE;
}
csc->chunk_array[2] = (uint64_t)(uintptr_t)&csc->chunks[2];
csc->cs.chunks = (uint64_t)(uintptr_t)csc->chunk_array;
+
+ for (i = 0; i < Elements(csc->reloc_indices_hashlist); i++) {
+ csc->reloc_indices_hashlist[i] = -1;
+ }
return TRUE;
}
csc->chunks[1].length_dw = 0;
csc->used_gart = 0;
csc->used_vram = 0;
- memset(csc->is_handle_added, 0, sizeof(csc->is_handle_added));
+
+ for (i = 0; i < Elements(csc->reloc_indices_hashlist); i++) {
+ csc->reloc_indices_hashlist[i] = -1;
+ }
}
static void radeon_destroy_cs_context(struct radeon_cs_context *csc)
radeon_cs_context_cleanup(csc);
FREE(csc->relocs_bo);
FREE(csc->relocs);
+ FREE(csc->buf);
}
radeon_drm_cs_create(struct radeon_winsys *rws,
enum ring_type ring_type,
void (*flush)(void *ctx, unsigned flags,
- struct pipe_fence_handle **fence),
+ struct pipe_fence_handle **fence),
void *flush_ctx,
struct radeon_winsys_cs_handle *trace_buf)
{
cs->cst = &cs->csc2;
cs->base.buf = cs->csc->buf;
cs->base.ring_type = ring_type;
+ cs->base.max_dw = ws->ib_max_size / 4;
p_atomic_inc(&ws->num_cs);
return &cs->base;
#define OUT_CS(cs, value) (cs)->buf[(cs)->cdw++] = (value)
-static INLINE void update_reloc(struct drm_radeon_cs_reloc *reloc,
- enum radeon_bo_domain rd,
- enum radeon_bo_domain wd,
- unsigned priority,
- enum radeon_bo_domain *added_domains)
+static inline void update_reloc(struct drm_radeon_cs_reloc *reloc,
+ enum radeon_bo_domain rd,
+ enum radeon_bo_domain wd,
+ unsigned priority,
+ enum radeon_bo_domain *added_domains)
{
*added_domains = (rd | wd) & ~(reloc->read_domains | reloc->write_domain);
reloc->flags = MAX2(reloc->flags, priority);
}
-int radeon_get_reloc(struct radeon_cs_context *csc, struct radeon_bo *bo,
- struct drm_radeon_cs_reloc **out_reloc)
+int radeon_get_reloc(struct radeon_cs_context *csc, struct radeon_bo *bo)
{
- struct drm_radeon_cs_reloc *reloc = NULL;
- unsigned hash = bo->handle & (sizeof(csc->is_handle_added)-1);
- int i = -1;
-
- if (csc->is_handle_added[hash]) {
- i = csc->reloc_indices_hashlist[hash];
- reloc = &csc->relocs[i];
-
- if (reloc->handle != bo->handle) {
- /* Hash collision, look for the BO in the list of relocs linearly. */
- for (i = csc->crelocs - 1; i >= 0; i--) {
- reloc = &csc->relocs[i];
- if (reloc->handle == bo->handle) {
- /* Put this reloc in the hash list.
- * This will prevent additional hash collisions if there are
- * several consecutive get_reloc calls for the same buffer.
- *
- * Example: Assuming buffers A,B,C collide in the hash list,
- * the following sequence of relocs:
- * AAAAAAAAAAABBBBBBBBBBBBBBCCCCCCCC
- * will collide here: ^ and here: ^,
- * meaning that we should get very few collisions in the end. */
- csc->reloc_indices_hashlist[hash] = i;
- break;
- }
- }
+ unsigned hash = bo->handle & (Elements(csc->reloc_indices_hashlist)-1);
+ int i = csc->reloc_indices_hashlist[hash];
+
+ /* not found or found */
+ if (i == -1 || csc->relocs_bo[i] == bo)
+ return i;
+
+ /* Hash collision, look for the BO in the list of relocs linearly. */
+ for (i = csc->crelocs - 1; i >= 0; i--) {
+ if (csc->relocs_bo[i] == bo) {
+ /* Put this reloc in the hash list.
+ * This will prevent additional hash collisions if there are
+ * several consecutive get_reloc calls for the same buffer.
+ *
+ * Example: Assuming buffers A,B,C collide in the hash list,
+ * the following sequence of relocs:
+ * AAAAAAAAAAABBBBBBBBBBBBBBCCCCCCCC
+ * will collide here: ^ and here: ^,
+ * meaning that we should get very few collisions in the end. */
+ csc->reloc_indices_hashlist[hash] = i;
+ return i;
}
}
- if (out_reloc)
- *out_reloc = reloc;
- return i;
+ return -1;
}
static unsigned radeon_add_reloc(struct radeon_drm_cs *cs,
{
struct radeon_cs_context *csc = cs->csc;
struct drm_radeon_cs_reloc *reloc;
- unsigned hash = bo->handle & (sizeof(csc->is_handle_added)-1);
+ unsigned hash = bo->handle & (Elements(csc->reloc_indices_hashlist)-1);
enum radeon_bo_domain rd = usage & RADEON_USAGE_READ ? domains : 0;
enum radeon_bo_domain wd = usage & RADEON_USAGE_WRITE ? domains : 0;
int i = -1;
priority = MIN2(priority, 15);
*added_domains = 0;
- i = radeon_get_reloc(csc, bo, &reloc);
+ i = radeon_get_reloc(csc, bo);
if (i >= 0) {
+ reloc = &csc->relocs[i];
update_reloc(reloc, rd, wd, priority, added_domains);
/* For async DMA, every add_reloc call must add a buffer to the list
reloc->write_domain = wd;
reloc->flags = priority;
- csc->is_handle_added[hash] = TRUE;
csc->reloc_indices_hashlist[hash] = csc->crelocs;
csc->chunks[1].length_dw += RELOC_DWORDS;
{
struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
- return radeon_get_reloc(cs->csc, (struct radeon_bo*)buf, NULL);
+ return radeon_get_reloc(cs->csc, (struct radeon_bo*)buf);
}
static boolean radeon_drm_cs_validate(struct radeon_winsys_cs *rcs)
switch (cs->base.ring_type) {
case RING_DMA:
- /* pad DMA ring to 8 DWs */
- if (cs->ws->info.chip_class <= SI) {
- while (rcs->cdw & 7)
- OUT_CS(&cs->base, 0xf0000000); /* NOP packet */
- } else {
- while (rcs->cdw & 7)
- OUT_CS(&cs->base, 0x00000000); /* NOP packet */
- }
- break;
+ /* pad DMA ring to 8 DWs */
+ if (cs->ws->info.chip_class <= SI) {
+ while (rcs->cdw & 7)
+ OUT_CS(&cs->base, 0xf0000000); /* NOP packet */
+ } else {
+ while (rcs->cdw & 7)
+ OUT_CS(&cs->base, 0x00000000); /* NOP packet */
+ }
+ break;
case RING_GFX:
- /* pad DMA ring to 8 DWs to meet CP fetch alignment requirements
- * r6xx, requires at least 4 dw alignment to avoid a hw bug.
- */
- if (cs->ws->info.chip_class <= SI) {
- while (rcs->cdw & 7)
- OUT_CS(&cs->base, 0x80000000); /* type2 nop packet */
- } else {
- while (rcs->cdw & 7)
- OUT_CS(&cs->base, 0xffff1000); /* type3 nop packet */
- }
- break;
+ /* pad DMA ring to 8 DWs to meet CP fetch alignment requirements
+ * r6xx, requires at least 4 dw alignment to avoid a hw bug.
+ * hawaii with old firmware needs type2 nop packet.
+ * accel_working2 with value 3 indicates the new firmware.
+ */
+ if (cs->ws->info.chip_class <= SI ||
+ (cs->ws->info.family == CHIP_HAWAII &&
+ cs->ws->accel_working2 < 3)) {
+ while (rcs->cdw & 7)
+ OUT_CS(&cs->base, 0x80000000); /* type2 nop packet */
+ } else {
+ while (rcs->cdw & 7)
+ OUT_CS(&cs->base, 0xffff1000); /* type3 nop packet */
+ }
+ break;
case RING_UVD:
- while (rcs->cdw & 15)
- OUT_CS(&cs->base, 0x80000000); /* type2 nop packet */
- break;
+ while (rcs->cdw & 15)
+ OUT_CS(&cs->base, 0x80000000); /* type2 nop packet */
+ break;
default:
- break;
+ break;
}
- if (rcs->cdw > RADEON_MAX_CMDBUF_DWORDS) {
+ if (rcs->cdw > rcs->max_dw) {
fprintf(stderr, "radeon: command stream overflowed\n");
}
cs->cst->cs_trace_id = cs_trace_id;
/* If the CS is not empty or overflowed, emit it in a separate thread. */
- if (cs->base.cdw && cs->base.cdw <= RADEON_MAX_CMDBUF_DWORDS && !debug_get_option_noop()) {
+ if (cs->base.cdw && cs->base.cdw <= cs->base.max_dw && !debug_get_option_noop()) {
unsigned i, crelocs;
crelocs = cs->cst->crelocs;
if (!bo->num_cs_references)
return FALSE;
- index = radeon_get_reloc(cs->csc, bo, NULL);
+ index = radeon_get_reloc(cs->csc, bo);
if (index == -1)
return FALSE;
/* Create a fence, which is a dummy BO. */
fence = cs->ws->base.buffer_create(&cs->ws->base, 1, 1, TRUE,
- RADEON_DOMAIN_GTT);
+ RADEON_DOMAIN_GTT, 0);
/* Add the fence as a dummy relocation. */
cs->ws->base.cs_add_reloc(rcs, cs->ws->base.buffer_get_cs_handle(fence),
RADEON_USAGE_READWRITE, RADEON_DOMAIN_GTT,