anv: Use a separate pool for binding tables when soft pinning

Soft pinning lets us satisfy the binding table address
requirements without using both sides of a growing state_pool.

If you do use both sides of a state pool, then you need to read
the state pool's center_bo_offset (with the device mutex held) to
know the final offset of relocations that target the state pool
bo.

By having a separate pool for binding tables that only grows in
the forward direction, the center_bo_offset is always 0 and
relocations don't need an update pass to adjust relocations with
the mutex held.

v2: - don't introduce a separate state flag for separate binding tables (Jason)
    - replace bo and map accessors with a single binding_table_pool accessor (Jason)
v3: - assert bt_block->offset >= 0 for the separate binding table (Jason)

Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
This commit is contained in:
Scott D Phillips 2018-03-14 10:31:16 -07:00 committed by Jason Ekstrand
parent e662bdb820
commit c7db0ed4e9
3 changed files with 53 additions and 11 deletions

View File

@ -452,7 +452,7 @@ anv_cmd_buffer_surface_base_address(struct anv_cmd_buffer *cmd_buffer)
{
struct anv_state *bt_block = u_vector_head(&cmd_buffer->bt_block_states);
return (struct anv_address) {
.bo = &cmd_buffer->device->surface_state_pool.block_pool.bo,
.bo = &anv_binding_table_pool(cmd_buffer->device)->block_pool.bo,
.offset = bt_block->offset,
};
}
@ -619,7 +619,8 @@ struct anv_state
anv_cmd_buffer_alloc_binding_table(struct anv_cmd_buffer *cmd_buffer,
uint32_t entries, uint32_t *state_offset)
{
struct anv_state_pool *state_pool = &cmd_buffer->device->surface_state_pool;
struct anv_device *device = cmd_buffer->device;
struct anv_state_pool *state_pool = &device->surface_state_pool;
struct anv_state *bt_block = u_vector_head(&cmd_buffer->bt_block_states);
struct anv_state state;
@ -629,12 +630,19 @@ anv_cmd_buffer_alloc_binding_table(struct anv_cmd_buffer *cmd_buffer,
return (struct anv_state) { 0 };
state.offset = cmd_buffer->bt_next;
state.map = state_pool->block_pool.map + bt_block->offset + state.offset;
state.map = anv_binding_table_pool(device)->block_pool.map +
bt_block->offset + state.offset;
cmd_buffer->bt_next += state.alloc_size;
assert(bt_block->offset < 0);
*state_offset = -bt_block->offset;
if (device->instance->physicalDevice.use_softpin) {
assert(bt_block->offset >= 0);
*state_offset = device->surface_state_pool.block_pool.start_address -
device->binding_table_pool.block_pool.start_address - bt_block->offset;
} else {
assert(bt_block->offset < 0);
*state_offset = -bt_block->offset;
}
return state;
}
@ -658,15 +666,13 @@ anv_cmd_buffer_alloc_dynamic_state(struct anv_cmd_buffer *cmd_buffer,
VkResult
anv_cmd_buffer_new_binding_table_block(struct anv_cmd_buffer *cmd_buffer)
{
struct anv_state_pool *state_pool = &cmd_buffer->device->surface_state_pool;
struct anv_state *bt_block = u_vector_add(&cmd_buffer->bt_block_states);
if (bt_block == NULL) {
anv_batch_set_error(&cmd_buffer->batch, VK_ERROR_OUT_OF_HOST_MEMORY);
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
}
*bt_block = anv_state_pool_alloc_back(state_pool);
*bt_block = anv_binding_table_pool_alloc(cmd_buffer->device);
cmd_buffer->bt_next = 0;
return VK_SUCCESS;
@ -740,7 +746,7 @@ anv_cmd_buffer_fini_batch_bo_chain(struct anv_cmd_buffer *cmd_buffer)
{
struct anv_state *bt_block;
u_vector_foreach(bt_block, &cmd_buffer->bt_block_states)
anv_state_pool_free(&cmd_buffer->device->surface_state_pool, *bt_block);
anv_binding_table_pool_free(cmd_buffer->device, *bt_block);
u_vector_finish(&cmd_buffer->bt_block_states);
anv_reloc_list_finish(&cmd_buffer->surface_relocs, &cmd_buffer->pool->alloc);
@ -772,7 +778,7 @@ anv_cmd_buffer_reset_batch_bo_chain(struct anv_cmd_buffer *cmd_buffer)
while (u_vector_length(&cmd_buffer->bt_block_states) > 1) {
struct anv_state *bt_block = u_vector_remove(&cmd_buffer->bt_block_states);
anv_state_pool_free(&cmd_buffer->device->surface_state_pool, *bt_block);
anv_binding_table_pool_free(cmd_buffer->device, *bt_block);
}
assert(u_vector_length(&cmd_buffer->bt_block_states) == 1);
cmd_buffer->bt_next = 0;

View File

@ -1641,9 +1641,18 @@ VkResult anv_CreateDevice(
if (result != VK_SUCCESS)
goto fail_instruction_state_pool;
if (physical_device->use_softpin) {
result = anv_state_pool_init(&device->binding_table_pool, device,
BINDING_TABLE_POOL_MIN_ADDRESS,
4096,
bo_flags);
if (result != VK_SUCCESS)
goto fail_surface_state_pool;
}
result = anv_bo_init_new(&device->workaround_bo, device, 1024);
if (result != VK_SUCCESS)
goto fail_surface_state_pool;
goto fail_binding_table_pool;
anv_device_init_trivial_batch(device);
@ -1694,6 +1703,9 @@ VkResult anv_CreateDevice(
anv_scratch_pool_finish(device, &device->scratch_pool);
anv_gem_munmap(device->workaround_bo.map, device->workaround_bo.size);
anv_gem_close(device, device->workaround_bo.gem_handle);
fail_binding_table_pool:
if (physical_device->use_softpin)
anv_state_pool_finish(&device->binding_table_pool);
fail_surface_state_pool:
anv_state_pool_finish(&device->surface_state_pool);
fail_instruction_state_pool:

View File

@ -955,6 +955,7 @@ struct anv_device {
struct anv_state_pool dynamic_state_pool;
struct anv_state_pool instruction_state_pool;
struct anv_state_pool binding_table_pool;
struct anv_state_pool surface_state_pool;
struct anv_bo workaround_bo;
@ -977,6 +978,29 @@ struct anv_device {
bool lost;
};
static inline struct anv_state_pool *
anv_binding_table_pool(struct anv_device *device)
{
if (device->instance->physicalDevice.use_softpin)
return &device->binding_table_pool;
else
return &device->surface_state_pool;
}
static inline struct anv_state
anv_binding_table_pool_alloc(struct anv_device *device) {
if (device->instance->physicalDevice.use_softpin)
return anv_state_pool_alloc(&device->binding_table_pool,
device->binding_table_pool.block_size, 0);
else
return anv_state_pool_alloc_back(&device->surface_state_pool);
}
static inline void
anv_binding_table_pool_free(struct anv_device *device, struct anv_state state) {
anv_state_pool_free(anv_binding_table_pool(device), state);
}
static void inline
anv_state_flush(struct anv_device *device, struct anv_state state)
{