draw.start = start;
draw.count = count;
+ draw.index_bias = 0;
cso_draw_vbo(cso, &info, NULL, draw);
}
draw.start = start;
draw.count = count;
+ draw.index_bias = 0;
cso_draw_vbo(cso, &info, NULL, draw);
}
} else
draw_pt_split_prim(prim, &first, &incr);
count = draw_pt_trim_count(draw_info[i].count, first, incr);
+ draw->pt.user.eltBias = draw->pt.user.eltSize ? draw_info[i].index_bias : 0;
if (count >= first)
frontend->run( frontend, draw_info[i].start, count );
* Debug- print the first 'count' vertices.
*/
static void
-draw_print_arrays(struct draw_context *draw, uint prim, int start, uint count)
+draw_print_arrays(struct draw_context *draw, uint prim, int start, uint count, int index_bias)
{
uint i;
assert(0);
return;
}
- ii += draw->pt.user.eltBias;
+ ii += index_bias;
debug_printf("Element[%u + %u] + %i -> Vertex %u:\n", start, i,
- draw->pt.user.eltBias, ii);
+ index_bias, ii);
}
else {
/* non-indexed arrays */
static inline void
prim_restart_loop(struct draw_context *draw,
const struct pipe_draw_info *info,
- unsigned start,
- unsigned count,
+ const struct pipe_draw_start_count_bias *draw_info,
const void *elements)
{
const unsigned elt_max = draw->pt.user.eltMax;
- struct pipe_draw_start_count_bias cur;
- cur.start = start;
+ struct pipe_draw_start_count_bias cur = *draw_info;
cur.count = 0;
/* The largest index within a loop using the i variable as the index.
* Used for overflow detection */
const unsigned MAX_LOOP_IDX = 0xffffffff;
- for (unsigned j = 0; j < count; j++) {
+ for (unsigned j = 0; j < draw_info->count; j++) {
unsigned restart_idx = 0;
- unsigned i = draw_overflow_uadd(start, j, MAX_LOOP_IDX);
+ unsigned i = draw_overflow_uadd(draw_info->start, j, MAX_LOOP_IDX);
switch (draw->pt.user.eltSize) {
case 1:
restart_idx = ((const uint8_t*)elements)[i];
if (draw->pt.user.eltSize) {
/* indexed prims (draw_elements) */
for (unsigned i = 0; i < num_draws; i++)
- prim_restart_loop(draw, info, draw_info[i].start, draw_info[i].count, draw->pt.user.elts);
+ prim_restart_loop(draw, info, &draw_info[i], draw->pt.user.elts);
}
else {
/* Non-indexed prims (draw_arrays).
if (info->index_size)
assert(draw->pt.user.elts);
- draw->pt.user.eltBias = use_info->index_size ? use_info->index_bias : 0;
draw->pt.user.min_index = use_info->index_bounds_valid ? use_info->min_index : 0;
draw->pt.user.max_index = use_info->index_bounds_valid ? use_info->max_index : ~0;
draw->pt.user.eltSize = use_info->index_size ? draw->pt.user.eltSizeIB : 0;
if (0) {
for (unsigned i = 0; i < num_draws; i++)
- draw_print_arrays(draw, use_info->mode, use_draws[i].start, MIN2(use_draws[i].count, 20));
+ draw_print_arrays(draw, use_info->mode, use_draws[i].start, MIN2(use_draws[i].count, 20), use_draws[i].index_bias);
}
index_limit = util_draw_max_index(draw->pt.vertex_buffer,
int sh, i;
DUMP(draw_info, info);
- DUMP(draw_start_count, draw);
+ DUMP(draw_start_count_bias, draw);
if (indirect) {
if (indirect->buffer)
DUMP_M(resource, indirect, buffer);
trace_dump_member(uint, state, vertices_per_patch);
- trace_dump_member(int, state, index_bias);
trace_dump_member(uint, state, min_index);
trace_dump_member(uint, state, max_index);
trace_dump_struct_begin("pipe_draw_start_count_bias");
trace_dump_member(uint, state, start);
trace_dump_member(uint, state, count);
+ trace_dump_member(int, state, index_bias);
trace_dump_struct_end();
}
new_info.index_bounds_valid = info->index_bounds_valid;
new_info.min_index = info->min_index;
new_info.max_index = info->max_index;
- new_info.index_bias = info->index_size ? info->index_bias : 0;
new_info.start_instance = info->start_instance;
new_info.instance_count = info->instance_count;
new_info.primitive_restart = info->primitive_restart;
u_upload_alloc(pc->pipe->stream_uploader, 0, new_info.index_size * new_draw.count, 4,
&ib_offset, &new_info.index.resource, &dst);
new_draw.start = ib_offset / new_info.index_size;
+ new_draw.index_bias = info->index_size ? draw->index_bias : 0;
if (info->index_size) {
trans_func(src, draw->start, draw->count, new_draw.count, info->restart_index, dst);
draw.count = params[0];
info.instance_count = params[1];
draw.start = params[2];
- info.index_bias = info_in->index_size ? params[3] : 0;
+ draw.index_bias = info_in->index_size ? params[3] : 0;
info.start_instance = info_in->index_size ? params[4] : params[3];
info.drawid = i;
draw.start = start;
draw.count = count;
+ draw.index_bias = 0;
pipe->draw_vbo(pipe, &info, NULL, &draw, 1);
}
info.has_user_indices = true;
info.index_size = index_size;
info.mode = mode;
- info.index_bias = index_bias;
+ draw.index_bias = index_bias;
draw.start = start;
draw.count = count;
draw.start = start;
draw.count = count;
+ draw.index_bias = 0;
pipe->draw_vbo(pipe, &info, NULL, &draw, 1);
}
info.has_user_indices = true;
info.index_size = index_size;
info.mode = mode;
- info.index_bias = index_bias;
+ draw.index_bias = index_bias;
info.start_instance = start_instance;
info.instance_count = instance_count;
util_dump_draw_info(FILE *stream, const struct pipe_draw_info *state);
void
-util_dump_draw_start_count(FILE *stream, const struct pipe_draw_start_count_bias *state);
+util_dump_draw_start_count_bias(FILE *stream, const struct pipe_draw_start_count_bias *state);
void
util_dump_draw_indirect_info(FILE *stream,
util_dump_member(stream, uint, state, vertices_per_patch);
- util_dump_member(stream, int, state, index_bias);
util_dump_member(stream, uint, state, min_index);
util_dump_member(stream, uint, state, max_index);
}
void
-util_dump_draw_start_count(FILE *stream, const struct pipe_draw_start_count_bias *state)
+util_dump_draw_start_count_bias(FILE *stream, const struct pipe_draw_start_count_bias *state)
{
util_dump_struct_begin(stream, "pipe_draw_start_count_bias");
util_dump_member(stream, uint, state, start);
util_dump_member(stream, uint, state, count);
+ util_dump_member(stream, int, state, index_bias);
util_dump_struct_end(stream);
}
info->has_user_indices = false;
info->index_bounds_valid = false;
info->take_index_buffer_ownership = false;
- info->_pad = 0;
+ info->index_bias_varies = false;
+ info->_pad2 = 0;
/* This shouldn't be set when merging single draws. */
info->increment_draw_id = false;
info->restart_index = 0;
} else {
assert(!info->primitive_restart);
- info->index_bias = 0;
info->primitive_restart = false;
info->restart_index = 0;
info->index.resource = NULL;
static bool
is_next_call_a_mergeable_draw(struct tc_draw_single *first_info,
struct tc_call *next,
- struct tc_draw_single **next_info)
+ struct tc_draw_single **next_info,
+ int *index_bias)
{
if (next->call_id != TC_CALL_draw_single)
return false;
*next_info = (struct tc_draw_single*)&next->payload;
+ *index_bias = (*next_info)->info._pad2;
simplify_draw_info(&(*next_info)->info);
STATIC_ASSERT(offsetof(struct pipe_draw_info, min_index) ==
struct tc_call *next = first + first->num_call_slots;
struct tc_draw_single *first_info =
(struct tc_draw_single*)&first->payload;
- struct tc_draw_single *next_info;
+ struct tc_draw_single *next_info = NULL;
+ int first_index_bias = first_info->info._pad2;
+ int index_bias = 0;
+ bool index_bias_varies = false;
simplify_draw_info(&first_info->info);
/* If at least 2 consecutive draw calls can be merged... */
if (next != last && next->call_id == TC_CALL_draw_single &&
first_info->info.drawid == 0 &&
- is_next_call_a_mergeable_draw(first_info, next, &next_info)) {
+ is_next_call_a_mergeable_draw(first_info, next, &next_info, &index_bias)) {
/* Merge up to 256 draw calls. */
struct pipe_draw_start_count_bias multi[256];
unsigned num_draws = 2;
/* u_threaded_context stores start/count in min/max_index for single draws. */
multi[0].start = first_info->info.min_index;
multi[0].count = first_info->info.max_index;
+ multi[0].index_bias = first_index_bias;
multi[1].start = next_info->info.min_index;
multi[1].count = next_info->info.max_index;
+ multi[1].index_bias = index_bias;
+ index_bias_varies = first_index_bias != index_bias;
if (next_info->info.index_size)
pipe_resource_reference(&next_info->info.index.resource, NULL);
/* Find how many other draws can be merged. */
next = next + next->num_call_slots;
for (; next != last && num_draws < ARRAY_SIZE(multi) &&
- is_next_call_a_mergeable_draw(first_info, next, &next_info);
+ is_next_call_a_mergeable_draw(first_info, next, &next_info, &index_bias);
next += next->num_call_slots, num_draws++) {
/* u_threaded_context stores start/count in min/max_index for single draws. */
multi[num_draws].start = next_info->info.min_index;
multi[num_draws].count = next_info->info.max_index;
+ multi[num_draws].index_bias = index_bias;
+ index_bias_varies |= first_index_bias != index_bias;
if (next_info->info.index_size)
pipe_resource_reference(&next_info->info.index.resource, NULL);
}
+ first_info->info.index_bias_varies = index_bias_varies;
pipe->draw_vbo(pipe, &first_info->info, NULL, multi, num_draws);
if (first_info->info.index_size)
pipe_resource_reference(&first_info->info.index.resource, NULL);
iter = next;
continue;
+ } else {
+ /* reset original index_bias from before simplify_draw_info() */
+ first_info->info._pad2 = first_index_bias;
+ if (next != last && next->call_id == TC_CALL_draw_single && first_info->info.drawid == 0 && next_info)
+ /* in this case, simplify_draw_info() will have zeroed the data here as well */
+ next_info->info._pad2 = index_bias;
}
}
/* u_threaded_context stores start/count in min/max_index for single draws. */
/* Drivers using u_threaded_context shouldn't use min/max_index. */
- struct pipe_draw_start_count_bias *draw =
- (struct pipe_draw_start_count_bias *)&info->info.min_index;
- STATIC_ASSERT(offsetof(struct pipe_draw_start_count_bias, start) == 0);
- STATIC_ASSERT(offsetof(struct pipe_draw_start_count_bias, count) == 4);
+ struct pipe_draw_start_count_bias draw;
+
+ draw.start = info->info.min_index;
+ draw.count = info->info.max_index;
+ draw.index_bias = info->info._pad2;
info->info.index_bounds_valid = false;
info->info.has_user_indices = false;
info->info.take_index_buffer_ownership = false;
- pipe->draw_vbo(pipe, &info->info, NULL, draw, 1);
+ pipe->draw_vbo(pipe, &info->info, NULL, &draw, 1);
if (info->info.index_size)
pipe_resource_reference(&info->info.index.resource, NULL);
}
/* u_threaded_context stores start/count in min/max_index for single draws. */
p->info.min_index = offset >> util_logbase2(index_size);
p->info.max_index = draws[0].count;
+ p->info._pad2 = draws[0].index_bias;
} else {
/* Non-indexed call or indexed with a real index buffer. */
struct tc_draw_single *p =
/* u_threaded_context stores start/count in min/max_index for single draws. */
p->info.min_index = draws[0].start;
p->info.max_index = draws[0].count;
+ p->info._pad2 = draws[0].index_bias;
}
return;
}
if (!count) {
p->slot[i].start = 0;
p->slot[i].count = 0;
+ p->slot[i].index_bias = 0;
continue;
}
(draws[i + total_offset].start << index_size_shift), size);
p->slot[i].start = (buffer_offset + offset) >> index_size_shift;
p->slot[i].count = count;
+ p->slot[i].index_bias = draws[i + total_offset].index_bias;
offset += size;
}
draw.count = indirect_data[offset + 0];
info->instance_count = indirect_data[offset + 1];
draw.start = indirect_data[offset + 2];
- info->index_bias = indirect_data[offset + 3];
+ draw.index_bias = indirect_data[offset + 3];
info->start_instance = indirect_data[offset + 4];
u_vbuf_draw_vbo(mgr, info, NULL, draw);
* The driver will not look at these values because indirect != NULL.
* These values determine the user buffer bounds to upload.
*/
- new_info.index_bias = index_bias0;
+ new_draw.index_bias = index_bias0;
new_info.index_bounds_valid = true;
new_info.min_index = ~0u;
new_info.max_index = 0;
assert(min_index <= max_index);
- start_vertex = min_index + new_info.index_bias;
+ start_vertex = min_index + new_draw.index_bias;
num_vertices = max_index + 1 - min_index;
/* Primitive restart doesn't work when unrolling indices.
if (unroll_indices) {
new_info.index_size = 0;
- new_info.index_bias = 0;
+ new_draw.index_bias = 0;
new_info.index_bounds_valid = true;
new_info.min_index = 0;
new_info.max_index = new_draw.count - 1;
size += 4;
break;
case D3D12_STATE_VAR_FIRST_VERTEX:
- ptr[0] = dinfo->index_size ? dinfo->index_bias : draw->start;
+ ptr[0] = dinfo->index_size ? draw->index_bias : draw->start;
size += 4;
break;
case D3D12_STATE_VAR_DEPTH_TRANSFORM:
if (dinfo->index_size > 0)
ctx->cmdlist->DrawIndexedInstanced(draws[0].count, dinfo->instance_count,
- draws[0].start, dinfo->index_bias,
+ draws[0].start, draws[0].index_bias,
dinfo->start_instance);
else
ctx->cmdlist->DrawInstanced(draws[0].count, dinfo->instance_count,
if (screen->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, info->instance_count,
- draws[0].count, info->index_size ? info->index_bias : draws[0].start);
+ draws[0].count, info->index_size ? draws->index_bias : draws[0].start);
} else {
if (info->index_size)
- etna_draw_indexed_primitives(ctx->stream, draw_mode, 0, prims, info->index_bias);
+ etna_draw_indexed_primitives(ctx->stream, draw_mode, 0, prims, draws->index_bias);
else
etna_draw_primitives(ctx->stream, draw_mode, draws[0].start, prims);
}
OUT_PKT0(ring, REG_A3XX_VFD_INDEX_MIN, 4);
OUT_RING(ring, info->index_bounds_valid
? add_sat(info->min_index,
- info->index_size ? info->index_bias : 0)
+ info->index_size ? emit->draw->index_bias : 0)
: 0); /* VFD_INDEX_MIN */
OUT_RING(ring, info->index_bounds_valid
? add_sat(info->max_index,
- info->index_size ? info->index_bias : 0)
+ info->index_size ? emit->draw->index_bias : 0)
: ~0); /* VFD_INDEX_MAX */
OUT_RING(ring, info->start_instance); /* VFD_INSTANCEID_OFFSET */
- OUT_RING(ring, info->index_size ? info->index_bias
+ OUT_RING(ring, info->index_size ? emit->draw->index_bias
: emit->draw->start); /* VFD_INDEX_OFFSET */
OUT_PKT0(ring, REG_A3XX_PC_RESTART_INDEX, 1);
fd4_emit_vertex_bufs(ring, emit);
OUT_PKT0(ring, REG_A4XX_VFD_INDEX_OFFSET, 2);
- OUT_RING(ring, info->index_size ? info->index_bias
+ OUT_RING(ring, info->index_size ? emit->draw->index_bias
: emit->draw->start); /* VFD_INDEX_OFFSET */
OUT_RING(ring, info->start_instance); /* ??? UNKNOWN_2209 */
fd5_emit_vertex_bufs(ring, emit);
OUT_PKT4(ring, REG_A5XX_VFD_INDEX_OFFSET, 2);
- OUT_RING(ring, info->index_size ? info->index_bias
+ OUT_RING(ring, info->index_size ? emit->draw->index_bias
: emit->draw->start); /* VFD_INDEX_OFFSET */
OUT_RING(ring, info->start_instance); /* VFD_INSTANCE_START_OFFSET */
}
}
- uint32_t index_start = info->index_size ? info->index_bias : draw->start;
+ uint32_t index_start = info->index_size ? draw->index_bias : draw->start;
if (ctx->last.dirty || (ctx->last.index_start != index_start)) {
OUT_PKT4(ring, REG_A6XX_VFD_INDEX_OFFSET, 1);
OUT_RING(ring, index_start); /* VFD_INDEX_OFFSET */
uint32_t offset = const_state->offsets.driver_param;
uint32_t vertex_params[IR3_DP_VS_COUNT] = {
[IR3_DP_DRAWID] = 0, /* filled by hw (CP_DRAW_INDIRECT_MULTI) */
- [IR3_DP_VTXID_BASE] = info->index_size ? info->index_bias : draw->start,
+ [IR3_DP_VTXID_BASE] = info->index_size ? draw->index_bias : draw->start,
[IR3_DP_INSTID_BASE] = info->start_instance,
[IR3_DP_VTXCNT_MAX] = ctx->streamout.max_tf_vtx,
};
changed = true;
ice->draw.params_valid = false;
} else {
- int firstvertex = info->index_size ? info->index_bias : draw->start;
+ int firstvertex = info->index_size ? draw->index_bias : draw->start;
if (!ice->draw.params_valid ||
ice->draw.params.firstvertex != firstvertex ||
prim.StartVertexLocation = sc->start;
if (draw->index_size) {
- prim.BaseVertexLocation += draw->index_bias;
+ prim.BaseVertexLocation += sc->index_bias;
}
}
}
lima_job_add_bo(job, LIMA_PIPE_GP, res->bo, LIMA_SUBMIT_BO_READ);
- unsigned start = info->index_size ? (ctx->min_index + info->index_bias) : draw->start;
+ unsigned start = info->index_size ? (ctx->min_index + draw->index_bias) : draw->start;
attribute[n++] = res->bo->va + pvb->buffer_offset + pve->src_offset
+ start * pvb->stride;
attribute[n++] = (pvb->stride << 11) |
{
struct push_context ctx;
unsigned i, index_size;
- bool apply_bias = info->index_size && info->index_bias;
+ bool apply_bias = info->index_size && draw->index_bias;
ctx.push = nv30->base.pushbuf;
ctx.translate = nv30->vertex->translate;
vb->buffer_offset, NOUVEAU_BO_RD);
if (apply_bias)
- data += info->index_bias * vb->stride;
+ data += draw->index_bias * vb->stride;
ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0);
}
nv30_draw_elements(nv30, shorten, info,
info->mode, draws[0].start, draws[0].count,
- info->instance_count, info->index_bias, info->index_size);
+ info->instance_count, draws[0].index_bias, info->index_size);
}
nv30_state_release(nv30);
unsigned i, index_size;
unsigned inst_count = info->instance_count;
unsigned vert_count = draw->count;
- bool apply_bias = info->index_size && info->index_bias;
+ bool apply_bias = info->index_size && draw->index_bias;
ctx.push = nv50->base.pushbuf;
ctx.translate = nv50->vertex->translate;
ctx.need_vertex_id = nv50->screen->base.class_3d >= NV84_3D_CLASS &&
nv50->vertprog->vp.need_vertex_id && (nv50->vertex->num_elements < 32);
- ctx.index_bias = info->index_size ? info->index_bias : 0;
+ ctx.index_bias = info->index_size ? draw->index_bias : 0;
ctx.instance_id = 0;
/* For indexed draws, gl_VertexID must be emitted for every vertex. */
data = vb->buffer.user;
if (apply_bias && likely(!(nv50->vertex->instance_bufs & (1 << i))))
- data += (ptrdiff_t)(info->index_size ? info->index_bias : 0) * vb->stride;
+ data += (ptrdiff_t)(info->index_size ? draw->index_bias : 0) * vb->stride;
ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0);
}
/* NOTE: caller must ensure that (min_index + index_bias) is >= 0 */
if (info->index_bounds_valid) {
- nv50->vb_elt_first = info->min_index + (info->index_size ? info->index_bias : 0);
+ nv50->vb_elt_first = info->min_index + (info->index_size ? draws->index_bias : 0);
nv50->vb_elt_limit = info->max_index - info->min_index;
} else {
nv50->vb_elt_first = 0;
nv50_draw_elements(nv50, shorten, info,
info->mode, draws[0].start, draws[0].count,
- info->instance_count, info->index_bias, info->index_size);
+ info->instance_count, draws->index_bias, info->index_size);
} else
if (unlikely(indirect && indirect->count_from_stream_output)) {
nva0_draw_stream_output(nv50, info, indirect);
/* NOTE: caller must ensure that (min_index + index_bias) is >= 0 */
if (info->index_bounds_valid) {
- nvc0->vb_elt_first = info->min_index + (info->index_size ? info->index_bias : 0);
+ nvc0->vb_elt_first = info->min_index + (info->index_size ? draws->index_bias : 0);
nvc0->vb_elt_limit = info->max_index - info->min_index;
} else {
nvc0->vb_elt_first = 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, info->index_size ? info->index_bias : 0);
+ PUSH_DATA (push, info->index_size ? draws->index_bias : 0);
PUSH_DATA (push, info->start_instance);
PUSH_DATA (push, info->drawid);
}
nvc0_draw_elements(nvc0, shorten, info,
info->mode, draws[0].start, draws[0].count,
- info->instance_count, info->index_bias, info->index_size);
+ info->instance_count, draws->index_bias, info->index_size);
} else {
nvc0_draw_arrays(nvc0,
info->mode, draws[0].start, draws[0].count,
sdraw.count = cmd->count;
single.start_instance = cmd->baseInstance;
single.instance_count = cmd->primCount;
- single.index_bias = cmd->baseVertex;
+ sdraw.index_bias = cmd->baseVertex;
} else {
DrawArraysIndirectCommand *cmd = (void *)buf_data;
sdraw.start = cmd->first;
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, sdraw.index_bias);
PUSH_DATA (push, single.start_instance);
PUSH_DATA (push, single.drawid + i);
}
{
struct push_context ctx;
unsigned i, index_size;
- unsigned index_bias = info->index_size ? info->index_bias : 0;
+ unsigned index_bias = info->index_size ? draw->index_bias : 0;
unsigned inst_count = info->instance_count;
unsigned vert_count = draw->count;
unsigned prim;
unsigned i;
unsigned a = nvc0->vertex->num_elements;
- if (!index_size || info->index_bias)
+ if (!index_size || draw->index_bias)
index_size = 4;
data = (uint32_t *)nouveau_scratch_get(&nvc0->base,
draw->count * index_size, &va, &bo);
nouveau_pushbuf_validate(push);
if (info->index_size) {
- if (!info->index_bias) {
+ if (!draw->index_bias) {
memcpy(data, ctx->idxbuf, draw->count * index_size);
} else {
switch (info->index_size) {
case 1:
- copy_indices_u8(data, ctx->idxbuf, info->index_bias, draw->count);
+ copy_indices_u8(data, ctx->idxbuf, draw->index_bias, draw->count);
break;
case 2:
- copy_indices_u16(data, ctx->idxbuf, info->index_bias, draw->count);
+ copy_indices_u16(data, ctx->idxbuf, draw->index_bias, draw->count);
break;
default:
- copy_indices_u32(data, ctx->idxbuf, info->index_bias, draw->count);
+ copy_indices_u32(data, ctx->idxbuf, draw->index_bias, draw->count);
break;
}
}
} else {
for (i = 0; i < draw->count; ++i)
- data[i] = i + (draw->start + info->index_bias);
+ data[i] = i + (draw->start + draw->index_bias);
}
format = (1 << NVC0_3D_VERTEX_ATTRIB_FORMAT_BUFFER__SHIFT) |
if (info->index_size) {
cfg.index_type = panfrost_translate_index_size(info->index_size);
cfg.indices = indices;
- cfg.base_vertex_offset = info->index_bias - ctx->offset_start;
+ cfg.base_vertex_offset = draw->index_bias - ctx->offset_start;
}
}
/* Take into account a negative bias */
ctx->indirect_draw = false;
- ctx->vertex_count = draw->count + (info->index_size ? abs(info->index_bias) : 0);
+ ctx->vertex_count = draw->count + (info->index_size ? abs(draw->index_bias) : 0);
ctx->instance_count = info->instance_count;
ctx->active_prim = info->mode;
/* Use the corresponding values */
vertex_count = max_index - min_index + 1;
- ctx->offset_start = min_index + info->index_bias;
+ ctx->offset_start = min_index + draw->index_bias;
} else {
ctx->offset_start = draw->start;
}
panfrost_draw_emit_vertex(batch, info, &invocation, shared_mem,
vs_vary, varyings, attribs, attrib_bufs,
vertex.cpu);
- panfrost_draw_emit_tiler(batch, info, NULL, &invocation, shared_mem,
+ panfrost_draw_emit_tiler(batch, info, draw, &invocation, shared_mem,
index_buf ? index_buf->ptr.gpu : 0,
fs_vary, varyings, pos, psiz, tiler.cpu);
/* 19 dwords for r300_draw_elements_immediate. Give up if the function fails. */
if (!r300_prepare_for_rendering(r300,
PREP_EMIT_STATES | PREP_VALIDATE_VBOS | PREP_EMIT_VARRAYS |
- PREP_INDEXED, NULL, 2+count_dwords, 0, info->index_bias, -1))
+ PREP_INDEXED, NULL, 2+count_dwords, 0, draw->index_bias, -1))
return;
r300_emit_draw_init(r300, info->mode, info->max_index);
OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (draw->count << 16) |
r300_translate_primitive(info->mode));
- if (info->index_bias && !r300->screen->caps.is_r500) {
+ if (draw->index_bias && !r300->screen->caps.is_r500) {
for (i = 0; i < draw->count-1; i += 2)
- OUT_CS(((ptr1[i+1] + info->index_bias) << 16) |
- (ptr1[i] + info->index_bias));
+ OUT_CS(((ptr1[i+1] + draw->index_bias) << 16) |
+ (ptr1[i] + draw->index_bias));
if (draw->count & 1)
- OUT_CS(ptr1[i] + info->index_bias);
+ OUT_CS(ptr1[i] + draw->index_bias);
} else {
for (i = 0; i < draw->count-1; i += 2)
OUT_CS(((ptr1[i+1]) << 16) |
OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (draw->count << 16) |
r300_translate_primitive(info->mode));
- if (info->index_bias && !r300->screen->caps.is_r500) {
+ if (draw->index_bias && !r300->screen->caps.is_r500) {
for (i = 0; i < draw->count-1; i += 2)
- OUT_CS(((ptr2[i+1] + info->index_bias) << 16) |
- (ptr2[i] + info->index_bias));
+ OUT_CS(((ptr2[i+1] + draw->index_bias) << 16) |
+ (ptr2[i] + draw->index_bias));
if (draw->count & 1)
- OUT_CS(ptr2[i] + info->index_bias);
+ OUT_CS(ptr2[i] + draw->index_bias);
} else {
OUT_CS_TABLE(ptr2, count_dwords);
}
R300_VAP_VF_CNTL__INDEX_SIZE_32bit |
r300_translate_primitive(info->mode));
- if (info->index_bias && !r300->screen->caps.is_r500) {
+ if (draw->index_bias && !r300->screen->caps.is_r500) {
for (i = 0; i < draw->count; i++)
- OUT_CS(ptr4[i] + info->index_bias);
+ OUT_CS(ptr4[i] + draw->index_bias);
} else {
OUT_CS_TABLE(ptr4, count_dwords);
}
int buffer_offset = 0, index_offset = 0; /* for index bias emulation */
uint16_t indices3[3];
- if (info->index_bias && !r300->screen->caps.is_r500) {
- r300_split_index_bias(r300, info->index_bias, &buffer_offset,
+ if (draw->index_bias && !r300->screen->caps.is_r500) {
+ r300_split_index_bias(r300, draw->index_bias, &buffer_offset,
&index_offset);
}
/* 19 dwords for emit_draw_elements. Give up if the function fails. */
if (!r300_prepare_for_rendering(r300,
PREP_EMIT_STATES | PREP_VALIDATE_VBOS | PREP_EMIT_VARRAYS |
- PREP_INDEXED, indexBuffer, 19, buffer_offset, info->index_bias,
+ PREP_INDEXED, indexBuffer, 19, buffer_offset, draw->index_bias,
instance_id))
goto done;
if (count) {
if (!r300_prepare_for_rendering(r300,
PREP_VALIDATE_VBOS | PREP_EMIT_VARRAYS | PREP_INDEXED,
- indexBuffer, 19, buffer_offset, info->index_bias,
+ indexBuffer, 19, buffer_offset, draw->index_bias,
instance_id))
goto done;
}
index_offset -= start_offset;
has_user_indices = false;
}
- index_bias = info->index_bias;
+ index_bias = draws->index_bias;
} else {
index_bias = indirect ? 0 : draws[0].start;
}
* Also reserve space for stopping queries at the end of IB, because
* the number of active queries is unlimited in theory.
*/
- return 2048 + sctx->num_cs_dw_queries_suspend + num_draws * 9;
+ return 2048 + sctx->num_cs_dw_queries_suspend + num_draws * 10;
}
static inline void si_context_add_resource_size(struct si_context *sctx, struct pipe_resource *r)
unsigned sh_base_reg = sctx->shader_pointers.sh_base[PIPE_SHADER_VERTEX];
bool render_cond_bit = sctx->render_cond_enabled;
+ unsigned drawid_base = info->drawid;
if (indirect) {
assert(num_draws == 1);
}
/* Base vertex and start instance. */
- int base_vertex = original_index_size ? info->index_bias : draws[0].start;
+ int base_vertex = original_index_size ? draws[0].index_bias : draws[0].start;
bool set_draw_id = sctx->vs_uses_draw_id;
bool set_base_instance = sctx->vs_uses_base_instance;
(info->start_instance != sctx->last_start_instance ||
sctx->last_start_instance == SI_START_INSTANCE_UNKNOWN)) ||
(set_draw_id &&
- (info->drawid != sctx->last_drawid ||
+ (drawid_base != sctx->last_drawid ||
sctx->last_drawid == SI_DRAW_ID_UNKNOWN)) ||
sh_base_reg != sctx->last_sh_base_reg) {
if (set_base_instance) {
radeon_set_sh_reg_seq(cs, sh_base_reg + SI_SGPR_BASE_VERTEX * 4, 3);
radeon_emit(cs, base_vertex);
- radeon_emit(cs, info->drawid);
+ radeon_emit(cs, drawid_base);
radeon_emit(cs, info->start_instance);
sctx->last_start_instance = info->start_instance;
- sctx->last_drawid = info->drawid;
+ sctx->last_drawid = drawid_base;
} else if (set_draw_id) {
radeon_set_sh_reg_seq(cs, sh_base_reg + SI_SGPR_BASE_VERTEX * 4, 2);
radeon_emit(cs, base_vertex);
- radeon_emit(cs, info->drawid);
+ radeon_emit(cs, drawid_base);
- sctx->last_drawid = info->drawid;
+ sctx->last_drawid = drawid_base;
} else {
radeon_set_sh_reg(cs, sh_base_reg + SI_SGPR_BASE_VERTEX * 4, base_vertex);
}
}
/* Don't update draw_id in the following code if it doesn't increment. */
- set_draw_id &= info->increment_draw_id;
+ bool increment_draw_id = num_draws > 1 && set_draw_id && info->increment_draw_id;
if (index_size) {
if (ALLOW_PRIM_DISCARD_CS && dispatch_prim_discard_cs) {
return;
}
- for (unsigned i = 0; i < num_draws; i++) {
- uint64_t va = index_va + draws[i].start * index_size;
+ /* NOT_EOP allows merging multiple draws into 1 wave, but only user VGPRs
+ * can be changed between draws, and GS fast launch must be disabled.
+ * NOT_EOP doesn't work on gfx9 and older.
+ *
+ * Instead of doing this, which evaluates the case conditions repeatedly:
+ * for (all draws) {
+ * if (case1);
+ * else;
+ * }
+ *
+ * Use this structuring to evaluate the case conditions once:
+ * if (case1) for (all draws);
+ * else for (all draws);
+ *
+ */
+ bool index_bias_varies = num_draws > 1 && info->index_bias_varies;
- if (i > 0 && set_draw_id) {
- unsigned draw_id = info->drawid + i;
+ if (increment_draw_id) {
+ if (index_bias_varies) {
+ for (unsigned i = 0; i < num_draws; i++) {
+ uint64_t va = index_va + draws[i].start * index_size;
- radeon_set_sh_reg(cs, sh_base_reg + SI_SGPR_DRAWID * 4, draw_id);
- sctx->last_drawid = draw_id;
- }
+ if (i > 0) {
+ radeon_set_sh_reg_seq(cs, sh_base_reg + SI_SGPR_BASE_VERTEX * 4, 2);
+ radeon_emit(cs, draws[i].index_bias);
+ radeon_emit(cs, drawid_base + i);
+ }
- radeon_emit(cs, PKT3(PKT3_DRAW_INDEX_2, 4, render_cond_bit));
- radeon_emit(cs, index_max_size);
- radeon_emit(cs, va);
- radeon_emit(cs, va >> 32);
- radeon_emit(cs, draws[i].count);
- radeon_emit(cs, V_0287F0_DI_SRC_SEL_DMA |
- /* NOT_EOP allows merging multiple draws into 1 wave, but only user VGPRs
- * can be changed between draws and GS fast launch must be disabled.
- * NOT_EOP doesn't work on gfx9 and older.
- */
- S_0287F0_NOT_EOP(GFX_VERSION >= GFX10 &&
- !set_draw_id &&
- i < num_draws - 1));
+ radeon_emit(cs, PKT3(PKT3_DRAW_INDEX_2, 4, render_cond_bit));
+ radeon_emit(cs, index_max_size);
+ radeon_emit(cs, va);
+ radeon_emit(cs, va >> 32);
+ radeon_emit(cs, draws[i].count);
+ radeon_emit(cs, V_0287F0_DI_SRC_SEL_DMA); /* NOT_EOP disabled */
+ }
+ if (num_draws > 1) {
+ sctx->last_base_vertex = draws[num_draws - 1].index_bias;
+ sctx->last_drawid = drawid_base + num_draws - 1;
+ }
+ } else {
+ /* Only DrawID varies. */
+ for (unsigned i = 0; i < num_draws; i++) {
+ uint64_t va = index_va + draws[i].start * index_size;
+
+ if (i > 0)
+ radeon_set_sh_reg(cs, sh_base_reg + SI_SGPR_DRAWID * 4, drawid_base + i);
+
+ radeon_emit(cs, PKT3(PKT3_DRAW_INDEX_2, 4, render_cond_bit));
+ radeon_emit(cs, index_max_size);
+ radeon_emit(cs, va);
+ radeon_emit(cs, va >> 32);
+ radeon_emit(cs, draws[i].count);
+ radeon_emit(cs, V_0287F0_DI_SRC_SEL_DMA); /* NOT_EOP disabled */
+ }
+ if (num_draws > 1)
+ sctx->last_drawid = drawid_base + num_draws - 1;
+ }
+ } else {
+ if (info->index_bias_varies) {
+ /* Only BaseVertex varies. */
+ for (unsigned i = 0; i < num_draws; i++) {
+ uint64_t va = index_va + draws[i].start * index_size;
+
+ if (i > 0)
+ radeon_set_sh_reg(cs, sh_base_reg + SI_SGPR_BASE_VERTEX * 4, draws[i].index_bias);
+
+ radeon_emit(cs, PKT3(PKT3_DRAW_INDEX_2, 4, render_cond_bit));
+ radeon_emit(cs, index_max_size);
+ radeon_emit(cs, va);
+ radeon_emit(cs, va >> 32);
+ radeon_emit(cs, draws[i].count);
+ radeon_emit(cs, V_0287F0_DI_SRC_SEL_DMA); /* NOT_EOP disabled */
+ }
+ if (num_draws > 1)
+ sctx->last_base_vertex = draws[num_draws - 1].index_bias;
+ } else {
+ /* DrawID and BaseVertex are constant. */
+ for (unsigned i = 0; i < num_draws; i++) {
+ uint64_t va = index_va + draws[i].start * index_size;
+
+ radeon_emit(cs, PKT3(PKT3_DRAW_INDEX_2, 4, render_cond_bit));
+ radeon_emit(cs, index_max_size);
+ radeon_emit(cs, va);
+ radeon_emit(cs, va >> 32);
+ radeon_emit(cs, draws[i].count);
+ radeon_emit(cs, V_0287F0_DI_SRC_SEL_DMA |
+ S_0287F0_NOT_EOP(GFX_VERSION >= GFX10 && i < num_draws - 1));
+ }
+ }
}
} else {
/* Set the index buffer for fast launch. The VS prolog will load the indices. */
radeon_emit(cs, index_va >> 32);
if (i > 0) {
- if (set_draw_id) {
- unsigned draw_id = info->drawid + i;
+ if (increment_draw_id) {
+ unsigned draw_id = drawid_base + i;
radeon_set_sh_reg(cs, sh_base_reg + SI_SGPR_DRAWID * 4, draw_id);
sctx->last_drawid = draw_id;
for (unsigned i = 0; i < num_draws; i++) {
if (i > 0) {
- if (set_draw_id) {
- unsigned draw_id = info->drawid + i;
+ if (increment_draw_id) {
+ unsigned draw_id = drawid_base + i;
radeon_set_sh_reg_seq(cs, sh_base_reg + SI_SGPR_BASE_VERTEX * 4, 2);
radeon_emit(cs, draws[i].start);
ret = svga_hwtnl_simple_draw_range_elements(hwtnl, index_buffer,
info->index_size,
- info->index_bias,
+ draw->index_bias,
info->index_bounds_valid ? info->min_index : 0,
info->index_bounds_valid ? info->max_index : ~0,
gen_prim, index_offset, count,
ret = svga_hwtnl_simple_draw_range_elements(hwtnl,
gen_buf,
gen_size,
- info->index_bias,
+ draw->index_bias,
info->index_bounds_valid ? info->min_index : 0,
info->index_bounds_valid ? info->max_index : ~0,
gen_prim, gen_offset,
* always start from 0 for DrawArrays and does not include baseVertex for
* DrawIndexed.
*/
- unsigned index_bias = info->index_size ? info->index_bias : 0;
+ unsigned index_bias = info->index_size ? draws->index_bias : 0;
if (svga->curr.vertex_id_bias != (draws[0].start + index_bias)) {
svga->curr.vertex_id_bias = draws[0].start + index_bias;
svga->dirty |= SVGA_NEW_VS_CONSTS;
.index.user = indices,
.start_instance = 0,
.instance_count = 1,
- .index_bias = bias,
.index_bounds_valid = true,
.min_index = svga_render->min_index,
.max_index = svga_render->max_index,
const struct pipe_draw_start_count_bias draw = {
.start = 0,
.count = nr_indices,
+ .index_bias = bias,
};
assert((svga_render->vbuf_offset - svga_render->vdecl_offset)
draws[0].count,
info->instance_count,
draws[0].start,
- info->index_bias,
+ draws->index_bias,
info->start_instance);
else
ctx->api.pfnSwrDrawInstanced(ctx->swrContext,
uint32_t i,
uint32_t *totelems,
uint32_t *base,
- uint32_t *size)
+ uint32_t *size,
+ int index_bias)
{
/* FIXME: The size is too large - we don't access the full extra stride. */
unsigned elems;
*size = elems * elem_pitch;
} else if (vb->stride) {
elems = info->max_index - info->min_index + 1;
- *totelems = (info->max_index + (info->index_size ? info->index_bias : 0)) + 1;
- *base = (info->min_index + (info->index_size ? info->index_bias : 0)) * vb->stride;
+ *totelems = (info->max_index + (info->index_size ? index_bias : 0)) + 1;
+ *base = (info->min_index + (info->index_size ? index_bias : 0)) * vb->stride;
*size = elems * elem_pitch;
} else {
*totelems = 1;
post_update_dirty_flags |= SWR_NEW_VERTEX;
uint32_t base;
- swr_user_vbuf_range(&info, ctx->velems, vb, i, &elems, &base, &size);
+ swr_user_vbuf_range(&info, ctx->velems, vb, i, &elems, &base, &size, draw->index_bias);
partial_inbounds = 0;
- min_vertex_index = info.min_index + (info.index_size ? info.index_bias : 0);
+ min_vertex_index = info.min_index + (info.index_size ? draw->index_bias : 0);
size = AlignUp(size, 4);
/* If size of client memory copy is too large, don't copy. The
/* The Base Vertex/Base Instance packet sets those values to nonzero
* for the next draw call only.
*/
- if ((info->index_size && info->index_bias) || info->start_instance) {
+ if ((info->index_size && draws->index_bias) || info->start_instance) {
cl_emit(&job->bcl, BASE_VERTEX_BASE_INSTANCE, base) {
base.base_instance = info->start_instance;
- base.base_vertex = info->index_size ? info->index_bias : 0;
+ base.base_vertex = info->index_size ? draws->index_bias : 0;
}
}
static void
vc4_emit_gl_shader_state(struct vc4_context *vc4,
const struct pipe_draw_info *info,
+ const struct pipe_draw_start_count_bias *draws,
uint32_t extra_index_bias)
{
struct vc4_job *job = vc4->job;
};
uint32_t max_index = 0xffff;
- unsigned index_bias = info->index_size ? info->index_bias : 0;
+ unsigned index_bias = info->index_size ? draws->index_bias : 0;
for (int i = 0; i < vtx->num_elements; i++) {
struct pipe_vertex_element *elem = &vtx->pipe[i];
struct pipe_vertex_buffer *vb =
bool needs_drawarrays_shader_state = false;
- unsigned index_bias = info->index_size ? info->index_bias : 0;
+ unsigned index_bias = info->index_size ? draws->index_bias : 0;
if ((vc4->dirty & (VC4_DIRTY_VTXBUF |
VC4_DIRTY_VTXSTATE |
VC4_DIRTY_PRIM_MODE |
vc4->prog.fs->uniform_dirty_bits)) ||
vc4->last_index_bias != index_bias) {
if (info->index_size)
- vc4_emit_gl_shader_state(vc4, info, 0);
+ vc4_emit_gl_shader_state(vc4, info, draws, 0);
else
needs_drawarrays_shader_state = true;
}
uint32_t step;
if (needs_drawarrays_shader_state) {
- vc4_emit_gl_shader_state(vc4, info,
+ vc4_emit_gl_shader_state(vc4, info, draws,
extra_index_bias);
}
virgl_encoder_write_dword(ctx->cbuf, info->mode);
virgl_encoder_write_dword(ctx->cbuf, !!info->index_size);
virgl_encoder_write_dword(ctx->cbuf, info->instance_count);
- virgl_encoder_write_dword(ctx->cbuf, info->index_size ? info->index_bias : 0);
+ virgl_encoder_write_dword(ctx->cbuf, info->index_size ? draw->index_bias : 0);
virgl_encoder_write_dword(ctx->cbuf, info->start_instance);
virgl_encoder_write_dword(ctx->cbuf, info->primitive_restart);
virgl_encoder_write_dword(ctx->cbuf, info->primitive_restart ? info->restart_index : 0);
update_drawid(ctx, draw_id);
vkCmdDrawIndexed(batch->state->cmdbuf,
draws[i].count, dinfo->instance_count,
- need_index_buffer_unref ? 0 : draws[i].start, dinfo->index_bias, dinfo->start_instance);
+ need_index_buffer_unref ? 0 : draws[i].start, draws[i].index_bias, dinfo->start_instance);
if (dinfo->increment_draw_id)
draw_id++;
}
return;
cmd->u.draw_indexed.instance_count = instanceCount;
- cmd->u.draw_indexed.vertex_offset = vertexOffset;
cmd->u.draw_indexed.first_instance = firstInstance;
cmd->u.draw_indexed.draw_count = 1;
cmd->u.draw_indexed.draws[0].start = firstIndex;
cmd->u.draw_indexed.draws[0].count = indexCount;
+ cmd->u.draw_indexed.draws[0].index_bias = vertexOffset;
cmd->u.draw_indexed.calc_start = true;
cmd_buf_queue(cmd_buffer, cmd);
state->info.index.resource = state->index_buffer;
state->info.start_instance = cmd->u.draw_indexed.first_instance;
state->info.instance_count = cmd->u.draw_indexed.instance_count;
- state->info.index_bias = cmd->u.draw_indexed.vertex_offset;
state->info.view_mask = subpass->view_mask;
if (state->info.primitive_restart)
struct lvp_cmd_draw_indexed {
uint32_t instance_count;
- uint32_t vertex_offset;
uint32_t first_instance;
bool calc_start;
uint32_t draw_count;
draw.instance_count = 1;
draw.index_size = 0;
sc.start = 0;
- draw.index_bias = 0;
+ sc.index_bias = 0;
draw.min_index = 0;
draw.max_index = VertexCount - 1;
init_draw_info(&info, &draw, device, PrimitiveType, PrimitiveCount);
info.index_size = 0;
draw.start = StartVertex;
- info.index_bias = 0;
+ draw.index_bias = 0;
info.min_index = draw.start;
info.max_index = draw.start + draw.count - 1;
info.index.resource = NULL;
init_draw_info(&info, &draw, device, PrimitiveType, PrimitiveCount);
info.index_size = context->index_size;
draw.start = context->index_offset / context->index_size + StartIndex;
- info.index_bias = BaseVertexIndex;
+ draw.index_bias = BaseVertexIndex;
info.index_bounds_valid = true;
/* These don't include index bias: */
info.min_index = MinVertexIndex;
init_draw_info(&info, &draw, device, PrimitiveType, PrimitiveCount);
info.index_size = index_size;
draw.start = index_offset / info.index_size;
- info.index_bias = 0;
+ draw.index_bias = 0;
info.index_bounds_valid = true;
info.min_index = MinVertexIndex;
info.max_index = MinVertexIndex + NumVertices - 1;
* - PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS: Indirect draw count
*
* Differences against glMultiDraw and glMultiMode:
- * - "info->mode" and "info->index_bias" are always constant due to the lack
+ * - "info->mode" and "draws->index_bias" are always constant due to the lack
* of hardware support and CPU performance concerns. Only start and count
* vary.
* - if "info->increment_draw_id" is false, draw_id doesn't change between
bool increment_draw_id:1; /**< whether drawid increments for direct draws */
bool take_index_buffer_ownership:1; /**< callee inherits caller's refcount
(no need to reference indexbuf, but still needs to unreference it) */
- char _pad:1; /**< padding for memcmp */
+ bool index_bias_varies:1; /**< true if index_bias varies between draws */
unsigned start_instance; /**< first instance id */
unsigned instance_count; /**< number of instances */
unsigned drawid; /**< id of this draw in a multidraw */
-
- /**
- * For indexed drawing, these fields apply after index lookup.
- */
- int index_bias; /**< a bias to be added to each index */
+ int _pad2; /**< padding for memcmp and index_bias reuse */
/**
* Primitive restart enable/index (only applies to indexed drawing)
info.mode = PIPE_PRIM_TRIANGLES;
draw.start = 0;
draw.count = 3;
+ draw.index_bias = 0;
/* draw NUM_INST triangles */
info.instance_count = NUM_INST;
unsigned num_draws);
/**
- * Same as DrawGallium, but base_vertex and mode can also change between draws.
+ * Same as DrawGallium, but mode can also change between draws.
*
- * If index_bias != NULL, index_bias changes for each draw.
* If mode != NULL, mode changes for each draw.
* At least one of them must be non-NULL.
*
* "info" is not const and the following fields can be changed by
* the callee in addition to the fields listed by DrawGallium:
* - info->mode (if mode != NULL)
- * - info->index_bias (if index_bias != NULL)
*
* This function exists to decrease complexity of DrawGallium.
*/
struct pipe_draw_info *info,
const struct pipe_draw_start_count_bias *draws,
const unsigned char *mode,
- const int *base_vertex,
unsigned num_draws);
/**
prim.end = 1;
prim.start = index_size && info->has_user_indices ? 0 : draws[i].start;
prim.count = draws[i].count;
- prim.basevertex = index_size ? info->index_bias : 0;
+ prim.basevertex = index_size ? draws[i].index_bias : 0;
prim.draw_id = info->drawid + (info->increment_draw_id ? i : 0);
if (!index_size) {
prim[num_prims].end = 1;
prim[num_prims].start = draws[i].start;
prim[num_prims].count = draws[i].count;
- prim[num_prims].basevertex = info->index_size ? info->index_bias : 0;
+ prim[num_prims].basevertex = info->index_size ? draws[i].index_bias : 0;
prim[num_prims].draw_id = info->drawid + (info->increment_draw_id ? i : 0);
if (!index_size) {
struct pipe_draw_info *info,
const struct pipe_draw_start_count_bias *draws,
const unsigned char *mode,
- const int *base_vertex,
unsigned num_draws)
{
- enum {
- MODE = 1,
- BASE_VERTEX = 2,
- };
- unsigned mask = (mode ? MODE : 0) | (base_vertex ? BASE_VERTEX : 0);
unsigned i, first;
-
+
/* Find consecutive draws where mode and base_vertex don't vary. */
- switch (mask) {
- case MODE:
- for (i = 0, first = 0; i <= num_draws; i++) {
- if (i == num_draws || mode[i] != mode[first]) {
- info->mode = mode[first];
- ctx->Driver.DrawGallium(ctx, info, &draws[first], i - first);
- first = i;
- }
- }
- break;
-
- case BASE_VERTEX:
- for (i = 0, first = 0; i <= num_draws; i++) {
- if (i == num_draws || base_vertex[i] != base_vertex[first]) {
- info->index_bias = base_vertex[first];
- ctx->Driver.DrawGallium(ctx, info, &draws[first], i - first);
- first = i;
- }
+ for (i = 0, first = 0; i <= num_draws; i++) {
+ if (i == num_draws || mode[i] != mode[first]) {
+ info->mode = mode[first];
+ ctx->Driver.DrawGallium(ctx, info, &draws[first], i - first);
+ first = i;
}
- break;
-
- case MODE | BASE_VERTEX:
- for (i = 0, first = 0; i <= num_draws; i++) {
- if (i == num_draws ||
- mode[i] != mode[first] ||
- base_vertex[i] != base_vertex[first]) {
- info->mode = mode[first];
- info->index_bias = base_vertex[first];
- ctx->Driver.DrawGallium(ctx, info, &draws[first], i - first);
- first = i;
- }
- }
- break;
-
- default:
- assert(!"invalid parameters in DrawGalliumComplex");
- break;
}
}
-
-
+
/**
* Check that element 'j' of the array has reasonable data.
* Map VBO if needed.
info.index_bounds_valid = true;
info.increment_draw_id = false;
info.take_index_buffer_ownership = false;
- info._pad = 0;
+ info.index_bias_varies = false;
/* Packed section end. */
+ info._pad2 = 0;
info.start_instance = baseInstance;
info.instance_count = numInstances;
info.drawid = 0;
info.index_bounds_valid = false;
info.increment_draw_id = primcount > 1;
info.take_index_buffer_ownership = false;
- info._pad = 0;
+ info.index_bias_varies = false;
/* Packed section end. */
+ info._pad2 = 0;
info.start_instance = 0;
info.instance_count = 1;
info.drawid = 0;
info.index_bounds_valid = index_bounds_valid;
info.increment_draw_id = false;
info.take_index_buffer_ownership = false;
- info._pad = 0;
+ info.index_bias_varies = false;
/* Packed section end. */
+ info._pad2 = 0;
info.start_instance = baseInstance;
info.instance_count = numInstances;
info.drawid = 0;
info.view_mask = 0;
- info.index_bias = basevertex;
info.restart_index = ctx->Array._RestartIndex[index_size_shift];
if (info.has_user_indices) {
info.index.gl_bo = index_bo;
draw.start = (uintptr_t)indices >> index_size_shift;
}
+ draw.index_bias = basevertex;
info.min_index = start;
info.max_index = end;
}
}
- /* See if BaseVertex is constant across all draws. */
- bool basevertex_is_constant = true;
- if (basevertex) {
- for (int i = 1; i < primcount; i++) {
- if (basevertex[i] != basevertex[0]) {
- basevertex_is_constant = false;
- break;
- }
- }
- }
-
struct gl_buffer_object *index_bo = ctx->Array.VAO->IndexBufferObj;
struct pipe_draw_info info;
info.index_bounds_valid = false;
info.increment_draw_id = primcount > 1;
info.take_index_buffer_ownership = false;
- info._pad = 0;
+ info.index_bias_varies = !!basevertex;
/* Packed section end. */
+ info._pad2 = 0;
info.start_instance = 0;
info.instance_count = 1;
info.drawid = 0;
draw[i].start =
((uintptr_t)indices[i] - min_index_ptr) >> index_size_shift;
draw[i].count = count[i];
+ draw[i].index_bias = basevertex ? basevertex[i] : 0;
}
} else {
for (int i = 0; i < primcount; i++) {
draw[i].start = (uintptr_t)indices[i] >> index_size_shift;
draw[i].count = count[i];
+ draw[i].index_bias = basevertex ? basevertex[i] : 0;
}
}
- if (basevertex_is_constant) {
- info.index_bias = basevertex ? basevertex[0] : 0;
- ctx->Driver.DrawGallium(ctx, &info, draw, primcount);
- } else {
- ctx->Driver.DrawGalliumComplex(ctx, &info, draw, NULL, basevertex,
- primcount);
- }
+ ctx->Driver.DrawGallium(ctx, &info, draw, primcount);
FREE_PRIMS(draw, primcount);
} else {
/* draw[i].start would overflow. Draw one at a time. */
/* Reset these, because the callee can change them. */
info.index_bounds_valid = false;
- info.index_bias = basevertex ? basevertex[i] : 0;
info.drawid = i;
info.index.user = indices[i];
draw.start = 0;
+ draw.index_bias = basevertex ? basevertex[i] : 0;
draw.count = count[i];
ctx->Driver.DrawGallium(ctx, &info, &draw, 1);
struct pipe_draw_info *info,
const struct pipe_draw_start_count_bias *draws,
const unsigned char *mode,
- const int *base_vertex,
unsigned num_draws);
void GLAPIENTRY
struct pipe_draw_info *info,
const struct pipe_draw_start_count_bias *draws,
const unsigned char *mode,
- const int *base_vertex,
unsigned num_draws)
{
struct st_context *st = st_context(ctx);
if (!prepare_indexed_draw(st, ctx, info, draws, num_draws))
return;
- enum {
- MODE = 1,
- BASE_VERTEX = 2,
- };
- unsigned mask = (mode ? MODE : 0) | (base_vertex ? BASE_VERTEX : 0);
unsigned i, first;
struct cso_context *cso = st->cso_context;
/* Find consecutive draws where mode and base_vertex don't vary. */
- switch (mask) {
- case MODE:
- for (i = 0, first = 0; i <= num_draws; i++) {
- if (i == num_draws || mode[i] != mode[first]) {
- info->mode = mode[first];
- cso_multi_draw(cso, info, &draws[first], i - first);
- first = i;
-
- /* We can pass the reference only once. st_buffer_object keeps
- * the reference alive for later draws.
- */
- info->take_index_buffer_ownership = false;
- }
- }
- break;
-
- case BASE_VERTEX:
- for (i = 0, first = 0; i <= num_draws; i++) {
- if (i == num_draws || base_vertex[i] != base_vertex[first]) {
- info->index_bias = base_vertex[first];
- cso_multi_draw(cso, info, &draws[first], i - first);
- first = i;
-
- /* We can pass the reference only once. st_buffer_object keeps
- * the reference alive for later draws.
- */
- info->take_index_buffer_ownership = false;
- }
- }
- break;
-
- case MODE | BASE_VERTEX:
- for (i = 0, first = 0; i <= num_draws; i++) {
- if (i == num_draws ||
- mode[i] != mode[first] ||
- base_vertex[i] != base_vertex[first]) {
- info->mode = mode[first];
- info->index_bias = base_vertex[first];
- cso_multi_draw(cso, info, &draws[first], i - first);
- first = i;
-
- /* We can pass the reference only once. st_buffer_object keeps
- * the reference alive for later draws.
- */
- info->take_index_buffer_ownership = false;
- }
+ for (i = 0, first = 0; i <= num_draws; i++) {
+ if (i == num_draws || mode[i] != mode[first]) {
+ info->mode = mode[first];
+ cso_multi_draw(cso, info, &draws[first], i - first);
+ first = i;
+
+ /* We can pass the reference only once. st_buffer_object keeps
+ * the reference alive for later draws.
+ */
+ info->take_index_buffer_ownership = false;
}
- break;
-
- default:
- assert(!"invalid parameters in DrawGalliumComplex");
- break;
}
}
d.start = start + prims[i].start;
info.mode = prims[i].mode;
- info.index_bias = prims[i].basevertex;
+ d.index_bias = prims[i].basevertex;
info.drawid = prims[i].draw_id;
if (!ib) {
info.min_index = d.start;
ctx->Driver.DrawGalliumComplex(ctx, &exec->vtx.info,
exec->vtx.draw,
exec->vtx.mode,
- NULL,
exec->vtx.prim_count);
/* Get new storage -- unless asked not to. */
for (unsigned i = 0; i < merged_prim_count; i++) {
node->merged.start_count[i].start = merged_prims[i].start;
node->merged.start_count[i].count = merged_prims[i].count;
+ node->merged.start_count[i].index_bias = 0;
if (merged_prim_count > 1)
node->merged.mode[i] = merged_prims[i].mode;
}
ctx->Driver.DrawGalliumComplex(ctx, info,
node->merged.start_count,
node->merged.mode,
- NULL,
node->merged.num_draws);
} else {
ctx->Driver.DrawGallium(ctx, info,