[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