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,

Reply via email to