[Mesa-dev] [PATCH 4/4] nvc0: add support for indirect drawing

Christoph Bumiller e0425955 at student.tuwien.ac.at
Fri Feb 1 13:50:23 PST 2013


---
 docs/GL3.txt                                 |    4 +-
 src/gallium/drivers/nvc0/nvc0_3d.xml.h       |    4 +
 src/gallium/drivers/nvc0/nvc0_graph_macros.h |  121 ++++++++++++++++++++++++++
 src/gallium/drivers/nvc0/nvc0_screen.c       |    6 ++
 src/gallium/drivers/nvc0/nvc0_vbo.c          |   56 +++++++++++--
 5 files changed, 183 insertions(+), 8 deletions(-)

diff --git a/docs/GL3.txt b/docs/GL3.txt
index 88621e3..b60dbb6 100644
--- a/docs/GL3.txt
+++ b/docs/GL3.txt
@@ -89,7 +89,7 @@ GL 4.0:
 GLSL 4.0                                             not started
 GL_ARB_texture_query_lod                             not started
 GL_ARB_draw_buffers_blend                            DONE (i965, r600, softpipe)
-GL_ARB_draw_indirect                                 not started
+GL_ARB_draw_indirect                                 DONE (nvc0, softpipe)
 GL_ARB_gpu_shader5                                   not started
 GL_ARB_gpu_shader_fp64                               not started
 GL_ARB_sample_shading                                not started
@@ -143,7 +143,7 @@ ARB_fragment_layer_viewport                          not started
 ARB_framebuffer_no_attachments                       not started
 ARB_internalformat_query2                            not started
 ARB_invalidate_subdata                               not started
-ARB_multi_draw_indirect                              not started
+ARB_multi_draw_indirect                              DONE (nvc0, softpipe)
 ARB_program_interface_query                          not started
 ARB_robust_buffer_access_behavior                    not started
 ARB_shader_image_size                                not started
diff --git a/src/gallium/drivers/nvc0/nvc0_3d.xml.h b/src/gallium/drivers/nvc0/nvc0_3d.xml.h
index 1cf1f96..d90c1b6 100644
--- a/src/gallium/drivers/nvc0/nvc0_3d.xml.h
+++ b/src/gallium/drivers/nvc0/nvc0_3d.xml.h
@@ -1340,5 +1340,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #define NVC0_3D_MACRO_TEP_SELECT				0x00003830
 
+#define NVC0_3D_MACRO_DRAW_ARRAYS_INDIRECT			0x00003838
+
+#define NVC0_3D_MACRO_DRAW_ELEMENTS_INDIRECT			0x00003840
+
 
 #endif /* NVC0_3D_XML */
diff --git a/src/gallium/drivers/nvc0/nvc0_graph_macros.h b/src/gallium/drivers/nvc0/nvc0_graph_macros.h
index f009980..e12ea6c 100644
--- a/src/gallium/drivers/nvc0/nvc0_graph_macros.h
+++ b/src/gallium/drivers/nvc0/nvc0_graph_macros.h
@@ -233,4 +233,125 @@ static const uint32_t nvc0_9097_tep_select[] = /* 0x10 */
    0x00003041, /* 0x10: send $r6 */
 };
 
