<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, May 2, 2018 at 9:01 AM, Scott D Phillips <span dir="ltr"><<a href="mailto:scott.d.phillips@intel.com" target="_blank">scott.d.phillips@intel.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Soft pinning lets us satisfy the binding table address<br>
requirements without using both sides of a growing state_pool.<br>
<br>
If you do use both sides of a state pool, then you need to read<br>
the state pool's center_bo_offset (with the device mutex held) to<br>
know the final offset of relocations that target the state pool<br>
bo.<br>
<br>
By having a separate pool for binding tables that only grows in<br>
the forward direction, the center_bo_offset is always 0 and<br>
relocations don't need an update pass to adjust relocations with<br>
the mutex held.<br>
---<br>
 src/intel/vulkan/anv_batch_<wbr>chain.c | 23 +++++++++++++++--------<br>
 src/intel/vulkan/anv_device.c      | 28 +++++++++++++++++++++++++++-<br>
 src/intel/vulkan/anv_private.h     | 36 ++++++++++++++++++++++++++++++<wbr>++++++<br>
 3 files changed, 78 insertions(+), 9 deletions(-)<br>
<br>
diff --git a/src/intel/vulkan/anv_batch_<wbr>chain.c b/src/intel/vulkan/anv_batch_<wbr>chain.c<br>
index 09514c7b84a..52f69045519 100644<br>
--- a/src/intel/vulkan/anv_batch_<wbr>chain.c<br>
+++ b/src/intel/vulkan/anv_batch_<wbr>chain.c<br>
@@ -452,7 +452,7 @@ anv_cmd_buffer_surface_base_<wbr>address(struct anv_cmd_buffer *cmd_buffer)<br>
 {<br>
    struct anv_state *bt_block = u_vector_head(&cmd_buffer->bt_<wbr>block_states);<br>
    return (struct anv_address) {<br>
-      .bo = &cmd_buffer->device-><a href="http://surface_state_pool.block_pool.bo" rel="noreferrer" target="_blank">surface_<wbr>state_pool.block_pool.bo</a>,<br>
+      .bo = anv_binding_table_pool_bo(cmd_<wbr>buffer->device),<br>
       .offset = bt_block->offset,<br>
    };<br>
 }<br>
@@ -619,7 +619,8 @@ struct anv_state<br>
 anv_cmd_buffer_alloc_binding_<wbr>table(struct anv_cmd_buffer *cmd_buffer,<br>
                                    uint32_t entries, uint32_t *state_offset)<br>
 {<br>
-   struct anv_state_pool *state_pool = &cmd_buffer->device->surface_<wbr>state_pool;<br>
+   struct anv_device *device = cmd_buffer->device;<br>
+   struct anv_state_pool *state_pool = &device->surface_state_pool;<br>
    struct anv_state *bt_block = u_vector_head(&cmd_buffer->bt_<wbr>block_states);<br>
    struct anv_state state;<br>
<br>
@@ -629,12 +630,18 @@ anv_cmd_buffer_alloc_binding_<wbr>table(struct anv_cmd_buffer *cmd_buffer,<br>
       return (struct anv_state) { 0 };<br>
<br>
    state.offset = cmd_buffer->bt_next;<br>
-   state.map = state_pool->block_pool.map + bt_block->offset + state.offset;<br>
+   state.map = anv_binding_table_pool_map(<wbr>device) + bt_block->offset +<br>
+      state.offset;<br>
<br>
    cmd_buffer->bt_next += state.alloc_size;<br>
<br>
-   assert(bt_block->offset < 0);<br>
-   *state_offset = -bt_block->offset;<br>
+   if (device->use_separate_binding_<wbr>table_pool) {<br>
+      *state_offset = device->surface_state_pool.<wbr>block_pool.offset -<br>
+         device->binding_table_pool.<wbr>block_pool.offset - bt_block->offset;<br>
+   } else {<br>
+      assert(bt_block->offset < 0);<br>
+      *state_offset = -bt_block->offset;<br>
+   }<br>
<br>
    return state;<br>
 }<br>
@@ -666,7 +673,7 @@ anv_cmd_buffer_new_binding_<wbr>table_block(struct anv_cmd_buffer *cmd_buffer)<br>
       return vk_error(VK_ERROR_OUT_OF_HOST_<wbr>MEMORY);<br>
    }<br>
