diff options
author | Chia-I Wu <[email protected]> | 2013-06-26 13:44:27 +0800 |
---|---|---|
committer | Chia-I Wu <[email protected]> | 2013-06-26 16:42:46 +0800 |
commit | 95c21f12f321bb33ae8e1f1b255680ac8eeffade (patch) | |
tree | be15c847df41f9b7b82c7ad18c2891b0b7c0bb12 /src/gallium/drivers/ilo | |
parent | 5fb5d4f0a6208e720998bbdbfe83df1035957f4a (diff) |
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.
Diffstat (limited to 'src/gallium/drivers/ilo')
-rw-r--r-- | src/gallium/drivers/ilo/ilo_3d.c | 21 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c | 4 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_context.c | 2 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_gpe.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_gpe_gen6.c | 32 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_gpe_gen6.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_gpe_gen7.c | 5 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_screen.c | 1 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_state.c | 62 |
9 files changed, 97 insertions, 36 deletions
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; |