summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChia-I Wu <[email protected]>2013-06-26 13:44:27 +0800
committerChia-I Wu <[email protected]>2013-06-26 16:42:46 +0800
commit95c21f12f321bb33ae8e1f1b255680ac8eeffade (patch)
treebe15c847df41f9b7b82c7ad18c2891b0b7c0bb12
parent5fb5d4f0a6208e720998bbdbfe83df1035957f4a (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.
-rw-r--r--src/gallium/drivers/ilo/ilo_3d.c21
-rw-r--r--src/gallium/drivers/ilo/ilo_3d_pipeline_gen6.c4
-rw-r--r--src/gallium/drivers/ilo/ilo_context.c2
-rw-r--r--src/gallium/drivers/ilo/ilo_gpe.h3
-rw-r--r--src/gallium/drivers/ilo/ilo_gpe_gen6.c32
-rw-r--r--src/gallium/drivers/ilo/ilo_gpe_gen6.h3
-rw-r--r--src/gallium/drivers/ilo/ilo_gpe_gen7.c5
-rw-r--r--src/gallium/drivers/ilo/ilo_screen.c1
-rw-r--r--src/gallium/drivers/ilo/ilo_state.c62
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;