gallium: separate indirect stuff from pipe_draw_info - 80 -> 56 bytes

For faster initialization of non-indirect draws.
This commit is contained in:
Marek Olšák 2017-04-02 15:24:19 +02:00
parent c24c3b94ed
commit 22f6624ed3
14 changed files with 153 additions and 114 deletions

View file

@ -145,8 +145,8 @@ util_draw_indirect(struct pipe_context *pipe,
params = (uint32_t *) params = (uint32_t *)
pipe_buffer_map_range(pipe, pipe_buffer_map_range(pipe,
info_in->indirect, info_in->indirect->buffer,
info_in->indirect_offset, info_in->indirect->offset,
num_params * sizeof(uint32_t), num_params * sizeof(uint32_t),
PIPE_TRANSFER_READ, PIPE_TRANSFER_READ,
&transfer); &transfer);

View file

@ -941,11 +941,16 @@ util_dump_draw_info(FILE *stream, const struct pipe_draw_info *state)
util_dump_member(stream, ptr, state, count_from_stream_output); util_dump_member(stream, ptr, state, count_from_stream_output);
util_dump_member(stream, ptr, state, indirect); if (!state->indirect) {
util_dump_member(stream, uint, state, indirect_offset); util_dump_member(stream, ptr, state, indirect);
util_dump_member(stream, uint, state, indirect_stride); } else {
util_dump_member(stream, uint, state, indirect_count); util_dump_member(stream, uint, state, indirect->offset);
util_dump_member(stream, uint, state, indirect_params_offset); util_dump_member(stream, uint, state, indirect->stride);
util_dump_member(stream, uint, state, indirect->draw_count);
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_struct_end(stream); util_dump_struct_end(stream);
} }

View file

@ -1168,15 +1168,15 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info)
int *data; int *data;
if (new_info.indexed) { if (new_info.indexed) {
data = pipe_buffer_map_range(pipe, new_info.indirect, data = pipe_buffer_map_range(pipe, new_info.indirect->buffer,
new_info.indirect_offset, 20, new_info.indirect->offset, 20,
PIPE_TRANSFER_READ, &transfer); PIPE_TRANSFER_READ, &transfer);
new_info.index_bias = data[3]; new_info.index_bias = data[3];
new_info.start_instance = data[4]; new_info.start_instance = data[4];
} }
else { else {
data = pipe_buffer_map_range(pipe, new_info.indirect, data = pipe_buffer_map_range(pipe, new_info.indirect->buffer,
new_info.indirect_offset, 16, new_info.indirect->offset, 16,
PIPE_TRANSFER_READ, &transfer); PIPE_TRANSFER_READ, &transfer);
new_info.start_instance = data[3]; new_info.start_instance = data[3];
} }

View file

@ -217,7 +217,7 @@ The integer capabilities:
pipe_draw_info::indirect_stride and ::indirect_count pipe_draw_info::indirect_stride and ::indirect_count
* ``PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS``: Whether the driver supports * ``PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS``: Whether the driver supports
taking the number of indirect draws from a separate parameter taking the number of indirect draws from a separate parameter
buffer, see pipe_draw_info::indirect_params. buffer, see pipe_draw_indirect_info::indirect_draw_count.
* ``PIPE_CAP_TGSI_FS_FINE_DERIVATIVE``: Whether the fragment shader supports * ``PIPE_CAP_TGSI_FS_FINE_DERIVATIVE``: Whether the fragment shader supports
the FINE versions of DDX/DDY. the FINE versions of DDX/DDY.
* ``PIPE_CAP_VENDOR_ID``: The vendor ID of the underlying hardware. If it's * ``PIPE_CAP_VENDOR_ID``: The vendor ID of the underlying hardware. If it's

View file

