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 <imirkin@alum.mit.edu>
Cc: 19.0 <mesa-stable@lists.freedesktop.org>
This commit is contained in:
Ilia Mirkin 2019-02-02 16:23:50 -05:00
parent 0f7a20e91e
commit 399215eb7a
3 changed files with 82 additions and 1 deletions

View file

@ -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 *);

View file

@ -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;
}

View file

@ -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)
{