mesa: implement GL_AMD_pinned_memory
authorMarek Olšák <marek.olsak@amd.com>
Tue, 10 Feb 2015 00:39:41 +0000 (01:39 +0100)
committerMarek Olšák <marek.olsak@amd.com>
Tue, 17 Feb 2015 16:31:48 +0000 (17:31 +0100)
It's not possible to query the current buffer binding, because the extension
doesn't define GL_..._BUFFER__BINDING_AMD.

Drivers should check the target parameter of Drivers.BufferData. If it's
equal to GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, the memory should be pinned.
That's all there is to it.

A piglit test is on the piglit mailing list.

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
src/mapi/glapi/gen/gl_API.xml
src/mesa/main/bufferobj.c
src/mesa/main/extensions.c
src/mesa/main/mtypes.h

index 17bf62a10facdb7694c95365c8266df124e7afb0..cc8aaf34e8a28d119202f3ec723f574c1b8dc4a4 100644 (file)
     <enum name="SKIP_DECODE_EXT"                      value="0x8A4A"/>
 </category>
 
+<category name="GL_AMD_pinned_memory" number="411">
+    <enum name="EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD"   value="0x9160"/>
+</category>
+
 <xi:include href="INTEL_performance_query.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
 
 <category name="GL_EXT_polygon_offset_clamp" number="460">
index 0c23b429e5b44c972f77b4e1a67ba512b4a62571..b372c68f21cfb69fafac94ac1f6f53cf045ef8f9 100644 (file)
@@ -117,6 +117,11 @@ get_buffer_target(struct gl_context *ctx, GLenum target)
          return &ctx->AtomicBuffer;
       }
       break;
+   case GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD:
+      if (ctx->Extensions.AMD_pinned_memory) {
+         return &ctx->ExternalVirtualMemoryBuffer;
+      }
+      break;
    default:
       return NULL;
    }
@@ -1242,6 +1247,10 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids)
             _mesa_BindBuffer( GL_TEXTURE_BUFFER, 0 );
          }
 
+         if (ctx->ExternalVirtualMemoryBuffer == bufObj) {
+            _mesa_BindBuffer(GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, 0);
+         }
+
          /* The ID is immediately freed for re-use */
          _mesa_HashRemove(ctx->Shared->BufferObjects, ids[i]);
          /* Make sure we do not run into the classic ABA problem on bind.
@@ -1381,7 +1390,16 @@ _mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data,
    ASSERT(ctx->Driver.BufferData);
    if (!ctx->Driver.BufferData(ctx, target, size, data, GL_DYNAMIC_DRAW,
                                flags, bufObj)) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferStorage()");
+      if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {
+         /* Even though the interaction between AMD_pinned_memory and
+          * glBufferStorage is not described in the spec, Graham Sellers
+          * said that it should behave the same as glBufferData.
+          */
+         _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferStorage()");
+      }
+      else {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferStorage()");
+      }
    }
 }
 
@@ -1465,7 +1483,18 @@ _mesa_BufferData(GLenum target, GLsizeiptrARB size,
                                GL_MAP_WRITE_BIT |
                                GL_DYNAMIC_STORAGE_BIT,
                                bufObj)) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferDataARB()");
+      if (target == GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD) {
+         /* From GL_AMD_pinned_memory:
+          *
+          *   INVALID_OPERATION is generated by BufferData if <target> is
+          *   EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD, and the store cannot be
+          *   mapped to the GPU address space.
+          */
+         _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferData()");
+      }
+      else {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBufferData()");
+      }
    }
 }
 
index 220b220d668758c48f163b97ad03d0789db1bfa4..685236a9194ff85e515016e02566c97e2f79c0a3 100644 (file)
@@ -335,6 +335,7 @@ static const struct extension extension_table[] = {
    { "GL_AMD_conservative_depth",                  o(ARB_conservative_depth),                  GL,             2009 },
    { "GL_AMD_draw_buffers_blend",                  o(ARB_draw_buffers_blend),                  GL,             2009 },
    { "GL_AMD_performance_monitor",                 o(AMD_performance_monitor),                 GL,             2007 },
+   { "GL_AMD_pinned_memory",                       o(AMD_pinned_memory),                       GL,             2013 },
    { "GL_AMD_seamless_cubemap_per_texture",        o(AMD_seamless_cubemap_per_texture),        GL,             2009 },
    { "GL_AMD_shader_stencil_export",               o(ARB_shader_stencil_export),               GL,             2009 },
    { "GL_AMD_shader_trinary_minmax",               o(dummy_true),                              GL,             2012 },
index 1c33ef4605b44ff6aa2c9546d8d079e3bc3fdf08..08133f1afe0b544c6acea2770a7aa8c63f15578c 100644 (file)
@@ -3837,6 +3837,7 @@ struct gl_extensions
    GLboolean OES_standard_derivatives;
    /* vendor extensions */
    GLboolean AMD_performance_monitor;
+   GLboolean AMD_pinned_memory;
    GLboolean AMD_seamless_cubemap_per_texture;
    GLboolean AMD_vertex_shader_layer;
    GLboolean AMD_vertex_shader_viewport_index;
@@ -4377,6 +4378,12 @@ struct gl_context
     */
    struct gl_buffer_object *AtomicBuffer;
 
+   /**
+    * Object currently associated w/ the GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD
+    * target.
+    */
+   struct gl_buffer_object *ExternalVirtualMemoryBuffer;
+
    /**
     * Array of atomic counter buffer binding points.
     */