[Mesa-dev] [PATCH 5/6] i965: Expose AMD_pinned_memory

Chris Wilson chris at chris-wilson.co.uk
Fri Oct 13 09:34:55 UTC 2017


All GEN GPU can bind to any piece of memory (thanks UMA), and so through
a special ioctl we can map a chunk of page-aligned client memory into
the GPU address space. However, not all GEN are equal. Some have
cache-coherency between the CPU and the GPU, whilst the others are
incoherent and rely on snooping on explicit flushes to push/pull dirty
data. Whereas we can use client buffers as a general replacement for kernel
allocated buffers with LLC (cache coherency), using snooped buffers
behaves differently and so must be used with care.

AMD_pinned_memory supposes that the client memory buffer is suitable
for any general usage (e.g. vertex data, texture data) and so only on
LLC can we offer that extension.
---
 src/mesa/drivers/dri/i965/intel_buffer_objects.c | 55 ++++++++++++++++--------
 src/mesa/drivers/dri/i965/intel_extensions.c     | 11 +++++
 2 files changed, 49 insertions(+), 17 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/intel_buffer_objects.c b/src/mesa/drivers/dri/i965/intel_buffer_objects.c
index 49e68bd739..425c5e1372 100644
--- a/src/mesa/drivers/dri/i965/intel_buffer_objects.c
+++ b/src/mesa/drivers/dri/i965/intel_buffer_objects.c
@@ -72,6 +72,23 @@ mark_buffer_invalid(struct intel_buffer_object *intel_obj)
    intel_obj->valid_data_end = 0;
 }
 
+/** Allocates a new brw_bo to store the data for the buffer object. */
+static void
+mark_new_state(struct brw_context *brw,
+               struct intel_buffer_object *intel_obj)
+{
+   /* the buffer might be bound as a uniform buffer, need to update it
+    */
+   if (intel_obj->Base.UsageHistory & USAGE_UNIFORM_BUFFER)
+      brw->ctx.NewDriverState |= BRW_NEW_UNIFORM_BUFFER;
+   if (intel_obj->Base.UsageHistory & USAGE_SHADER_STORAGE_BUFFER)
+      brw->ctx.NewDriverState |= BRW_NEW_UNIFORM_BUFFER;
+   if (intel_obj->Base.UsageHistory & USAGE_TEXTURE_BUFFER)
+      brw->ctx.NewDriverState |= BRW_NEW_TEXTURE_BUFFER;
+   if (intel_obj->Base.UsageHistory & USAGE_ATOMIC_COUNTER_BUFFER)
+      brw->ctx.NewDriverState |= BRW_NEW_ATOMIC_BUFFER;
+}
+
 /** Allocates a new brw_bo to store the data for the buffer object. */
 static void
 alloc_buffer_object(struct brw_context *brw,
@@ -98,17 +115,7 @@ alloc_buffer_object(struct brw_context *brw,
    }
    intel_obj->buffer = brw_bo_alloc(brw->bufmgr, "bufferobj", size, 64);
 
-   /* the buffer might be bound as a uniform buffer, need to update it
-    */
-   if (intel_obj->Base.UsageHistory & USAGE_UNIFORM_BUFFER)
-      brw->ctx.NewDriverState |= BRW_NEW_UNIFORM_BUFFER;
-   if (intel_obj->Base.UsageHistory & USAGE_SHADER_STORAGE_BUFFER)
-      brw->ctx.NewDriverState |= BRW_NEW_UNIFORM_BUFFER;
-   if (intel_obj->Base.UsageHistory & USAGE_TEXTURE_BUFFER)
-      brw->ctx.NewDriverState |= BRW_NEW_TEXTURE_BUFFER;
-   if (intel_obj->Base.UsageHistory & USAGE_ATOMIC_COUNTER_BUFFER)
-      brw->ctx.NewDriverState |= BRW_NEW_ATOMIC_BUFFER;
-
+   mark_new_state(brw, intel_obj);
    mark_buffer_inactive(intel_obj);
    mark_buffer_invalid(intel_obj);
 }
@@ -206,13 +213,27 @@ brw_buffer_data(struct gl_context *ctx,
       release_buffer(intel_obj);
 
    if (size != 0) {
-      alloc_buffer_object(brw, intel_obj);
-      if (!intel_obj->buffer)
-         return false;
-
-      if (data != NULL) {
-         brw_bo_subdata(intel_obj->buffer, 0, size, data);
+      if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {
+         intel_obj->buffer =
+            brw_bo_alloc_userptr(brw->bufmgr, "bufferobj(userptr)",
+                                 (void *)data, size, 0);
+         if (!intel_obj->buffer)
+            return false;
+
+         mark_new_state(brw, intel_obj);
+         mark_buffer_inactive(intel_obj);
          mark_buffer_valid_data(intel_obj, 0, size);
+      } else {
+         alloc_buffer_object(brw, intel_obj);
+         if (!intel_obj->buffer)
+            return false;
+
+         if (data != NULL) {
+            brw_bo_subdata(intel_obj->buffer, 0, size, data);
+            mark_new_state(brw, intel_obj);
+            mark_buffer_inactive(intel_obj);
+            mark_buffer_valid_data(intel_obj, 0, size);
+         }
       }
    }
 
diff --git a/src/mesa/drivers/dri/i965/intel_extensions.c b/src/mesa/drivers/dri/i965/intel_extensions.c
index 519d0a56cb..844a2290f4 100644
--- a/src/mesa/drivers/dri/i965/intel_extensions.c
+++ b/src/mesa/drivers/dri/i965/intel_extensions.c
@@ -196,6 +196,17 @@ intelInitExtensions(struct gl_context *ctx)
 
       ctx->Extensions.ARB_timer_query = brw->screen->hw_has_timestamp;
 
+      /* AMD_pinned_memory assumes the flexibility of using client memory
+       * for any buffer (incl. vertex buffers) which rules out the prospect
+       * of using snooped buffers, as using snooped buffers without
+       * cogniscience is likely to be detrimental to performance and require
+       * extensive checking in the driver for correctness, e.g. to prevent
+       * illegal snoop <-> snoop transfers.
+       */
+      ctx->Extensions.AMD_pinned_memory =
+         brw->screen->kernel_features & KERNEL_ALLOWS_USERPTR &&
+         brw->screen->devinfo.has_llc;
+
       /* Only enable this in core profile because other parts of Mesa behave
        * slightly differently when the extension is enabled.
        */
-- 
2.15.0.rc0



More information about the mesa-dev mailing list