diff options
-rw-r--r-- | src/gallium/drivers/nouveau/nvc0/nvc0_context.h | 1 | ||||
-rw-r--r-- | src/gallium/drivers/nouveau/nvc0/nvc0_vbo.c | 5 | ||||
-rw-r--r-- | src/gallium/drivers/nouveau/nvc0/nvc0_vbo_translate.c | 77 |
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) { |