+/* NVC0_3D_MACRO_DRAW_ELEMENTS_INDIRECT
+ *
+ * NOTE: Saves and restores VB_ELEMENT,INSTANCE_BASE.
+ *
+ * arg     = mode
+ * parm[0] = count
+ * parm[1] = instance_count
+ * parm[2] = start
+ * parm[3] = index_bias
+ * parm[4] = start_instance
+ */
+static const uint32_t nvc0_9097_draw_elts_indirect[] =
+{
+   /* 0x00: parm $r3 (count) */
+   /* 0x01: parm $r2 (instance_count) */
+   /* 0x02: parm $r4 maddr 0x5f7 (INDEX_BATCH_FIRST, start) */
+   /* 0x04: parm $r4 send $r4 (index_bias, send start) */
+   /* 0x05: braz $r2 END */
+   /* 0x06: parm $r5 (start_instance) */
+   /* 0x07: read $r6 0x50d (VB_ELEMENT_BASE) */
+   /* 0x08: read $r7 0x50e (VB_INSTANCE_BASE) */
+   /* 0x09: maddr 0x150d (VB_ELEMENT,INSTANCE_BASE) */
+   /* 0x0a: send $r4 */
+   /* 0x0b: send $r5 */
+   /* 0x0c: mov $r4 0x1 */
+   /* 0x0d: maddr 0x586 (VERTEX_BEGIN_GL) */
+   /* 0x0e: send $r1 (mode) */
+   /* 0x0f: maddr 0x5f8 (INDEX_BATCH_COUNT) */
+   /* 0x10: send $r3 (count) */
+   /* 0x11: mov $r2 (sub $r2 $r4) */
+   /* 0x12: maddrsend 0x585 (VERTEX_END_GL) */
+   /* 0x13: branz $r2 AGAIN */
+   /* 0x14: mov $r1 (extrinsrt $r1 $r4 0 1 26) (set INSTANCE_NEXT) */
+   /* 0x15: maddr 0x150d (VB_ELEMENT,INSTANCE_BASE) */
+   /* 0x16: exit send $r6 */
+   /* 0x17: send $r7 */
+   /* 0x18: exit */
+   /* 0x19: nop */
+   0x00000301,
+   0x00000201,
+   0x017dc451,
+   0x00002431,
+   0x0004d007,
+   0x00000501,
+   0x01434615,
+   0x01438715,
+   0x05434021,
+   0x00002041,
+   0x00002841,
+   0x00004411,
+   0x01618021,
+   0x00000841,
+   0x017e0021,
+   0x00001841,
+   0x00051210,
+   0x01614071,
+   0xfffe9017,
+   0xd0410912,
+   0x05434021,
+   0x000030c1,
+   0x00003841,
+   0x00000091,
+   0x00000011
+};
+
+/* NVC0_3D_MACRO_DRAW_ARRAYS_INDIRECT:
+ *
+ * NOTE: Saves and restores VB_INSTANCE_BASE.
+ *
+ * arg     = mode
+ * parm[0] = count
+ * parm[1] = instance_count
+ * parm[2] = start
+ * parm[3] = start_instance
+ */
+static const uint32_t nvc0_9097_draw_arrays_indirect[] =
+{
+   /* 0x00: parm $r2 (count) */
+   /* 0x01: parm $r3 (instance_count) */
+   /* 0x02: parm $r4 maddr 0x35d (VERTEX_BUFFER_FIRST, start) */
+   /* 0x04: parm $r4 send $r4 (start_instance) */
+   /* 0x05: braz $r3 END */
+   /* 0x06: read $r6 0x50e (VB_INSTANCE_BASE) */
+   /* 0x07: maddr 0x50e (VB_INSTANCE_BASE) */
+   /* 0x08: mov $r5 0x1 */
+   /* 0x09: send $r4 */
+   /* 0x0a: maddr 0x586 (VERTEX_BEGIN_GL) */
+   /* 0x0b: send $r1 (mode) */
+   /* 0x0c: maddr 0x35e (VERTEX_BUFFER_COUNT) */
+   /* 0x0d: send $r2 */
+   /* 0x0e: mov $r3 (sub $r3 $r5) */
+   /* 0x0f: maddrsend 0x585 (VERTEX_END_GL) */
+   /* 0x10: branz $r3 AGAIN */
+   /* 0x11: mov $r1 (extrinsrt $r1 $r5 0 1 26) (set INSTANCE_NEXT) */
+   /* 0x12: exit maddr 0x50e (VB_INSTANCE_BASE to restore) */
+   /* 0x13: send $r6 */
+   /* 0x14: exit nop */
+   /* 0x15: nop */
+   0x00000201,
+   0x00000301,
+   0x00d74451,
+   0x00002431,
+   0x0003d807,
+   0x01438615,
+   0x01438021,
+   0x00004511,
+   0x00002041,
+   0x01618021,
+   0x00000841,
+   0x00d78021,
+   0x00001041,
+   0x00055b10,
+   0x01614071,
+   0xfffe9817,
+   0xd0414912,
+   0x014380a1,
+   0x00003041,
+   0x00000091,
+   0x00000011
+};
+
 #endif
diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c
index acc28d1..c0b6b9c 100644
--- a/src/gallium/drivers/nvc0/nvc0_screen.c
+++ b/src/gallium/drivers/nvc0/nvc0_screen.c
@@ -176,6 +176,8 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
    case PIPE_CAP_TEXTURE_MULTISAMPLE:
       return 0;
+   case PIPE_CAP_DRAW_INDIRECT:
+      return 1;
    default:
       NOUVEAU_ERR("unknown PIPE_CAP %d\n", param);
       return 0;
