etnaviv: HALTI2+ instanced draw
authorJonathan Marek <jonathan@marek.ca>
Mon, 6 Jan 2020 02:38:15 +0000 (21:38 -0500)
committerJonathan Marek <jonathan@marek.ca>
Wed, 8 Jan 2020 17:27:34 +0000 (12:27 -0500)
Fixes:
dEQP-GLES3.functional.draw.draw_arrays_instanced.*
dEQP-GLES3.functional.draw.draw_elements_instanced.*

Signed-off-by: Jonathan Marek <jonathan@marek.ca>
Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>
src/gallium/drivers/etnaviv/etnaviv_context.c
src/gallium/drivers/etnaviv/etnaviv_emit.c
src/gallium/drivers/etnaviv/etnaviv_internal.h
src/gallium/drivers/etnaviv/etnaviv_screen.c
src/gallium/drivers/etnaviv/etnaviv_state.c

index 5652107f4dc4eeab894084c517223f5ec3d03473..533b4033adc1c88f583e4118dfaeaa63119cb17b 100644 (file)
@@ -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)
index 4982cdb907496b4dd7dd3c0d0a8e934a27d9ac98..977f156958aa18d50ecf5090a73705176feecea1 100644 (file)
@@ -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);
index 25f6a38ab987ac663190997d32808c61920dc334..b226526410dba13901b668a5785a90bcf8dda9ec 100644 (file)
@@ -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;
 };
 
index df537f285bf8225ca507e9c7897dbce2286f3a6e..3f687c4314ab4ff75229cc5183c561caa200f28f 100644 (file)
@@ -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:
index 67f9512f74ec533f7b1aeb8930e492c3a627b45e..34d83f9a3fafed7a910180821e1dc568d75d9740 100644 (file)
@@ -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;