<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Fri, May 5, 2017 at 5:09 AM, Chris Wilson <span dir="ltr"><<a href="mailto:chris@chris-wilson.co.uk" target="_blank">chris@chris-wilson.co.uk</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">It is a requirement, not just of using the NO_RELOC mode, that all<br>
relocation values in the execobjects match their reloc.presumed_offset,<br>
as the kernel will skip performing *any* relocation if the presumed_offset<br>
matches the target object. As anv is setting unknown relocations to -1<br>
irrespective of the actual value, if the kernel placed the target at -1<br>
(i.e. 0xfffffffff000 for 48bit GTT), it would happily skip the relocation.<br>
To prevent this, we need to always do the userspace relocations to ensure<br>
the values match. To improve further, set the unknown object offset to 0<br>
(a valid location) on the offchance it is available and the migration<br>
skipped.<br></blockquote><div><br></div><div>Is this a real issue?  I specifically chose -1 because it *wasn't* page-aligned.  I don't think the kernel whacks off the bottom 12 bits before doing the comparison to determine whether or not the relocation needs to happen.<br><br></div><div>--Jason<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Signed-off-by: Chris Wilson <<a href="mailto:chris@chris-wilson.co.uk">chris@chris-wilson.co.uk</a>><br>
Cc: Jason Ekstrand <<a href="mailto:jason.ekstrand@intel.com">jason.ekstrand@intel.com</a>><br>
---<br>
 src/intel/vulkan/anv_batch_<wbr>chain.c | 97 ++++++++++++------------------<wbr>--------<br>
 src/intel/vulkan/anv_private.h     |  2 +-<br>
 2 files changed, 32 insertions(+), 67 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 0529f22b84..46c4ce6efb 100644<br>