@@ -314,6 +316,8 @@ nvc0_graph_set_macro(struct nvc0_screen *screen, uint32_t m, unsigned pos,
 
    size /= 4;
 
+   assert((pos + size) <= 0x800);
+
    BEGIN_NVC0(push, SUBC_3D(NVC0_GRAPH_MACRO_ID), 2);
    PUSH_DATA (push, (m - 0x3800) / 8);
    PUSH_DATA (push, pos);
@@ -748,6 +752,8 @@ nvc0_screen_create(struct nouveau_device *dev)
    MK_MACRO(NVC0_3D_MACRO_GP_SELECT, nvc0_9097_gp_select);
    MK_MACRO(NVC0_3D_MACRO_POLYGON_MODE_FRONT, nvc0_9097_poly_mode_front);
    MK_MACRO(NVC0_3D_MACRO_POLYGON_MODE_BACK, nvc0_9097_poly_mode_back);
+   MK_MACRO(NVC0_3D_MACRO_DRAW_ARRAYS_INDIRECT, nvc0_9097_draw_arrays_indirect);
+   MK_MACRO(NVC0_3D_MACRO_DRAW_ELEMENTS_INDIRECT, nvc0_9097_draw_elts_indirect);
 
    BEGIN_NVC0(push, NVC0_3D(RASTERIZE_ENABLE), 1);
    PUSH_DATA (push, 1);
diff --git a/src/gallium/drivers/nvc0/nvc0_vbo.c b/src/gallium/drivers/nvc0/nvc0_vbo.c
index 61a6341..6750aea 100644
--- a/src/gallium/drivers/nvc0/nvc0_vbo.c
+++ b/src/gallium/drivers/nvc0/nvc0_vbo.c
@@ -565,6 +565,8 @@ nvc0_draw_arrays(struct nvc0_context *nvc0,
    unsigned prim;
 
    if (nvc0->state.index_bias) {
+      /* index_bias is implied 0 if !info->indexed (really ?) */
+      /* TODO: can we deactivate it for the VERTEX_BUFFER_FIRST command ? */
       PUSH_SPACE(push, 1);
       IMMED_NVC0(push, NVC0_3D(VB_ELEMENT_BASE), 0);
       nvc0->state.index_bias = 0;
@@ -781,6 +783,42 @@ nvc0_draw_stream_output(struct nvc0_context *nvc0,
    }
 }
 
+static void
+nvc0_draw_indirect(struct nvc0_context *nvc0, const struct pipe_draw_info *info)
+{
+   struct nouveau_pushbuf *push = nvc0->base.pushbuf;
+   struct nv04_resource *buf = nv04_resource(info->indirect);
+   unsigned size;
+   const uint32_t offset = buf->offset + info->indirect_offset;
+
+   if (buf->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) {
+      buf->status &= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING;
+      /* must make FIFO wait for engines idle before continuing to process */
+      IMMED_NVC0(push, SUBC_3D(NV10_SUBCHAN_REF_CNT), 0);
+   }
+
+   PUSH_SPACE(push, 8);
+   if (info->indexed) {
+      assert(nvc0->idxbuf.buffer);
+      assert(nouveau_resource_mapped_by_gpu(nvc0->idxbuf.buffer));
+      size = 5 * 4;
+      BEGIN_1IC0(push, NVC0_3D(MACRO_DRAW_ELEMENTS_INDIRECT), 1 + size / 4);
+   } else {
+      if (nvc0->state.index_bias) {
+         /* index_bias is implied 0 if !info->indexed (really ?) */
+         IMMED_NVC0(push, NVC0_3D(VB_ELEMENT_BASE), 0);
+         nvc0->state.index_bias = 0;
+      }
+      size = 4 * 4;
+      BEGIN_1IC0(push, NVC0_3D(MACRO_DRAW_ARRAYS_INDIRECT), 1 + size / 4);
+   }
+   PUSH_DATA(push, nvc0_prim_gl(info->mode));
+#define NVC0_IB_ENTRY_1_NO_PREFETCH (1 << (31 - 8))
+   nouveau_pushbuf_space(push, 0, 0, 1);
+   nouveau_pushbuf_data(push,
+                        buf->bo, offset, NVC0_IB_ENTRY_1_NO_PREFETCH | size);
+}
+
 void
 nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
 {
@@ -863,16 +901,22 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
             shorten = FALSE;
       }
 
-      nvc0_draw_elements(nvc0, shorten,
-                         info->mode, info->start, info->count,
-                         info->instance_count, info->index_bias);
+      if (unlikely(info->indirect))
+         nvc0_draw_indirect(nvc0, info);
+      else
+         nvc0_draw_elements(nvc0, shorten,
+                            info->mode, info->start, info->count,
+                            info->instance_count, info->index_bias);
    } else
    if (unlikely(info->count_from_stream_output)) {
       nvc0_draw_stream_output(nvc0, info);
    } else {
-      nvc0_draw_arrays(nvc0,
-                       info->mode, info->start, info->count,
-                       info->instance_count);
+      if (unlikely(info->indirect))
+         nvc0_draw_indirect(nvc0, info);
+      else
+         nvc0_draw_arrays(nvc0,
+                          info->mode, info->start, info->count,
+                          info->instance_count);
    }
    push->kick_notify = nvc0_default_kick_notify;
 
-- 
1.7.3.4



More information about the mesa-dev mailing list