From 93ff6f59199800c2b3bf339500fb5f9d92cd43c0 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Sun, 5 Jan 2020 21:38:15 -0500 Subject: [PATCH] etnaviv: HALTI2+ instanced draw Fixes: dEQP-GLES3.functional.draw.draw_arrays_instanced.* dEQP-GLES3.functional.draw.draw_elements_instanced.* Signed-off-by: Jonathan Marek Reviewed-by: Christian Gmeiner --- src/gallium/drivers/etnaviv/etnaviv_context.c | 2 +- src/gallium/drivers/etnaviv/etnaviv_emit.c | 12 +++++++----- .../drivers/etnaviv/etnaviv_internal.h | 3 ++- src/gallium/drivers/etnaviv/etnaviv_screen.c | 3 +++ src/gallium/drivers/etnaviv/etnaviv_state.c | 19 +++++++++++++++---- 5 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.c b/src/gallium/drivers/etnaviv/etnaviv_context.c index 5652107f4dc..533b4033adc 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_context.c +++ b/src/gallium/drivers/etnaviv/etnaviv_context.c @@ -327,7 +327,7 @@ etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) if (ctx->specs.halti >= 2) { /* On HALTI2+ (GC3000 and higher) only use instanced drawing commands, as the blob does */ - etna_draw_instanced(ctx->stream, info->index_size, draw_mode, 1, + etna_draw_instanced(ctx->stream, info->index_size, draw_mode, info->instance_count, info->count, info->index_size ? info->index_bias : info->start); } else { if (info->index_size) diff --git a/src/gallium/drivers/etnaviv/etnaviv_emit.c b/src/gallium/drivers/etnaviv/etnaviv_emit.c index 4982cdb9074..977f156958a 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_emit.c +++ b/src/gallium/drivers/etnaviv/etnaviv_emit.c @@ -327,11 +327,6 @@ etna_emit_state(struct etna_context *ctx) /*14640*/ EMIT_STATE(NFE_VERTEX_STREAMS_CONTROL(x), ctx->vertex_buffer.cvb[x].FE_VERTEX_STREAM_CONTROL); } } - for (int x = 0; x < ctx->vertex_buffer.count; ++x) { - if (ctx->vertex_buffer.cvb[x].FE_VERTEX_STREAM_BASE_ADDR.bo) { - /*14680*/ EMIT_STATE(NFE_VERTEX_STREAMS_VERTEX_DIVISOR(x), ctx->vertex_buffer.cvb[x].FE_VERTEX_STREAM_VERTEX_DIVISOR); - } - } } else if(ctx->specs.stream_count > 1) { /* hw w/ multiple vertex streams */ for (int x = 0; x < ctx->vertex_buffer.count; ++x) { /*00680*/ EMIT_STATE_RELOC(FE_VERTEX_STREAMS_BASE_ADDR(x), &ctx->vertex_buffer.cvb[x].FE_VERTEX_STREAM_BASE_ADDR); @@ -346,6 +341,13 @@ etna_emit_state(struct etna_context *ctx) /*00650*/ EMIT_STATE(FE_VERTEX_STREAM_CONTROL, ctx->vertex_buffer.cvb[0].FE_VERTEX_STREAM_CONTROL); } } + /* gallium has instance divisor as part of elements state */ + if ((dirty & (ETNA_DIRTY_VERTEX_ELEMENTS)) && ctx->specs.halti >= 2) { + for (int x = 0; x < ctx->vertex_elements->num_buffers; ++x) { + /*14680*/ EMIT_STATE(NFE_VERTEX_STREAMS_VERTEX_DIVISOR(x), ctx->vertex_elements->NFE_VERTEX_STREAMS_VERTEX_DIVISOR[x]); + } + } + if (unlikely(dirty & (ETNA_DIRTY_SHADER | ETNA_DIRTY_RASTERIZER))) { /*00804*/ EMIT_STATE(VS_OUTPUT_COUNT, vs_output_count); diff --git a/src/gallium/drivers/etnaviv/etnaviv_internal.h b/src/gallium/drivers/etnaviv/etnaviv_internal.h index 25f6a38ab98..b226526410d 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_internal.h +++ b/src/gallium/drivers/etnaviv/etnaviv_internal.h @@ -228,12 +228,13 @@ struct compiled_vertex_elements_state { uint32_t NFE_GENERIC_ATTRIB_CONFIG0[VIVS_NFE_GENERIC_ATTRIB__LEN]; uint32_t NFE_GENERIC_ATTRIB_SCALE[VIVS_NFE_GENERIC_ATTRIB__LEN]; uint32_t NFE_GENERIC_ATTRIB_CONFIG1[VIVS_NFE_GENERIC_ATTRIB__LEN]; + unsigned num_buffers; + uint32_t NFE_VERTEX_STREAMS_VERTEX_DIVISOR[VIVS_NFE_VERTEX_STREAMS__LEN]; }; /* Compiled context->set_vertex_buffer result */ struct compiled_set_vertex_buffer { uint32_t FE_VERTEX_STREAM_CONTROL; - uint32_t FE_VERTEX_STREAM_VERTEX_DIVISOR; struct etna_reloc FE_VERTEX_STREAM_BASE_ADDR; }; diff --git a/src/gallium/drivers/etnaviv/etnaviv_screen.c b/src/gallium/drivers/etnaviv/etnaviv_screen.c index df537f285bf..3f687c4314a 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_screen.c +++ b/src/gallium/drivers/etnaviv/etnaviv_screen.c @@ -190,6 +190,9 @@ etna_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) return 255; case PIPE_CAP_MAX_VERTEX_BUFFERS: return screen->specs.stream_count; + case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: + return VIV_FEATURE(screen, chipMinorFeatures4, HALTI2); + /* Texturing. */ case PIPE_CAP_TEXTURE_SHADOW_MAP: diff --git a/src/gallium/drivers/etnaviv/etnaviv_state.c b/src/gallium/drivers/etnaviv/etnaviv_state.c index 67f9512f74e..34d83f9a3fa 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_state.c +++ b/src/gallium/drivers/etnaviv/etnaviv_state.c @@ -551,7 +551,7 @@ etna_vertex_elements_state_create(struct pipe_context *pctx, /* TODO: does mesa this for us? */ bool incompatible = false; for (unsigned idx = 0; idx < num_elements; ++idx) { - if (elements[idx].vertex_buffer_index >= ctx->specs.stream_count || elements[idx].instance_divisor > 0) + if (elements[idx].vertex_buffer_index >= ctx->specs.stream_count) incompatible = true; } @@ -564,8 +564,10 @@ etna_vertex_elements_state_create(struct pipe_context *pctx, unsigned start_offset = 0; /* start of current consecutive stretch */ bool nonconsecutive = true; /* previous value of nonconsecutive */ + uint32_t buffer_mask = 0; /* mask of buffer_idx already seen */ for (unsigned idx = 0; idx < num_elements; ++idx) { + unsigned buffer_idx = elements[idx].vertex_buffer_index; unsigned element_size = util_format_get_blocksize(elements[idx].src_format); unsigned end_offset = elements[idx].src_offset + element_size; uint32_t format_type, normalize; @@ -578,7 +580,7 @@ etna_vertex_elements_state_create(struct pipe_context *pctx, /* check whether next element is consecutive to this one */ nonconsecutive = (idx == (num_elements - 1)) || - elements[idx + 1].vertex_buffer_index != elements[idx].vertex_buffer_index || + elements[idx + 1].vertex_buffer_index != buffer_idx || end_offset != elements[idx + 1].src_offset; format_type = translate_vertex_format_type(elements[idx].src_format); @@ -593,7 +595,7 @@ etna_vertex_elements_state_create(struct pipe_context *pctx, format_type | VIVS_FE_VERTEX_ELEMENT_CONFIG_NUM(util_format_get_nr_components(elements[idx].src_format)) | normalize | VIVS_FE_VERTEX_ELEMENT_CONFIG_ENDIAN(ENDIAN_MODE_NO_SWAP) | - VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM(elements[idx].vertex_buffer_index) | + VIVS_FE_VERTEX_ELEMENT_CONFIG_STREAM(buffer_idx) | VIVS_FE_VERTEX_ELEMENT_CONFIG_START(elements[idx].src_offset) | VIVS_FE_VERTEX_ELEMENT_CONFIG_END(end_offset - start_offset); } else { /* HALTI5 spread vertex attrib config over two registers */ @@ -601,7 +603,7 @@ etna_vertex_elements_state_create(struct pipe_context *pctx, format_type | VIVS_NFE_GENERIC_ATTRIB_CONFIG0_NUM(util_format_get_nr_components(elements[idx].src_format)) | normalize | VIVS_NFE_GENERIC_ATTRIB_CONFIG0_ENDIAN(ENDIAN_MODE_NO_SWAP) | - VIVS_NFE_GENERIC_ATTRIB_CONFIG0_STREAM(elements[idx].vertex_buffer_index) | + VIVS_NFE_GENERIC_ATTRIB_CONFIG0_STREAM(buffer_idx) | VIVS_NFE_GENERIC_ATTRIB_CONFIG0_START(elements[idx].src_offset); cs->NFE_GENERIC_ATTRIB_CONFIG1[idx] = COND(nonconsecutive, VIVS_NFE_GENERIC_ATTRIB_CONFIG1_NONCONSECUTIVE) | @@ -612,6 +614,15 @@ etna_vertex_elements_state_create(struct pipe_context *pctx, cs->NFE_GENERIC_ATTRIB_SCALE[idx] = 1; else cs->NFE_GENERIC_ATTRIB_SCALE[idx] = fui(1.0f); + + /* instance_divisor is part of elements state but should be the same for all buffers */ + if (buffer_mask & 1 << buffer_idx) + assert(cs->NFE_VERTEX_STREAMS_VERTEX_DIVISOR[buffer_idx] == elements[idx].instance_divisor); + else + cs->NFE_VERTEX_STREAMS_VERTEX_DIVISOR[buffer_idx] = elements[idx].instance_divisor; + + buffer_mask |= 1 << buffer_idx; + cs->num_buffers = MAX2(cs->num_buffers, buffer_idx + 1); } return cs; -- 2.30.2