u_upload_mgr: new features
authorMarek Olšák <maraeo@gmail.com>
Mon, 27 Dec 2010 21:32:31 +0000 (22:32 +0100)
committerMarek Olšák <maraeo@gmail.com>
Thu, 6 Jan 2011 15:16:29 +0000 (16:16 +0100)
- Added a parameter to specify a minimum offset that should be returned.
  r300g needs this to better implement user buffer uploads. This weird
  requirement comes from the fact that the Radeon DRM doesn't support negative
  offsets.

- Added a parameter to notify a driver that the upload flush occured.
  A driver may skip buffer validation if there was no flush, resulting
  in a better performance.

- Added a new upload function that returns a pointer to the upload buffer
  directly, so that the buffer can be filled e.g. by the translate module.

src/gallium/auxiliary/util/u_upload_mgr.c
src/gallium/auxiliary/util/u_upload_mgr.h
src/gallium/drivers/i965/brw_draw_upload.c
src/gallium/drivers/r300/r300_screen_buffer.c
src/gallium/drivers/svga/svga_draw_elements.c
src/gallium/drivers/svga/svga_state_vdecl.c

index 4d97bf0377ffdef031b42cb901c7c0cbf5030dbb..80c9b635f0e4dd3caf2cff558b3af8ef6a4752fe 100644 (file)
@@ -43,7 +43,7 @@ struct u_upload_mgr {
 
    unsigned default_size;
    unsigned alignment;
-   unsigned usage;
+   unsigned bind;
 
    /* The active buffer:
     */
@@ -58,7 +58,7 @@ struct u_upload_mgr {
 struct u_upload_mgr *u_upload_create( struct pipe_context *pipe,
                                       unsigned default_size,
                                       unsigned alignment,
-                                      unsigned usage )
+                                      unsigned bind )
 {
    struct u_upload_mgr *upload = CALLOC_STRUCT( u_upload_mgr );
    if (!upload)
@@ -67,7 +67,7 @@ struct u_upload_mgr *u_upload_create( struct pipe_context *pipe,
    upload->pipe = pipe;
    upload->default_size = default_size;
    upload->alignment = alignment;
-   upload->usage = usage;
+   upload->bind = bind;
    upload->buffer = NULL;
 
    return upload;
@@ -115,7 +115,7 @@ u_upload_alloc_buffer( struct u_upload_mgr *upload,
    size = align(MAX2(upload->default_size, min_size), 4096);
 
    upload->buffer = pipe_buffer_create( upload->pipe->screen,
-                                        upload->usage,
+                                        upload->bind,
                                         size );
    if (upload->buffer == NULL) 
       goto fail;
@@ -135,33 +135,61 @@ fail:
    return PIPE_ERROR_OUT_OF_MEMORY;
 }
 
-
-enum pipe_error u_upload_data( struct u_upload_mgr *upload,
-                               unsigned size,
-                               const void *data,
-                               unsigned *out_offset,
-                               struct pipe_resource **outbuf )
+enum pipe_error u_upload_alloc( struct u_upload_mgr *upload,
+                                unsigned min_out_offset,
+                                unsigned size,
+                                unsigned *out_offset,
+                                struct pipe_resource **outbuf,
+                                boolean *flushed,
+                                void **ptr )
 {
    unsigned alloc_size = align( size, upload->alignment );
-   enum pipe_error ret = PIPE_OK;
+   unsigned alloc_offset = align(min_out_offset, upload->alignment);
+   unsigned offset;
 
-   if (upload->offset + alloc_size > upload->size) {
-      ret = u_upload_alloc_buffer( upload, alloc_size );
+   if (MAX2(upload->offset, alloc_offset) + alloc_size > upload->size) {
+      enum pipe_error ret = u_upload_alloc_buffer(upload,
+                                                  alloc_offset + alloc_size);
       if (ret)
          return ret;
+
+      *flushed = TRUE;
+   } else {
+      *flushed = FALSE;
    }
 
-   assert(upload->offset < upload->buffer->width0);
-   assert(upload->offset + size <= upload->buffer->width0);
+   offset = MAX2(upload->offset, alloc_offset);
+
+   assert(offset < upload->buffer->width0);
+   assert(offset + size <= upload->buffer->width0);
    assert(size);
 
-   memcpy(upload->map + upload->offset, data, size);
+   *ptr = upload->map + offset;
 
    /* Emit the return values:
     */
    pipe_resource_reference( outbuf, upload->buffer );
-   *out_offset = upload->offset;
-   upload->offset += alloc_size;
+   *out_offset = offset;
+   upload->offset = offset + alloc_size;
+   return PIPE_OK;
+}
+
+enum pipe_error u_upload_data( struct u_upload_mgr *upload,
+                               unsigned min_out_offset,
+                               unsigned size,
+                               const void *data,
+                               unsigned *out_offset,
+                               struct pipe_resource **outbuf,
+                               boolean *flushed )
+{
+   uint8_t *ptr;
+   enum pipe_error ret = u_upload_alloc(upload, min_out_offset, size,
+                                        out_offset, outbuf, flushed,
+                                        (void**)&ptr);
+   if (ret)
+      return ret;
+
+   memcpy(ptr, data, size);
    return PIPE_OK;
 }
 
@@ -172,11 +200,13 @@ enum pipe_error u_upload_data( struct u_upload_mgr *upload,
  * renders or DrawElements calls.
  */
 enum pipe_error u_upload_buffer( struct u_upload_mgr *upload,
+                                 unsigned min_out_offset,
                                  unsigned offset,
                                  unsigned size,
                                  struct pipe_resource *inbuf,
                                  unsigned *out_offset,
-                                 struct pipe_resource **outbuf )
+                                 struct pipe_resource **outbuf,
+                                 boolean *flushed )
 {
    enum pipe_error ret = PIPE_OK;
    struct pipe_transfer *transfer = NULL;
@@ -195,13 +225,12 @@ enum pipe_error u_upload_buffer( struct u_upload_mgr *upload,
    if (0)
       debug_printf("upload ptr %p ofs %d sz %d\n", map, offset, size);
 
-   ret = u_upload_data( upload, 
+   ret = u_upload_data( upload,
+                        min_out_offset,
                         size,
                         map + offset,
                         out_offset,
-                        outbuf );
-   if (ret)
-      goto done;
+                        outbuf, flushed );
 
 done:
    if (map)
index de016df02e02f826c8456b5bdd4ebb7960d0b072..fc8f4d3687a5af37b0f6b76305e9ca6a591ecabd 100644 (file)
@@ -32,6 +32,8 @@
 #ifndef U_UPLOAD_MGR_H
 #define U_UPLOAD_MGR_H
 
+#include "pipe/p_compiler.h"
+
 struct pipe_context;
 struct pipe_resource;
 
@@ -39,7 +41,7 @@ struct pipe_resource;
 struct u_upload_mgr *u_upload_create( struct pipe_context *pipe,
                                       unsigned default_size,
                                       unsigned alignment,
-                                      unsigned usage );
+                                      unsigned bind );
 
 void u_upload_destroy( struct u_upload_mgr *upload );
 
@@ -53,20 +55,55 @@ void u_upload_destroy( struct u_upload_mgr *upload );
  */
 void u_upload_flush( struct u_upload_mgr *upload );
 
+/**
+ * Sub-allocate new memory from the upload buffer.
+ *
+ * \param upload           Upload manager
+ * \param min_out_offset   Minimum offset that should be returned in out_offset.
+ * \param size             Size of the allocation.
+ * \param out_offset       Pointer to where the new buffer offset will be returned.
+ * \param outbuf           Pointer to where the upload buffer will be returned.
+ * \param flushed          Whether the upload buffer was flushed.
+ * \param ptr              Pointer to the allocated memory that is returned.
+ */
+enum pipe_error u_upload_alloc( struct u_upload_mgr *upload,
+                                unsigned min_out_offset,
+                                unsigned size,
+                                unsigned *out_offset,
+                                struct pipe_resource **outbuf,
+                                boolean *flushed,
+                                void **ptr );
+
 
+/**
+ * Allocate and write data to the upload buffer.
+ *
+ * Same as u_upload_alloc, but in addition to that, it copies "data"
+ * to the pointer returned from u_upload_alloc.
+ */
 enum pipe_error u_upload_data( struct u_upload_mgr *upload,
+                               unsigned min_out_offset,
                                unsigned size,
                                const void *data,
                                unsigned *out_offset,
-                               struct pipe_resource **outbuf );
+                               struct pipe_resource **outbuf,
+                               boolean *flushed );
 
 
+/**
+ * Allocate and copy an input buffer to the upload buffer.
+ *
+ * Same as u_upload_data, except that the input data comes from a buffer
+ * instead of a user pointer.
+ */
 enum pipe_error u_upload_buffer( struct u_upload_mgr *upload,
+                                 unsigned min_out_offset,
                                  unsigned offset,
                                  unsigned size,
                                  struct pipe_resource *inbuf,
                                  unsigned *out_offset,
-                                 struct pipe_resource **outbuf );
+                                 struct pipe_resource **outbuf,
+                                 boolean *flushed );
 
 
 
index ebeb1e146aa9bee5d95f955131efa88b68daf3d1..cf9405470c88e7f8e97be005ed223395700a96e7 100644 (file)
@@ -89,13 +89,16 @@ static int brw_prepare_vertices(struct brw_context *brw)
                          vb->buffer->width0 - vb->buffer_offset :
                          MAX2(vb->buffer->width0 - vb->buffer_offset,
                               vb->stride * (max_index + 1 - min_index)));
+        boolean flushed;
 
-        ret = u_upload_buffer( brw->vb.upload_vertex, 
+        ret = u_upload_buffer( brw->vb.upload_vertex,
+                               0,
                                vb->buffer_offset + min_index * vb->stride,
                                size,
                                vb->buffer,
                                &offset,
-                               &upload_buf );
+                               &upload_buf,
+                               &flushed );
         if (ret)
            return ret;
 
@@ -251,13 +254,16 @@ static int brw_prepare_indices(struct brw_context *brw)
    /* Turn userbuffer into a proper hardware buffer?
     */
    if (brw_buffer_is_user_buffer(index_buffer)) {
+      boolean flushed;
 
       ret = u_upload_buffer( brw->vb.upload_index,
+                             0,
                             index_offset,
                             ib_size,
                             index_buffer,
                             &offset,
-                            &upload_buf );
+                            &upload_buf,
+                            &flushed );
       if (ret)
         return ret;
 
index f96998195af7033711a2f9bbd875ce88ced1448e..11ad87ed89bfae4e30ecb89a859ba6f13005e35d 100644 (file)
@@ -62,15 +62,16 @@ void r300_upload_index_buffer(struct r300_context *r300,
                              unsigned count)
 {
     unsigned index_offset;
+    boolean flushed;
     uint8_t *ptr = r300_buffer(*index_buffer)->user_buffer;
 
     *index_buffer = NULL;
 
     u_upload_data(r300->upload_ib,
-                  count * index_size,
+                  0, count * index_size,
                   ptr + (*start * index_size),
                   &index_offset,
-                  index_buffer);
+                  index_buffer, &flushed);
 
     *start = index_offset / index_size;
 }
@@ -78,6 +79,7 @@ void r300_upload_index_buffer(struct r300_context *r300,
 void r300_upload_user_buffers(struct r300_context *r300)
 {
     int i, nr = r300->velems->count;
+    boolean flushed;
 
     for (i = 0; i < nr; i++) {
         struct pipe_vertex_buffer *vb =
@@ -85,9 +87,9 @@ void r300_upload_user_buffers(struct r300_context *r300)
 
         if (r300_buffer_is_user_buffer(vb->buffer)) {
             u_upload_data(r300->upload_vb,
-                          vb->buffer->width0,
+                          0, vb->buffer->width0,
                           r300_buffer(vb->buffer)->user_buffer,
-                          &vb->buffer_offset, &vb->buffer);
+                          &vb->buffer_offset, &vb->buffer, &flushed);
 
             r300->validate_buffers = TRUE;
             r300->vertex_arrays_dirty = TRUE;
index c7ea014bba5cbbe133453eef2f586bb1581a3d26..83527c6ef496ce4d04084adf8ce7f50152251a3a 100644 (file)
@@ -120,14 +120,17 @@ svga_hwtnl_simple_draw_range_elements( struct svga_hwtnl *hwtnl,
    if (index_buffer && 
        svga_buffer_is_user_buffer(index_buffer)) 
    {
+      boolean flushed;
       assert( index_buffer->width0 >= index_offset + count * index_size );
 
       ret = u_upload_buffer( hwtnl->upload_ib,
+                             0,
                              index_offset,
                              count * index_size,
                              index_buffer,
                              &index_offset,
-                             &upload_buffer );
+                             &upload_buffer,
+                             &flushed );
       if (ret)
          goto done;
 
index 3af7bf2b35872d3c6e8d683b0c9d09145c541fc5..958d00393f2f28b90ddbd58fd80eb8cafd203d2d 100644 (file)
@@ -57,12 +57,14 @@ upload_user_buffers( struct svga_context *svga )
          struct svga_buffer *buffer = svga_buffer(svga->curr.vb[i].buffer);
 
          if (!buffer->uploaded.buffer) {
+            boolean flushed;
             ret = u_upload_buffer( svga->upload_vb,
-                                   0,
+                                   0, 0,
                                    buffer->b.b.width0,
                                    &buffer->b.b,
                                    &buffer->uploaded.offset,
-                                   &buffer->uploaded.buffer );
+                                   &buffer->uploaded.buffer,
+                                   &flushed);
             if (ret)
                return ret;