diff options
author | Bruno Jiménez <[email protected]> | 2014-07-16 23:12:43 +0200 |
---|---|---|
committer | Tom Stellard <[email protected]> | 2014-07-23 10:29:17 -0400 |
commit | 1f705b2bee4c83674593f92df81ec888e2a2e23d (patch) | |
tree | a752eb4df5f69d1af34869f992030504efe77955 | |
parent | 23ae2db8549ab0bd66252449db968e8aec4a3acc (diff) |
r600g/compute: Add a function for moving items in the pool
This function will be used in the future by compute_memory_defrag
to move items forward in the pool.
It does so by first checking for overlaping ranges, if the ranges
don't overlap it will copy the contents directly. If they overlap
it will try first to make a temporary buffer, if this buffer fails
to allocate, it will finally fall back to a mapping.
Note that it will only be needed to move items forward, it only
checks for overlapping ranges in that case. If needed, it can
easily be added by changing the first if.
Reviewed-by: Tom Stellard <[email protected]>
-rw-r--r-- | src/gallium/drivers/r600/compute_memory_pool.c | 89 | ||||
-rw-r--r-- | src/gallium/drivers/r600/compute_memory_pool.h | 4 |
2 files changed, 93 insertions, 0 deletions
diff --git a/src/gallium/drivers/r600/compute_memory_pool.c b/src/gallium/drivers/r600/compute_memory_pool.c index fe19d9ef81c..0b413180851 100644 --- a/src/gallium/drivers/r600/compute_memory_pool.c +++ b/src/gallium/drivers/r600/compute_memory_pool.c @@ -408,6 +408,95 @@ void compute_memory_demote_item(struct compute_memory_pool *pool, item->start_in_dw = -1; } +/** + * Moves the item \a item forward in the pool to \a new_start_in_dw + * + * This function assumes two things: + * 1) The item is \b only moved forward + * 2) The item \b won't change it's position inside the \a item_list + * + * \param item The item that will be moved + * \param new_start_in_dw The new position of the item in \a item_list + */ +void compute_memory_move_item(struct compute_memory_pool *pool, + struct compute_memory_item *item, uint64_t new_start_in_dw, + struct pipe_context *pipe) +{ + struct pipe_screen *screen = (struct pipe_screen *)pool->screen; + struct r600_context *rctx = (struct r600_context *)pipe; + struct pipe_resource *src = (struct pipe_resource *)pool->bo; + struct pipe_resource *dst; + struct pipe_box box; + + struct compute_memory_item *prev; + + COMPUTE_DBG(pool->screen, "* compute_memory_move_item()\n" + " + Moving item %i from %u (%u bytes) to %u (%u bytes)\n", + item->id, item->start_in_dw, item->start_in_dw * 4, + new_start_in_dw, new_start_in_dw * 4); + + if (pool->item_list != item->link.prev) { + prev = container_of(item->link.prev, item, link); + assert(prev->start_in_dw + prev->size_in_dw <= new_start_in_dw); + } + + u_box_1d(item->start_in_dw * 4, item->size_in_dw * 4, &box); + + /* If the ranges don't overlap, we can just copy the item directly */ + if (new_start_in_dw + item->size_in_dw <= item->start_in_dw) { + dst = (struct pipe_resource *)pool->bo; + + rctx->b.b.resource_copy_region(pipe, + dst, 0, new_start_in_dw * 4, 0, 0, + src, 0, &box); + } else { + /* The ranges overlap, we will try first to use an intermediate + * resource to move the item */ + dst = (struct pipe_resource *)r600_compute_buffer_alloc_vram( + pool->screen, item->size_in_dw * 4); + + if (dst != NULL) { + rctx->b.b.resource_copy_region(pipe, + dst, 0, 0, 0, 0, + src, 0, &box); + + src = dst; + dst = (struct pipe_resource *)pool->bo; + + box.x = 0; + + rctx->b.b.resource_copy_region(pipe, + dst, 0, new_start_in_dw * 4, 0, 0, + src, 0, &box); + + pool->screen->b.b.resource_destroy(screen, src); + + } else { + /* The allocation of the temporary resource failed, + * falling back to use mappings */ + uint32_t *map; + int64_t offset; + struct pipe_transfer *trans; + + offset = item->start_in_dw - new_start_in_dw; + + u_box_1d(new_start_in_dw * 4, (offset + item->size_in_dw) * 4, &box); + + map = pipe->transfer_map(pipe, src, 0, PIPE_TRANSFER_READ_WRITE, + &box, &trans); + + assert(map); + assert(trans); + + memmove(map, map + offset, item->size_in_dw * 4); + + pipe->transfer_unmap(pipe, trans); + } + } + + item->start_in_dw = new_start_in_dw; +} + void compute_memory_free(struct compute_memory_pool* pool, int64_t id) { struct compute_memory_item *item, *next; diff --git a/src/gallium/drivers/r600/compute_memory_pool.h b/src/gallium/drivers/r600/compute_memory_pool.h index 259474a493d..73320100dbd 100644 --- a/src/gallium/drivers/r600/compute_memory_pool.h +++ b/src/gallium/drivers/r600/compute_memory_pool.h @@ -93,6 +93,10 @@ int compute_memory_promote_item(struct compute_memory_pool *pool, void compute_memory_demote_item(struct compute_memory_pool *pool, struct compute_memory_item *item, struct pipe_context *pipe); +void compute_memory_move_item(struct compute_memory_pool *pool, + struct compute_memory_item *item, uint64_t new_start_in_dw, + struct pipe_context *pipe); + void compute_memory_free(struct compute_memory_pool* pool, int64_t id); struct compute_memory_item* compute_memory_alloc(struct compute_memory_pool* pool, int64_t size_in_dw); ///Creates pending allocations |