--- a/src/intel/vulkan/anv_batch_<wbr>chain.c<br>
+++ b/src/intel/vulkan/anv_batch_<wbr>chain.c<br>
@@ -1205,28 +1205,10 @@ anv_reloc_list_apply(struct anv_device *device,<br>
  * probably the fastest mechanism for doing relocations since the kernel would<br>
  * have to make a full copy of all the relocations lists.<br>
  */<br>
-static bool<br>
+static void<br>
 relocate_cmd_buffer(struct anv_cmd_buffer *cmd_buffer,<br>
                     struct anv_execbuf *exec)<br>
 {<br>
-   static int userspace_relocs = -1;<br>
-   if (userspace_relocs < 0)<br>
-      userspace_relocs = env_var_as_boolean("ANV_<wbr>USERSPACE_RELOCS", true);<br>
-   if (!userspace_relocs)<br>
-      return false;<br>
-<br>
-   /* First, we have to check to see whether or not we can even do the<br>
-    * relocation.  New buffers which have never been submitted to the kernel<br>
-    * don't have a valid offset so we need to let the kernel do relocations so<br>
-    * that we can get offsets for them.  On future execbuf2 calls, those<br>
-    * buffers will have offsets and we will be able to skip relocating.<br>
-    * Invalid offsets are indicated by anv_bo::offset == (uint64_t)-1.<br>
-    */<br>
-   for (uint32_t i = 0; i < exec->bo_count; i++) {<br>
-      if (exec->bos[i]->offset == (uint64_t)-1)<br>
-         return false;<br>
-   }<br>
-<br>
    /* Since surface states are shared between command buffers and we don't<br>
     * know what order they will be submitted to the kernel, we don't know<br>
     * what address is actually written in the surface state object at any<br>
@@ -1248,8 +1230,6 @@ relocate_cmd_buffer(struct anv_cmd_buffer *cmd_buffer,<br>
<br>
    for (uint32_t i = 0; i < exec->bo_count; i++)<br>
       exec->objects[i].offset = exec->bos[i]->offset;<br>
-<br>
-   return true;<br>
 }<br>
<br>
 static VkResult<br>
@@ -1334,55 +1314,40 @@ setup_execbuf_for_cmd_buffer(<wbr>struct anv_execbuf *execbuf,<br>
       .buffer_count = execbuf->bo_count,<br>
       .batch_start_offset = 0,<br>
       .batch_len = batch->next - batch->start,<br>
-      .cliprects_ptr = 0,<br>
-      .num_cliprects = 0,<br>
-      .DR1 = 0,<br>
-      .DR4 = 0,<br>
-      .flags = I915_EXEC_HANDLE_LUT | I915_EXEC_RENDER |<br>
-               I915_EXEC_CONSTANTS_REL_<wbr>GENERAL,<br>
+      .flags =<br>
+             I915_EXEC_RENDER |<br>
+             I915_EXEC_HANDLE_LUT |<br>
+             I915_EXEC_NO_RELOC |<br>
+             I915_EXEC_CONSTANTS_REL_<wbr>GENERAL,<br>
       .rsvd1 = cmd_buffer->device->context_<wbr>id,<br>
       .rsvd2 = 0,<br>
    };<br>
<br>
-   if (relocate_cmd_buffer(cmd_<wbr>buffer, execbuf)) {<br>
-      /* If we were able to successfully relocate everything, tell the kernel<br>
-       * that it can skip doing relocations. The requirement for using<br>
-       * NO_RELOC is:<br>
-       *<br>
-       *  1) The addresses written in the objects must match the corresponding<br>
-       *     reloc.presumed_offset which in turn must match the corresponding<br>
-       *     execobject.offset.<br>
-       *<br>
-       *  2) To avoid stalling, execobject.offset should match the current<br>
-       *     address of that object within the active context.<br>
-       *<br>
-       * In order to satisfy all of the invariants that make userspace<br>
-       * relocations to be safe (see relocate_cmd_buffer()), we need to<br>
-       * further ensure that the addresses we use match those used by the<br>
-       * kernel for the most recent execbuf2.<br>
-       *<br>
-       * The kernel may still choose to do relocations anyway if something has<br>
-       * moved in the GTT. In this case, the relocation list still needs to be<br>
-       * valid.  All relocations on the batch buffers are already valid and<br>
-       * kept up-to-date.  For surface state relocations, by applying the<br>
-       * relocations in relocate_cmd_buffer, we ensured that the address in<br>
-       * the RENDER_SURFACE_STATE matches presumed_offset, so it should be<br>
-       * safe for the kernel to relocate them as needed.<br>
-       */<br>
-      execbuf->execbuf.flags |= I915_EXEC_NO_RELOC;<br>
-   } else {<br>
-      /* In the case where we fall back to doing kernel relocations, we need<br>
-       * to ensure that the relocation list is valid.  All relocations on the<br>
-       * batch buffers are already valid and kept up-to-date.  Since surface<br>
-       * states are shared between command buffers and we don't know what<br>
-       * order they will be submitted to the kernel, we don't know what<br>
-       * address is actually written in the surface state object at any given<br>
-       * time.  The only option is to set a bogus presumed offset and let the<br>
-       * kernel relocate them.<br>
-       */<br>
-      for (size_t i = 0; i < cmd_buffer->surface_relocs.<wbr>num_relocs; i++)<br>
-         cmd_buffer->surface_relocs.<wbr>relocs[i].presumed_offset = -1;<br>
-   }<br>
+   /* If we were able to successfully relocate everything, tell the kernel<br>
+    * that it can skip doing relocations. The requirement for using<br>
+    * NO_RELOC is:<br>
+    *<br>
+    *  1) The addresses written in the objects must match the corresponding<br>
+    *     reloc.presumed_offset which in turn must match the corresponding<br>
+    *     execobject.offset.<br>
+    *<br>
+    *  2) To avoid stalling, execobject.offset should match the current<br>
+    *     address of that object within the active context.<br>
+    *<br>
+    * In order to satisfy all of the invariants that make userspace<br>
+    * relocations to be safe (see relocate_cmd_buffer()), we need to<br>
+    * further ensure that the addresses we use match those used by the<br>
+    * kernel for the most recent execbuf2.<br>
+    *<br>
+    * The kernel may still choose to do relocations anyway if something has<br>
+    * moved in the GTT. In this case, the relocation list still needs to be<br>
+    * valid.  All relocations on the batch buffers are already valid and<br>
+    * kept up-to-date.  For surface state relocations, by applying the<br>
+    * relocations in relocate_cmd_buffer, we ensured that the address in<br>
+    * the RENDER_SURFACE_STATE matches presumed_offset, so it should be<br>
+    * safe for the kernel to relocate them as needed.<br>
+    */<br>
+   relocate_cmd_buffer(cmd_<wbr>buffer, execbuf);<br>
<br>
    return VK_SUCCESS;<br>
 }<br>
diff --git a/src/intel/vulkan/anv_<wbr>private.h b/src/intel/vulkan/anv_<wbr>private.h<br>
index 21d0ac2122..f9381fb8eb 100644<br>
--- a/src/intel/vulkan/anv_<wbr>private.h<br>
+++ b/src/intel/vulkan/anv_<wbr>private.h<br>
@@ -400,7 +400,7 @@ anv_bo_init(struct anv_bo *bo, uint32_t gem_handle, uint64_t size)<br>
 {<br>
    bo->gem_handle = gem_handle;<br>
    bo->index = 0;<br>
-   bo->offset = -1;<br>
+   bo->offset = 0;<br>
    bo->size = size;<br>
    bo->map = NULL;<br>
    bo->flags = 0;<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.11.0<br>
<br>
______________________________<wbr>_________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div></div>