ilo: enable persistent and coherent transfers
authorChia-I Wu <olvaffe@gmail.com>
Mon, 28 Jul 2014 01:50:31 +0000 (09:50 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Mon, 28 Jul 2014 14:57:22 +0000 (22:57 +0800)
Enable PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT and reorder caps a bit.

src/gallium/drivers/ilo/ilo_resource.c
src/gallium/drivers/ilo/ilo_screen.c
src/gallium/drivers/ilo/ilo_transfer.c

index 182bb60d3014d132c292acf75ee718995326f34a..c812c19279d49c1b4e2299d59df054dc0575c904 100644 (file)
@@ -710,7 +710,7 @@ tex_layout_init_hiz(struct tex_layout *layout)
    }
 }
 
-static void
+static bool
 tex_layout_init(struct tex_layout *layout,
                 struct pipe_screen *screen,
                 const struct pipe_resource *templ,
@@ -732,12 +732,22 @@ tex_layout_init(struct tex_layout *layout,
    tex_layout_init_alignments(layout);
    tex_layout_init_qpitch(layout);
 
+   if (templ->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT) {
+      /* require on-the-fly tiling/untiling or format conversion */
+      if (layout->separate_stencil ||
+          layout->format == PIPE_FORMAT_S8_UINT ||
+          layout->format != templ->format)
+         return false;
+   }
+
    if (slices) {
       int lv;
 
       for (lv = 0; lv <= templ->last_level; lv++)
          layout->levels[lv].slices = slices[lv];
    }
+
+   return true;
 }
 
 static void
@@ -1344,7 +1354,10 @@ tex_create(struct pipe_screen *screen,
 
    tex->imported = (handle != NULL);
 
-   tex_layout_init(&layout, screen, templ, tex->slices);
+   if (!tex_layout_init(&layout, screen, templ, tex->slices)) {
+      tex_destroy(tex);
+      return NULL;
+   }
 
    switch (templ->target) {
    case PIPE_TEXTURE_1D:
index f4968f9bc3cd78ff82eb4ee12c84aae6020c5117..09980dd20f2e56b1ddad9d18ee3c18623da4a9b0 100644 (file)
@@ -362,10 +362,6 @@ ilo_get_param(struct pipe_screen *screen, enum pipe_cap param)
       return ILO_MAX_SO_BINDINGS / ILO_MAX_SO_BUFFERS;
    case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
       return ILO_MAX_SO_BINDINGS;
-   case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES:
-   case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS:
-   case PIPE_CAP_MAX_VERTEX_STREAMS:
-      return 0;
    case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
       if (is->dev.gen >= ILO_GEN(7))
          return is->dev.has_gen7_sol_reset;
@@ -424,14 +420,20 @@ ilo_get_param(struct pipe_screen *screen, enum pipe_cap param)
    case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES:
       return true;
    case PIPE_CAP_TGSI_VS_LAYER_VIEWPORT:
+   case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES:
+   case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS:
    case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS:
    case PIPE_CAP_TEXTURE_GATHER_SM5:
+      return 0;
    case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT:
+      return true;
    case PIPE_CAP_FAKE_SW_MSAA:
    case PIPE_CAP_TEXTURE_QUERY_LOD:
    case PIPE_CAP_SAMPLE_SHADING:
    case PIPE_CAP_TEXTURE_GATHER_OFFSETS:
    case PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION:
+   case PIPE_CAP_MAX_VERTEX_STREAMS:
+   case PIPE_CAP_DRAW_INDIRECT:
       return 0;
 
    default:
index 4d6706309befe912e1155fe5086fc0591757b3cd..0f1347b70a333bd49e32e173e4492bb026c843da 100644 (file)
  *    synchronization at all on mapping.
  *  - When PIPE_TRANSFER_MAP_DIRECTLY is set, no staging area is allowed.
  *  - When PIPE_TRANSFER_DONTBLOCK is set, we should fail if we have to block.
+ *  - When PIPE_TRANSFER_PERSISTENT is set, GPU may access the buffer while it
+ *    is mapped.  Synchronization is done by defining memory barriers,
+ *    explicitly via memory_barrier() or implicitly via
+ *    transfer_flush_region(), as well as GPU fences.
+ *  - When PIPE_TRANSFER_COHERENT is set, updates by either CPU or GPU should
+ *    be made visible to the other side immediately.  Since the kernel flushes
+ *    GPU caches at the end of each batch buffer, CPU always sees GPU updates.
+ *    We could use a coherent mapping to make all persistent mappings
+ *    coherent.
  *
  * These also apply to textures, except that we may additionally need to do
  * format conversion or tiling/untiling.
@@ -90,7 +99,7 @@ resource_get_transfer_method(struct pipe_resource *res, unsigned usage,
          need_convert = false;
 
       if (need_convert) {
-         if (usage & PIPE_TRANSFER_MAP_DIRECTLY)
+         if (usage & (PIPE_TRANSFER_MAP_DIRECTLY | PIPE_TRANSFER_PERSISTENT))
             return false;
 
          *method = m;
@@ -104,6 +113,8 @@ resource_get_transfer_method(struct pipe_resource *res, unsigned usage,
       m = ILO_TRANSFER_MAP_GTT; /* to have a linear view */
    else if (is->dev.has_llc)
       m = ILO_TRANSFER_MAP_CPU; /* fast and mostly coherent */
+   else if (usage & PIPE_TRANSFER_PERSISTENT)
+      m = ILO_TRANSFER_MAP_GTT; /* for coherency */
    else if (usage & PIPE_TRANSFER_READ)
       m = ILO_TRANSFER_MAP_CPU; /* gtt read is too slow */
    else
@@ -146,7 +157,8 @@ usage_allows_staging_bo(unsigned usage)
                                    PIPE_TRANSFER_DISCARD_RANGE |
                                    PIPE_TRANSFER_FLUSH_EXPLICIT);
    const unsigned reasons_against = (PIPE_TRANSFER_READ |
-                                     PIPE_TRANSFER_MAP_DIRECTLY);
+                                     PIPE_TRANSFER_MAP_DIRECTLY |
+                                     PIPE_TRANSFER_PERSISTENT);
 
    return (usage & can_writeback) && !(usage & reasons_against);
 }