@ -297,10 +297,12 @@ dd_dump_draw_vbo(struct dd_draw_state *dstate, struct pipe_draw_info *info, FILE
if (info->count_from_stream_output) if (info->count_from_stream_output)
DUMP_M(stream_output_target, info, DUMP_M(stream_output_target, info,
count_from_stream_output); count_from_stream_output);
if (info->indirect) if (info->indirect) {
DUMP_M(resource, info, indirect); DUMP_M(resource, info, indirect->buffer);
if (info->indirect_params) if (info->indirect->indirect_draw_count)
DUMP_M(resource, info, indirect_params); DUMP_M(resource, info, indirect->indirect_draw_count);
}
fprintf(f, "\n"); fprintf(f, "\n");
/* TODO: dump active queries */ /* TODO: dump active queries */
@ -500,7 +502,7 @@ dd_dump_call(FILE *f, struct dd_draw_state *state, struct dd_call *call)
{ {
switch (call->type) { switch (call->type) {
case CALL_DRAW_VBO: case CALL_DRAW_VBO:
dd_dump_draw_vbo(state, &call->info.draw_vbo, f); dd_dump_draw_vbo(state, &call->info.draw_vbo.draw, f);
break; break;
case CALL_LAUNCH_GRID: case CALL_LAUNCH_GRID:
dd_dump_launch_grid(state, &call->info.launch_grid, f); dd_dump_launch_grid(state, &call->info.launch_grid, f);
@ -619,9 +621,9 @@ dd_unreference_copy_of_call(struct dd_call *dst)
{ {
switch (dst->type) { switch (dst->type) {
case CALL_DRAW_VBO: case CALL_DRAW_VBO:
pipe_so_target_reference(&dst->info.draw_vbo.count_from_stream_output, NULL); pipe_so_target_reference(&dst->info.draw_vbo.draw.count_from_stream_output, NULL);
pipe_resource_reference(&dst->info.draw_vbo.indirect, NULL); pipe_resource_reference(&dst->info.draw_vbo.indirect.buffer, NULL);
pipe_resource_reference(&dst->info.draw_vbo.indirect_params, NULL); pipe_resource_reference(&dst->info.draw_vbo.indirect.indirect_draw_count, NULL);
break; break;
case CALL_LAUNCH_GRID: case CALL_LAUNCH_GRID:
pipe_resource_reference(&dst->info.launch_grid.indirect, NULL); pipe_resource_reference(&dst->info.launch_grid.indirect, NULL);
@ -661,13 +663,17 @@ dd_copy_call(struct dd_call *dst, struct dd_call *src)
switch (src->type) { switch (src->type) {
case CALL_DRAW_VBO: case CALL_DRAW_VBO:
pipe_so_target_reference(&dst->info.draw_vbo.count_from_stream_output, pipe_so_target_reference(&dst->info.draw_vbo.draw.count_from_stream_output,
src->info.draw_vbo.count_from_stream_output); src->info.draw_vbo.draw.count_from_stream_output);
pipe_resource_reference(&dst->info.draw_vbo.indirect, pipe_resource_reference(&dst->info.draw_vbo.indirect.buffer,
src->info.draw_vbo.indirect); src->info.draw_vbo.indirect.buffer);
pipe_resource_reference(&dst->info.draw_vbo.indirect_params, pipe_resource_reference(&dst->info.draw_vbo.indirect.indirect_draw_count,
src->info.draw_vbo.indirect_params); src->info.draw_vbo.indirect.indirect_draw_count);
dst->info.draw_vbo = src->info.draw_vbo; dst->info.draw_vbo = src->info.draw_vbo;
if (!src->info.draw_vbo.draw.indirect)
dst->info.draw_vbo.draw.indirect = NULL;
else
dst->info.draw_vbo.draw.indirect = &dst->info.draw_vbo.indirect;
break; break;
case CALL_LAUNCH_GRID: case CALL_LAUNCH_GRID:
pipe_resource_reference(&dst->info.launch_grid.indirect, pipe_resource_reference(&dst->info.launch_grid.indirect,
@ -1173,7 +1179,13 @@ dd_context_draw_vbo(struct pipe_context *_pipe,
struct dd_call call; struct dd_call call;
call.type = CALL_DRAW_VBO; call.type = CALL_DRAW_VBO;
call.info.draw_vbo = *info; call.info.draw_vbo.draw = *info;
if (info->indirect) {
call.info.draw_vbo.indirect = *info->indirect;
call.info.draw_vbo.draw.indirect = &call.info.draw_vbo.indirect;
} else {
memset(&call.info.draw_vbo.indirect, 0, sizeof(*info->indirect));
}
dd_before_draw(dctx); dd_before_draw(dctx);
pipe->draw_vbo(pipe, info); pipe->draw_vbo(pipe, info);

View file

@ -104,12 +104,17 @@ struct call_generate_mipmap {
unsigned last_layer; unsigned last_layer;
}; };
struct call_draw_info {
struct pipe_draw_info draw;
struct pipe_draw_indirect_info indirect;
};
struct dd_call struct dd_call
{ {
enum call_type type; enum call_type type;
union { union {
struct pipe_draw_info draw_vbo; struct call_draw_info draw_vbo;
struct pipe_grid_info launch_grid; struct pipe_grid_info launch_grid;
struct call_resource_copy_region resource_copy_region; struct call_resource_copy_region resource_copy_region;
struct pipe_blit_info blit; struct pipe_blit_info blit;

View file

@ -818,10 +818,10 @@ static void
nvc0_draw_indirect(struct nvc0_context *nvc0, const struct pipe_draw_info *info) nvc0_draw_indirect(struct nvc0_context *nvc0, const struct pipe_draw_info *info)
{ {
struct nouveau_pushbuf *push = nvc0->base.pushbuf; struct nouveau_pushbuf *push = nvc0->base.pushbuf;
struct nv04_resource *buf = nv04_resource(info->indirect); struct nv04_resource *buf = nv04_resource(info->indirect->buffer);
struct nv04_resource *buf_count = nv04_resource(info->indirect_params); struct nv04_resource *buf_count = nv04_resource(info->indirect->indirect_draw_count);
unsigned size, macro, count = info->indirect_count, drawid = info->drawid; unsigned size, macro, count = info->indirect->draw_count, drawid = info->drawid;
uint32_t offset = buf->offset + info->indirect_offset; uint32_t offset = buf->offset + info->indirect->offset;
struct nvc0_screen *screen = nvc0->screen; struct nvc0_screen *screen = nvc0->screen;
PUSH_SPACE(push, 7); PUSH_SPACE(push, 7);
@ -870,7 +870,7 @@ nvc0_draw_indirect(struct nvc0_context *nvc0, const struct pipe_draw_info *info)
*/ */
while (count) { while (count) {
unsigned draws = count, pushes, i; unsigned draws = count, pushes, i;
if (info->indirect_stride == size * 4) { if (info->indirect->stride == size * 4) {
draws = MIN2(draws, (NV04_PFIFO_MAX_PACKET_LEN - 4) / size); draws = MIN2(draws, (NV04_PFIFO_MAX_PACKET_LEN - 4) / size);
pushes = 1; pushes = 1;
} else { } else {
@ -890,20 +890,20 @@ nvc0_draw_indirect(struct nvc0_context *nvc0, const struct pipe_draw_info *info)
if (buf_count) { if (buf_count) {
nouveau_pushbuf_data(push, nouveau_pushbuf_data(push,
buf_count->bo, buf_count->bo,
buf_count->offset + info->indirect_params_offset, buf_count->offset + info->indirect->indirect_draw_count_offset,
NVC0_IB_ENTRY_1_NO_PREFETCH | 4); NVC0_IB_ENTRY_1_NO_PREFETCH | 4);
} }
if (pushes == 1) { if (pushes == 1) {
nouveau_pushbuf_data(push, nouveau_pushbuf_data(push,
buf->bo, offset, buf->bo, offset,
NVC0_IB_ENTRY_1_NO_PREFETCH | (size * 4 * draws)); NVC0_IB_ENTRY_1_NO_PREFETCH | (size * 4 * draws));
offset += draws * info->indirect_stride; offset += draws * info->indirect->stride;
} else { } else {
for (i = 0; i < pushes; i++) { for (i = 0; i < pushes; i++) {
nouveau_pushbuf_data(push, nouveau_pushbuf_data(push,
buf->bo, offset, buf->bo, offset,
NVC0_IB_ENTRY_1_NO_PREFETCH | (size * 4)); NVC0_IB_ENTRY_1_NO_PREFETCH | (size * 4));
offset += info->indirect_stride; offset += info->indirect->stride;
} }
} }
count -= draws; count -= draws;

View file

@ -1770,11 +1770,11 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
} }
else { else {
/* Have to get start/count from indirect buffer, slow path ahead... */ /* Have to get start/count from indirect buffer, slow path ahead... */
struct r600_resource *indirect_resource = (struct r600_resource *)info->indirect; struct r600_resource *indirect_resource = (struct r600_resource *)info->indirect->buffer;
unsigned *data = r600_buffer_map_sync_with_rings(&rctx->b, indirect_resource, unsigned *data = r600_buffer_map_sync_with_rings(&rctx->b, indirect_resource,
PIPE_TRANSFER_READ); PIPE_TRANSFER_READ);
if (data) { if (data) {
data += info->indirect_offset / sizeof(unsigned); data += info->indirect->offset / sizeof(unsigned);
start = data[2] * ib.index_size; start = data[2] * ib.index_size;
count = data[0]; count = data[0];
} }
@ -1918,7 +1918,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
radeon_emit(cs, PKT3(PKT3_NUM_INSTANCES, 0, 0)); radeon_emit(cs, PKT3(PKT3_NUM_INSTANCES, 0, 0));
radeon_emit(cs, info->instance_count); radeon_emit(cs, info->instance_count);
} else { } else {
uint64_t va = r600_resource(info->indirect)->gpu_address; uint64_t va = r600_resource(info->indirect->buffer)->gpu_address;
assert(rctx->b.chip_class >= EVERGREEN); assert(rctx->b.chip_class >= EVERGREEN);
// Invalidate so non-indirect draw calls reset this state // Invalidate so non-indirect draw calls reset this state
@ -1932,7 +1932,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, PKT3(PKT3_NOP, 0, 0));
radeon_emit(cs, radeon_add_to_buffer_list(&rctx->b, &rctx->b.gfx, radeon_emit(cs, radeon_add_to_buffer_list(&rctx->b, &rctx->b.gfx,
(struct r600_resource*)info->indirect, (struct r600_resource*)info->indirect->buffer,
RADEON_USAGE_READ, RADEON_USAGE_READ,
RADEON_PRIO_DRAW_INDIRECT)); RADEON_PRIO_DRAW_INDIRECT));
} }
@ -1982,7 +1982,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
radeon_emit(cs, max_size); radeon_emit(cs, max_size);
radeon_emit(cs, PKT3(EG_PKT3_DRAW_INDEX_INDIRECT, 1, render_cond_bit)); radeon_emit(cs, PKT3(EG_PKT3_DRAW_INDEX_INDIRECT, 1, render_cond_bit));
radeon_emit(cs, info->indirect_offset); radeon_emit(cs, info->indirect->offset);
radeon_emit(cs, V_0287F0_DI_SRC_SEL_DMA); radeon_emit(cs, V_0287F0_DI_SRC_SEL_DMA);
} }
} }
@ -2012,7 +2012,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info
} }
else { else {
radeon_emit(cs, PKT3(EG_PKT3_DRAW_INDIRECT, 1, render_cond_bit)); radeon_emit(cs, PKT3(EG_PKT3_DRAW_INDIRECT, 1, render_cond_bit));
radeon_emit(cs, info->indirect_offset); radeon_emit(cs, info->indirect->offset);
} }
radeon_emit(cs, V_0287F0_DI_SRC_SEL_AUTO_INDEX | radeon_emit(cs, V_0287F0_DI_SRC_SEL_AUTO_INDEX |
(info->count_from_stream_output ? S_0287F0_USE_OPAQUE(1) : 0)); (info->count_from_stream_output ? S_0287F0_USE_OPAQUE(1) : 0));

View file

@ -627,6 +627,7 @@ static void si_emit_draw_packets(struct si_context *sctx,
const struct pipe_draw_info *info, const struct pipe_draw_info *info,
const struct pipe_index_buffer *ib) const struct pipe_index_buffer *ib)
{ {
struct pipe_draw_indirect_info *indirect = info->indirect;
struct radeon_winsys_cs *cs = sctx->b.gfx.cs; struct radeon_winsys_cs *cs = sctx->b.gfx.cs;
unsigned sh_base_reg = sctx->shader_userdata.sh_base[PIPE_SHADER_VERTEX]; unsigned sh_base_reg = sctx->shader_userdata.sh_base[PIPE_SHADER_VERTEX];
bool render_cond_bit = sctx->b.render_cond && !sctx->b.render_cond_force_off; bool render_cond_bit = sctx->b.render_cond && !sctx->b.render_cond_force_off;
@ -707,8 +708,8 @@ static void si_emit_draw_packets(struct si_context *sctx,
sctx->last_index_size = -1; sctx->last_index_size = -1;
} }
if (info->indirect) { if (indirect) {
uint64_t indirect_va = r600_resource(info->indirect)->gpu_address; uint64_t indirect_va = r600_resource(indirect->buffer)->gpu_address;
assert(indirect_va % 8 == 0); assert(indirect_va % 8 == 0);
@ -720,13 +721,13 @@ static void si_emit_draw_packets(struct si_context *sctx,
radeon_emit(cs, indirect_va >> 32); radeon_emit(cs, indirect_va >> 32);
radeon_add_to_buffer_list(&sctx->b, &sctx->b.gfx, radeon_add_to_buffer_list(&sctx->b, &sctx->b.gfx,
(struct r600_resource *)info->indirect, (struct r600_resource *)indirect->buffer,
RADEON_USAGE_READ, RADEON_PRIO_DRAW_INDIRECT); RADEON_USAGE_READ, RADEON_PRIO_DRAW_INDIRECT);
unsigned di_src_sel = info->indexed ? V_0287F0_DI_SRC_SEL_DMA unsigned di_src_sel = info->indexed ? V_0287F0_DI_SRC_SEL_DMA
: V_0287F0_DI_SRC_SEL_AUTO_INDEX; : V_0287F0_DI_SRC_SEL_AUTO_INDEX;
assert(info->indirect_offset % 4 == 0); assert(indirect->offset % 4 == 0);
if (info->indexed) { if (info->indexed) {
radeon_emit(cs, PKT3(PKT3_INDEX_BASE, 1, 0)); radeon_emit(cs, PKT3(PKT3_INDEX_BASE, 1, 0));
@ -741,37 +742,37 @@ static void si_emit_draw_packets(struct si_context *sctx,
radeon_emit(cs, PKT3(info->indexed ? PKT3_DRAW_INDEX_INDIRECT radeon_emit(cs, PKT3(info->indexed ? PKT3_DRAW_INDEX_INDIRECT
: PKT3_DRAW_INDIRECT, : PKT3_DRAW_INDIRECT,
3, render_cond_bit)); 3, render_cond_bit));
radeon_emit(cs, info->indirect_offset); radeon_emit(cs, indirect->offset);
radeon_emit(cs, (sh_base_reg + SI_SGPR_BASE_VERTEX * 4 - SI_SH_REG_OFFSET) >> 2); radeon_emit(cs, (sh_base_reg + SI_SGPR_BASE_VERTEX * 4 - SI_SH_REG_OFFSET) >> 2);
radeon_emit(cs, (sh_base_reg + SI_SGPR_START_INSTANCE * 4 - SI_SH_REG_OFFSET) >> 2); radeon_emit(cs, (sh_base_reg + SI_SGPR_START_INSTANCE * 4 - SI_SH_REG_OFFSET) >> 2);
radeon_emit(cs, di_src_sel); radeon_emit(cs, di_src_sel);
} else { } else {
uint64_t count_va = 0; uint64_t count_va = 0;
if (info->indirect_params) { if (indirect->indirect_draw_count) {
struct r600_resource *params_buf = struct r600_resource *params_buf =
(struct r600_resource *)info->indirect_params; (struct r600_resource *)indirect->indirect_draw_count;
radeon_add_to_buffer_list( radeon_add_to_buffer_list(
&sctx->b, &sctx->b.gfx, params_buf, &sctx->b, &sctx->b.gfx, params_buf,
RADEON_USAGE_READ, RADEON_PRIO_DRAW_INDIRECT); RADEON_USAGE_READ, RADEON_PRIO_DRAW_INDIRECT);
count_va = params_buf->gpu_address + info->indirect_params_offset; count_va = params_buf->gpu_address + indirect->indirect_draw_count_offset;
} }
radeon_emit(cs, PKT3(info->indexed ? PKT3_DRAW_INDEX_INDIRECT_MULTI : radeon_emit(cs, PKT3(info->indexed ? PKT3_DRAW_INDEX_INDIRECT_MULTI :
PKT3_DRAW_INDIRECT_MULTI, PKT3_DRAW_INDIRECT_MULTI,
8, render_cond_bit)); 8, render_cond_bit));
radeon_emit(cs, info->indirect_offset); radeon_emit(cs, indirect->offset);
radeon_emit(cs, (sh_base_reg + SI_SGPR_BASE_VERTEX * 4 - SI_SH_REG_OFFSET) >> 2); radeon_emit(cs, (sh_base_reg + SI_SGPR_BASE_VERTEX * 4 - SI_SH_REG_OFFSET) >> 2);
radeon_emit(cs, (sh_base_reg + SI_SGPR_START_INSTANCE * 4 - SI_SH_REG_OFFSET) >> 2); radeon_emit(cs, (sh_base_reg + SI_SGPR_START_INSTANCE * 4 - SI_SH_REG_OFFSET) >> 2);
radeon_emit(cs, ((sh_base_reg + SI_SGPR_DRAWID * 4 - SI_SH_REG_OFFSET) >> 2) | radeon_emit(cs, ((sh_base_reg + SI_SGPR_DRAWID * 4 - SI_SH_REG_OFFSET) >> 2) |
S_2C3_DRAW_INDEX_ENABLE(1) | S_2C3_DRAW_INDEX_ENABLE(1) |
S_2C3_COUNT_INDIRECT_ENABLE(!!info->indirect_params)); S_2C3_COUNT_INDIRECT_ENABLE(!!indirect->indirect_draw_count));
radeon_emit(cs, info->indirect_count); radeon_emit(cs, indirect->draw_count);
radeon_emit(cs, count_va); radeon_emit(cs, count_va);
radeon_emit(cs, count_va >> 32); radeon_emit(cs, count_va >> 32);
radeon_emit(cs, info->indirect_stride); radeon_emit(cs, indirect->stride);
radeon_emit(cs, di_src_sel); radeon_emit(cs, di_src_sel);
} }
} else { } else {
@ -1072,17 +1073,19 @@ static void si_get_draw_start_count(struct si_context *sctx,
const struct pipe_draw_info *info, const struct pipe_draw_info *info,
unsigned *start, unsigned *count) unsigned *start, unsigned *count)
{ {
if (info->indirect) { struct pipe_draw_indirect_info *indirect = info->indirect;
if (indirect) {
unsigned indirect_count; unsigned indirect_count;
struct pipe_transfer *transfer; struct pipe_transfer *transfer;
unsigned begin, end; unsigned begin, end;
unsigned map_size; unsigned map_size;
unsigned *data; unsigned *data;
if (info->indirect_params) { if (indirect->indirect_draw_count) {
data = pipe_buffer_map_range(&sctx->b.b, data = pipe_buffer_map_range(&sctx->b.b,
info->indirect_params, indirect->indirect_draw_count,
info->indirect_params_offset, indirect->indirect_draw_count_offset,
sizeof(unsigned), sizeof(unsigned),
PIPE_TRANSFER_READ, &transfer); PIPE_TRANSFER_READ, &transfer);
@ -1090,7 +1093,7 @@ static void si_get_draw_start_count(struct si_context *sctx,
pipe_buffer_unmap(&sctx->b.b, transfer); pipe_buffer_unmap(&sctx->b.b, transfer);
} else { } else {
indirect_count = info->indirect_count; indirect_count = indirect->draw_count;
} }
if (!indirect_count) { if (!indirect_count) {
@ -1098,9 +1101,9 @@ static void si_get_draw_start_count(struct si_context *sctx,
return; return;
} }
map_size = (indirect_count - 1) * info->indirect_stride + 3 * sizeof(unsigned); map_size = (indirect_count - 1) * indirect->stride + 3 * sizeof(unsigned);
data = pipe_buffer_map_range(&sctx->b.b, info->indirect, data = pipe_buffer_map_range(&sctx->b.b, indirect->buffer,
info->indirect_offset, map_size, indirect->offset, map_size,
PIPE_TRANSFER_READ, &transfer); PIPE_TRANSFER_READ, &transfer);
begin = UINT_MAX; begin = UINT_MAX;
@ -1115,7 +1118,7 @@ static void si_get_draw_start_count(struct si_context *sctx,
end = MAX2(end, start + count); end = MAX2(end, start + count);
} }
data += info->indirect_stride / sizeof(unsigned); data += indirect->stride / sizeof(unsigned);
} }
pipe_buffer_unmap(&sctx->b.b, transfer); pipe_buffer_unmap(&sctx->b.b, transfer);
@ -1301,18 +1304,20 @@ void si_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info)
} }
if (info->indirect) { if (info->indirect) {
/* Add the buffer size for memory checking in need_cs_space. */ struct pipe_draw_indirect_info *indirect = info->indirect;
r600_context_add_resource_size(ctx, info->indirect);
if (r600_resource(info->indirect)->TC_L2_dirty) { /* Add the buffer size for memory checking in need_cs_space. */
r600_context_add_resource_size(ctx, indirect->buffer);
if (r600_resource(indirect->buffer)->TC_L2_dirty) {
sctx->b.flags |= SI_CONTEXT_WRITEBACK_GLOBAL_L2; sctx->b.flags |= SI_CONTEXT_WRITEBACK_GLOBAL_L2;
r600_resource(info->indirect)->TC_L2_dirty = false; r600_resource(indirect->buffer)->TC_L2_dirty = false;
} }
if (info->indirect_params && if (indirect->indirect_draw_count &&
r600_resource(info->indirect_params)->TC_L2_dirty) { r600_resource(indirect->indirect_draw_count)->TC_L2_dirty) {
sctx->b.flags |= SI_CONTEXT_WRITEBACK_GLOBAL_L2; sctx->b.flags |= SI_CONTEXT_WRITEBACK_GLOBAL_L2;
r600_resource(info->indirect_params)->TC_L2_dirty = false; r600_resource(indirect->indirect_draw_count)->TC_L2_dirty = false;
} }
} }

View file

@ -812,8 +812,16 @@ void trace_dump_draw_info(const struct pipe_draw_info *state)
trace_dump_member(ptr, state, count_from_stream_output); trace_dump_member(ptr, state, count_from_stream_output);
trace_dump_member(ptr, state, indirect); if (!state->indirect) {
trace_dump_member(uint, state, indirect_offset); trace_dump_member(ptr, state, indirect);
} else {
trace_dump_member(uint, state, indirect->offset);
trace_dump_member(uint, state, indirect->stride);
trace_dump_member(uint, state, indirect->draw_count);
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_struct_end(); trace_dump_struct_end();
} }

View file

@ -641,6 +641,40 @@ struct pipe_index_buffer
}; };
struct pipe_draw_indirect_info
{
unsigned offset; /**< must be 4 byte aligned */
unsigned stride; /**< must be 4 byte aligned */
unsigned draw_count; /**< number of indirect draws */
unsigned indirect_draw_count_offset; /**< must be 4 byte aligned */
/* Indirect draw parameters resource is laid out as follows:
*
* if indexed is TRUE:
* struct {
* uint32_t count;
* uint32_t instance_count;
* uint32_t start;
* int32_t index_bias;
* uint32_t start_instance;
* };
* otherwise:
* struct {
* uint32_t count;
* uint32_t instance_count;
* uint32_t start;
* uint32_t start_instance;
* };
*/
struct pipe_resource *buffer;
/* Indirect draw count resource: If not NULL, contains a 32-bit value which
* is to be used as the real draw_count.
*/
struct pipe_resource *indirect_draw_count;
};
/** /**
* Information to describe a draw_vbo call. * Information to describe a draw_vbo call.
*/ */
@ -671,40 +705,9 @@ struct pipe_draw_info
*/ */
unsigned restart_index; unsigned restart_index;
unsigned indirect_offset; /**< must be 4 byte aligned */
unsigned indirect_stride; /**< must be 4 byte aligned */
unsigned indirect_count; /**< number of indirect draws */
unsigned indirect_params_offset; /**< must be 4 byte aligned */
/* Pointers must be at the end for an optimal structure layout on 64-bit. */ /* Pointers must be at the end for an optimal structure layout on 64-bit. */
/* Indirect draw parameters resource: If not NULL, most values are taken struct pipe_draw_indirect_info *indirect; /**< Indirect draw. */
* from this buffer instead, which is laid out as follows:
*
* if indexed is TRUE:
* struct {
* uint32_t count;
* uint32_t instance_count;
* uint32_t start;
* int32_t index_bias;
* uint32_t start_instance;
* };
* otherwise:
* struct {
* uint32_t count;
* uint32_t instance_count;
* uint32_t start;
* uint32_t start_instance;
* };
*/
struct pipe_resource *indirect;
/* Indirect draw count resource: If not NULL, contains a 32-bit value which
* is to be used as the real indirect_count. In that case indirect_count
* becomes the maximum possible value.
*/
struct pipe_resource *indirect_params;
/** /**
* Stream output target. If not NULL, it's used to provide the 'count' * Stream output target. If not NULL, it's used to provide the 'count'

View file

@ -3031,7 +3031,6 @@ NineDevice9_ProcessVertices( struct NineDevice9 *This,
draw.restart_index = 0; draw.restart_index = 0;
draw.count_from_stream_output = NULL; draw.count_from_stream_output = NULL;
draw.indirect = NULL; draw.indirect = NULL;
draw.indirect_params = NULL;
draw.instance_count = 1; draw.instance_count = 1;
draw.indexed = FALSE; draw.indexed = FALSE;
draw.start = 0; draw.start = 0;

View file

@ -2559,7 +2559,6 @@ init_draw_info(struct pipe_draw_info *info,
info->restart_index = 0; info->restart_index = 0;
info->count_from_stream_output = NULL; info->count_from_stream_output = NULL;
info->indirect = NULL; info->indirect = NULL;
info->indirect_params = NULL;
} }
CSMT_ITEM_NO_WAIT(nine_context_draw_primitive, CSMT_ITEM_NO_WAIT(nine_context_draw_primitive,

View file

@ -264,6 +264,7 @@ st_indirect_draw_vbo(struct gl_context *ctx,
{ {
struct st_context *st = st_context(ctx); struct st_context *st = st_context(ctx);
struct pipe_draw_info info; struct pipe_draw_info info;
struct pipe_draw_indirect_info indirect;
/* Mesa core state should have been validated already */ /* Mesa core state should have been validated already */
assert(ctx->NewState == 0x0); assert(ctx->NewState == 0x0);
@ -281,6 +282,7 @@ st_indirect_draw_vbo(struct gl_context *ctx,
return; return;
} }
memset(&indirect, 0, sizeof(indirect));
util_draw_init_info(&info); util_draw_init_info(&info);
if (ib) { if (ib) {
@ -294,8 +296,9 @@ st_indirect_draw_vbo(struct gl_context *ctx,
info.mode = translate_prim(ctx, mode); info.mode = translate_prim(ctx, mode);
info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices; info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices;
info.indirect = st_buffer_object(indirect_data)->buffer; info.indirect = &indirect;
info.indirect_offset = indirect_offset; indirect.buffer = st_buffer_object(indirect_data)->buffer;
indirect.offset = indirect_offset;
if (ST_DEBUG & DEBUG_DRAW) { if (ST_DEBUG & DEBUG_DRAW) {
debug_printf("st/draw indirect: mode %s drawcount %d indexed %d\n", debug_printf("st/draw indirect: mode %s drawcount %d indexed %d\n",
@ -308,18 +311,18 @@ st_indirect_draw_vbo(struct gl_context *ctx,
int i; int i;
assert(!indirect_params); assert(!indirect_params);
info.indirect_count = 1; indirect.draw_count = 1;
for (i = 0; i < draw_count; i++) { for (i = 0; i < draw_count; i++) {
info.drawid = i; info.drawid = i;
cso_draw_vbo(st->cso_context, &info); cso_draw_vbo(st->cso_context, &info);
info.indirect_offset += stride; indirect.offset += stride;
} }
} else { } else {
info.indirect_count = draw_count; indirect.draw_count = draw_count;
info.indirect_stride = stride; indirect.stride = stride;
if (indirect_params) { if (indirect_params) {
info.indirect_params = st_buffer_object(indirect_params)->buffer; indirect.indirect_draw_count = st_buffer_object(indirect_params)->buffer;
info.indirect_params_offset = indirect_params_offset; indirect.indirect_draw_count_offset = indirect_params_offset;
} }
cso_draw_vbo(st->cso_context, &info); cso_draw_vbo(st->cso_context, &info);
} }