ilo: mapping a resource may make some states dirty
authorChia-I Wu <olvaffe@gmail.com>
Thu, 13 Jun 2013 10:22:40 +0000 (18:22 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Thu, 13 Jun 2013 15:47:18 +0000 (23:47 +0800)
When a resource is busy and is mapped with
PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE, the underlying bo is replaced.  We need
to mark states affected by the resource dirty.

With this change, we no longer have to emit vertex buffers and index buffer
unconditionally.

src/gallium/drivers/ilo/ilo_3d.c
src/gallium/drivers/ilo/ilo_state.c
src/gallium/drivers/ilo/ilo_state.h
src/gallium/drivers/ilo/ilo_transfer.c

index aba92a0375a2b233071aa984756b68af288d3c4f..b2cbcf04e0ca208af5ff86ea6daec20f9aae8885 100644 (file)
@@ -661,13 +661,6 @@ ilo_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
             ILO_3D_PIPELINE_INVALIDATE_KERNEL_BO);
    }
 
-   /*
-    * The VBs and/or IB may have different BOs due to being mapped with
-    * PIPE_TRANSFER_DISCARD_x.  We should track that instead of setting the
-    * dirty flags for the performance reason.
-    */
-   ilo->dirty |= ILO_DIRTY_VERTEX_BUFFERS | ILO_DIRTY_INDEX_BUFFER;
-
    /* If draw_vbo ever fails, return immediately. */
    if (!draw_vbo(hw3d, ilo, info, &prim_generated, &prim_emitted))
       return;
index 3fe19e0fba9c9ee89a5669d7838b6dcecf08cc10..865bc5c7bd9c35cb7c514e3608765f5f716c9ccb 100644 (file)
@@ -1156,3 +1156,103 @@ ilo_cleanup_states(struct ilo_context *ilo)
    for (i = 0; i < ilo->global_binding.count; i++)
       pipe_resource_reference(&ilo->global_binding.resources[i], NULL);
 }
