mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-26 12:50:10 +01:00
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.
This commit is contained in:
parent
5fb5d4f0a6
commit
95c21f12f3
9 changed files with 97 additions and 36 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue