<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>