Module: Mesa Branch: main Commit: b30428416ae5f50705c998693e4769ba5b4f0700 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=b30428416ae5f50705c998693e4769ba5b4f0700
Author: Lionel Landwerlin <lionel.g.landwer...@intel.com> Date: Thu Oct 12 09:28:43 2023 +0300 anv: deal with state stream allocation failures In case we run out of space, all the parts of the driver that rely on this should deal with failure. The helpers will set the batch in error state so that it cannot be submitted by the application. Signed-off-by: Lionel Landwerlin <lionel.g.landwer...@intel.com> Reviewed-by: Tapani Pälli <tapani.pa...@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25955> --- src/intel/vulkan/anv_batch_chain.c | 44 +++++++++++++++++++--- src/intel/vulkan/anv_cmd_buffer.c | 8 +++- src/intel/vulkan/anv_descriptor_set.c | 12 +++++- src/intel/vulkan/anv_private.h | 9 ++++- src/intel/vulkan/genX_blorp_exec.c | 7 ++-- src/intel/vulkan/genX_cmd_buffer.c | 33 +++++++++------- .../vulkan/genX_cmd_draw_generated_indirect.h | 4 ++ src/intel/vulkan/genX_query.c | 3 ++ src/intel/vulkan/genX_simple_shader.c | 23 +++++++++-- src/intel/vulkan_hasvk/genX_blorp_exec.c | 2 +- 10 files changed, 114 insertions(+), 31 deletions(-) diff --git a/src/intel/vulkan/anv_batch_chain.c b/src/intel/vulkan/anv_batch_chain.c index eb39ae6e85b..60af0fa3157 100644 --- a/src/intel/vulkan/anv_batch_chain.c +++ b/src/intel/vulkan/anv_batch_chain.c @@ -721,19 +721,47 @@ anv_cmd_buffer_alloc_binding_table(struct anv_cmd_buffer *cmd_buffer, } struct anv_state -anv_cmd_buffer_alloc_surface_state(struct anv_cmd_buffer *cmd_buffer) +anv_cmd_buffer_alloc_surface_states(struct anv_cmd_buffer *cmd_buffer, + uint32_t count) { + if (count == 0) + return ANV_STATE_NULL; struct isl_device *isl_dev = &cmd_buffer->device->isl_dev; - return anv_state_stream_alloc(&cmd_buffer->surface_state_stream, - isl_dev->ss.size, isl_dev->ss.align); + struct anv_state state = + anv_state_stream_alloc(&cmd_buffer->surface_state_stream, + count * isl_dev->ss.size, + isl_dev->ss.align); + if (state.map == NULL) + anv_batch_set_error(&cmd_buffer->batch, VK_ERROR_OUT_OF_DEVICE_MEMORY); + return state; } struct anv_state anv_cmd_buffer_alloc_dynamic_state(struct anv_cmd_buffer *cmd_buffer, uint32_t size, uint32_t alignment) { - return anv_state_stream_alloc(&cmd_buffer->dynamic_state_stream, - size, alignment); + if (size == 0) + return ANV_STATE_NULL; + struct anv_state state = + anv_state_stream_alloc(&cmd_buffer->dynamic_state_stream, + size, alignment); + if (state.map == NULL) + anv_batch_set_error(&cmd_buffer->batch, VK_ERROR_OUT_OF_DEVICE_MEMORY); + return state; +} + +struct anv_state +anv_cmd_buffer_alloc_general_state(struct anv_cmd_buffer *cmd_buffer, + uint32_t size, uint32_t alignment) +{ + if (size == 0) + return ANV_STATE_NULL; + struct anv_state state = + anv_state_stream_alloc(&cmd_buffer->general_state_stream, + size, alignment); + if (state.map == NULL) + anv_batch_set_error(&cmd_buffer->batch, VK_ERROR_OUT_OF_DEVICE_MEMORY); + return state; } /** Allocate space associated with a command buffer @@ -753,6 +781,12 @@ anv_cmd_buffer_alloc_space(struct anv_cmd_buffer *cmd_buffer, struct anv_state state = anv_state_stream_alloc(&cmd_buffer->dynamic_state_stream, size, alignment); + if (state.map == NULL) { + anv_batch_set_error(&cmd_buffer->batch, VK_ERROR_OUT_OF_DEVICE_MEMORY); + return (struct anv_cmd_alloc) { + .address = ANV_NULL_ADDRESS, + }; + } return (struct anv_cmd_alloc) { .address = anv_state_pool_state_address( diff --git a/src/intel/vulkan/anv_cmd_buffer.c b/src/intel/vulkan/anv_cmd_buffer.c index 524ad475415..8f9fb72c5b5 100644 --- a/src/intel/vulkan/anv_cmd_buffer.c +++ b/src/intel/vulkan/anv_cmd_buffer.c @@ -1063,6 +1063,8 @@ anv_cmd_buffer_cs_push_constants(struct anv_cmd_buffer *cmd_buffer) aligned_total_push_constants_size, push_constant_alignment); } + if (state.map == NULL) + return state; void *dst = state.map; const void *src = (char *)data + (range->start * 32); @@ -1164,7 +1166,8 @@ void anv_CmdPushDescriptorSetKHR( struct anv_push_descriptor_set *push_set = &anv_cmd_buffer_get_pipe_state(cmd_buffer, pipelineBindPoint)->push_descriptor; - anv_push_descriptor_set_init(cmd_buffer, push_set, set_layout); + if (!anv_push_descriptor_set_init(cmd_buffer, push_set, set_layout)) + return; anv_descriptor_set_write(cmd_buffer->device, &push_set->set, descriptorWriteCount, pDescriptorWrites); @@ -1194,7 +1197,8 @@ void anv_CmdPushDescriptorSetWithTemplateKHR( struct anv_push_descriptor_set *push_set = &anv_cmd_buffer_get_pipe_state(cmd_buffer, template->bind_point)->push_descriptor; - anv_push_descriptor_set_init(cmd_buffer, push_set, set_layout); + if (!anv_push_descriptor_set_init(cmd_buffer, push_set, set_layout)) + return; anv_descriptor_set_write_template(cmd_buffer->device, &push_set->set, template, diff --git a/src/intel/vulkan/anv_descriptor_set.c b/src/intel/vulkan/anv_descriptor_set.c index 5dd7df16903..62202bec0c8 100644 --- a/src/intel/vulkan/anv_descriptor_set.c +++ b/src/intel/vulkan/anv_descriptor_set.c @@ -1345,6 +1345,11 @@ anv_descriptor_set_create(struct anv_device *device, if (!pool->host_only) { set->desc_surface_state = anv_descriptor_pool_alloc_state(pool); + if (set->desc_surface_state.map == NULL) { + anv_descriptor_pool_free_set(pool, set); + return vk_error(pool, VK_ERROR_OUT_OF_DEVICE_MEMORY); + } + anv_fill_buffer_surface_state(device, set->desc_surface_state.map, format, ISL_SWIZZLE_IDENTITY, ISL_SURF_USAGE_CONSTANT_BUFFER_BIT, @@ -1533,7 +1538,7 @@ VkResult anv_FreeDescriptorSets( return VK_SUCCESS; } -void +bool anv_push_descriptor_set_init(struct anv_cmd_buffer *cmd_buffer, struct anv_push_descriptor_set *push_set, struct anv_descriptor_set_layout *layout) @@ -1580,6 +1585,9 @@ anv_push_descriptor_set_init(struct anv_cmd_buffer *cmd_buffer, anv_state_stream_alloc(push_stream, anv_descriptor_set_layout_descriptor_buffer_size(layout, 0), ANV_UBO_ALIGNMENT); + if (desc_mem.map == NULL) + return false; + if (set->desc_mem.alloc_size) { /* TODO: Do we really need to copy all the time? */ memcpy(desc_mem.map, set->desc_mem.map, @@ -1593,6 +1601,8 @@ anv_push_descriptor_set_init(struct anv_cmd_buffer *cmd_buffer, set->desc_offset = anv_address_physical(set->desc_addr) - push_base_address; } + + return true; } void diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index c11595cc53b..abd1d8f9a2b 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -637,6 +637,7 @@ struct anv_state_table { int fd; struct anv_free_entry *map; uint32_t size; + uint64_t max_size; struct anv_block_state state; struct u_vector cleanups; }; @@ -2478,7 +2479,7 @@ uint32_t anv_descriptor_set_layout_descriptor_buffer_size(const struct anv_descriptor_set_layout *set_layout, uint32_t var_desc_count); -void +bool anv_push_descriptor_set_init(struct anv_cmd_buffer *cmd_buffer, struct anv_push_descriptor_set *push_set, struct anv_descriptor_set_layout *layout); @@ -3776,10 +3777,14 @@ 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 -anv_cmd_buffer_alloc_surface_state(struct anv_cmd_buffer *cmd_buffer); +anv_cmd_buffer_alloc_surface_states(struct anv_cmd_buffer *cmd_buffer, + uint32_t count); struct anv_state anv_cmd_buffer_alloc_dynamic_state(struct anv_cmd_buffer *cmd_buffer, uint32_t size, uint32_t alignment); +struct anv_state +anv_cmd_buffer_alloc_general_state(struct anv_cmd_buffer *cmd_buffer, + uint32_t size, uint32_t alignment); void anv_cmd_buffer_chain_command_buffers(struct anv_cmd_buffer **cmd_buffers, diff --git a/src/intel/vulkan/genX_blorp_exec.c b/src/intel/vulkan/genX_blorp_exec.c index 3cf2ae9b768..587dbc46db9 100644 --- a/src/intel/vulkan/genX_blorp_exec.c +++ b/src/intel/vulkan/genX_blorp_exec.c @@ -139,8 +139,7 @@ blorp_alloc_general_state(struct blorp_batch *batch, struct anv_cmd_buffer *cmd_buffer = batch->driver_batch; struct anv_state state = - anv_state_stream_alloc(&cmd_buffer->general_state_stream, size, - alignment); + anv_cmd_buffer_alloc_general_state(cmd_buffer, size, alignment); *offset = state.offset; return state.map; @@ -168,7 +167,9 @@ blorp_alloc_binding_table(struct blorp_batch *batch, unsigned num_entries, for (unsigned i = 0; i < num_entries; i++) { struct anv_state surface_state = - anv_cmd_buffer_alloc_surface_state(cmd_buffer); + anv_cmd_buffer_alloc_surface_states(cmd_buffer, 1); + if (surface_state.map == NULL) + return false; bt_map[i] = surface_state.offset + state_offset; surface_offsets[i] = surface_state.offset; diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c index fa3f1415951..9a8ac921304 100644 --- a/src/intel/vulkan/genX_cmd_buffer.c +++ b/src/intel/vulkan/genX_cmd_buffer.c @@ -1264,12 +1264,9 @@ anv_cmd_buffer_init_attachments(struct anv_cmd_buffer *cmd_buffer, const struct isl_device *isl_dev = &cmd_buffer->device->isl_dev; const uint32_t ss_stride = align(isl_dev->ss.size, isl_dev->ss.align); gfx->att_states = - anv_state_stream_alloc(&cmd_buffer->surface_state_stream, - num_states * ss_stride, isl_dev->ss.align); - if (gfx->att_states.map == NULL) { - return anv_batch_set_error(&cmd_buffer->batch, - VK_ERROR_OUT_OF_DEVICE_MEMORY); - } + anv_cmd_buffer_alloc_surface_states(cmd_buffer, num_states); + if (gfx->att_states.map == NULL) + return VK_ERROR_OUT_OF_DEVICE_MEMORY; struct anv_state next_state = gfx->att_states; next_state.alloc_size = isl_dev->ss.size; @@ -1874,7 +1871,11 @@ emit_dynamic_buffer_binding_table_entry(struct anv_cmd_buffer *cmd_buffer, struct anv_address address = anv_address_add(desc->buffer->address, offset); - struct anv_state surface_state = anv_cmd_buffer_alloc_surface_state(cmd_buffer); + struct anv_state surface_state = + anv_cmd_buffer_alloc_surface_states(cmd_buffer, 1); + if (surface_state.map == NULL) + return ANV_STATE_NULL; + enum isl_format format = anv_isl_format_for_descriptor_type(cmd_buffer->device, desc->type); @@ -1987,7 +1988,6 @@ emit_indirect_descriptor_binding_table_entry(struct anv_cmd_buffer *cmd_buffer, unreachable("Invalid descriptor type"); } - assert(surface_state.map); return surface_state.offset; } @@ -2086,7 +2086,9 @@ emit_binding_table(struct anv_cmd_buffer *cmd_buffer, assert(shader->stage == MESA_SHADER_COMPUTE && s == 0); struct anv_state surface_state = - anv_cmd_buffer_alloc_surface_state(cmd_buffer); + anv_cmd_buffer_alloc_surface_states(cmd_buffer, 1); + if (surface_state.map == NULL) + return VK_ERROR_OUT_OF_DEVICE_MEMORY; const enum isl_format format = anv_isl_format_for_descriptor_type(cmd_buffer->device, @@ -2329,7 +2331,9 @@ flush_push_descriptor_set(struct anv_cmd_buffer *cmd_buffer, if (bview != NULL) { bview->general.state = - anv_cmd_buffer_alloc_surface_state(cmd_buffer); + anv_cmd_buffer_alloc_surface_states(cmd_buffer, 1); + if (bview->general.state.map == NULL) + return; anv_descriptor_write_surface_state(cmd_buffer->device, desc, bview->general.state); } @@ -2341,7 +2345,10 @@ flush_push_descriptor_set(struct anv_cmd_buffer *cmd_buffer, anv_isl_format_for_descriptor_type(cmd_buffer->device, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); - set->desc_surface_state = anv_cmd_buffer_alloc_surface_state(cmd_buffer); + set->desc_surface_state = + anv_cmd_buffer_alloc_surface_states(cmd_buffer, 1); + if (set->desc_surface_state.map == NULL) + return; anv_fill_buffer_surface_state(cmd_buffer->device, set->desc_surface_state.map, format, ISL_SWIZZLE_IDENTITY, @@ -5926,8 +5933,8 @@ genX(cmd_buffer_dispatch_kernel)(struct anv_cmd_buffer *cmd_buffer, indirect_data_size += kernel->bin->bind_map.kernel_args_size; indirect_data_size = ALIGN(indirect_data_size, 64); struct anv_state indirect_data = - anv_state_stream_alloc(&cmd_buffer->general_state_stream, - indirect_data_size, 64); + anv_cmd_buffer_alloc_general_state(cmd_buffer, + indirect_data_size, 64); memset(indirect_data.map, 0, indirect_data.alloc_size); struct brw_kernel_sysvals sysvals = {}; diff --git a/src/intel/vulkan/genX_cmd_draw_generated_indirect.h b/src/intel/vulkan/genX_cmd_draw_generated_indirect.h index acd768890f4..943a9700eed 100644 --- a/src/intel/vulkan/genX_cmd_draw_generated_indirect.h +++ b/src/intel/vulkan/genX_cmd_draw_generated_indirect.h @@ -61,6 +61,8 @@ genX(cmd_buffer_emit_generate_draws)(struct anv_cmd_buffer *cmd_buffer, struct anv_state push_data_state = genX(simple_shader_alloc_push)(simple_state, sizeof(struct anv_generated_indirect_params)); + if (push_data_state.map == NULL) + return ANV_STATE_NULL; struct anv_graphics_pipeline *pipeline = cmd_buffer->state.gfx.pipeline; const struct brw_vs_prog_data *vs_prog_data = get_vs_prog_data(pipeline); @@ -323,6 +325,8 @@ genX(cmd_buffer_emit_indirect_generated_draws_inplace)(struct anv_cmd_buffer *cm indexed, 0 /* ring_count */); struct anv_generated_indirect_params *params = params_state.map; + if (params == NULL) + return; anv_batch_advance(&cmd_buffer->batch, draw_cmd_size); diff --git a/src/intel/vulkan/genX_query.c b/src/intel/vulkan/genX_query.c index cb99830a7dd..9047418b58a 100644 --- a/src/intel/vulkan/genX_query.c +++ b/src/intel/vulkan/genX_query.c @@ -1731,6 +1731,9 @@ copy_query_results_with_shader(struct anv_cmd_buffer *cmd_buffer, struct anv_state push_data_state = genX(simple_shader_alloc_push)(&state, sizeof(struct anv_query_copy_params)); + if (push_data_state.map == NULL) + return; + struct anv_query_copy_params *params = push_data_state.map; uint32_t copy_flags = diff --git a/src/intel/vulkan/genX_simple_shader.c b/src/intel/vulkan/genX_simple_shader.c index ee87eb6ef48..8d609ed6026 100644 --- a/src/intel/vulkan/genX_simple_shader.c +++ b/src/intel/vulkan/genX_simple_shader.c @@ -216,6 +216,9 @@ genX(emit_simpler_shader_init_fragment)(struct anv_simple_shader *state) struct anv_state cc_state = anv_state_stream_alloc(state->dynamic_state_stream, 4 * GENX(CC_VIEWPORT_length), 32); + if (cc_state.map == NULL) + return; + struct GENX(CC_VIEWPORT) cc_viewport = { .MinimumDepth = 0.0f, .MaximumDepth = 1.0f, @@ -380,16 +383,23 @@ genX(emit_simple_shader_init)(struct anv_simple_shader *state) struct anv_state genX(simple_shader_alloc_push)(struct anv_simple_shader *state, uint32_t size) { + struct anv_state s; + if (state->kernel->stage == MESA_SHADER_FRAGMENT) { - return anv_state_stream_alloc(state->dynamic_state_stream, - size, ANV_UBO_ALIGNMENT); + s = anv_state_stream_alloc(state->dynamic_state_stream, + size, ANV_UBO_ALIGNMENT); } else { #if GFX_VERx10 >= 125 - return anv_state_stream_alloc(state->general_state_stream, align(size, 64), 64); + s = anv_state_stream_alloc(state->general_state_stream, align(size, 64), 64); #else - return anv_state_stream_alloc(state->dynamic_state_stream, size, 64); + s = anv_state_stream_alloc(state->dynamic_state_stream, size, 64); #endif } + + if (s.map == NULL) + anv_batch_set_error(state->batch, VK_ERROR_OUT_OF_DEVICE_MEMORY); + + return s; } /** Get the address of allocated push constant data by @@ -433,6 +443,8 @@ genX(emit_simple_shader_dispatch)(struct anv_simple_shader *state, struct anv_state vs_data_state = anv_state_stream_alloc(state->dynamic_state_stream, 9 * sizeof(uint32_t), 32); + if (vs_data_state.map == NULL) + return; float x0 = 0.0f, x1 = MIN2(num_threads, 8192); float y0 = 0.0f, y1 = DIV_ROUND_UP(num_threads, 8192); @@ -602,6 +614,9 @@ genX(emit_simple_shader_dispatch)(struct anv_simple_shader *state, struct anv_state iface_desc_state = anv_state_stream_alloc(state->dynamic_state_stream, GENX(INTERFACE_DESCRIPTOR_DATA_length) * 4, 64); + if (iface_desc_state.map == NULL) + return; + struct GENX(INTERFACE_DESCRIPTOR_DATA) iface_desc = { .KernelStartPointer = state->kernel->kernel.offset + brw_cs_prog_data_prog_offset(prog_data, diff --git a/src/intel/vulkan_hasvk/genX_blorp_exec.c b/src/intel/vulkan_hasvk/genX_blorp_exec.c index 0005e527ac9..2c4c3e4036e 100644 --- a/src/intel/vulkan_hasvk/genX_blorp_exec.c +++ b/src/intel/vulkan_hasvk/genX_blorp_exec.c @@ -165,7 +165,7 @@ blorp_alloc_general_state(struct blorp_batch *batch, return state.map; } -static void +static bool blorp_alloc_binding_table(struct blorp_batch *batch, unsigned num_entries, unsigned state_size, unsigned state_alignment, uint32_t *bt_offset,