vk/device: Make reloc lists growable
authorJason Ekstrand <jason.ekstrand@intel.com>
Tue, 26 May 2015 00:38:15 +0000 (17:38 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Wed, 27 May 2015 18:48:28 +0000 (11:48 -0700)
src/vulkan/device.c
src/vulkan/pipeline.c
src/vulkan/private.h

index 5c2e276210d63b2316bf7162bf357a8b415ce20a..4cbf409b216b59f145722982f1d950a97de71a54 100644 (file)
@@ -501,6 +501,75 @@ VkResult anv_GetDeviceQueue(
    return VK_SUCCESS;
 }
 
+static VkResult
+anv_reloc_list_init(struct anv_reloc_list *list, struct anv_device *device)
+{
+   list->num_relocs = 0;
+   list->array_length = 256;
+   list->relocs =
+      anv_device_alloc(device, list->array_length * sizeof(*list->relocs), 8,
+                       VK_SYSTEM_ALLOC_TYPE_INTERNAL);
+
+   if (list->relocs == NULL)
+      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+   list->reloc_bos =
+      anv_device_alloc(device, list->array_length * sizeof(*list->reloc_bos), 8,
+                       VK_SYSTEM_ALLOC_TYPE_INTERNAL);
+
+   if (list->relocs == NULL) {
+      anv_device_free(device, list->relocs);
+      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+   }
+
+   return VK_SUCCESS;
+}
+
+static void
+anv_reloc_list_finish(struct anv_reloc_list *list, struct anv_device *device)
+{
+   anv_device_free(device, list->relocs);
+   anv_device_free(device, list->reloc_bos);
+}
+
+static VkResult
+anv_reloc_list_grow(struct anv_reloc_list *list, struct anv_device *device,
+                    size_t num_additional_relocs)
+{
+   if (list->num_relocs + num_additional_relocs <= list->array_length)
+      return VK_SUCCESS;
+
+   size_t new_length = list->array_length * 2;
+   while (new_length < list->num_relocs + num_additional_relocs)
+      new_length *= 2;
+
+   struct drm_i915_gem_relocation_entry *new_relocs =
+      anv_device_alloc(device, new_length * sizeof(*list->relocs), 8,
+                       VK_SYSTEM_ALLOC_TYPE_INTERNAL);
+   if (new_relocs == NULL)
+      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+   struct anv_bo **new_reloc_bos =
+      anv_device_alloc(device, new_length * sizeof(*list->reloc_bos), 8,
+                       VK_SYSTEM_ALLOC_TYPE_INTERNAL);
+   if (new_relocs == NULL) {
+      anv_device_free(device, new_relocs);
+      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+   }
+
+   memcpy(new_relocs, list->relocs, list->num_relocs * sizeof(*list->relocs));
+   memcpy(new_reloc_bos, list->reloc_bos,
+          list->num_relocs * sizeof(*list->reloc_bos));
+
+   anv_device_free(device, list->relocs);
+   anv_device_free(device, list->reloc_bos);
+
+   list->relocs = new_relocs;
+   list->reloc_bos = new_reloc_bos;
+
+   return VK_SUCCESS;
+}
+
 VkResult
 anv_batch_init(struct anv_batch *batch, struct anv_device *device)
 {
@@ -510,16 +579,23 @@ anv_batch_init(struct anv_batch *batch, struct anv_device *device)
    if (result != VK_SUCCESS)
       return result;
 
-   batch->cmd_relocs.num_relocs = 0;
+   result = anv_reloc_list_init(&batch->cmd_relocs, device);
+   if (result != VK_SUCCESS) {
+      anv_bo_pool_free(&device->batch_bo_pool, &batch->bo);
+      return result;
+   }
+
+   batch->device = device;
    batch->next = batch->bo.map;
 
    return VK_SUCCESS;
 }
 
 void
-anv_batch_finish(struct anv_batch *batch, struct anv_device *device)
+anv_batch_finish(struct anv_batch *batch)
 {
-   anv_bo_pool_free(&device->batch_bo_pool, &batch->bo);
+   anv_bo_pool_free(&batch->device->batch_bo_pool, &batch->bo);
+   anv_reloc_list_finish(&batch->cmd_relocs, batch->device);
 }
 
 void
@@ -540,31 +616,32 @@ anv_batch_emit_dwords(struct anv_batch *batch, int num_dwords)
 }
 
 static void
