summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_context.h1
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c5
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_vbo_translate.c77
3 files changed, 82 insertions, 1 deletions
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h
index eb057bf2489..c1351062676 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h
@@ -434,6 +434,7 @@ nvc0_video_buffer_create(struct pipe_context *pipe,
/* nvc0_push.c */
void nvc0_push_vbo(struct nvc0_context *, const struct pipe_draw_info *);
+void nvc0_push_vbo_indirect(struct nvc0_context *, const struct pipe_draw_info *);
/* nve4_compute.c */
void nve4_launch_grid(struct pipe_context *, const struct pipe_grid_info *);
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c
index 3fbe7614e52..7d6be9382d1 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c
@@ -1040,7 +1040,10 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
}
if (nvc0->state.vbo_mode) {
- nvc0_push_vbo(nvc0, info);
+ if (info->indirect)
+ nvc0_push_vbo_indirect(nvc0, info);
+ else
+ nvc0_push_vbo(nvc0, info);
goto cleanup;
}
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo_translate.c b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo_translate.c
index 256e20df2e4..4333fb26d23 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_vbo_translate.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_vbo_translate.c
@@ -466,6 +466,83 @@ nvc0_prim_gl(unsigned prim)
}
}
+typedef struct {
+ uint32_t count;
+ uint32_t primCount;
+ uint32_t first;
+ uint32_t baseInstance;
+} DrawArraysIndirectCommand;
+
+typedef struct {
+ uint32_t count;
+ uint32_t primCount;
+ uint32_t firstIndex;
+ int32_t baseVertex;
+ uint32_t baseInstance;
+} DrawElementsIndirectCommand;
+
+void
+nvc0_push_vbo_indirect(struct nvc0_context *nvc0, const struct pipe_draw_info *info)
+{
+ /* The strategy here is to just read the commands from the indirect buffer
+ * and do the draws. This is suboptimal, but will only happen in the case
+ * that conversion is required for FIXED or DOUBLE inputs.
+ */
+ struct nvc0_screen *screen = nvc0->screen;
+ struct nouveau_pushbuf *push = nvc0->base.pushbuf;
+ struct nv04_resource *buf = nv04_resource(info->indirect->buffer);
+ struct nv04_resource *buf_count = nv04_resource(info->indirect->indirect_draw_count);
+ unsigned i;
+
+ unsigned draw_count = info->indirect->draw_count;
+ if (buf_count) {
+ uint32_t *count = nouveau_resource_map_offset(
+ &nvc0->base, buf_count, info->indirect->indirect_draw_count_offset,
+ NOUVEAU_BO_RD);
+ draw_count = *count;
+ }
+
+ uint8_t *buf_data = nouveau_resource_map_offset(
+ &nvc0->base, buf, info->indirect->offset, NOUVEAU_BO_RD);
+ struct pipe_draw_info single = *info;
+ single.indirect = NULL;
+ for (i = 0; i < draw_count; i++, buf_data += info->indirect->stride) {
+ if (info->index_size) {
+ DrawElementsIndirectCommand *cmd = (void *)buf_data;
+ single.start = info->start + cmd->firstIndex;
+ single.count = cmd->count;
+ single.start_instance = cmd->baseInstance;
+ single.instance_count = cmd->primCount;
+ single.index_bias = cmd->baseVertex;
+ } else {
+ DrawArraysIndirectCommand *cmd = (void *)buf_data;
+ single.start = cmd->first;
+ single.count = cmd->count;
+ single.start_instance = cmd->baseInstance;
+ single.instance_count = cmd->primCount;
+ }
+
+ if (nvc0->vertprog->vp.need_draw_parameters) {
+ PUSH_SPACE(push, 9);
+ BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
+ PUSH_DATA (push, NVC0_CB_AUX_SIZE);
+ PUSH_DATAh(push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(0));
+ PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(0));
+ BEGIN_1IC0(push, NVC0_3D(CB_POS), 1 + 3);
+ PUSH_DATA (push, NVC0_CB_AUX_DRAW_INFO);
+ PUSH_DATA (push, single.index_bias);
+ PUSH_DATA (push, single.start_instance);
+ PUSH_DATA (push, single.drawid + i);
+ }
+
+ nvc0_push_vbo(nvc0, &single);
+ }
+
+ nouveau_resource_unmap(buf);
+ if (buf_count)
+ nouveau_resource_unmap(buf_count);
+}
+
void
nvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info)
{