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)
/*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);
/*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);
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;
};
/* 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;
}
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;
/* 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);
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 */
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) |
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;