-anv_reloc_list_append(struct anv_reloc_list *list,
+anv_reloc_list_append(struct anv_reloc_list *list, struct anv_device *device,
                       struct anv_reloc_list *other, uint32_t offset)
 {
-   uint32_t i, count;
+   anv_reloc_list_grow(list, device, other->num_relocs);
+   /* TODO: Handle failure */
 
-   count = list->num_relocs;
-   memcpy(&list->relocs[count], &other->relocs[0],
+   memcpy(&list->relocs[list->num_relocs], &other->relocs[0],
           other->num_relocs * sizeof(other->relocs[0]));
-   memcpy(&list->reloc_bos[count], &other->reloc_bos[0],
+   memcpy(&list->reloc_bos[list->num_relocs], &other->reloc_bos[0],
           other->num_relocs * sizeof(other->reloc_bos[0]));
-   for (i = 0; i < other->num_relocs; i++)
-      list->relocs[i + count].offset += offset;
 
-   count += other->num_relocs;
+   for (uint32_t i = 0; i < other->num_relocs; i++)
+      list->relocs[i + list->num_relocs].offset += offset;
+
+   list->num_relocs += other->num_relocs;
 }
 
 static uint64_t
-anv_reloc_list_add(struct anv_reloc_list *list,
-                   uint32_t offset,
-                   struct anv_bo *target_bo, uint32_t delta)
+anv_reloc_list_add(struct anv_reloc_list *list, struct anv_device *device,
+                   uint32_t offset, struct anv_bo *target_bo, uint32_t delta)
 {
    struct drm_i915_gem_relocation_entry *entry;
    int index;
 
-   assert(list->num_relocs < ANV_BATCH_MAX_RELOCS);
+   anv_reloc_list_grow(list, device, 1);
+   /* TODO: Handle failure */
 
    /* XXX: Can we use I915_EXEC_HANDLE_LUT? */
    index = list->num_relocs++;
@@ -589,7 +666,8 @@ anv_batch_emit_batch(struct anv_batch *batch, struct anv_batch *other)
    memcpy(batch->next, other->bo.map, size);
 
    offset = batch->next - batch->bo.map;
-   anv_reloc_list_append(&batch->cmd_relocs, &other->cmd_relocs, offset);
+   anv_reloc_list_append(&batch->cmd_relocs, batch->device,
+                         &other->cmd_relocs, offset);
 
    batch->next += size;
 }
@@ -598,7 +676,7 @@ uint64_t
 anv_batch_emit_reloc(struct anv_batch *batch,
                      void *location, struct anv_bo *bo, uint32_t delta)
 {
-   return anv_reloc_list_add(&batch->cmd_relocs,
+   return anv_reloc_list_add(&batch->cmd_relocs, batch->device,
                              location - batch->bo.map, bo, delta);
 }
 
@@ -2147,10 +2225,11 @@ anv_cmd_buffer_destroy(struct anv_device *device,
 
    anv_gem_munmap(cmd_buffer->surface_bo.map, BATCH_SIZE);
    anv_gem_close(device, cmd_buffer->surface_bo.gem_handle);
+   anv_reloc_list_finish(&cmd_buffer->surface_relocs, device);
    anv_state_stream_finish(&cmd_buffer->surface_state_stream);
    anv_state_stream_finish(&cmd_buffer->dynamic_state_stream);
    anv_state_stream_finish(&cmd_buffer->binding_table_state_stream);
-   anv_batch_finish(&cmd_buffer->batch, device);
+   anv_batch_finish(&cmd_buffer->batch);
    anv_device_free(device, cmd_buffer->exec2_objects);
    anv_device_free(device, cmd_buffer->exec2_bos);
    anv_device_free(device, cmd_buffer);
@@ -2195,7 +2274,7 @@ VkResult anv_CreateCommandBuffer(
 
    /* Start surface_next at 1 so surface offset 0 is invalid. */
    cmd_buffer->surface_next = 1;
-   cmd_buffer->surface_relocs.num_relocs = 0;
+   anv_reloc_list_init(&cmd_buffer->surface_relocs, device);
 
    cmd_buffer->exec2_objects =
       anv_device_alloc(device, 8192 * sizeof(cmd_buffer->exec2_objects[0]), 8,
@@ -2235,7 +2314,7 @@ VkResult anv_CreateCommandBuffer(
  fail_surface_bo:
    anv_gem_close(device, cmd_buffer->surface_bo.gem_handle);
  fail_batch:
-   anv_batch_finish(&cmd_buffer->batch, device);
+   anv_batch_finish(&cmd_buffer->batch);
  fail:
    anv_device_free(device, cmd_buffer);
 
@@ -2546,6 +2625,7 @@ void anv_CmdBindDescriptorSets(
             /* The address goes in dwords 8 and 9 of the SURFACE_STATE */
             *(uint64_t *)(state.map + 8 * 4) =
                anv_reloc_list_add(&cmd_buffer->surface_relocs,
+                                  cmd_buffer->device,
                                   state.offset + 8 * 4,
                                   view->bo, view->offset);
 
@@ -3321,6 +3401,7 @@ anv_cmd_buffer_fill_render_targets(struct anv_cmd_buffer *cmd_buffer)
       /* The address goes in dwords 8 and 9 of the SURFACE_STATE */
       *(uint64_t *)(state.map + 8 * 4) =
          anv_reloc_list_add(&cmd_buffer->surface_relocs,
+                            cmd_buffer->device,
                             state.offset + 8 * 4,
                             view->bo, view->offset);
 
index e33b7e6c37637df598ed4bd8f703641fac3f86e5..c0606dabba7075fd543895656e2784dff170c9fb 100644 (file)
@@ -378,7 +378,7 @@ anv_pipeline_destroy(struct anv_device *device,
    assert(obj_type == VK_OBJECT_TYPE_PIPELINE);
 
    anv_compiler_free(pipeline);
-   anv_batch_finish(&pipeline->batch, pipeline->device);
+   anv_batch_finish(&pipeline->batch);
    anv_device_free(pipeline->device, pipeline);
 }
 
index 6e43258c90317a378851cf5d682054b0e4c81cdf..a77fb28449bdfc0fe11debd80a51037550715892 100644 (file)
@@ -389,23 +389,24 @@ int anv_gem_userptr(struct anv_device *device, void *mem, size_t size);
 
 VkResult anv_bo_init_new(struct anv_bo *bo, struct anv_device *device, uint64_t size);
 
-/* TODO: Remove hardcoded reloc limit. */
-#define ANV_BATCH_MAX_RELOCS 256
-
 struct anv_reloc_list {
    size_t                                       num_relocs;
-   struct drm_i915_gem_relocation_entry         relocs[ANV_BATCH_MAX_RELOCS];
-   struct anv_bo *                              reloc_bos[ANV_BATCH_MAX_RELOCS];
+   size_t                                       array_length;
+   struct drm_i915_gem_relocation_entry *       relocs;
+   struct anv_bo **                             reloc_bos;
 };
 
 struct anv_batch {
+   struct anv_device *                          device;
+
    struct anv_bo                                bo;
    void *                                       next;
+
    struct anv_reloc_list                        cmd_relocs;
 };
 
 VkResult anv_batch_init(struct anv_batch *batch, struct anv_device *device);
-void anv_batch_finish(struct anv_batch *batch, struct anv_device *device);
+void anv_batch_finish(struct anv_batch *batch);
 void anv_batch_reset(struct anv_batch *batch);
 void *anv_batch_emit_dwords(struct anv_batch *batch, int num_dwords);
 void anv_batch_emit_batch(struct anv_batch *batch, struct anv_batch *other);