diff --git a/src/intel/vulkan/anv_batch_chain.c b/src/intel/vulkan/anv_batch_chain.c index 44e2bab3f11..88c2e088d3d 100644 --- a/src/intel/vulkan/anv_batch_chain.c +++ b/src/intel/vulkan/anv_batch_chain.c @@ -691,6 +691,63 @@ anv_cmd_buffer_alloc_dynamic_state(struct anv_cmd_buffer *cmd_buffer, size, alignment); } +/** Allocate space associated with a command buffer + * + * Some commands like vkCmdBuildAccelerationStructuresKHR() can end up needing + * large amount of temporary buffers. This function is here to deal with those + * potentially larger allocations, using a side BO if needed. + * + */ +struct anv_cmd_alloc +anv_cmd_buffer_alloc_space(struct anv_cmd_buffer *cmd_buffer, + size_t size, uint32_t alignment) +{ + /* Below 16k, source memory from dynamic state, otherwise allocate a BO. */ + if (size < 16 * 1024) { + struct anv_state state = + anv_state_stream_alloc(&cmd_buffer->dynamic_state_stream, + size, alignment); + + return (struct anv_cmd_alloc) { + .address = (struct anv_address) { + .bo = cmd_buffer->device->dynamic_state_pool.block_pool.bo, + .offset = state.offset, + }, + .map = state.map, + .size = size, + }; + } + + assert(alignment <= 4096); + + struct anv_bo *bo = NULL; + VkResult result = + anv_device_alloc_bo(cmd_buffer->device, + "cmd-buffer-space", + align_u32(size, 4096), + ANV_BO_ALLOC_MAPPED, + 0, + &bo); + if (result != VK_SUCCESS) { + anv_batch_set_error(&cmd_buffer->batch, VK_ERROR_OUT_OF_DEVICE_MEMORY); + return ANV_EMPTY_ALLOC; + } + + struct anv_bo **bo_entry = + u_vector_add(&cmd_buffer->dynamic_bos); + if (bo_entry == NULL) { + anv_batch_set_error(&cmd_buffer->batch, VK_ERROR_OUT_OF_HOST_MEMORY); + return ANV_EMPTY_ALLOC; + } + *bo_entry = bo; + + return (struct anv_cmd_alloc) { + .address = (struct anv_address) { .bo = bo }, + .map = bo->map, + .size = size, + }; +} + VkResult anv_cmd_buffer_new_binding_table_block(struct anv_cmd_buffer *cmd_buffer) { @@ -1322,6 +1379,14 @@ setup_execbuf_for_cmd_buffer(struct anv_execbuf *execbuf, return result; } + struct anv_bo **bo_entry; + u_vector_foreach(bo_entry, &cmd_buffer->dynamic_bos) { + result = anv_execbuf_add_bo(cmd_buffer->device, execbuf, + *bo_entry, NULL, 0); + if (result != VK_SUCCESS) + return result; + } + return VK_SUCCESS; } diff --git a/src/intel/vulkan/anv_cmd_buffer.c b/src/intel/vulkan/anv_cmd_buffer.c index 0da704647f4..37ac1bd1fda 100644 --- a/src/intel/vulkan/anv_cmd_buffer.c +++ b/src/intel/vulkan/anv_cmd_buffer.c @@ -129,6 +129,11 @@ static VkResult anv_create_cmd_buffer( anv_state_stream_init(&cmd_buffer->general_state_stream, &device->general_state_pool, 16384); + int success = u_vector_init_pow2(&cmd_buffer->dynamic_bos, 8, + sizeof(struct anv_bo *)); + if (!success) + goto fail_batch_bo; + cmd_buffer->self_mod_locations = NULL; anv_cmd_state_init(cmd_buffer); @@ -141,6 +146,8 @@ static VkResult anv_create_cmd_buffer( return VK_SUCCESS; + fail_batch_bo: + anv_cmd_buffer_fini_batch_bo_chain(cmd_buffer); fail_vk: vk_command_buffer_finish(&cmd_buffer->vk); fail_alloc: @@ -195,6 +202,12 @@ anv_cmd_buffer_destroy(struct vk_command_buffer *vk_cmd_buffer) anv_state_stream_finish(&cmd_buffer->dynamic_state_stream); anv_state_stream_finish(&cmd_buffer->general_state_stream); + while (u_vector_length(&cmd_buffer->dynamic_bos) > 0) { + struct anv_bo **bo = u_vector_remove(&cmd_buffer->dynamic_bos); + anv_device_release_bo(cmd_buffer->device, *bo); + } + u_vector_finish(&cmd_buffer->dynamic_bos); + anv_cmd_state_finish(cmd_buffer); vk_free(&cmd_buffer->vk.pool->alloc, cmd_buffer->self_mod_locations); @@ -225,6 +238,11 @@ anv_cmd_buffer_reset(struct anv_cmd_buffer *cmd_buffer) anv_state_stream_init(&cmd_buffer->general_state_stream, &cmd_buffer->device->general_state_pool, 16384); + while (u_vector_length(&cmd_buffer->dynamic_bos) > 0) { + struct anv_bo **bo = u_vector_remove(&cmd_buffer->dynamic_bos); + anv_device_release_bo(cmd_buffer->device, *bo); + } + anv_measure_reset(cmd_buffer); u_trace_fini(&cmd_buffer->trace); diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 6be0b6a38ba..938532c534d 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -2654,6 +2654,15 @@ struct anv_cmd_buffer { */ uint32_t total_batch_size; + /** + * A vector of anv_bo pointers for chunks of memory used by the command + * buffer that are too large to be allocated through dynamic_state_stream. + * This is the case for large enough acceleration structures. + * + * initialized by anv_cmd_buffer_init_batch_bo_chain() + */ + struct u_vector dynamic_bos; + /** * */ @@ -2709,6 +2718,30 @@ struct anv_state anv_cmd_buffer_alloc_dynamic_state(struct anv_cmd_buffer *cmd_buffer, uint32_t size, uint32_t alignment); +/** + * A allocation tied to a command buffer. + * + * Don't use anv_cmd_alloc::address::map to write memory from userspace, use + * anv_cmd_alloc::map instead. + */ +struct anv_cmd_alloc { + struct anv_address address; + void *map; + size_t size; +}; + +#define ANV_EMPTY_ALLOC ((struct anv_cmd_alloc) { .map = NULL, .size = 0 }) + +static inline bool +anv_cmd_alloc_is_empty(struct anv_cmd_alloc alloc) +{ + return alloc.size == 0; +} + +struct anv_cmd_alloc +anv_cmd_buffer_alloc_space(struct anv_cmd_buffer *cmd_buffer, + size_t size, uint32_t alignment); + VkResult anv_cmd_buffer_new_binding_table_block(struct anv_cmd_buffer *cmd_buffer);