void (*destroy)(dri_bufmgr *bufmgr);
/**
- * Add relocation entry in reloc_buf, to be set on command submission.
+ * Add relocation entry in reloc_buf, which will be updated with the
+ * target buffer's real offset on on command submission.
+ *
+ * Relocations remain in place for the lifetime of the buffer object.
*
* \param reloc_buf Buffer to write the relocation into.
* \param flags BO flags to be used in validating the target buffer.
struct fake_buffer_reloc
{
- dri_bo *reloc_buf;
+ /** Buffer object that the relocation points at. */
dri_bo *target_buf;
+ /** Offset of the relocation entry within reloc_buf. */
GLuint offset;
+ /** Cached value of the offset when we last performed this relocation. */
+ GLuint last_target_offset;
+ /** Value added to target_buf's offset to get the relocation entry. */
GLuint delta;
+ /** Flags to validate the target buffer under. */
uint64_t validate_flags;
- GLboolean relocated;
};
struct block {
GLboolean debug;
- /** fake relocation list */
- struct fake_buffer_reloc reloc[MAX_RELOCS];
- GLuint nr_relocs;
GLboolean performed_rendering;
- GLboolean in_relocation;
} dri_bufmgr_fake;
-#define RELOC_CACHE_COUNT 10
-/**
- * Relocation cache entry.
- *
- * These are used in buffer relocation to avoid re-mapping (and therefore
- * dirtying) a buffer to emit constant relocations.
- */
-struct reloc_cache {
- unsigned int offset;
- uint32_t data;
-};
-
typedef struct _dri_bo_fake {
dri_bo bo;
unsigned int alignment;
GLboolean is_static, validated;
unsigned int map_count;
- /**
- * Relocation count with this as reloc_buffer, to assist in determining the
- * order to perform relocations.
- */
- unsigned int nr_relocs;
- struct reloc_cache reloc_cache[RELOC_CACHE_COUNT];
/* Flags for the buffer to be validated with in command submission */
uint64_t validate_flags;
- /* Number of entries in the relocation data cache */
- unsigned int reloc_cache_count;
-
+ /** relocation list */
+ struct fake_buffer_reloc *relocs;
+ GLuint nr_relocs;
struct block *block;
void *backing_store;
if (bo_fake->block)
free_block(bufmgr_fake, bo_fake->block);
free_backing_store(bo);
+ free(bo_fake->relocs);
free(bo);
DBG("drm_bo_unreference: free %s\n", bo_fake->name);
return;
if (bo_fake->map_count++ != 0)
return 0;
- /* Clear the relocation cache if unknown data is going to be written in. */
- if (!bufmgr_fake->in_relocation && write_enable) {
- bo_fake->reloc_cache_count = 0;
- }
-
{
DBG("drm_bo_map: (buf %d: %s, %d kb)\n", bo_fake->id, bo_fake->name,
bo_fake->bo.size / 1024);
bo_fake->block->on_hardware = 1;
move_to_tail(&bufmgr_fake->on_hardware, bo_fake->block);
+ bo_fake->validated = GL_TRUE;
bufmgr_fake->need_fence = 1;
return 0;
dri_fake_emit_reloc(dri_bo *reloc_buf, uint64_t flags, GLuint delta,
GLuint offset, dri_bo *target_buf)
{
- dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)reloc_buf->bufmgr;
- struct fake_buffer_reloc *r = &bufmgr_fake->reloc[bufmgr_fake->nr_relocs++];
- dri_bo_fake *target_fake = (dri_bo_fake *)target_buf;
+ struct fake_buffer_reloc *r;
dri_bo_fake *reloc_fake = (dri_bo_fake *)reloc_buf;
int i;
- assert(bufmgr_fake->nr_relocs <= MAX_RELOCS);
+ if (reloc_fake->relocs == NULL) {
+ reloc_fake->relocs = malloc(sizeof(struct fake_buffer_reloc) *
+ MAX_RELOCS);
+ }
- dri_bo_reference(target_buf);
+ r = &reloc_fake->relocs[reloc_fake->nr_relocs++];
- if (target_fake->flags == 0) {
- target_fake->validate_flags = flags;
- } else {
- /* Mask the memory location to the intersection of all the memory
- * locations the buffer is being validated to.
- */
- target_fake->validate_flags =
- (target_fake->validate_flags & ~DRM_BO_MASK_MEM) |
- (flags & target_fake->validate_flags & DRM_BO_MASK_MEM);
- /* All the other flags just accumulate. */
- target_fake->validate_flags |= flags & ~DRM_BO_MASK_MEM;
- }
- reloc_fake->nr_relocs++;
+ assert(reloc_fake->nr_relocs <= MAX_RELOCS);
+
+ dri_bo_reference(target_buf);
- r->reloc_buf = reloc_buf;
r->target_buf = target_buf;
r->offset = offset;
+ r->last_target_offset = target_buf->offset;
r->delta = delta;
r->validate_flags = flags;
/* Check that a conflicting relocation hasn't already been emitted. */
- for (i = 0; i < bufmgr_fake->nr_relocs - 1; i++) {
- struct fake_buffer_reloc *r2 = &bufmgr_fake->reloc[i];
-
- assert(r->reloc_buf != r2->reloc_buf ||
- r->offset != r2->offset ||
- (r->target_buf == r2->target_buf &&
- r->delta == r2->delta &&
- r->validate_flags == r2->validate_flags));
+ for (i = 0; i < reloc_fake->nr_relocs - 1; i++) {
+ struct fake_buffer_reloc *r2 = &reloc_fake->relocs[i];
+
+ assert(r->offset != r2->offset);
}
return;
}
-static void *
-dri_fake_process_relocs(dri_bo *batch_buf, GLuint *count_p)
+/**
+ * Incorporates the validation flags associated with each relocation into
+ * the combined validation flags for the buffer on this batchbuffer submission.
+ */
+static void
+dri_fake_calculate_validate_flags(dri_bo *bo)
{
- dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)batch_buf->bufmgr;
- GLuint i;
- GLuint count = 0;
- GLboolean cont;
- int ret;
+ dri_bo_fake *bo_fake = (dri_bo_fake *)bo;
+ int i;
- bufmgr_fake->performed_rendering = GL_FALSE;
- bufmgr_fake->in_relocation = GL_TRUE;
+ for (i = 0; i < bo_fake->nr_relocs; i++) {
+ struct fake_buffer_reloc *r = &bo_fake->relocs[i];
+ dri_bo_fake *target_fake = (dri_bo_fake *)r->target_buf;
- /* Loop over the relocation list validating and writing the relocation
- * entries for target buffers that don't contain any remaining relocations.
- * In the current examples we have, the depth of the tree of relocations
- * is small (up to 3), so this loop shouldn't hurt too bad.
- */
- do {
- cont = GL_FALSE;
-
- for (i = 0; i < bufmgr_fake->nr_relocs; i++) {
- struct fake_buffer_reloc *r = &bufmgr_fake->reloc[i];
- dri_bo_fake *reloc_fake = (dri_bo_fake *)r->reloc_buf;
- dri_bo_fake *target_fake = (dri_bo_fake *)r->target_buf;
- uint32_t reloc_data;
- int c;
- GLboolean cached = GL_FALSE;
-
- if (r->relocated)
- continue;
-
- /* If there are still relocations to be done in the buffer, don't
- * validate it yet.
+ /* Do the same for the tree of buffers we depend on */
+ dri_fake_calculate_validate_flags(r->target_buf);
+
+ if (target_fake->flags == 0) {
+ target_fake->validate_flags = r->validate_flags;
+ } else {
+ /* Mask the memory location to the intersection of all the memory
+ * locations the buffer is being validated to.
*/
- if (target_fake->nr_relocs != 0)
- continue;
-
- /* Validate the target buffer if that hasn't been done. */
- if (!target_fake->validated) {
- ret = dri_fake_bo_validate(r->target_buf,
- target_fake->validate_flags);
- if (ret != 0) {
- dri_fence *fo;
-
- dri_bo_unmap(r->reloc_buf);
- fo = dri_fake_fence_validated(batch_buf->bufmgr,
- "batchbuffer failure fence",
- GL_TRUE);
- dri_fence_unreference(fo);
- goto done;
- }
- if (target_fake->validate_flags & DRM_BO_FLAG_WRITE)
- bufmgr_fake->performed_rendering = GL_TRUE;
- count++;
- }
+ target_fake->validate_flags =
+ (target_fake->validate_flags & ~DRM_BO_MASK_MEM) |
+ (r->validate_flags & target_fake->validate_flags &
+ DRM_BO_MASK_MEM);
+ /* All the other flags just accumulate. */
+ target_fake->validate_flags |= r->validate_flags & ~DRM_BO_MASK_MEM;
+ }
+ }
+}
+
+
+static int
+dri_fake_reloc_and_validate_buffer(dri_bo *bo)
+{
+ dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr;
+ dri_bo_fake *bo_fake = (dri_bo_fake *)bo;
+ int i, ret;
+
+ assert(bo_fake->map_count == 0);
+
+ for (i = 0; i < bo_fake->nr_relocs; i++) {
+ struct fake_buffer_reloc *r = &bo_fake->relocs[i];
+ dri_bo_fake *target_fake = (dri_bo_fake *)r->target_buf;
+ uint32_t reloc_data;
- /* Calculate the value of the relocation entry. */
+ /* Validate the target buffer if that hasn't been done. */
+ if (!target_fake->validated) {
+ ret = dri_fake_reloc_and_validate_buffer(r->target_buf);
+ if (ret != 0)
+ return ret;
+ }
+ /* Calculate the value of the relocation entry. */
+ if (r->target_buf->offset != r->last_target_offset) {
reloc_data = r->target_buf->offset + r->delta;
- /* Check the relocation cache of the buffer to see if we don't need
- * to bother writing this one.
- */
- for (c = 0; c < reloc_fake->reloc_cache_count; c++) {
- if (reloc_fake->reloc_cache[c].offset == r->offset &&
- reloc_fake->reloc_cache[c].data == reloc_data) {
- cached = GL_TRUE;
- }
- }
+ if (bo->virtual == NULL)
+ dri_bo_map(bo, GL_TRUE);
- if (!cached) {
- /* Map and write in the relocation to reloc_buf */
- if (reloc_fake->map_count == 0)
- dri_bo_map(r->reloc_buf, GL_TRUE);
+ *(uint32_t *)(bo->virtual + r->offset) = reloc_data;
- *(uint32_t *)(r->reloc_buf->virtual + r->offset) = reloc_data;
+ r->last_target_offset = r->target_buf->offset;
+ }
+ }
- /* Stick this new entry in the relocation cache if possible */
- if (reloc_fake->reloc_cache_count < RELOC_CACHE_COUNT) {
- struct reloc_cache *entry;
+ if (bo->virtual != NULL)
+ dri_bo_unmap(bo);
- entry = &reloc_fake->reloc_cache[reloc_fake->reloc_cache_count];
- entry->offset = r->offset;
- entry->data = reloc_data;
+ if (bo_fake->validate_flags & DRM_BO_FLAG_WRITE)
+ bufmgr_fake->performed_rendering = GL_TRUE;
- reloc_fake->reloc_cache_count++;
- }
- }
+ return dri_fake_bo_validate(bo, bo_fake->validate_flags);
+}
- /* Mark this relocation in reloc_buf as done. If it was the last
- * reloc to be done to it, unmap the buffer so it can be validated
- * next.
- */
- reloc_fake->nr_relocs--;
- if (reloc_fake->nr_relocs == 0 && reloc_fake->map_count != 0)
- dri_bo_unmap(r->reloc_buf);
+static void *
+dri_fake_process_relocs(dri_bo *batch_buf, GLuint *count_p)
+{
+ dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)batch_buf->bufmgr;
+ dri_bo_fake *batch_fake = (dri_bo_fake *)batch_buf;
+ int ret;
- r->relocated = GL_TRUE;
+ bufmgr_fake->performed_rendering = GL_FALSE;
- cont = GL_TRUE;
- }
- } while (cont);
+ dri_fake_calculate_validate_flags(batch_buf);
- ret = dri_fake_bo_validate(batch_buf, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_EXE);
+ batch_fake->validate_flags = DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ;
+ ret = dri_fake_reloc_and_validate_buffer(batch_buf);
assert(ret == 0);
- *count_p = count;
- bufmgr_fake->in_relocation = GL_FALSE;
- done:
+ *count_p = 0; /* junk */
+
return NULL;
}
+static void
+dri_bo_fake_post_submit(dri_bo *bo)
+{
+ dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr;
+ dri_bo_fake *bo_fake = (dri_bo_fake *)bo;
+ int i;
+
+ for (i = 0; i < bo_fake->nr_relocs; i++) {
+ struct fake_buffer_reloc *r = &bo_fake->relocs[i];
+ dri_bo_fake *target_fake = (dri_bo_fake *)r->target_buf;
+
+ if (target_fake->validated)
+ dri_bo_fake_post_submit(r->target_buf);
+
+ DBG("%s@0x%08x + 0x%08x -> %s@0x%08x + 0x%08x\n",
+ bo_fake->name, (uint32_t)bo->offset, r->offset,
+ target_fake->name, (uint32_t)r->target_buf->offset, r->delta);
+ }
+
+ assert(bo_fake->map_count == 0);
+ bo_fake->validated = GL_FALSE;
+ bo_fake->validate_flags = 0;
+}
+
+
static void
dri_fake_post_submit(dri_bo *batch_buf, dri_fence **last_fence)
{
dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)batch_buf->bufmgr;
dri_fence *fo;
- int i;
fo = dri_fake_fence_validated(batch_buf->bufmgr, "Batch fence", GL_TRUE);
dri_fence_unreference(fo);
}
- /* Clean up the validation list. */
- for (i = 0; i < bufmgr_fake->nr_relocs; i++) {
- struct fake_buffer_reloc *r = &bufmgr_fake->reloc[i];
- dri_bo_fake *reloc_fake = (dri_bo_fake *)r->reloc_buf;
- dri_bo_fake *target_fake = (dri_bo_fake *)r->target_buf;
-
- assert(r->relocated);
- assert(reloc_fake->map_count == 0);
- DBG("%s@0x%08x + 0x%08x -> %s@0x%08x + 0x%08x\n",
- reloc_fake->name, (uint32_t)r->reloc_buf->offset, r->offset,
- target_fake->name, (uint32_t)r->target_buf->offset, r->delta);
-
- reloc_fake->validate_flags = 0;
- target_fake->validated = GL_FALSE;
- r->relocated = GL_FALSE;
- dri_bo_unreference(r->target_buf);
- }
- bufmgr_fake->nr_relocs = 0;
+ dri_bo_fake_post_submit(batch_buf);
}
dri_bufmgr *
cc_unit_create_from_key(struct brw_context *brw, struct brw_cc_unit_key *key)
{
struct brw_cc_unit_state cc;
+ dri_bo *bo;
memset(&cc, 0, sizeof(cc));
if (INTEL_DEBUG & DEBUG_STATS)
cc.cc5.statistics_enable = 1;
- return brw_upload_cache(&brw->cache, BRW_CC_UNIT,
- key, sizeof(*key),
- &brw->cc.vp_bo, 1,
- &cc, sizeof(cc),
- NULL, NULL);
+ bo = brw_upload_cache(&brw->cache, BRW_CC_UNIT,
+ key, sizeof(*key),
+ &brw->cc.vp_bo, 1,
+ &cc, sizeof(cc),
+ NULL, NULL);
+
+ /* Emit CC viewport relocation */
+ dri_emit_reloc(bo,
+ DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
+ 0,
+ offsetof(struct brw_cc_unit_state, cc4),
+ brw->cc.vp_bo);
+
+ return bo;
}
static void upload_cc_unit( struct brw_context *brw )
brw->cc.state_bo = cc_unit_create_from_key(brw, &key);
}
-static void emit_reloc_cc_unit(struct brw_context *brw)
-{
- /* Emit CC viewport relocation */
- dri_emit_reloc(brw->cc.state_bo,
- DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
- 0,
- offsetof(struct brw_cc_unit_state, cc4),
- brw->cc.vp_bo);
-}
-
const struct brw_tracked_state brw_cc_unit = {
.dirty = {
.mesa = _NEW_STENCIL | _NEW_COLOR | _NEW_DEPTH,
.cache = CACHE_NEW_CC_VP
},
.update = upload_cc_unit,
- .emit_reloc = emit_reloc_cc_unit,
};
struct brw_clip_unit_key *key)
{
struct brw_clip_unit_state clip;
+ dri_bo *bo;
memset(&clip, 0, sizeof(clip));
clip.viewport_ymin = -1;
clip.viewport_ymax = 1;
- brw->clip.thread0_delta = clip.thread0.grf_reg_count << 1;
- return brw_upload_cache(&brw->cache, BRW_CLIP_UNIT,
- key, sizeof(*key),
- &brw->clip.prog_bo, 1,
- &clip, sizeof(clip),
- NULL, NULL);
+ bo = brw_upload_cache(&brw->cache, BRW_CLIP_UNIT,
+ key, sizeof(*key),
+ &brw->clip.prog_bo, 1,
+ &clip, sizeof(clip),
+ NULL, NULL);
+
+ if (!brw->metaops.active) {
+ /* Emit clip program relocation */
+ dri_emit_reloc(bo,
+ DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
+ clip.thread0.grf_reg_count << 1,
+ offsetof(struct brw_clip_unit_state, thread0),
+ brw->clip.prog_bo);
+ }
+
+ return bo;
}
static void upload_clip_unit( struct brw_context *brw )
}
}
-static void emit_reloc_clip_unit(struct brw_context *brw)
-{
- if (!brw->metaops.active) {
- /* Emit clip program relocation */
- dri_emit_reloc(brw->clip.state_bo,
- DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
- brw->clip.thread0_delta,
- offsetof(struct brw_clip_unit_state, thread0),
- brw->clip.prog_bo);
- }
-}
-
const struct brw_tracked_state brw_clip_unit = {
.dirty = {
.mesa = 0,
.cache = CACHE_NEW_CLIP_PROG
},
.update = upload_clip_unit,
- .emit_reloc = emit_reloc_clip_unit,
};
struct brw_tracked_state {
struct brw_state_flags dirty;
void (*update)( struct brw_context *brw );
- void (*emit_reloc)( struct brw_context *brw );
GLboolean always_update;
};
struct {
struct brw_vs_prog_data *prog_data;
- GLuint thread0_delta;
dri_bo *prog_bo;
dri_bo *state_bo;
} vs;
struct brw_gs_prog_data *prog_data;
GLboolean prog_active;
- GLuint thread0_delta;
dri_bo *prog_bo;
dri_bo *state_bo;
} gs;
struct {
struct brw_clip_prog_data *prog_data;
- GLuint thread0_delta;
dri_bo *prog_bo;
dri_bo *state_bo;
dri_bo *vp_bo;
struct {
struct brw_sf_prog_data *prog_data;
- GLuint thread0_delta;
- GLuint sf5_delta;
dri_bo *prog_bo;
dri_bo *state_bo;
dri_bo *vp_bo;
dri_bo *bind_bo;
dri_bo *surf_bo[BRW_WM_MAX_SURF];
- GLuint thread0_delta;
- GLuint thread2_delta;
- GLuint wm4_delta;
dri_bo *prog_bo;
dri_bo *state_bo;
} wm;
gs_unit_create_from_key(struct brw_context *brw, struct brw_gs_unit_key *key)
{
struct brw_gs_unit_state gs;
+ dri_bo *bo;
memset(&gs, 0, sizeof(gs));
if (INTEL_DEBUG & DEBUG_STATS)
gs.thread4.stats_enable = 1;
- brw->gs.thread0_delta = gs.thread0.grf_reg_count << 1;
- return brw_upload_cache(&brw->cache, BRW_GS_UNIT,
- key, sizeof(*key),
- &brw->gs.prog_bo, 1,
- &gs, sizeof(gs),
- NULL, NULL);
+ bo = brw_upload_cache(&brw->cache, BRW_GS_UNIT,
+ key, sizeof(*key),
+ &brw->gs.prog_bo, 1,
+ &gs, sizeof(gs),
+ NULL, NULL);
+
+ if (key->prog_active) {
+ /* Emit GS program relocation */
+ dri_emit_reloc(bo,
+ DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
+ gs.thread0.grf_reg_count << 1,
+ offsetof(struct brw_gs_unit_state, thread0),
+ brw->gs.prog_bo);
+ }
+
+ return bo;
}
static void upload_gs_unit( struct brw_context *brw )
}
}
-static void emit_reloc_gs_unit(struct brw_context *brw)
-{
- if (brw->gs.prog_active) {
- /* Emit GS program relocation */
- dri_emit_reloc(brw->gs.state_bo,
- DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
- brw->gs.thread0_delta,
- offsetof(struct brw_gs_unit_state, thread0),
- brw->gs.prog_bo);
- }
-}
-
const struct brw_tracked_state brw_gs_unit = {
.dirty = {
.mesa = 0,
.cache = CACHE_NEW_GS_PROG
},
.update = upload_gs_unit,
- .emit_reloc = emit_reloc_gs_unit,
};
dri_bo **reloc_bufs)
{
struct brw_sf_unit_state sf;
+ dri_bo *bo;
memset(&sf, 0, sizeof(sf));
sf.sf6.dest_org_vbias = 0x8;
sf.sf6.dest_org_hbias = 0x8;
- brw->sf.thread0_delta = sf.thread0.grf_reg_count << 1;
- brw->sf.sf5_delta = sf.sf5.front_winding | (sf.sf5.viewport_transform << 1);
+ bo = brw_upload_cache(&brw->cache, BRW_SF_UNIT,
+ key, sizeof(*key),
+ reloc_bufs, 2,
+ &sf, sizeof(sf),
+ NULL, NULL);
- return brw_upload_cache(&brw->cache, BRW_SF_UNIT,
- key, sizeof(*key),
- reloc_bufs, 2,
- &sf, sizeof(sf),
- NULL, NULL);
+ /* Emit SF program relocation */
+ dri_emit_reloc(bo,
+ DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
+ sf.thread0.grf_reg_count << 1,
+ offsetof(struct brw_sf_unit_state, thread0),
+ brw->sf.prog_bo);
+
+ /* Emit SF viewport relocation */
+ dri_emit_reloc(bo,
+ DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
+ sf.sf5.front_winding | (sf.sf5.viewport_transform << 1),
+ offsetof(struct brw_sf_unit_state, sf5),
+ brw->sf.vp_bo);
+
+ return bo;
}
static void upload_sf_unit( struct brw_context *brw )
}
}
-static void emit_reloc_sf_unit(struct brw_context *brw)
-{
- /* Emit SF program relocation */
- dri_emit_reloc(brw->sf.state_bo,
- DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
- brw->sf.thread0_delta,
- offsetof(struct brw_sf_unit_state, thread0),
- brw->sf.prog_bo);
-
- /* Emit SF viewport relocation */
- dri_emit_reloc(brw->sf.state_bo,
- DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
- brw->sf.sf5_delta,
- offsetof(struct brw_sf_unit_state, sf5),
- brw->sf.vp_bo);
-}
-
const struct brw_tracked_state brw_sf_unit = {
.dirty = {
.mesa = (_NEW_POLYGON |
CACHE_NEW_SF_PROG)
},
.update = upload_sf_unit,
- .emit_reloc = emit_reloc_sf_unit,
};
/* emit_foo(brw); */
}
- if (atom->emit_reloc != NULL)
- atom->emit_reloc(brw);
accumulate_state(&examined, &atom->dirty);
if (check_state(state, &atom->dirty) || atom->always_update)
atom->update( brw );
- if (atom->emit_reloc != NULL)
- atom->emit_reloc(brw);
}
}
vs_unit_create_from_key(struct brw_context *brw, struct brw_vs_unit_key *key)
{
struct brw_vs_unit_state vs;
+ dri_bo *bo;
memset(&vs, 0, sizeof(vs));
*/
vs.vs6.vs_enable = 1;
- brw->vs.thread0_delta = vs.thread0.grf_reg_count << 1;
- return brw_upload_cache(&brw->cache, BRW_VS_UNIT,
- key, sizeof(*key),
- &brw->vs.prog_bo, 1,
- &vs, sizeof(vs),
- NULL, NULL);
+ bo = brw_upload_cache(&brw->cache, BRW_VS_UNIT,
+ key, sizeof(*key),
+ &brw->vs.prog_bo, 1,
+ &vs, sizeof(vs),
+ NULL, NULL);
+
+ /* Emit VS program relocation */
+ dri_emit_reloc(bo,
+ DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
+ vs.thread0.grf_reg_count << 1,
+ offsetof(struct brw_vs_unit_state, thread0),
+ brw->vs.prog_bo);
+
+ return bo;
}
static void upload_vs_unit( struct brw_context *brw )
}
}
-static void emit_reloc_vs_unit(struct brw_context *brw)
-{
- /* Emit VS program relocation */
- dri_emit_reloc(brw->vs.state_bo,
- DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
- brw->vs.thread0_delta,
- offsetof(struct brw_vs_unit_state, thread0),
- brw->vs.prog_bo);
-}
-
const struct brw_tracked_state brw_vs_unit = {
.dirty = {
.mesa = _NEW_TRANSFORM,
.cache = CACHE_NEW_VS_PROG
},
.update = upload_vs_unit,
- .emit_reloc = emit_reloc_vs_unit,
};
brw->wm.sdc_bo, key.sampler_count,
&sampler, sizeof(sampler),
NULL, NULL);
- }
-}
-static void emit_reloc_wm_samplers(struct brw_context *brw)
-{
- GLuint unit;
-
- if (brw->wm.sampler_count == 0)
- return;
+ /* Emit SDC relocations */
+ for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
+ if (!brw->attribs.Texture->Unit[i]._ReallyEnabled)
+ continue;
- /* Emit SDC relocations */
- for (unit = 0; unit < BRW_MAX_TEX_UNIT; unit++) {
- if (!brw->attribs.Texture->Unit[unit]._ReallyEnabled)
- continue;
-
- dri_emit_reloc(brw->wm.sampler_bo,
- DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
- 0,
- unit * sizeof(struct brw_sampler_state) +
- offsetof(struct brw_sampler_state, ss2),
- brw->wm.sdc_bo[unit]);
+ dri_emit_reloc(brw->wm.sampler_bo,
+ DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
+ 0,
+ i * sizeof(struct brw_sampler_state) +
+ offsetof(struct brw_sampler_state, ss2),
+ brw->wm.sdc_bo[i]);
+ }
}
}
.cache = 0
},
.update = upload_wm_samplers,
- .emit_reloc = emit_reloc_wm_samplers,
};
dri_bo **reloc_bufs)
{
struct brw_wm_unit_state wm;
+ dri_bo *bo;
memset(&wm, 0, sizeof(wm));
if (INTEL_DEBUG & DEBUG_STATS || key->stats_wm)
wm.wm4.stats_enable = 1;
- brw->wm.thread0_delta = wm.thread0.grf_reg_count << 1;
- brw->wm.thread2_delta = wm.thread2.per_thread_scratch_space;
- brw->wm.wm4_delta = wm.wm4.stats_enable | (wm.wm4.sampler_count << 2);
+ bo = brw_upload_cache(&brw->cache, BRW_WM_UNIT,
+ key, sizeof(*key),
+ reloc_bufs, 3,
+ &wm, sizeof(wm),
+ NULL, NULL);
- return brw_upload_cache(&brw->cache, BRW_WM_UNIT,
- key, sizeof(*key),
- reloc_bufs, 3,
- &wm, sizeof(wm),
- NULL, NULL);
+ /* Emit WM program relocation */
+ dri_emit_reloc(bo,
+ DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
+ wm.thread0.grf_reg_count << 1,
+ offsetof(struct brw_wm_unit_state, thread0),
+ brw->wm.prog_bo);
+
+ /* Emit scratch space relocation */
+ if (key->total_scratch != 0) {
+ dri_emit_reloc(bo,
+ DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE,
+ wm.thread2.per_thread_scratch_space,
+ offsetof(struct brw_wm_unit_state, thread2),
+ brw->wm.scratch_buffer);
+ }
+
+ /* Emit sampler state relocation */
+ if (key->sampler_count != 0) {
+ dri_emit_reloc(bo,
+ DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
+ wm.wm4.stats_enable | (wm.wm4.sampler_count << 2),
+ offsetof(struct brw_wm_unit_state, wm4),
+ brw->wm.sampler_bo);
+ }
+
+ return bo;
}
}
}
-static void emit_reloc_wm_unit(struct brw_context *brw)
-{
- /* Emit WM program relocation */
- dri_emit_reloc(brw->wm.state_bo,
- DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
- brw->wm.thread0_delta,
- offsetof(struct brw_wm_unit_state, thread0),
- brw->wm.prog_bo);
-
- /* Emit scratch space relocation */
- if (brw->wm.scratch_buffer != NULL) {
- dri_emit_reloc(brw->wm.state_bo,
- DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE,
- brw->wm.thread2_delta,
- offsetof(struct brw_wm_unit_state, thread2),
- brw->wm.scratch_buffer);
- }
-
- /* Emit sampler state relocation */
- if (brw->wm.sampler_bo != NULL) {
- dri_emit_reloc(brw->wm.state_bo,
- DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
- brw->wm.wm4_delta,
- offsetof(struct brw_wm_unit_state, wm4),
- brw->wm.sampler_bo);
- }
-}
-
const struct brw_tracked_state brw_wm_unit = {
.dirty = {
.mesa = (_NEW_POLYGON |
CACHE_NEW_SAMPLER)
},
.update = upload_wm_unit,
- .emit_reloc = emit_reloc_wm_unit,
};
struct brw_wm_surface_key *key )
{
struct brw_surface_state surf;
+ dri_bo *bo;
memset(&surf, 0, sizeof(surf));
surf.ss0.cube_neg_z = 1;
}
- return brw_upload_cache( &brw->cache, BRW_SS_SURFACE,
- key, sizeof(*key),
- &key->bo, 1,
- &surf, sizeof(surf),
- NULL, NULL );
+ bo = brw_upload_cache(&brw->cache, BRW_SS_SURFACE,
+ key, sizeof(*key),
+ &key->bo, 1,
+ &surf, sizeof(surf),
+ NULL, NULL);
+
+ /* Emit relocation to surface contents */
+ dri_emit_reloc(bo,
+ DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
+ 0,
+ offsetof(struct brw_surface_state, ss1),
+ key->bo);
+
+ return bo;
}
static void
&surf, sizeof(surf),
NULL, NULL);
- brw->wm.nr_surfaces = 1;
+ if (region_bo != NULL) {
+ dri_emit_reloc(brw->wm.surf_bo[unit],
+ DRM_BO_FLAG_MEM_TT |
+ DRM_BO_FLAG_READ |
+ DRM_BO_FLAG_WRITE,
+ 0,
+ offsetof(struct brw_surface_state, ss1),
+ region_bo);
+ }
}
}
data, data_size,
NULL, NULL);
+ /* Emit binding table relocations to surface state */
+ for (i = 0; i < BRW_WM_MAX_SURF; i++) {
+ if (brw->wm.surf_bo[i] != NULL) {
+ dri_emit_reloc(bind_bo,
+ DRM_BO_FLAG_MEM_TT |
+ DRM_BO_FLAG_READ |
+ DRM_BO_FLAG_WRITE,
+ 0,
+ i * 4,
+ brw->wm.surf_bo[i]);
+ }
+ }
+
free(data);
}
GLuint i;
brw_update_region_surface(brw, brw->state.draw_region, 0);
+ brw->wm.nr_surfaces = 1;
for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
struct gl_texture_unit *texUnit = &brw->attribs.Texture->Unit[i];
brw->wm.bind_bo = brw_wm_get_binding_table(brw);
}
-static void emit_reloc_wm_surfaces(struct brw_context *brw)
-{
- int unit, i;
-
- /* Emit SS framebuffer relocation */
- if (brw->state.draw_region != NULL) {
- dri_emit_reloc(brw->wm.surf_bo[0],
- DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE,
- 0,
- offsetof(struct brw_surface_state, ss1),
- brw->state.draw_region->buffer);
- }
-
- /* Emit SS relocations for texture buffers */
- for (unit = 0; unit < BRW_MAX_TEX_UNIT; unit++) {
- struct gl_texture_unit *texUnit = &brw->attribs.Texture->Unit[unit];
- struct gl_texture_object *tObj = texUnit->_Current;
- struct intel_texture_object *intelObj = intel_texture_object(tObj);
-
- if (texUnit->_ReallyEnabled && intelObj->mt != NULL) {
- dri_emit_reloc(brw->wm.surf_bo[unit + 1],
- DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
- 0,
- offsetof(struct brw_surface_state, ss1),
- intelObj->mt->region->buffer);
- }
- }
-
- /* Emit binding table relocations to surface state */
- for (i = 0; i < BRW_WM_MAX_SURF; i++) {
- if (brw->wm.surf_bo[i] != NULL) {
- dri_emit_reloc(brw->wm.bind_bo,
- DRM_BO_FLAG_MEM_TT |
- DRM_BO_FLAG_READ |
- DRM_BO_FLAG_WRITE,
- 0,
- i * 4,
- brw->wm.surf_bo[i]);
- }
- }
-}
-
const struct brw_tracked_state brw_wm_surfaces = {
.dirty = {
.mesa = _NEW_COLOR | _NEW_TEXTURE | _NEW_BUFFERS,
.cache = 0
},
.update = upload_wm_surfaces,
- .emit_reloc = emit_reloc_wm_surfaces,
};
struct intel_bo_list list; /* list of buffers to be validated */
} dri_bufmgr_ttm;
+/**
+ * Private information associated with a relocation that isn't already stored
+ * in the relocation buffer to be passed to the kernel.
+ */
+struct dri_ttm_reloc {
+ dri_bo *target_buf;
+ uint64_t validate_flags;
+};
+
typedef struct _dri_bo_ttm {
dri_bo bo;
drmBO drm_bo;
const char *name;
+ /* Index of the buffer within the validation list while preparing a
+ * batchbuffer execution.
+ */
+ int validate_index;
+
/** DRM buffer object containing relocation list */
drmBO *reloc_buf;
- uint32_t *relocs;
+ uint32_t *reloc_buf_data;
+ struct dri_ttm_reloc *relocs;
} dri_bo_ttm;
typedef struct _dri_fence_ttm
for (l = list->list.next; l != &list->list; l = list->list.next) {
struct intel_bo_node *node =
DRMLISTENTRY(struct intel_bo_node, l, head);
- dri_bo_ttm *bo_ttm = (dri_bo_ttm *)node->bo;
DRMLISTDEL(l);
- /* Clear relocation list */
- if (bo_ttm->relocs != NULL)
- bo_ttm->relocs[0] = bo_ttm->relocs[0] & ~0xffff;
-
dri_bo_unreference(node->bo);
drmFree(node);
DRMLISTENTRY(struct intel_bo_node, l, head);
dri_bo_ttm *bo_ttm = (dri_bo_ttm *)node->bo;
- if (bo_ttm->relocs != NULL) {
- for (j = 0; j < (bo_ttm->relocs[0] & 0xffff); j++) {
- uint32_t *reloc_entry = bo_ttm->relocs + I915_RELOC_HEADER +
+ if (bo_ttm->reloc_buf_data != NULL) {
+ for (j = 0; j < (bo_ttm->reloc_buf_data[0] & 0xffff); j++) {
+ uint32_t *reloc_entry = bo_ttm->reloc_buf_data +
+ I915_RELOC_HEADER +
j * I915_RELOC0_STRIDE;
DBG("%2d: %s@0x%08x -> %d + 0x%08x\n",
* access flags.
*/
static struct intel_bo_node *
-intel_add_validate_buffer(dri_bufmgr_ttm *bufmgr_ttm,
- dri_bo *buf,
- uint64_t flags,
- int *itemLoc)
+intel_add_validate_buffer(dri_bo *buf,
+ uint64_t flags)
{
+ dri_bufmgr_ttm *bufmgr_ttm = (dri_bufmgr_ttm *)buf->bufmgr;
struct intel_bo_list *list = &bufmgr_ttm->list;
struct intel_bo_node *cur;
dri_bo_ttm *ttm_buf = (dri_bo_ttm *)buf;
}
cur->flags = memFlags | modeFlags;
}
- *itemLoc = count;
+
+ ttm_buf->validate_index = count;
return cur;
}
return 0;
bo_ttm->reloc_buf = malloc(sizeof(bo_ttm->drm_bo));
+ bo_ttm->relocs = malloc(sizeof(struct dri_ttm_reloc) *
+ bufmgr_ttm->max_relocs);
ret = drmBOCreate(bufmgr_ttm->fd,
RELOC_BUF_SIZE(bufmgr_ttm->max_relocs), 0,
ret = drmBOMap(bufmgr_ttm->fd, bo_ttm->reloc_buf,
DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE,
- 0, (void **)&bo_ttm->relocs);
+ 0, (void **)&bo_ttm->reloc_buf_data);
if (ret) {
fprintf(stderr, "Failed to map relocation BO: %s\n",
strerror(-ret));
* DWORD 2: unused
* DWORD 3: unused
*/
- bo_ttm->relocs[0] = I915_RELOC_TYPE_0 << 16;
- bo_ttm->relocs[1] = 0;
- bo_ttm->relocs[2] = 0;
- bo_ttm->relocs[3] = 0;
+ bo_ttm->reloc_buf_data[0] = I915_RELOC_TYPE_0 << 16;
+ bo_ttm->reloc_buf_data[1] = 0;
+ bo_ttm->reloc_buf_data[2] = 0;
+ bo_ttm->reloc_buf_data[3] = 0;
return 0;
}
ttm_buf->name = name;
ttm_buf->refcount = 1;
ttm_buf->reloc_buf = NULL;
+ ttm_buf->reloc_buf_data = NULL;
ttm_buf->relocs = NULL;
DBG("bo_create: %p (%s)\n", &ttm_buf->bo, ttm_buf->name);
ttm_buf->name = name;
ttm_buf->refcount = 1;
ttm_buf->reloc_buf = NULL;
+ ttm_buf->reloc_buf_data = NULL;
ttm_buf->relocs = NULL;
DBG("bo_create_from_handle: %p %08x (%s)\n",
int ret;
if (ttm_buf->reloc_buf) {
+ int i;
+
+ /* Unreference all the target buffers */
+ for (i = 0; i < (ttm_buf->reloc_buf_data[0] & 0xffff); i++)
+ dri_bo_unreference(ttm_buf->relocs[i].target_buf);
+ free(ttm_buf->relocs);
+
+ /* Free the kernel BO containing relocation entries */
drmBOUnmap(bufmgr_ttm->fd, ttm_buf->reloc_buf);
drmBOUnreference(bufmgr_ttm->fd, ttm_buf->reloc_buf);
free(ttm_buf->reloc_buf);
{
dri_bufmgr_ttm *bufmgr_ttm = (dri_bufmgr_ttm *)reloc_buf->bufmgr;
dri_bo_ttm *reloc_buf_ttm = (dri_bo_ttm *)reloc_buf;
- struct intel_bo_node *node;
- int index;
int num_relocs;
uint32_t *this_reloc;
- node = intel_add_validate_buffer(bufmgr_ttm, target_buf, flags, &index);
-
intel_setup_reloc_list(reloc_buf);
- num_relocs = (reloc_buf_ttm->relocs[0] & 0xffff);
+ num_relocs = (reloc_buf_ttm->reloc_buf_data[0] & 0xffff);
/* Check overflow */
- assert((reloc_buf_ttm->relocs[0] & 0xffff) < bufmgr_ttm->max_relocs);
+ assert((reloc_buf_ttm->reloc_buf_data[0] & 0xffff) <
+ bufmgr_ttm->max_relocs);
- this_reloc = reloc_buf_ttm->relocs + I915_RELOC_HEADER +
+ this_reloc = reloc_buf_ttm->reloc_buf_data + I915_RELOC_HEADER +
num_relocs * I915_RELOC0_STRIDE;
this_reloc[0] = offset;
this_reloc[1] = delta;
- this_reloc[2] = index;
+ this_reloc[2] = -1; /* To be filled in at exec time */
this_reloc[3] = 0;
- reloc_buf_ttm->relocs[0]++; /* Increment relocation count */
+ reloc_buf_ttm->relocs[num_relocs].validate_flags = flags;
+ reloc_buf_ttm->relocs[num_relocs].target_buf = target_buf;
+ dri_bo_reference(target_buf);
+
+ reloc_buf_ttm->reloc_buf_data[0]++; /* Increment relocation count */
/* Check wraparound */
- assert((reloc_buf_ttm->relocs[0] & 0xffff) != 0);
+ assert((reloc_buf_ttm->reloc_buf_data[0] & 0xffff) != 0);
}
+/**
+ * Walk the tree of relocations rooted at BO and accumulate the list of
+ * validations to be performed and update the relocation buffers with
+ * index values into the validation list.
+ */
+static void
+dri_ttm_bo_process_reloc(dri_bo *bo)
+{
+ dri_bo_ttm *bo_ttm = (dri_bo_ttm *)bo;
+ unsigned int nr_relocs;
+ int i;
+
+ if (bo_ttm->reloc_buf_data == NULL)
+ return;
+
+ nr_relocs = bo_ttm->reloc_buf_data[0] & 0xffff;
+
+ for (i = 0; i < nr_relocs; i++) {
+ struct dri_ttm_reloc *r = &bo_ttm->relocs[i];
+ dri_bo_ttm *target_ttm = (dri_bo_ttm *)r->target_buf;
+ uint32_t *reloc_entry;
+
+ /* Continue walking the tree depth-first. */
+ dri_ttm_bo_process_reloc(r->target_buf);
+
+ /* Add the target to the validate list */
+ intel_add_validate_buffer(r->target_buf, r->validate_flags);
+
+ /* Update the index of the target in the relocation entry */
+ reloc_entry = bo_ttm->reloc_buf_data + I915_RELOC_HEADER +
+ i * I915_RELOC0_STRIDE;
+ reloc_entry[2] = target_ttm->validate_index;
+ }
+}
static void *
dri_ttm_process_reloc(dri_bo *batch_buf, GLuint *count)
{
dri_bufmgr_ttm *bufmgr_ttm = (dri_bufmgr_ttm *)batch_buf->bufmgr;
void *ptr;
- int index;
+
+ /* Update indices and set up the validate list. */
+ dri_ttm_bo_process_reloc(batch_buf);
/* Add the batch buffer to the validation list. There are no relocations
* pointing to it.
*/
- intel_add_validate_buffer(bufmgr_ttm, batch_buf,
- DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_EXE,
- &index);
+ intel_add_validate_buffer(batch_buf,
+ DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_EXE);
ptr = intel_setup_validate_list(bufmgr_ttm, count);