From: Chia-I Wu Date: Wed, 26 Jun 2013 05:44:27 +0000 (+0800) Subject: ilo: support PIPE_CAP_USER_INDEX_BUFFERS X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=95c21f12f321bb33ae8e1f1b255680ac8eeffade;p=mesa.git ilo: support PIPE_CAP_USER_INDEX_BUFFERS We want to access the user buffer, if available, when primitive restart is enabled and the restart index/primitive type is not natively supported. And since we are handling index buffer uploads in the driver with this change, we can also work around misalignment of index buffer offsets. --- diff --git a/src/gallium/drivers/ilo/ilo_3d.c b/src/gallium/drivers/ilo/ilo_3d.c index 69808d90751..ef3aeced340 100644 --- a/src/gallium/drivers/ilo/ilo_3d.c +++ b/src/gallium/drivers/ilo/ilo_3d.c @@ -605,15 +605,22 @@ ilo_draw_vbo_with_sw_restart(struct pipe_context *pipe, return; } - struct pipe_transfer *transfer = NULL; - const void *map = NULL; - map = pipe_buffer_map(pipe, ilo->ib.state.buffer, - PIPE_TRANSFER_READ, &transfer); + if (ilo->ib.state.buffer) { + struct pipe_transfer *transfer; + const void *map; - sub_prim_count = ilo_find_sub_primitives(map + ilo->ib.state.offset, - ilo->ib.state.index_size, info, restart_info); + map = pipe_buffer_map(pipe, ilo->ib.state.buffer, + PIPE_TRANSFER_READ, &transfer); - pipe_buffer_unmap(pipe, transfer); + sub_prim_count = ilo_find_sub_primitives(map + ilo->ib.state.offset, + ilo->ib.state.index_size, info, restart_info); + + pipe_buffer_unmap(pipe, transfer); + } + else { + sub_prim_count = ilo_find_sub_primitives(ilo->ib.state.user_buffer, + ilo->ib.state.index_size, info, restart_info); + } info = restart_info; diff --git a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c index 00da47f3bb2..190f6a9d9fb 100644 --- a/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c +++ b/src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c @@ -401,7 +401,7 @@ gen6_pipeline_vf(struct ilo_3d_pipeline *p, /* 3DSTATE_INDEX_BUFFER */ if (DIRTY(INDEX_BUFFER) || session->batch_bo_changed) { p->gen6_3DSTATE_INDEX_BUFFER(p->dev, - &ilo->ib.state, ilo->draw->primitive_restart, p->cp); + &ilo->ib, ilo->draw->primitive_restart, p->cp); } /* 3DSTATE_VERTEX_BUFFERS */ @@ -455,7 +455,7 @@ gen6_pipeline_vf_draw(struct ilo_3d_pipeline *p, struct gen6_pipeline_session *session) { /* 3DPRIMITIVE */ - p->gen6_3DPRIMITIVE(p->dev, ilo->draw, false, p->cp); + p->gen6_3DPRIMITIVE(p->dev, ilo->draw, &ilo->ib, false, p->cp); p->state.has_gen6_wa_pipe_control = false; } diff --git a/src/gallium/drivers/ilo/ilo_context.c b/src/gallium/drivers/ilo/ilo_context.c index e355a9c3089..7fd5ab6b524 100644 --- a/src/gallium/drivers/ilo/ilo_context.c +++ b/src/gallium/drivers/ilo/ilo_context.c @@ -145,7 +145,7 @@ ilo_context_create(struct pipe_screen *screen, void *priv) } ilo->uploader = u_upload_create(&ilo->base, 1024 * 1024, 16, - PIPE_BIND_CONSTANT_BUFFER); + PIPE_BIND_CONSTANT_BUFFER | PIPE_BIND_INDEX_BUFFER); if (!ilo->uploader) { ilo_context_destroy(&ilo->base); return NULL; diff --git a/src/gallium/drivers/ilo/ilo_gpe.h b/src/gallium/drivers/ilo/ilo_gpe.h index 7825e58a40f..aa979f31a09 100644 --- a/src/gallium/drivers/ilo/ilo_gpe.h +++ b/src/gallium/drivers/ilo/ilo_gpe.h @@ -64,6 +64,9 @@ struct ilo_vb_state { struct ilo_ib_state { struct pipe_index_buffer state; + + struct pipe_resource *resource; + int64_t draw_start_offset; }; struct ilo_ve_cso { diff --git a/src/gallium/drivers/ilo/ilo_gpe_gen6.c b/src/gallium/drivers/ilo/ilo_gpe_gen6.c index 75721f160ab..9c88b0a5b31 100644 --- a/src/gallium/drivers/ilo/ilo_gpe_gen6.c +++ b/src/gallium/drivers/ilo/ilo_gpe_gen6.c @@ -1027,13 +1027,13 @@ gen6_emit_3DSTATE_VERTEX_ELEMENTS(const struct ilo_dev_info *dev, static void gen6_emit_3DSTATE_INDEX_BUFFER(const struct ilo_dev_info *dev, - const struct pipe_index_buffer *ib, + const struct ilo_ib_state *ib, bool enable_cut_index, struct ilo_cp *cp) { const uint32_t cmd = ILO_GPE_CMD(0x3, 0x0, 0x0a); const uint8_t cmd_len = 3; - const struct ilo_buffer *buf = ilo_buffer(ib->buffer); + const struct ilo_buffer *buf = ilo_buffer(ib->resource); uint32_t start_offset, end_offset; int format; @@ -1042,21 +1042,18 @@ gen6_emit_3DSTATE_INDEX_BUFFER(const struct ilo_dev_info *dev, if (!buf) return; - format = gen6_translate_index_size(ib->index_size); + format = gen6_translate_index_size(ib->state.index_size); - start_offset = ib->offset; - /* start_offset must be aligned to index size */ - if (start_offset % ib->index_size) { - /* TODO need a u_upload_mgr to upload the IB to an aligned address */ - assert(!"unaligned index buffer offset"); - start_offset -= start_offset % ib->index_size; - } - - /* end_offset must also be aligned */ + /* + * set start_offset to 0 here and adjust pipe_draw_info::start with + * ib->draw_start_offset in 3DPRIMITIVE + */ + start_offset = 0; end_offset = buf->bo_size; - end_offset -= (end_offset % ib->index_size); - /* it is inclusive */ - end_offset -= 1; + + /* end_offset must also be aligned and is inclusive */ + end_offset -= (end_offset % ib->state.index_size); + end_offset--; ilo_cp_begin(cp, cmd_len); ilo_cp_write(cp, cmd | (cmd_len - 2) | @@ -3086,6 +3083,7 @@ gen6_emit_PIPE_CONTROL(const struct ilo_dev_info *dev, static void gen6_emit_3DPRIMITIVE(const struct ilo_dev_info *dev, const struct pipe_draw_info *info, + const struct ilo_ib_state *ib, bool rectlist, struct ilo_cp *cp) { @@ -3096,6 +3094,8 @@ gen6_emit_3DPRIMITIVE(const struct ilo_dev_info *dev, const int vb_access = (info->indexed) ? GEN4_3DPRIM_VERTEXBUFFER_ACCESS_RANDOM : GEN4_3DPRIM_VERTEXBUFFER_ACCESS_SEQUENTIAL; + const uint32_t vb_start = info->start + + ((info->indexed) ? ib->draw_start_offset : 0); ILO_GPE_VALID_GEN(dev, 6, 6); @@ -3104,7 +3104,7 @@ gen6_emit_3DPRIMITIVE(const struct ilo_dev_info *dev, prim << GEN4_3DPRIM_TOPOLOGY_TYPE_SHIFT | vb_access); ilo_cp_write(cp, info->count); - ilo_cp_write(cp, info->start); + ilo_cp_write(cp, vb_start); ilo_cp_write(cp, info->instance_count); ilo_cp_write(cp, info->start_instance); ilo_cp_write(cp, info->index_bias); diff --git a/src/gallium/drivers/ilo/ilo_gpe_gen6.h b/src/gallium/drivers/ilo/ilo_gpe_gen6.h index 489371c27ce..7e24f97b8ca 100644 --- a/src/gallium/drivers/ilo/ilo_gpe_gen6.h +++ b/src/gallium/drivers/ilo/ilo_gpe_gen6.h @@ -209,7 +209,7 @@ typedef void typedef void (*ilo_gpe_gen6_3DSTATE_INDEX_BUFFER)(const struct ilo_dev_info *dev, - const struct pipe_index_buffer *ib, + const struct ilo_ib_state *ib, bool enable_cut_index, struct ilo_cp *cp); @@ -362,6 +362,7 @@ typedef void typedef void (*ilo_gpe_gen6_3DPRIMITIVE)(const struct ilo_dev_info *dev, const struct pipe_draw_info *info, + const struct ilo_ib_state *ib, bool rectlist, struct ilo_cp *cp); diff --git a/src/gallium/drivers/ilo/ilo_gpe_gen7.c b/src/gallium/drivers/ilo/ilo_gpe_gen7.c index 21764c9ff3c..2a590be2ddc 100644 --- a/src/gallium/drivers/ilo/ilo_gpe_gen7.c +++ b/src/gallium/drivers/ilo/ilo_gpe_gen7.c @@ -1182,6 +1182,7 @@ gen7_emit_3DSTATE_SO_BUFFER(const struct ilo_dev_info *dev, static void gen7_emit_3DPRIMITIVE(const struct ilo_dev_info *dev, const struct pipe_draw_info *info, + const struct ilo_ib_state *ib, bool rectlist, struct ilo_cp *cp) { @@ -1192,6 +1193,8 @@ gen7_emit_3DPRIMITIVE(const struct ilo_dev_info *dev, const int vb_access = (info->indexed) ? GEN7_3DPRIM_VERTEXBUFFER_ACCESS_RANDOM : GEN7_3DPRIM_VERTEXBUFFER_ACCESS_SEQUENTIAL; + const uint32_t vb_start = info->start + + ((info->indexed) ? ib->draw_start_offset : 0); ILO_GPE_VALID_GEN(dev, 7, 7); @@ -1199,7 +1202,7 @@ gen7_emit_3DPRIMITIVE(const struct ilo_dev_info *dev, ilo_cp_write(cp, cmd | (cmd_len - 2)); ilo_cp_write(cp, vb_access | prim); ilo_cp_write(cp, info->count); - ilo_cp_write(cp, info->start); + ilo_cp_write(cp, vb_start); ilo_cp_write(cp, info->instance_count); ilo_cp_write(cp, info->start_instance); ilo_cp_write(cp, info->index_bias); diff --git a/src/gallium/drivers/ilo/ilo_screen.c b/src/gallium/drivers/ilo/ilo_screen.c index aaceb7a6494..3f7c8cfab55 100644 --- a/src/gallium/drivers/ilo/ilo_screen.c +++ b/src/gallium/drivers/ilo/ilo_screen.c @@ -391,7 +391,6 @@ ilo_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_COMPUTE: return false; /* TODO */ case PIPE_CAP_USER_INDEX_BUFFERS: - return false; case PIPE_CAP_USER_CONSTANT_BUFFERS: return true; case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT: diff --git a/src/gallium/drivers/ilo/ilo_state.c b/src/gallium/drivers/ilo/ilo_state.c index 0e4e937879f..ede72623f17 100644 --- a/src/gallium/drivers/ilo/ilo_state.c +++ b/src/gallium/drivers/ilo/ilo_state.c @@ -126,6 +126,44 @@ finalize_constant_buffers(struct ilo_context *ilo) } } +static void +finalize_index_buffer(struct ilo_context *ilo) +{ + struct pipe_resource *res; + unsigned offset, size; + bool uploaded = false; + + if (!ilo->draw->indexed) + return; + + res = ilo->ib.resource; + offset = ilo->ib.state.index_size * ilo->draw->start; + size = ilo->ib.state.index_size * ilo->draw->count; + + if (ilo->ib.state.user_buffer) { + u_upload_data(ilo->uploader, 0, size, + ilo->ib.state.user_buffer + offset, &offset, &res); + uploaded = true; + } + else if (unlikely(ilo->ib.state.offset % ilo->ib.state.index_size)) { + u_upload_buffer(ilo->uploader, 0, ilo->ib.state.offset + offset, size, + ilo->ib.state.buffer, &offset, &res); + uploaded = true; + } + + if (uploaded) { + ilo->ib.resource = res; + + assert(offset % ilo->ib.state.index_size == 0); + ilo->ib.draw_start_offset = offset / ilo->ib.state.index_size; + + /* could be negative */ + ilo->ib.draw_start_offset -= ilo->draw->start; + + ilo->dirty |= ILO_DIRTY_INDEX_BUFFER; + } +} + /** * Finalize states. Some states depend on other states and are * incomplete/invalid until finalized. @@ -138,6 +176,7 @@ ilo_finalize_3d_states(struct ilo_context *ilo, finalize_shader_states(ilo); finalize_constant_buffers(ilo); + finalize_index_buffer(ilo); u_upload_unmap(ilo->uploader); } @@ -818,19 +857,28 @@ ilo_set_index_buffer(struct pipe_context *pipe, struct ilo_context *ilo = ilo_context(pipe); if (state) { - /* no PIPE_CAP_USER_INDEX_BUFFERS */ - assert(!state->user_buffer); - - ilo->ib.state.index_size = state->index_size; - ilo->ib.state.offset = state->offset; pipe_resource_reference(&ilo->ib.state.buffer, state->buffer); + ilo->ib.state.offset = state->offset; + ilo->ib.state.index_size = state->index_size; + + /* state->offset does not apply for user buffer */ ilo->ib.state.user_buffer = state->user_buffer; + + /* + * when there is no state->buffer or state->offset is misaligned, + * ilo_finalize_3d_states() will set these to the valid values + */ + pipe_resource_reference(&ilo->ib.resource, state->buffer); + ilo->ib.draw_start_offset = state->offset / state->index_size; } else { - ilo->ib.state.index_size = 0; - ilo->ib.state.offset = 0; pipe_resource_reference(&ilo->ib.state.buffer, NULL); + ilo->ib.state.offset = 0; + ilo->ib.state.index_size = 0; ilo->ib.state.user_buffer = NULL; + + pipe_resource_reference(&ilo->ib.resource, NULL); + ilo->ib.draw_start_offset = 0; } ilo->dirty |= ILO_DIRTY_INDEX_BUFFER;