mesa: implement sparse buffer commitment
authorNicolai Hähnle <nicolai.haehnle@amd.com>
Thu, 2 Feb 2017 22:24:35 +0000 (23:24 +0100)
committerNicolai Hähnle <nicolai.haehnle@amd.com>
Wed, 5 Apr 2017 08:31:02 +0000 (10:31 +0200)
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
src/mesa/main/bufferobj.c
src/mesa/main/dd.h

index a4ccf8c..27eaf77 100644 (file)
@@ -4061,14 +4061,80 @@ _mesa_InvalidateBufferData(GLuint buffer)
       ctx->Driver.InvalidateBufferSubData(ctx, bufObj, 0, bufObj->Size);
 }
 
+static void
+buffer_page_commitment(struct gl_context *ctx,
+                       struct gl_buffer_object *bufferObj,
+                       GLintptr offset, GLsizeiptr size,
+                       GLboolean commit, const char *func)
+{
+   if (!(bufferObj->StorageFlags & GL_SPARSE_STORAGE_BIT_ARB)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(not a sparse buffer object)",
+                  func);
+      return;
+   }
+
+   if (size < 0 || size > bufferObj->Size ||
+       offset < 0 || offset > bufferObj->Size - size) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "%s(out of bounds)",
+                  func);
+      return;
+   }
+
+   /* The GL_ARB_sparse_buffer extension specification says:
+    *
+    *     "INVALID_VALUE is generated by BufferPageCommitmentARB if <offset> is
+    *     not an integer multiple of SPARSE_BUFFER_PAGE_SIZE_ARB, or if <size>
+    *     is not an integer multiple of SPARSE_BUFFER_PAGE_SIZE_ARB and does
+    *     not extend to the end of the buffer's data store."
+    */
+   if (offset % ctx->Const.SparseBufferPageSize != 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset not aligned to page size)",
+                  func);
+      return;
+   }
+
+   if (size % ctx->Const.SparseBufferPageSize != 0 &&
+       offset + size != bufferObj->Size) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "%s(size not aligned to page size)",
+                  func);
+      return;
+   }
+
+   ctx->Driver.BufferPageCommitment(ctx, bufferObj, offset, size, commit);
+}
+
 void GLAPIENTRY
 _mesa_BufferPageCommitmentARB(GLenum target, GLintptr offset, GLsizeiptr size,
                               GLboolean commit)
 {
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_buffer_object *bufferObj;
+
+   bufferObj = get_buffer(ctx, "glBufferPageCommitmentARB", target,
+                          GL_INVALID_ENUM);
+   if (!bufferObj)
+      return;
+
+   buffer_page_commitment(ctx, bufferObj, offset, size, commit,
+                          "glBufferPageCommitmentARB");
 }
 
 void GLAPIENTRY
 _mesa_NamedBufferPageCommitmentARB(GLuint buffer, GLintptr offset,
                                    GLsizeiptr size, GLboolean commit)
 {
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_buffer_object *bufferObj;
+
+   bufferObj = _mesa_lookup_bufferobj(ctx, buffer);
+   if (!bufferObj || bufferObj == &DummyBufferObject) {
+      /* Note: the extension spec is not clear about the excpected error value. */
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glNamedBufferPageCommitmentARB(name = %u) invalid object",
+                  buffer);
+      return;
+   }
+
+   buffer_page_commitment(ctx, bufferObj, offset, size, commit,
+                          "glNamedBufferPageCommitmentARB");
 }
index b3a85f1..3f31025 100644 (file)
@@ -1040,6 +1040,16 @@ struct dd_function_table {
     * Mesa will only call this function if GL multithreading is enabled.
     */
    void (*SetBackgroundContext)(struct gl_context *ctx);
+
+   /**
+    * \name GL_ARB_sparse_buffer interface
+    */
+   /*@{*/
+   void (*BufferPageCommitment)(struct gl_context *ctx,
+                                struct gl_buffer_object *bufferObj,
+                                GLintptr offset, GLsizeiptr size,
+                                GLboolean commit);
+   /*@}*/
 };