<br>
-   *bt_block = anv_state_pool_alloc_back(<wbr>state_pool);<br>
+   *bt_block = anv_binding_table_pool_alloc(<wbr>cmd_buffer->device);<br>
    cmd_buffer->bt_next = 0;<br>
<br>
    return VK_SUCCESS;<br>
@@ -740,7 +747,7 @@ anv_cmd_buffer_fini_batch_bo_<wbr>chain(struct anv_cmd_buffer *cmd_buffer)<br>
 {<br>
    struct anv_state *bt_block;<br>
    u_vector_foreach(bt_block, &cmd_buffer->bt_block_states)<br>
-      anv_state_pool_free(&cmd_<wbr>buffer->device->surface_state_<wbr>pool, *bt_block);<br>
+      anv_binding_table_pool_free(<wbr>cmd_buffer->device, *bt_block);<br>
    u_vector_finish(&cmd_buffer-><wbr>bt_block_states);<br>
<br>
    anv_reloc_list_finish(&cmd_<wbr>buffer->surface_relocs, &cmd_buffer->pool->alloc);<br>
@@ -772,7 +779,7 @@ anv_cmd_buffer_reset_batch_bo_<wbr>chain(struct anv_cmd_buffer *cmd_buffer)<br>
<br>
    while (u_vector_length(&cmd_buffer-><wbr>bt_block_states) > 1) {<br>
       struct anv_state *bt_block = u_vector_remove(&cmd_buffer-><wbr>bt_block_states);<br>
-      anv_state_pool_free(&cmd_<wbr>buffer->device->surface_state_<wbr>pool, *bt_block);<br>
+      anv_binding_table_pool_free(<wbr>cmd_buffer->device, *bt_block);<br>
    }<br>
    assert(u_vector_length(&cmd_<wbr>buffer->bt_block_states) == 1);<br>
    cmd_buffer->bt_next = 0;<br>
diff --git a/src/intel/vulkan/anv_device.<wbr>c b/src/intel/vulkan/anv_device.<wbr>c<br>
index 2837d2f83ca..d1f57081b77 100644<br>
--- a/src/intel/vulkan/anv_device.<wbr>c<br>
+++ b/src/intel/vulkan/anv_device.<wbr>c<br>
@@ -1637,9 +1637,32 @@ VkResult anv_CreateDevice(<br>
    if (result != VK_SUCCESS)<br>
       goto fail_instruction_state_pool;<br>
<br>
+   device->use_separate_binding_<wbr>table_pool = physical_device->has_exec_<wbr>softpin;<br>
+<br>
+   if (device->use_separate_binding_<wbr>table_pool) {<br>
+      result = anv_state_pool_init(&device-><wbr>binding_table_pool, device, 4096,<br>
+                                   bo_flags);<br>
+      if (result != VK_SUCCESS)<br>
+         goto fail_surface_state_pool;<br>
+<br>
+      if (device->surface_state_pool.<wbr>block_pool.offset <<br>
+          device->binding_table_pool.<wbr>block_pool.offset) {<br>
+<br>
+         uint64_t tmp;<br>
+         tmp = device->surface_state_pool.<wbr>block_pool.offset;<br>
+         device->surface_state_pool.<wbr>block_pool.offset =<br>
+            device->binding_table_pool.<wbr>block_pool.offset;<br>
+         device->binding_table_pool.<wbr>block_pool.offset = tmp;<br>
+         tmp = device->surface_state_pool.<wbr>block_pool.bo.offset;<br>
+         device->surface_state_pool.<wbr>block_pool.bo.offset =<br>
+            device->binding_table_pool.<wbr>block_pool.bo.offset;<br>
+         device->binding_table_pool.<wbr>block_pool.bo.offset = tmp;<br></blockquote><div><br></div><div>If we hard-code the memory layout, this should go away, I think.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      }<br>
+   }<br>
+<br>
    result = anv_bo_init_new(&device-><wbr>workaround_bo, device, 1024);<br>
    if (result != VK_SUCCESS)<br>
-      goto fail_surface_state_pool;<br>
+      goto fail_binding_table_pool;<br>
<br>
    anv_device_init_trivial_batch(<wbr>device);<br>
<br>
@@ -1690,6 +1713,9 @@ VkResult anv_CreateDevice(<br>
    anv_scratch_pool_finish(<wbr>device, &device->scratch_pool);<br>
    anv_gem_munmap(device-><wbr>workaround_bo.map, device->workaround_bo.size);<br>
    anv_gem_close(device, device->workaround_bo.gem_<wbr>handle);<br>
+ fail_binding_table_pool:<br>
+   if (device->use_separate_binding_<wbr>table_pool)<br>
+      anv_state_pool_finish(&device-<wbr>>binding_table_pool);<br>
  fail_surface_state_pool:<br>
    anv_state_pool_finish(&device-<wbr>>surface_state_pool);<br>
  fail_instruction_state_pool:<br>
diff --git a/src/intel/vulkan/anv_<wbr>private.h b/src/intel/vulkan/anv_<wbr>private.h<br>
index 23527eebaab..81d50b3e770 100644<br>
--- a/src/intel/vulkan/anv_<wbr>private.h<br>
+++ b/src/intel/vulkan/anv_<wbr>private.h<br>
@@ -916,6 +916,9 @@ struct anv_device {<br>
     struct anv_state_pool                       instruction_state_pool;<br>
     struct anv_state_pool                       surface_state_pool;<br>
<br>
+    bool                                        use_separate_binding_table_<wbr>pool;<br></blockquote><div><br></div><div>Do we need a separate bool?  I suspect not.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+    struct anv_state_pool                       binding_table_pool;<br>
+<br>
     struct anv_bo                               workaround_bo;<br>
     struct anv_bo                               trivial_batch_bo;<br>
     struct anv_bo                               hiz_clear_bo;<br>
@@ -936,6 +939,39 @@ struct anv_device {<br>
     bool                                        lost;<br>
 };<br>
<br>
+static inline struct anv_bo*<br>
+anv_binding_table_pool_bo(<wbr>struct anv_device *device) {<br>
+   if (device->use_separate_binding_<wbr>table_pool)<br>
+      return &device-><a href="http://binding_table_pool.block_pool.bo" rel="noreferrer" target="_blank">binding_table_pool.<wbr>block_pool.bo</a>;<br>
+   else<br>
+      return &device-><a href="http://surface_state_pool.block_pool.bo" rel="noreferrer" target="_blank">surface_state_pool.<wbr>block_pool.bo</a>;<br>
+}<br>
+<br>
+static inline void*<br>
+anv_binding_table_pool_map(<wbr>struct anv_device *device) {<br>
+   if (device->use_separate_binding_<wbr>table_pool)<br>
+      return device->binding_table_pool.<wbr>block_pool.map;<br>
+   else<br>
+      return device->surface_state_pool.<wbr>block_pool.map;<br>
+}<br>
+<br>
+static inline struct anv_state<br>
+anv_binding_table_pool_alloc(<wbr>struct anv_device *device) {<br>
+   if (device->use_separate_binding_<wbr>table_pool)<br>
+      return anv_state_pool_alloc(&device-><wbr>binding_table_pool,<br>
+                                  device->binding_table_pool.<wbr>block_size, 0);<br>
+   else<br>
+      return anv_state_pool_alloc_back(&<wbr>device->surface_state_pool);<br>
+}<br>
+<br>
+static inline void<br>
+anv_binding_table_pool_free(<wbr>struct anv_device *device, struct anv_state state) {<br>
+   if (device->use_separate_binding_<wbr>table_pool)<br>
+      anv_state_pool_free(&device-><wbr>binding_table_pool, state);<br>
+   else<br>
+      anv_state_pool_free(&device-><wbr>surface_state_pool, state);<br>
+}<br></blockquote><div><br></div><div>Three of these four would be a lot simpler if we had a fifth <br><br></div><div>static inline anv_state_pool *<br></div><div>anv_binding_table_pool(struct anv_device *device)<br>{<br>
   if (device->use_separate_binding_<wbr>table_pool)<br>      return &device->binding_table_pool;<br>
   else<br>
      return &device->surface_state_pool;<br>}<br><br></div><div>For that matter, the first two might not be needed at all.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
 static void inline<br>
 anv_state_flush(struct anv_device *device, struct anv_state state)<br>
 {<br>
<span class="HOEnZb"><font color="#888888">-- <br>
2.14.3<br>
<br>
</font></span></blockquote></div><br></div></div>