gallium: move count_from_stream_output into pipe_draw_indirect_info

This removes some overhead from tc_draw_vbo and increases the maximum number
of draws per batch from 153 to 192 in u_threaded_context.

Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7441>
This commit is contained in:
Marek Olšák 2020-10-30 09:53:50 -04:00 committed by Marge Bot
parent 238ee7b801
commit 1a717dca04
40 changed files with 196 additions and 165 deletions

View File

@ -1727,10 +1727,14 @@ cso_draw_vbo(struct cso_context *cso,
struct u_vbuf *vbuf = cso->vbuf_current;
/* We can't have both indirect drawing and SO-vertex-count drawing */
assert(info->indirect == NULL || info->count_from_stream_output == NULL);
assert(!info->indirect ||
info->indirect->buffer == NULL ||
info->indirect->count_from_stream_output == NULL);
/* We can't have SO-vertex-count drawing with an index buffer */
assert(info->count_from_stream_output == NULL || info->index_size == 0);
assert(info->index_size == 0 ||
!info->indirect ||
info->indirect->count_from_stream_output == NULL);
if (vbuf) {
u_vbuf_draw_vbo(vbuf, info);

View File

@ -445,9 +445,9 @@ resolve_draw_info(const struct pipe_draw_info *raw_info,
{
memcpy(info, raw_info, sizeof(struct pipe_draw_info));
if (raw_info->count_from_stream_output) {
if (raw_info->indirect && raw_info->indirect->count_from_stream_output) {
struct draw_so_target *target =
(struct draw_so_target *)info->count_from_stream_output;
(struct draw_so_target *)info->indirect->count_from_stream_output;
assert(vertex_buffer != NULL);
info->count = vertex_buffer->stride == 0 ? 0 :
target->internal_offset / vertex_buffer->stride;
@ -455,6 +455,7 @@ resolve_draw_info(const struct pipe_draw_info *raw_info,
/* Stream output draw can not be indexed */
debug_assert(!info->index_size);
info->max_index = info->count - 1;
info->indirect = NULL;
}
}

View File

@ -356,13 +356,14 @@ dd_dump_draw_vbo(struct dd_draw_state *dstate, struct pipe_draw_info *info, FILE
int sh, i;
DUMP(draw_info, info);
if (info->count_from_stream_output)
DUMP_M(stream_output_target, info,
count_from_stream_output);
if (info->indirect) {
DUMP_M(resource, info, indirect->buffer);
if (info->indirect->buffer)
DUMP_M(resource, info, indirect->buffer);
if (info->indirect->indirect_draw_count)
DUMP_M(resource, info, indirect->indirect_draw_count);
if (info->indirect->count_from_stream_output)
DUMP_M(stream_output_target, info,
indirect->count_from_stream_output);
}
fprintf(f, "\n");
@ -705,7 +706,7 @@ dd_unreference_copy_of_call(struct dd_call *dst)
case CALL_FLUSH:
break;
case CALL_DRAW_VBO:
pipe_so_target_reference(&dst->info.draw_vbo.draw.count_from_stream_output, NULL);
pipe_so_target_reference(&dst->info.draw_vbo.indirect.count_from_stream_output, NULL);
pipe_resource_reference(&dst->info.draw_vbo.indirect.buffer, NULL);
pipe_resource_reference(&dst->info.draw_vbo.indirect.indirect_draw_count, NULL);
if (dst->info.draw_vbo.draw.index_size &&
@ -1305,9 +1306,6 @@ dd_context_draw_vbo(struct pipe_context *_pipe,
record->call.type = CALL_DRAW_VBO;
record->call.info.draw_vbo.draw = *info;
record->call.info.draw_vbo.draw.count_from_stream_output = NULL;
pipe_so_target_reference(&record->call.info.draw_vbo.draw.count_from_stream_output,
info->count_from_stream_output);
if (info->index_size && !info->has_user_indices) {
record->call.info.draw_vbo.draw.index.resource = NULL;
pipe_resource_reference(&record->call.info.draw_vbo.draw.index.resource,
@ -1324,6 +1322,9 @@ dd_context_draw_vbo(struct pipe_context *_pipe,
record->call.info.draw_vbo.indirect.indirect_draw_count = NULL;
pipe_resource_reference(&record->call.info.draw_vbo.indirect.indirect_draw_count,
info->indirect->indirect_draw_count);
record->call.info.draw_vbo.indirect.count_from_stream_output = NULL;
pipe_so_target_reference(&record->call.info.draw_vbo.indirect.count_from_stream_output,
info->indirect->count_from_stream_output);
} else {
memset(&record->call.info.draw_vbo.indirect, 0, sizeof(*info->indirect));
}

View File

@ -793,7 +793,6 @@ void trace_dump_draw_info(const struct pipe_draw_info *state)
trace_dump_member(uint, state, restart_index);
trace_dump_member(ptr, state, index.resource);
trace_dump_member(ptr, state, count_from_stream_output);
if (!state->indirect) {
trace_dump_member(ptr, state, indirect);
@ -804,6 +803,7 @@ void trace_dump_draw_info(const struct pipe_draw_info *state)
trace_dump_member(uint, state, indirect->indirect_draw_count_offset);
trace_dump_member(ptr, state, indirect->buffer);
trace_dump_member(ptr, state, indirect->indirect_draw_count);
trace_dump_member(ptr, state, indirect->count_from_stream_output);
}
trace_dump_struct_end();

View File

@ -139,7 +139,7 @@ util_draw_indirect(struct pipe_context *pipe,
unsigned num_params = info_in->index_size ? 5 : 4;
assert(info_in->indirect);
assert(!info_in->count_from_stream_output);
assert(!info_in->indirect->count_from_stream_output);
memcpy(&info, info_in, sizeof(info));

View File

@ -941,7 +941,6 @@ util_dump_draw_info(FILE *stream, const struct pipe_draw_info *state)
else
util_dump_member(stream, ptr, state, index.resource);
}
util_dump_member(stream, ptr, state, count_from_stream_output);
if (!state->indirect) {
util_dump_member(stream, ptr, state, indirect);
@ -952,6 +951,7 @@ util_dump_draw_info(FILE *stream, const struct pipe_draw_info *state)
util_dump_member(stream, uint, state, indirect->indirect_draw_count_offset);
util_dump_member(stream, ptr, state, indirect->buffer);
util_dump_member(stream, ptr, state, indirect->indirect_draw_count);
util_dump_member(stream, ptr, state, indirect->count_from_stream_output);
}
util_dump_struct_end(stream);

View File

@ -114,7 +114,7 @@ util_translate_prim_restart_ib(struct pipe_context *context,
dst_index_size = MAX2(2, info->index_size);
assert(dst_index_size == 2 || dst_index_size == 4);
if (info->indirect) {
if (info->indirect && info->indirect->buffer) {
indirect = read_indirect_elements(context, info->indirect);
count = indirect.count;
start = indirect.firstIndex;
@ -235,7 +235,7 @@ util_draw_vbo_without_prim_restart(struct pipe_context *context,
assert(info->index_size);
assert(info->primitive_restart);
if (info->indirect) {
if (info->indirect && info->indirect->buffer) {
indirect = read_indirect_elements(context, info->indirect);
info_count = indirect.count;
info_start = indirect.firstIndex;

View File

@ -126,7 +126,6 @@ tc_batch_execute(void *job, UNUSED int thread_index)
if (next != last && next->call_id == TC_CALL_draw_vbo &&
first_info->draw.drawid == 0 &&
!first_info->draw.indirect &&
!first_info->draw.count_from_stream_output &&
is_next_call_a_mergeable_draw(first_info, next, &next_info)) {
/* Merge up to 256 draw calls. */
struct pipe_draw_start_count multi[256];
@ -2199,12 +2198,12 @@ tc_call_draw_vbo(struct pipe_context *pipe, union tc_payload *payload)
struct tc_full_draw_info *info = (struct tc_full_draw_info*)payload;
pipe->draw_vbo(pipe, &info->draw);
pipe_so_target_reference(&info->draw.count_from_stream_output, NULL);
if (info->draw.index_size)
pipe_resource_reference(&info->draw.index.resource, NULL);
if (info->draw.indirect) {
pipe_resource_reference(&info->indirect.buffer, NULL);
pipe_resource_reference(&info->indirect.indirect_draw_count, NULL);
pipe_so_target_reference(&info->indirect.count_from_stream_output, NULL);
}
}
@ -2243,9 +2242,6 @@ tc_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *info)
return;
struct tc_full_draw_info *p = tc_add_draw_vbo(_pipe, false);
p->draw.count_from_stream_output = NULL;
pipe_so_target_reference(&p->draw.count_from_stream_output,
info->count_from_stream_output);
memcpy(&p->draw, info, sizeof(*info));
p->draw.has_user_indices = false;
p->draw.index.resource = buffer;
@ -2253,9 +2249,6 @@ tc_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *info)
} else {
/* Non-indexed call or indexed with a real index buffer. */
struct tc_full_draw_info *p = tc_add_draw_vbo(_pipe, indirect != NULL);
p->draw.count_from_stream_output = NULL;
pipe_so_target_reference(&p->draw.count_from_stream_output,
info->count_from_stream_output);
if (index_size) {
tc_set_resource_reference(&p->draw.index.resource,
info->index.resource);
@ -2266,6 +2259,9 @@ tc_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *info)
tc_set_resource_reference(&p->draw.indirect->buffer, indirect->buffer);
tc_set_resource_reference(&p->indirect.indirect_draw_count,
indirect->indirect_draw_count);
p->indirect.count_from_stream_output = NULL;
pipe_so_target_reference(&p->indirect.count_from_stream_output,
indirect->count_from_stream_output);
memcpy(&p->indirect, indirect, sizeof(*indirect));
p->draw.indirect = &p->indirect;
}

View File

@ -1306,7 +1306,7 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info)
new_info = *info;
/* Handle indirect (multi)draws. */
if (new_info.indirect) {
if (new_info.indirect && new_info.indirect->buffer) {
const struct pipe_draw_indirect_info *indirect = new_info.indirect;
unsigned draw_count = 0;

View File

@ -231,7 +231,7 @@ etna_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
uint32_t draw_mode;
unsigned i;
if (!info->count_from_stream_output && !info->indirect &&
if (!info->indirect &&
!info->primitive_restart &&
!u_trim_pipe_prim(info->mode, (unsigned*)&info->count))
return;

View File

@ -97,7 +97,7 @@ fd4_draw_emit(struct fd_batch *batch, struct fd_ringbuffer *ring,
enum pc_di_src_sel src_sel;
uint32_t idx_size, idx_offset;
if (info->indirect) {
if (info->indirect && info->indirect->buffer) {
struct fd_resource *ind = fd_resource(info->indirect->buffer);
emit_marker(ring, 7);

View File

@ -91,7 +91,7 @@ fd5_draw_emit(struct fd_batch *batch, struct fd_ringbuffer *ring,
enum pc_di_src_sel src_sel;
uint32_t max_indices, idx_offset;
if (info->indirect) {
if (info->indirect && info->indirect->buffer) {
struct fd_resource *ind = fd_resource(info->indirect->buffer);
emit_marker5(ring, 7);

View File

@ -195,7 +195,7 @@ fd6_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info,
if (emit.key.gs)
emit.key.key.has_gs = true;
if (!(emit.key.hs || emit.key.ds || emit.key.gs || info->indirect))
if (!(emit.key.hs || emit.key.ds || emit.key.gs || (info->indirect && info->indirect->buffer)))
fd6_vsc_update_sizes(ctx->batch, info);
fixup_shader_state(ctx, &emit.key.key);
@ -315,7 +315,7 @@ fd6_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info,
*/
emit_marker6(ring, 7);
if (info->indirect) {
if (info->indirect && info->indirect->buffer) {
draw_emit_indirect(ring, &draw0, info, index_offset);
} else {
draw_emit(ring, &draw0, info, index_offset);

View File

@ -175,7 +175,7 @@ batch_draw_tracking(struct fd_batch *batch, const struct pipe_draw_info *info)
resource_read(batch, info->index.resource);
/* Mark indirect draw buffer as being read */
if (info->indirect)
if (info->indirect && info->indirect->buffer)
resource_read(batch, info->indirect->buffer);
/* Mark textures as being read */
@ -218,13 +218,13 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
* to be able to emulate it, to determine if game is feeding us
* bogus data:
*/
if (info->indirect && (fd_mesa_debug & FD_DBG_NOINDR)) {
if (info->indirect && info->indirect->buffer && (fd_mesa_debug & FD_DBG_NOINDR)) {
util_draw_indirect(pctx, info);
return;
}
if (info->mode != PIPE_PRIM_MAX &&
!info->count_from_stream_output && !info->indirect &&
!info->indirect &&
!info->primitive_restart &&
!u_trim_pipe_prim(info->mode, (unsigned*)&info->count))
return;

View File

@ -118,7 +118,7 @@ iris_update_draw_parameters(struct iris_context *ice,
if (ice->state.vs_uses_draw_params) {
struct iris_state_ref *draw_params = &ice->draw.draw_params;
if (info->indirect) {
if (info->indirect && info->indirect->buffer) {
pipe_resource_reference(&draw_params->res, info->indirect->buffer);
draw_params->offset =
info->indirect->offset + (info->index_size ? 12 : 8);
@ -192,7 +192,7 @@ iris_indirect_draw_vbo(struct iris_context *ice,
iris_update_draw_parameters(ice, &info);
batch->screen->vtbl.upload_render_state(ice, batch, &info);
batch->screen->vtbl.upload_render_state(ice, batch, &info, info.indirect);
ice->state.dirty &= ~IRIS_ALL_DIRTY_FOR_RENDER;
ice->state.stage_dirty &= ~IRIS_ALL_STAGE_DIRTY_FOR_RENDER;
@ -221,7 +221,7 @@ iris_simple_draw_vbo(struct iris_context *ice,
iris_update_draw_parameters(ice, draw);
batch->screen->vtbl.upload_render_state(ice, batch, draw);
batch->screen->vtbl.upload_render_state(ice, batch, draw, draw->indirect);
}
/**
@ -234,6 +234,7 @@ iris_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
struct iris_screen *screen = (struct iris_screen*)ice->ctx.screen;
const struct gen_device_info *devinfo = &screen->devinfo;
struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
struct pipe_draw_indirect_info *indirect = info->indirect;
if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
return;
@ -269,7 +270,7 @@ iris_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
iris_handle_always_flush_cache(batch);
if (info->indirect)
if (indirect && indirect->buffer)
iris_indirect_draw_vbo(ice, info);
else
iris_simple_draw_vbo(ice, info);

View File

@ -60,7 +60,8 @@ struct iris_vtable {
void (*init_compute_context)(struct iris_batch *batch);
void (*upload_render_state)(struct iris_context *ice,
struct iris_batch *batch,
const struct pipe_draw_info *draw);
const struct pipe_draw_info *draw,
const struct pipe_draw_indirect_info *indirect);
void (*update_surface_base_address)(struct iris_batch *batch,
struct iris_binder *binder);
void (*upload_compute_state)(struct iris_context *ice,

View File

@ -6417,7 +6417,8 @@ iris_upload_dirty_render_state(struct iris_context *ice,
static void
iris_upload_render_state(struct iris_context *ice,
struct iris_batch *batch,
const struct pipe_draw_info *draw)
const struct pipe_draw_info *draw,
const struct pipe_draw_indirect_info *indirect)
{
bool use_predicate = ice->state.predicate == IRIS_PREDICATE_STATE_USE_BIT;
@ -6492,14 +6493,14 @@ iris_upload_render_state(struct iris_context *ice,
#define _3DPRIM_START_INSTANCE 0x243C
#define _3DPRIM_BASE_VERTEX 0x2440
if (draw->indirect) {
if (draw->indirect->indirect_draw_count) {
if (indirect && !indirect->count_from_stream_output) {
if (indirect->indirect_draw_count) {
use_predicate = true;
struct iris_bo *draw_count_bo =
iris_resource_bo(draw->indirect->indirect_draw_count);
iris_resource_bo(indirect->indirect_draw_count);
unsigned draw_count_offset =
draw->indirect->indirect_draw_count_offset;
indirect->indirect_draw_count_offset;
iris_emit_pipe_control_flush(batch,
"ensure indirect draw buffer is flushed",
@ -6551,43 +6552,43 @@ iris_upload_render_state(struct iris_context *ice,
iris_batch_emit(batch, &mi_predicate, sizeof(uint32_t));
}
}
struct iris_bo *bo = iris_resource_bo(draw->indirect->buffer);
struct iris_bo *bo = iris_resource_bo(indirect->buffer);
assert(bo);
iris_emit_cmd(batch, GENX(MI_LOAD_REGISTER_MEM), lrm) {
lrm.RegisterAddress = _3DPRIM_VERTEX_COUNT;
lrm.MemoryAddress = ro_bo(bo, draw->indirect->offset + 0);
lrm.MemoryAddress = ro_bo(bo, indirect->offset + 0);
}
iris_emit_cmd(batch, GENX(MI_LOAD_REGISTER_MEM), lrm) {
lrm.RegisterAddress = _3DPRIM_INSTANCE_COUNT;
lrm.MemoryAddress = ro_bo(bo, draw->indirect->offset + 4);
lrm.MemoryAddress = ro_bo(bo, indirect->offset + 4);
}
iris_emit_cmd(batch, GENX(MI_LOAD_REGISTER_MEM), lrm) {
lrm.RegisterAddress = _3DPRIM_START_VERTEX;
lrm.MemoryAddress = ro_bo(bo, draw->indirect->offset + 8);
lrm.MemoryAddress = ro_bo(bo, indirect->offset + 8);
}
if (draw->index_size) {
iris_emit_cmd(batch, GENX(MI_LOAD_REGISTER_MEM), lrm) {
lrm.RegisterAddress = _3DPRIM_BASE_VERTEX;
lrm.MemoryAddress = ro_bo(bo, draw->indirect->offset + 12);
lrm.MemoryAddress = ro_bo(bo, indirect->offset + 12);
}
iris_emit_cmd(batch, GENX(MI_LOAD_REGISTER_MEM), lrm) {
lrm.RegisterAddress = _3DPRIM_START_INSTANCE;
lrm.MemoryAddress = ro_bo(bo, draw->indirect->offset + 16);
lrm.MemoryAddress = ro_bo(bo, indirect->offset + 16);
}
} else {
iris_emit_cmd(batch, GENX(MI_LOAD_REGISTER_MEM), lrm) {
lrm.RegisterAddress = _3DPRIM_START_INSTANCE;
lrm.MemoryAddress = ro_bo(bo, draw->indirect->offset + 12);
lrm.MemoryAddress = ro_bo(bo, indirect->offset + 12);
}
iris_emit_cmd(batch, GENX(MI_LOAD_REGISTER_IMM), lri) {
lri.RegisterOffset = _3DPRIM_BASE_VERTEX;
lri.DataDWord = 0;
}
}
} else if (draw->count_from_stream_output) {
} else if (indirect && indirect->count_from_stream_output) {
struct iris_stream_output_target *so =
(void *) draw->count_from_stream_output;
(void *) indirect->count_from_stream_output;
/* XXX: Replace with actual cache tracking */
iris_emit_pipe_control_flush(batch,
@ -6615,7 +6616,7 @@ iris_upload_render_state(struct iris_context *ice,
prim.VertexAccessType = draw->index_size > 0 ? RANDOM : SEQUENTIAL;
prim.PredicateEnable = use_predicate;
if (draw->indirect || draw->count_from_stream_output) {
if (indirect) {
prim.IndirectParameterEnable = true;
} else {
prim.StartInstanceLocation = draw->start_instance;

View File

@ -61,7 +61,7 @@ llvmpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
if (!llvmpipe_check_render_cond(lp))
return;
if (info->indirect) {
if (info->indirect && info->indirect->buffer) {
util_draw_indirect(pipe, info);
return;
}

View File

@ -292,10 +292,10 @@ nv50_push_vbo(struct nv50_context *nv50, const struct pipe_draw_info *info)
ctx.primitive_restart = info->primitive_restart;
ctx.restart_index = info->restart_index;
} else {
if (unlikely(info->count_from_stream_output)) {
if (unlikely(info->indirect && info->indirect->count_from_stream_output)) {
struct pipe_context *pipe = &nv50->base.pipe;
struct nv50_so_target *targ;
targ = nv50_so_target(info->count_from_stream_output);
targ = nv50_so_target(info->indirect->count_from_stream_output);
if (!targ->pq) {
NOUVEAU_ERR("draw_stream_output not supported on pre-NVA0 cards\n");
return;

View File

@ -702,7 +702,7 @@ nva0_draw_stream_output(struct nv50_context *nv50,
const struct pipe_draw_info *info)
{
struct nouveau_pushbuf *push = nv50->base.pushbuf;
struct nv50_so_target *so = nv50_so_target(info->count_from_stream_output);
struct nv50_so_target *so = nv50_so_target(info->indirect->count_from_stream_output);
struct nv04_resource *res = nv04_resource(so->pipe.buffer);
unsigned num_instances = info->instance_count;
unsigned mode = nv50_prim_gl(info->mode);
@ -874,7 +874,7 @@ nv50_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
info->mode, info->start, info->count,
info->instance_count, info->index_bias, info->index_size);
} else
if (unlikely(info->count_from_stream_output)) {
if (unlikely(info->indirect && info->indirect->count_from_stream_output)) {
nva0_draw_stream_output(nv50, info);
} else {
nv50_draw_arrays(nv50,

View File

@ -769,7 +769,7 @@ nvc0_draw_stream_output(struct nvc0_context *nvc0,
const struct pipe_draw_info *info)
{
struct nouveau_pushbuf *push = nvc0->base.pushbuf;
struct nvc0_so_target *so = nvc0_so_target(info->count_from_stream_output);
struct nvc0_so_target *so = nvc0_so_target(info->indirect->count_from_stream_output);
struct nv04_resource *res = nv04_resource(so->pipe.buffer);
unsigned mode = nvc0_prim_gl(info->mode);
unsigned num_instances = info->instance_count;
@ -938,7 +938,7 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
* if index count is larger and we expect repeated vertices, suggest upload.
*/
nvc0->vbo_push_hint =
!info->indirect && info->index_size &&
(!info->indirect || info->indirect->count_from_stream_output) && info->index_size &&
(nvc0->vb_elt_limit >= (info->count * 2));
/* Check whether we want to switch vertex-submission mode. */
@ -1005,7 +1005,7 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
nvc0_state_validate_3d(nvc0, ~0);
if (nvc0->vertprog->vp.need_draw_parameters && !info->indirect) {
if (nvc0->vertprog->vp.need_draw_parameters && (!info->indirect || info->indirect->count_from_stream_output)) {
PUSH_SPACE(push, 9);
BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
PUSH_DATA (push, NVC0_CB_AUX_SIZE);
@ -1057,7 +1057,7 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
}
if (nvc0->state.vbo_mode) {
if (info->indirect)
if (info->indirect && info->indirect->buffer)
nvc0_push_vbo_indirect(nvc0, info);
else
nvc0_push_vbo(nvc0, info);
@ -1088,10 +1088,10 @@ nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
nvc0->base.vbo_dirty = false;
}
if (unlikely(info->indirect)) {
if (unlikely(info->indirect && info->indirect->buffer)) {
nvc0_draw_indirect(nvc0, info);
} else
if (unlikely(info->count_from_stream_output)) {
if (unlikely(info->indirect && info->indirect->count_from_stream_output)) {
nvc0_draw_stream_output(nvc0, info);
} else
if (info->index_size) {

View File

@ -596,10 +596,10 @@ nvc0_push_vbo(struct nvc0_context *nvc0, const struct pipe_draw_info *info)
nvc0_push_map_idxbuf(&ctx, nvc0, info);
index_size = info->index_size;
} else {
if (unlikely(info->count_from_stream_output)) {
if (unlikely(info->indirect && info->indirect->count_from_stream_output)) {
struct pipe_context *pipe = &nvc0->base.pipe;
struct nvc0_so_target *targ;
targ = nvc0_so_target(info->count_from_stream_output);
targ = nvc0_so_target(info->indirect->count_from_stream_output);
pipe->get_query_result(pipe, targ->pq, true, (void *)&vert_count);
vert_count /= targ->stride;
}

View File

@ -363,8 +363,8 @@ panfrost_draw_emit_tiler(struct panfrost_batch *batch,
cfg.base_vertex_offset = info->index_bias - ctx->offset_start;
cfg.index_count = info->count;
} else {
cfg.index_count = info->count_from_stream_output ?
pan_so_target(info->count_from_stream_output)->offset :
cfg.index_count = info->indirect && info->indirect->count_from_stream_output ?
pan_so_target(info->indirect->count_from_stream_output)->offset :
ctx->vertex_count;
}
}

View File

@ -2065,8 +2065,15 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
int index_bias;
struct r600_shader_atomic combined_atomics[8];
uint8_t atomic_used_mask = 0;
struct pipe_draw_indirect_info *indirect = info->indirect;
struct pipe_stream_output_target *count_from_so = NULL;
if (!info->indirect && !info->count && (index_size || !info->count_from_stream_output)) {
if (indirect && indirect->count_from_stream_output) {
count_from_so = indirect->count_from_stream_output;
indirect = NULL;
}
if (!indirect && !info->count && (index_size || !count_from_so)) {
return;
}
@ -2137,17 +2144,17 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
void *ptr;
unsigned start, count;
if (likely(!info->indirect)) {
if (likely(!indirect)) {
start = 0;
count = info->count;
}
else {
/* Have to get start/count from indirect buffer, slow path ahead... */
struct r600_resource *indirect_resource = (struct r600_resource *)info->indirect->buffer;
struct r600_resource *indirect_resource = (struct r600_resource *)indirect->buffer;
unsigned *data = r600_buffer_map_sync_with_rings(&rctx->b, indirect_resource,
PIPE_MAP_READ);
if (data) {
data += info->indirect->offset / sizeof(unsigned);
data += indirect->offset / sizeof(unsigned);
start = data[2] * index_size;
count = data[0];
}
@ -2176,7 +2183,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
* and the indices are emitted via PKT3_DRAW_INDEX_IMMD.
* Indirect draws never use immediate indices.
* Note: Instanced rendering in combination with immediate indices hangs. */
if (has_user_indices && (R600_BIG_ENDIAN || info->indirect ||
if (has_user_indices && (R600_BIG_ENDIAN || indirect ||
info->instance_count > 1 ||
info->count*index_size > 20)) {
indexbuf = NULL;
@ -2194,7 +2201,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
if (rctx->vgt_state.vgt_multi_prim_ib_reset_en != info->primitive_restart ||
rctx->vgt_state.vgt_multi_prim_ib_reset_indx != info->restart_index ||
rctx->vgt_state.vgt_indx_offset != index_bias ||
(rctx->vgt_state.last_draw_was_indirect && !info->indirect)) {
(rctx->vgt_state.last_draw_was_indirect && !indirect)) {
rctx->vgt_state.vgt_multi_prim_ib_reset_en = info->primitive_restart;
rctx->vgt_state.vgt_multi_prim_ib_reset_indx = info->restart_index;
rctx->vgt_state.vgt_indx_offset = index_bias;
@ -2274,7 +2281,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
}
/* Update start instance. */
if (!info->indirect && rctx->last_start_instance != info->start_instance) {
if (!indirect && rctx->last_start_instance != info->start_instance) {
radeon_set_ctl_const(cs, R_03CFF4_SQ_VTX_START_INST_LOC, info->start_instance);
rctx->last_start_instance = info->start_instance;
}
@ -2289,11 +2296,11 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
}
/* Draw packets. */
if (likely(!info->indirect)) {
if (likely(!indirect)) {
radeon_emit(cs, PKT3(PKT3_NUM_INSTANCES, 0, 0));
radeon_emit(cs, info->instance_count);
} else {
uint64_t va = r600_resource(info->indirect->buffer)->gpu_address;
uint64_t va = r600_resource(indirect->buffer)->gpu_address;
assert(rctx->b.chip_class >= EVERGREEN);
// Invalidate so non-indirect draw calls reset this state
@ -2307,7 +2314,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
radeon_emit(cs, PKT3(PKT3_NOP, 0, 0));
radeon_emit(cs, radeon_add_to_buffer_list(&rctx->b, &rctx->b.gfx,
(struct r600_resource*)info->indirect->buffer,
(struct r600_resource*)indirect->buffer,
RADEON_USAGE_READ,
RADEON_PRIO_DRAW_INDIRECT));
}
@ -2328,7 +2335,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
} else {
uint64_t va = r600_resource(indexbuf)->gpu_address + index_offset;
if (likely(!info->indirect)) {
if (likely(!indirect)) {
radeon_emit(cs, PKT3(PKT3_DRAW_INDEX, 3, render_cond_bit));
radeon_emit(cs, va);
radeon_emit(cs, (va >> 32UL) & 0xFF);
@ -2357,13 +2364,13 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
radeon_emit(cs, max_size);
radeon_emit(cs, PKT3(EG_PKT3_DRAW_INDEX_INDIRECT, 1, render_cond_bit));
radeon_emit(cs, info->indirect->offset);
radeon_emit(cs, indirect->offset);
radeon_emit(cs, V_0287F0_DI_SRC_SEL_DMA);
}
}
} else {
if (unlikely(info->count_from_stream_output)) {
struct r600_so_target *t = (struct r600_so_target*)info->count_from_stream_output;
if (unlikely(count_from_so)) {
struct r600_so_target *t = (struct r600_so_target*)count_from_so;
uint64_t va = t->buf_filled_size->gpu_address + t->buf_filled_size_offset;
radeon_set_context_reg(cs, R_028B30_VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE, t->stride_in_dw);
@ -2381,16 +2388,16 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
RADEON_PRIO_SO_FILLED_SIZE));
}
if (likely(!info->indirect)) {
if (likely(!indirect)) {
radeon_emit(cs, PKT3(PKT3_DRAW_INDEX_AUTO, 1, render_cond_bit));
radeon_emit(cs, info->count);
}
else {
radeon_emit(cs, PKT3(EG_PKT3_DRAW_INDIRECT, 1, render_cond_bit));
radeon_emit(cs, info->indirect->offset);
radeon_emit(cs, indirect->offset);
}
radeon_emit(cs, V_0287F0_DI_SRC_SEL_AUTO_INDEX |
(info->count_from_stream_output ? S_0287F0_USE_OPAQUE(1) : 0));
(count_from_so ? S_0287F0_USE_OPAQUE(1) : 0));
}
/* SMX returns CONTEXT_DONE too early workaround */

View File

@ -477,6 +477,22 @@ static bool si_is_line_stipple_enabled(struct si_context *sctx)
(rs->polygon_mode_is_lines || util_prim_is_lines(sctx->current_rast_prim));
}
static bool num_instanced_prims_less_than(const struct pipe_draw_info *info,
const struct pipe_draw_indirect_info *indirect,
enum pipe_prim_type prim,
unsigned min_vertex_count,
unsigned instance_count,
unsigned num_prims)
{
if (indirect) {
return indirect->buffer ||
(instance_count > 1 && indirect->count_from_stream_output);
} else {
return instance_count > 1 &&
si_num_prims_for_vertices(prim, min_vertex_count, info->vertices_per_patch) < num_prims;
}
}
ALWAYS_INLINE
static unsigned si_get_ia_multi_vgt_param(struct si_context *sctx,
const struct pipe_draw_info *info,
@ -484,6 +500,7 @@ static unsigned si_get_ia_multi_vgt_param(struct si_context *sctx,
unsigned instance_count, bool primitive_restart,
unsigned min_vertex_count)
{
const struct pipe_draw_indirect_info *indirect = info->indirect;
union si_vgt_param_key key = sctx->ia_multi_vgt_param_key;
unsigned primgroup_size;
unsigned ia_multi_vgt_param;
@ -497,14 +514,11 @@ static unsigned si_get_ia_multi_vgt_param(struct si_context *sctx,
}
key.u.prim = prim;
key.u.uses_instancing = info->indirect || instance_count > 1;
key.u.uses_instancing = (indirect && indirect->buffer) || instance_count > 1;
key.u.multi_instances_smaller_than_primgroup =
info->indirect ||
(instance_count > 1 &&
(info->count_from_stream_output ||
si_num_prims_for_vertices(prim, min_vertex_count, info->vertices_per_patch) < primgroup_size));
num_instanced_prims_less_than(info, indirect, prim, min_vertex_count, instance_count, primgroup_size);
key.u.primitive_restart = primitive_restart;
key.u.count_from_stream_output = info->count_from_stream_output != NULL;
key.u.count_from_stream_output = indirect && indirect->count_from_stream_output;
key.u.line_stipple_enabled = si_is_line_stipple_enabled(sctx);
ia_multi_vgt_param =
@ -521,11 +535,7 @@ static unsigned si_get_ia_multi_vgt_param(struct si_context *sctx,
* only applies it to Hawaii. Do what Vulkan does.
*/
if (sctx->family == CHIP_HAWAII && G_028AA8_SWITCH_ON_EOI(ia_multi_vgt_param) &&
(info->indirect ||
(instance_count > 1 &&
(info->count_from_stream_output ||
si_num_prims_for_vertices(prim, min_vertex_count, info->vertices_per_patch) <= 1))))
num_instanced_prims_less_than(info, indirect, prim, min_vertex_count, instance_count, 2))
sctx->flags |= SI_CONTEXT_VGT_FLUSH;
}
@ -771,15 +781,18 @@ static void si_emit_draw_packets(struct si_context *sctx, const struct pipe_draw
unsigned sh_base_reg = sctx->shader_pointers.sh_base[PIPE_SHADER_VERTEX];
bool render_cond_bit = sctx->render_cond && !sctx->render_cond_force_off;
uint32_t index_max_size = 0;
uint32_t use_opaque = 0;
uint64_t index_va = 0;
if (info->count_from_stream_output) {
struct si_streamout_target *t = (struct si_streamout_target *)info->count_from_stream_output;
if (indirect && indirect->count_from_stream_output) {
struct si_streamout_target *t = (struct si_streamout_target *)indirect->count_from_stream_output;
radeon_set_context_reg(cs, R_028B30_VGT_STRMOUT_DRAW_OPAQUE_VERTEX_STRIDE, t->stride_in_dw);
si_cp_copy_data(sctx, sctx->gfx_cs, COPY_DATA_REG, NULL,
R_028B2C_VGT_STRMOUT_DRAW_OPAQUE_BUFFER_FILLED_SIZE >> 2, COPY_DATA_SRC_MEM,
t->buf_filled_size, t->buf_filled_size_offset);
use_opaque = S_0287F0_USE_OPAQUE(1);
indirect = NULL;
}
/* draw packet */
@ -975,8 +988,7 @@ static void si_emit_draw_packets(struct si_context *sctx, const struct pipe_draw
radeon_emit(cs, PKT3(PKT3_DRAW_INDEX_AUTO, 1, render_cond_bit));
radeon_emit(cs, draws[i].count);
radeon_emit(cs, V_0287F0_DI_SRC_SEL_AUTO_INDEX |
S_0287F0_USE_OPAQUE(!!info->count_from_stream_output));
radeon_emit(cs, V_0287F0_DI_SRC_SEL_AUTO_INDEX | use_opaque);
}
if (num_draws > 1 && !sctx->num_vs_blit_sgprs)
sctx->last_base_vertex = draws[num_draws - 1].start;
@ -1563,7 +1575,7 @@ static void si_get_draw_start_count(struct si_context *sctx, const struct pipe_d
{
struct pipe_draw_indirect_info *indirect = info->indirect;
if (indirect) {
if (indirect && !indirect->count_from_stream_output) {
unsigned indirect_count;
struct pipe_transfer *transfer;
unsigned begin, end;
@ -1761,11 +1773,12 @@ static void si_multi_draw_vbo(struct pipe_context *ctx,
{
struct si_context *sctx = (struct si_context *)ctx;
struct si_state_rasterizer *rs = sctx->queued.named.rasterizer;
struct pipe_draw_indirect_info *indirect = info->indirect;
struct pipe_resource *indexbuf = info->index.resource;
unsigned dirty_tex_counter, dirty_buf_counter;
enum pipe_prim_type rast_prim, prim = info->mode;
unsigned index_size = info->index_size;
unsigned index_offset = info->indirect ? draws[0].start * index_size : 0;
unsigned index_offset = indirect && indirect->buffer ? draws[0].start * index_size : 0;
unsigned instance_count = info->instance_count;
bool primitive_restart =
info->primitive_restart &&
@ -1776,7 +1789,7 @@ static void si_multi_draw_vbo(struct pipe_context *ctx,
* no workaround for indirect draws, but we can at least skip
* direct draws.
*/
if (unlikely(!info->indirect && !instance_count))
if (unlikely(!indirect && !instance_count))
return;
struct si_shader_selector *vs = sctx->vs_shader.cso;
@ -1892,7 +1905,7 @@ static void si_multi_draw_vbo(struct pipe_context *ctx,
} else if (info->has_user_indices) {
unsigned start_offset;
assert(!info->indirect);
assert(!indirect);
assert(num_draws == 1);
start_offset = draws[0].start * index_size;
@ -1920,15 +1933,14 @@ static void si_multi_draw_vbo(struct pipe_context *ctx,
unsigned min_direct_count = 0;
unsigned total_direct_count = 0;
if (info->indirect) {
struct pipe_draw_indirect_info *indirect = info->indirect;
if (indirect) {
/* Add the buffer size for memory checking in need_cs_space. */
si_context_add_resource_size(sctx, indirect->buffer);
if (indirect->buffer)
si_context_add_resource_size(sctx, indirect->buffer);
/* Indirect buffers use TC L2 on GFX9, but not older hw. */
if (sctx->chip_class <= GFX8) {
if (si_resource(indirect->buffer)->TC_L2_dirty) {
if (indirect->buffer && si_resource(indirect->buffer)->TC_L2_dirty) {
sctx->flags |= SI_CONTEXT_WB_L2;
si_resource(indirect->buffer)->TC_L2_dirty = false;
}
@ -1956,7 +1968,6 @@ static void si_multi_draw_vbo(struct pipe_context *ctx,
: /* Add, then return true. */
(sctx->compute_num_verts_ineligible += total_direct_count,
false)) && /* Add, then return false. */
(!info->count_from_stream_output || pd_msg("draw_opaque")) &&
(primitive_restart ?
/* Supported prim types with primitive restart: */
(prim == PIPE_PRIM_TRIANGLE_STRIP || pd_msg("bad prim type with primitive restart")) &&
@ -2126,7 +2137,7 @@ static void si_multi_draw_vbo(struct pipe_context *ctx,
masked_atoms |= si_get_atom_bit(sctx, &sctx->atoms.s.scissors);
gfx9_scissor_bug = true;
if (info->count_from_stream_output ||
if ((indirect && indirect->count_from_stream_output) ||
sctx->dirty_atoms & si_atoms_that_always_roll_context() ||
sctx->dirty_states & si_states_that_always_roll_context())
sctx->context_roll = true;

View File

@ -69,7 +69,7 @@ softpipe_draw_vbo(struct pipe_context *pipe,
if (!softpipe_check_render_cond(sp))
return;
if (info->indirect) {
if (info->indirect && info->indirect->buffer) {
util_draw_indirect(pipe, info);
return;
}

View File

@ -83,7 +83,7 @@ retry_draw_auto(struct svga_context *svga,
const struct pipe_draw_info *info)
{
assert(svga_have_sm5(svga));
assert(info->count_from_stream_output);
assert(info->indirect->count_from_stream_output);
assert(info->instance_count == 1);
/* SO drawing implies core profile and none of these prim types */
assert(info->mode != PIPE_PRIM_QUADS &&
@ -117,7 +117,7 @@ retry_draw_auto(struct svga_context *svga,
0, /* start instance */
1, /* only 1 instance supported */
NULL, /* indirect drawing info */
info->count_from_stream_output));
info->indirect->count_from_stream_output));
return PIPE_OK;
}
@ -132,7 +132,7 @@ retry_draw_indirect(struct svga_context *svga,
const struct pipe_draw_info *info)
{
assert(svga_have_sm5(svga));
assert(info->indirect);
assert(info->indirect && info->indirect->buffer);
/* indirect drawing implies core profile and none of these prim types */
assert(info->mode != PIPE_PRIM_QUADS &&
info->mode != PIPE_PRIM_QUAD_STRIP &&
@ -273,8 +273,7 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
goto done;
}
if (!info->indirect && !info->count_from_stream_output &&
!u_trim_pipe_prim(info->mode, &count))
if (!info->indirect && !u_trim_pipe_prim(info->mode, &count))
goto done;
needed_swtnl = svga->state.sw.need_swtnl;
@ -318,7 +317,7 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
svga_is_using_flat_shading(svga),
svga->curr.rast->templ.flatshade_first);
if (info->count_from_stream_output) {
if (info->indirect && info->indirect->count_from_stream_output) {
unsigned stream = 0;
assert(count == 0);
@ -332,7 +331,7 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
/* Check the stream index of the specified stream output target */
for (unsigned i = 0; i < ARRAY_SIZE(svga->so_targets); i++) {
if (svga->vcount_so_targets[i] == info->count_from_stream_output) {
if (svga->vcount_so_targets[i] == info->indirect->count_from_stream_output) {
stream = (svga->vcount_buffer_stream >> (i * 4)) & 0xf;
break;
}
@ -342,10 +341,10 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
}
}
if (info->count_from_stream_output && count == 0) {
if (info->indirect && info->indirect->count_from_stream_output && count == 0) {
ret = retry_draw_auto(svga, info);
}
else if (info->indirect) {
else if (info->indirect && info->indirect->buffer) {
ret = retry_draw_indirect(svga, info);
}
else if (info->index_size) {

View File

@ -41,7 +41,7 @@ swr_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
{
struct swr_context *ctx = swr_context(pipe);
if (!info->count_from_stream_output && !info->indirect &&
if (!info->indirect &&
!info->primitive_restart &&
!u_trim_pipe_prim(info->mode, (unsigned*)&info->count))
return;
@ -49,7 +49,7 @@ swr_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
if (!swr_check_render_cond(pipe))
return;
if (info->indirect) {
if (info->indirect && info->indirect->buffer) {
util_draw_indirect(pipe, info);
return;
}
@ -66,11 +66,12 @@ swr_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
struct pipe_draw_info resolved_info;
/* DrawTransformFeedback */
if (info->count_from_stream_output) {
if (info->indirect && info->indirect->count_from_stream_output) {
// trick copied from softpipe to modify const struct *info
memcpy(&resolved_info, (void*)info, sizeof(struct pipe_draw_info));
resolved_info.count = ctx->so_primCounter * resolved_info.vertices_per_patch;
resolved_info.max_index = resolved_info.count - 1;
resolved_info.indirect = NULL;
info = &resolved_info;
}

View File

@ -52,10 +52,10 @@ tegra_draw_vbo(struct pipe_context *pcontext,
struct pipe_draw_indirect_info indirect;
struct pipe_draw_info info;
if (pinfo && (pinfo->indirect || pinfo->index_size)) {
if (pinfo && ((pinfo->indirect && pinfo->indirect->buffer) || pinfo->index_size)) {
memcpy(&info, pinfo, sizeof(info));
if (pinfo->indirect) {
if (pinfo->indirect && pinfo->indirect->buffer) {
memcpy(&indirect, pinfo->indirect, sizeof(indirect));
indirect.buffer = tegra_resource_unwrap(info.indirect->buffer);
info.indirect = &indirect;

View File

@ -1088,7 +1088,7 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
{
struct v3d_context *v3d = v3d_context(pctx);
if (!info->count_from_stream_output && !info->indirect &&
if (!info->indirect &&
!info->primitive_restart &&
!u_trim_pipe_prim(info->mode, (unsigned*)&info->count))
return;
@ -1127,7 +1127,7 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
for (int s = 0; s < PIPE_SHADER_COMPUTE; s++)
v3d_predraw_check_stage_inputs(pctx, s);
if (info->indirect) {
if (info->indirect && info->indirect->buffer) {
v3d_flush_jobs_writing_resource(v3d, info->indirect->buffer,
V3D_FLUSH_DEFAULT, false);
}
@ -1155,7 +1155,7 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
* on the last submitted render, rather than tracking the last
* rendering to each texture's BO.
*/
if (v3d->tex[PIPE_SHADER_VERTEX].num_textures || info->indirect) {
if (v3d->tex[PIPE_SHADER_VERTEX].num_textures || (info->indirect && info->indirect->buffer)) {
perf_debug("Blocking binner on last render "
"due to vertex texturing or indirect drawing.\n");
job->submit.in_sync_bcl = v3d->out_sync;
@ -1284,7 +1284,7 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
}
#endif
if (info->indirect) {
if (info->indirect && info->indirect->buffer) {
cl_emit(&job->bcl, INDIRECT_INDEXED_INSTANCED_PRIM_LIST, prim) {
prim.index_type = ffs(info->index_size) - 1;
#if V3D_VERSION < 40
@ -1335,7 +1335,7 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
if (info->has_user_indices)
pipe_resource_reference(&prsc, NULL);
} else {
if (info->indirect) {
if (info->indirect && info->indirect->buffer) {
cl_emit(&job->bcl, INDIRECT_VERTEX_ARRAY_INSTANCED_PRIMS, prim) {
prim.mode = hw_prim_type | prim_tf_enable;
prim.number_of_draw_indirect_array_records = info->indirect->draw_count;
@ -1346,7 +1346,8 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
}
} else if (info->instance_count > 1) {
struct pipe_stream_output_target *so =
info->count_from_stream_output;
info->indirect && info->indirect->count_from_stream_output ?
info->indirect->count_from_stream_output : NULL;
uint32_t vert_count = so ?
v3d_stream_output_target_get_vertex_count(so) :
info->count;
@ -1358,7 +1359,8 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
}
} else {
struct pipe_stream_output_target *so =
info->count_from_stream_output;
info->indirect && info->indirect->count_from_stream_output ?
info->indirect->count_from_stream_output : NULL;
uint32_t vert_count = so ?
v3d_stream_output_target_get_vertex_count(so) :
info->count;

View File

@ -291,7 +291,7 @@ vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
struct vc4_context *vc4 = vc4_context(pctx);
struct pipe_draw_info local_info;
if (!info->count_from_stream_output && !info->indirect &&
if (!info->indirect &&
!info->primitive_restart &&
!u_trim_pipe_prim(info->mode, (unsigned*)&info->count))
return;

View File

@ -855,7 +855,7 @@ static void virgl_draw_vbo(struct pipe_context *ctx,
struct virgl_indexbuf ib = {};
struct pipe_draw_info info = *dinfo;
if (!dinfo->count_from_stream_output && !dinfo->indirect &&
if (!dinfo->indirect &&
!dinfo->primitive_restart &&
!u_trim_pipe_prim(dinfo->mode, (unsigned*)&dinfo->count))
return;

View File

@ -712,7 +712,7 @@ int virgl_encoder_draw_vbo(struct virgl_context *ctx,
uint32_t length = VIRGL_DRAW_VBO_SIZE;
if (info->mode == PIPE_PRIM_PATCHES)
length = VIRGL_DRAW_VBO_SIZE_TESS;
if (info->indirect)
if (info->indirect && info->indirect->buffer)
length = VIRGL_DRAW_VBO_SIZE_INDIRECT;
virgl_encoder_write_cmd_dword(ctx, VIRGL_CMD0(VIRGL_CCMD_DRAW_VBO, 0, length));
virgl_encoder_write_dword(ctx->cbuf, info->start);
@ -726,8 +726,8 @@ int virgl_encoder_draw_vbo(struct virgl_context *ctx,
virgl_encoder_write_dword(ctx->cbuf, info->restart_index);
virgl_encoder_write_dword(ctx->cbuf, info->min_index);
virgl_encoder_write_dword(ctx->cbuf, info->max_index);
if (info->count_from_stream_output)
virgl_encoder_write_dword(ctx->cbuf, info->count_from_stream_output->buffer_size);
if (info->indirect && info->indirect->count_from_stream_output)
virgl_encoder_write_dword(ctx->cbuf, info->indirect->count_from_stream_output->buffer_size);
else
virgl_encoder_write_dword(ctx->cbuf, 0);
if (length >= VIRGL_DRAW_VBO_SIZE_TESS) {

View File

@ -214,7 +214,9 @@ zink_draw_vbo(struct pipe_context *pctx,
struct zink_screen *screen = zink_screen(pctx->screen);
struct zink_rasterizer_state *rast_state = ctx->rast_state;
struct zink_depth_stencil_alpha_state *dsa_state = ctx->dsa_state;
struct zink_so_target *so_target = zink_so_target(dinfo->count_from_stream_output);
struct zink_so_target *so_target =
dinfo->indirect && dinfo->indirect->count_from_stream_output ?
zink_so_target(dinfo->indirect->count_from_stream_output) : NULL;
VkBuffer counter_buffers[PIPE_MAX_SO_OUTPUTS];
VkDeviceSize counter_buffer_offsets[PIPE_MAX_SO_OUTPUTS] = {};
bool need_index_buffer_unref = false;
@ -514,7 +516,7 @@ zink_draw_vbo(struct pipe_context *pctx,
struct zink_resource *res = zink_resource(index_buffer);
vkCmdBindIndexBuffer(batch->cmdbuf, res->buffer, index_offset, index_type);
zink_batch_reference_resource_rw(batch, res, false);
if (dinfo->indirect) {
if (dinfo->indirect && dinfo->indirect->buffer) {
struct zink_resource *indirect = zink_resource(dinfo->indirect->buffer);
zink_batch_reference_resource_rw(batch, indirect, false);
vkCmdDrawIndexedIndirect(batch->cmdbuf, indirect->buffer, dinfo->indirect->offset, dinfo->indirect->draw_count, dinfo->indirect->stride);
@ -528,7 +530,7 @@ zink_draw_vbo(struct pipe_context *pctx,
screen->vk_CmdDrawIndirectByteCountEXT(batch->cmdbuf, dinfo->instance_count, dinfo->start_instance,
zink_resource(so_target->counter_buffer)->buffer, so_target->counter_buffer_offset, 0,
MIN2(so_target->stride, screen->info.tf_props.maxTransformFeedbackBufferDataStride));
} else if (dinfo->indirect) {
} else if (dinfo->indirect && dinfo->indirect->buffer) {
struct zink_resource *indirect = zink_resource(dinfo->indirect->buffer);
zink_batch_reference_resource_rw(batch, indirect, false);
vkCmdDrawIndirect(batch->cmdbuf, indirect->buffer, dinfo->indirect->offset, dinfo->indirect->draw_count, dinfo->indirect->stride);

View File

@ -3174,7 +3174,6 @@ NineDevice9_ProcessVertices( struct NineDevice9 *This,
draw.start_instance = 0;
draw.primitive_restart = FALSE;
draw.restart_index = 0;
draw.count_from_stream_output = NULL;
draw.indirect = NULL;
draw.instance_count = 1;
draw.index_size = 0;

View File

@ -2318,7 +2318,6 @@ init_draw_info(struct pipe_draw_info *info,
info->primitive_restart = FALSE;
info->has_user_indices = FALSE;
info->restart_index = 0;
info->count_from_stream_output = NULL;
info->indirect = NULL;
}

View File

@ -712,6 +712,8 @@ struct pipe_draw_indirect_info
* uint32_t start;
* uint32_t start_instance;
* };
*
* If NULL, count_from_stream_output != NULL.
*/
struct pipe_resource *buffer;
@ -719,6 +721,22 @@ struct pipe_draw_indirect_info
* is to be used as the real draw_count.
*/
struct pipe_resource *indirect_draw_count;
/**
* Stream output target. If not NULL, it's used to provide the 'count'
* parameter based on the number vertices captured by the stream output
* stage. (or generally, based on the number of bytes captured)
*
* Only 'mode', 'start_instance', and 'instance_count' are taken into
* account, all the other variables from pipe_draw_info are ignored.
*
* 'start' is implicitly 0 and 'count' is set as discussed above.
* The draw command is non-indexed.
*
* Note that this only provides the count. The vertex buffers must
* be set via set_vertex_buffers manually.
*/
struct pipe_stream_output_target *count_from_stream_output;
};
struct pipe_draw_start_count {
@ -777,22 +795,6 @@ struct pipe_draw_info
} index;
struct pipe_draw_indirect_info *indirect; /**< Indirect draw. */
/**
* Stream output target. If not NULL, it's used to provide the 'count'
* parameter based on the number vertices captured by the stream output
* stage. (or generally, based on the number of bytes captured)
*
* Only 'mode', 'start_instance', and 'instance_count' are taken into
* account, all the other variables from pipe_draw_info are ignored.
*
* 'start' is implicitly 0 and 'count' is set as discussed above.
* The draw command is non-indexed.
*
* Note that this only provides the count. The vertex buffers must
* be set via set_vertex_buffers manually.
*/
struct pipe_stream_output_target *count_from_stream_output;
};

View File

@ -214,7 +214,8 @@ st_end_transform_feedback(struct gl_context *ctx,
bool
st_transform_feedback_draw_init(struct gl_transform_feedback_object *obj,
unsigned stream, struct pipe_draw_info *out)
unsigned stream,
struct pipe_draw_indirect_info *out)
{
struct st_transform_feedback_object *sobj =
st_transform_feedback_object(obj);

View File

@ -31,14 +31,15 @@
struct dd_function_table;
struct gl_transform_feedback_object;
struct pipe_draw_info;
struct pipe_draw_indirect_info;
extern void
st_init_xformfb_functions(struct dd_function_table *functions);
extern bool
st_transform_feedback_draw_init(struct gl_transform_feedback_object *obj,
unsigned stream, struct pipe_draw_info *out);
unsigned stream,
struct pipe_draw_indirect_info *out);
#endif /* ST_CB_XFORMFB_H */

View File

@ -177,7 +177,6 @@ st_draw_vbo(struct gl_context *ctx,
info.primitive_restart = false;
info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices;
info.indirect = NULL;
info.count_from_stream_output = NULL;
info.restart_index = 0;
info.start_instance = base_instance;
info.instance_count = num_instances;
@ -330,15 +329,18 @@ st_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
{
struct st_context *st = st_context(ctx);
struct pipe_draw_info info;
struct pipe_draw_indirect_info indirect;
prepare_draw(st, ctx);
memset(&indirect, 0, sizeof(indirect));
util_draw_init_info(&info);
info.start = 0; /* index offset / index size */
info.max_index = ~0u; /* so that u_vbuf can tell that it's unknown */
info.mode = translate_prim(ctx, mode);
info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices;
info.instance_count = num_instances;
info.indirect = &indirect;
if (ST_DEBUG & DEBUG_DRAW) {
debug_printf("st/draw transform feedback: mode %s\n",
@ -347,7 +349,7 @@ st_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
/* Transform feedback drawing is always non-indexed. */
/* Set info.count_from_stream_output. */
if (!st_transform_feedback_draw_init(tfb_vertcount, stream, &info))
if (!st_transform_feedback_draw_init(tfb_vertcount, stream, &indirect))
return;
cso_draw_vbo(st->cso_context, &info);