+
+/**
+ * Mark all states that have the resource dirty.
+ */
+void
+ilo_mark_states_with_resource_dirty(struct ilo_context *ilo,
+                                    const struct pipe_resource *res)
+{
+   uint32_t states = 0;
+   unsigned sh, i;
+
+   if (res->target == PIPE_BUFFER) {
+      uint32_t vb_mask = ilo->vb.enabled_mask;
+
+      while (vb_mask) {
+         const unsigned idx = u_bit_scan(&vb_mask);
+
+         if (ilo->vb.states[idx].buffer == res) {
+            states |= ILO_DIRTY_VERTEX_BUFFERS;
+            break;
+         }
+      }
+
+      if (ilo->ib.state.buffer == res)
+         states |= ILO_DIRTY_INDEX_BUFFER;
+
+      for (i = 0; i < ilo->so.count; i++) {
+         if (ilo->so.states[i]->buffer == res) {
+            states |= ILO_DIRTY_STREAM_OUTPUT_TARGETS;
+            break;
+         }
+      }
+   }
+
+   for (sh = 0; sh < PIPE_SHADER_TYPES; sh++) {
+      for (i = 0; i < ilo->view[sh].count; i++) {
+         struct pipe_sampler_view *view = ilo->view[sh].states[i];
+
+         if (view->texture == res) {
+            static const unsigned view_dirty_bits[PIPE_SHADER_TYPES] = {
+               [PIPE_SHADER_VERTEX]    = ILO_DIRTY_VERTEX_SAMPLER_VIEWS,
+               [PIPE_SHADER_FRAGMENT]  = ILO_DIRTY_FRAGMENT_SAMPLER_VIEWS,
+               [PIPE_SHADER_GEOMETRY]  = ILO_DIRTY_GEOMETRY_SAMPLER_VIEWS,
+               [PIPE_SHADER_COMPUTE]   = ILO_DIRTY_COMPUTE_SAMPLER_VIEWS,
+            };
+
+            states |= view_dirty_bits[sh];
+            break;
+         }
+      }
+
+      if (res->target == PIPE_BUFFER) {
+         for (i = 0; i < Elements(ilo->cbuf[sh].cso); i++) {
+            struct ilo_cbuf_cso *cbuf = &ilo->cbuf[sh].cso[i];
+
+            if (cbuf->resource == res) {
+               states |= ILO_DIRTY_CONSTANT_BUFFER;
+               break;
+            }
+         }
+      }
+   }
+
+   for (i = 0; i < ilo->resource.count; i++) {
+      if (ilo->resource.states[i]->texture == res) {
+         states |= ILO_DIRTY_SHADER_RESOURCES;
+         break;
+      }
+   }
+
+   /* for now? */
+   if (res->target != PIPE_BUFFER) {
+      for (i = 0; i < ilo->fb.state.nr_cbufs; i++) {
+         if (ilo->fb.state.cbufs[i]->texture == res) {
+            states |= ILO_DIRTY_FRAMEBUFFER;
+            break;
+         }
+      }
+
+      if (ilo->fb.state.zsbuf && ilo->fb.state.zsbuf->texture == res)
+         states |= ILO_DIRTY_FRAMEBUFFER;
+   }
+
+   for (i = 0; i < ilo->cs_resource.count; i++) {
+      pipe_surface_reference(&ilo->cs_resource.states[i], NULL);
+      if (ilo->cs_resource.states[i]->texture == res) {
+         states |= ILO_DIRTY_COMPUTE_RESOURCES;
+         break;
+      }
+   }
+
+   for (i = 0; i < ilo->global_binding.count; i++) {
+      if (ilo->global_binding.resources[i] == res) {
+         states |= ILO_DIRTY_GLOBAL_BINDING;
+         break;
+      }
+   }
+
+   ilo->dirty |= states;
+}
index c73e8fb835b4da198f078661dc18a6c628f5c4e5..8a0d5e7f14d3b4c90cc038bcf168f276eb5f31d7 100644 (file)
@@ -113,6 +113,7 @@ enum ilo_dirty_flags {
    ILO_DIRTY_ALL                      = 0xffffffff,
 };
 
+struct pipe_resource;
 struct ilo_context;
 
 void
@@ -127,4 +128,8 @@ ilo_cleanup_states(struct ilo_context *ilo);
 void
 ilo_finalize_states(struct ilo_context *ilo);
 
+void
+ilo_mark_states_with_resource_dirty(struct ilo_context *ilo,
+                                    const struct pipe_resource *res);
+
 #endif /* ILO_STATE_H */
index dcb9ab96d8bc257a8a84273735a8a95548f25721..9f68d4ad9761b8f0f44ecafe1e0f33e8dc73077c 100644 (file)
@@ -32,6 +32,7 @@
 #include "ilo_cp.h"
 #include "ilo_context.h"
 #include "ilo_resource.h"
+#include "ilo_state.h"
 #include "ilo_transfer.h"
 
 static bool
@@ -135,8 +136,10 @@ choose_transfer_method(struct ilo_context *ilo, struct ilo_transfer *xfer)
       else if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) {
          /* discard old bo and allocate a new one for mapping */
          if ((tex && ilo_texture_alloc_bo(tex)) ||
-             (buf && ilo_buffer_alloc_bo(buf)))
+             (buf && ilo_buffer_alloc_bo(buf))) {
+            ilo_mark_states_with_resource_dirty(ilo, res);
             will_stall = false;
+         }
       }
       else if (usage & PIPE_TRANSFER_FLUSH_EXPLICIT) {
          /*
@@ -920,8 +923,10 @@ buf_pwrite(struct ilo_context *ilo, struct ilo_buffer *buf,
 
       if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) {
          /* old data not needed so discard the old bo to avoid stalling */
-         if (ilo_buffer_alloc_bo(buf))
+         if (ilo_buffer_alloc_bo(buf)) {
+            ilo_mark_states_with_resource_dirty(ilo, &buf->base);
             will_stall = false;
+         }
       }
       else {
          /*