From: Ilia Mirkin Date: Sat, 2 Feb 2019 21:23:50 +0000 (-0500) Subject: nvc0: add support for handling indirect draws with attrib conversion X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=399215eb7a0517463e5757c598d6cff6ae2301d0;p=mesa.git nvc0: add support for handling indirect draws with attrib conversion The hardware does not natively support FIXED and DOUBLE formats. If those are used in an indirect draw, they have to be converted. Our conversion tries to be clever about only converting the data that's needed. However for indirect, that won't work. Given that DOUBLE or FIXED are highly unlikely to ever be used with indirect draws, read the indirect buffer on the CPU and issue draws directly. Fixes the failing dEQP-GLES31.functional.draw_indirect.random.* tests. Signed-off-by: Ilia Mirkin Cc: 19.0 --- 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) {