diff options
author | Jason Ekstrand <[email protected]> | 2015-09-28 12:39:34 -0700 |
---|---|---|
committer | Jason Ekstrand <[email protected]> | 2015-09-28 16:01:14 -0700 |
commit | d93f6385a7a41d6ea13809005520a44283a40405 (patch) | |
tree | 68f96a72ff062e0e39c876d3fe9fa8e8325cb806 /src/vulkan/anv_batch_chain.c | |
parent | 8c00f9ab56050a1a33f19025e27abf9323cbe0d0 (diff) |
anv/batch_chain: Add helpers for fixing up block_pool relocations
Diffstat (limited to 'src/vulkan/anv_batch_chain.c')
-rw-r--r-- | src/vulkan/anv_batch_chain.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/vulkan/anv_batch_chain.c b/src/vulkan/anv_batch_chain.c index 51ba7ef4a31..e8581a93095 100644 --- a/src/vulkan/anv_batch_chain.c +++ b/src/vulkan/anv_batch_chain.c @@ -880,6 +880,68 @@ anv_cmd_buffer_process_relocs(struct anv_cmd_buffer *cmd_buffer, } } +static void +adjust_relocations_from_block_pool(struct anv_block_pool *pool, + struct anv_reloc_list *relocs) +{ + for (size_t i = 0; i < relocs->num_relocs; i++) { + /* In general, we don't know how stale the relocated value is. It + * may have been used last time or it may not. Since we don't want + * to stomp it while the GPU may be accessing it, we haven't updated + * it anywhere else in the code. Instead, we just set the presumed + * offset to what it is now based on the delta and the data in the + * block pool. Then the kernel will update it for us if needed. + */ + uint32_t *reloc_data = pool->map + relocs->relocs[i].offset; + relocs->relocs[i].presumed_offset = *reloc_data - relocs->relocs[i].delta; + + /* All of the relocations from this block pool to other BO's should + * have been emitted relative to the surface block pool center. We + * need to add the center offset to make them relative to the + * beginning of the actual GEM bo. + */ + relocs->relocs[i].offset += pool->center_bo_offset; + } +} + +static void +adjust_relocations_to_block_pool(struct anv_block_pool *pool, + struct anv_bo *from_bo, + struct anv_reloc_list *relocs, + uint32_t *last_pool_center_bo_offset) +{ + assert(*last_pool_center_bo_offset <= pool->center_bo_offset); + uint32_t delta = pool->center_bo_offset - *last_pool_center_bo_offset; + + /* When we initially emit relocations into a block pool, we don't + * actually know what the final center_bo_offset will be so we just emit + * it as if center_bo_offset == 0. Now that we know what the center + * offset is, we need to walk the list of relocations and adjust any + * relocations that point to the pool bo with the correct offset. + */ + for (size_t i = 0; i < relocs->num_relocs; i++) { + if (relocs->reloc_bos[i] == &pool->bo) { + /* Adjust the delta value in the relocation to correctly + * correspond to the new delta. Initially, this value may have + * been negative (if treated as unsigned), but we trust in + * uint32_t roll-over to fix that for us at this point. + */ + relocs->relocs[i].delta += delta; + + /* Since the delta has changed, we need to update the actual + * relocated value with the new presumed value. This function + * should only be called on batch buffers, so we know it isn't in + * use by the GPU at the moment. + */ + uint32_t *reloc_data = from_bo->map + relocs->relocs[i].offset; + *reloc_data = relocs->relocs[i].presumed_offset + + relocs->relocs[i].delta; + } + } + + *last_pool_center_bo_offset = pool->center_bo_offset; +} + void anv_cmd_buffer_prepare_execbuf(struct anv_cmd_buffer *cmd_buffer) { |