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;
/* 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 */
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;
}
}
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;
struct ilo_ib_state {
struct pipe_index_buffer state;
+
+ struct pipe_resource *resource;
+ int64_t draw_start_offset;
};
struct ilo_ve_cso {
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;
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) |
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)
{
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);
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);
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);
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);
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)
{
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);
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);
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:
}
}
+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.
finalize_shader_states(ilo);
finalize_constant_buffers(ilo);
+ finalize_index_buffer(ilo);
u_upload_unmap(ilo->uploader);
}
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;