From 9904e647cca0a15c80557ed7bcc6893faf147436 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Fri, 19 Jun 2015 15:10:02 +0800 Subject: [PATCH] ilo: add ilo_state_index_buffer It serves the same purpose as ilo_state_vertex_buffer does. --- .../drivers/ilo/core/ilo_builder_3d_top.h | 95 +++++----------- src/gallium/drivers/ilo/core/ilo_state_vf.c | 104 ++++++++++++++++++ src/gallium/drivers/ilo/core/ilo_state_vf.h | 22 ++++ src/gallium/drivers/ilo/ilo_render_gen6.c | 4 +- src/gallium/drivers/ilo/ilo_render_gen8.c | 2 +- src/gallium/drivers/ilo/ilo_state.c | 13 +++ src/gallium/drivers/ilo/ilo_state.h | 1 + 7 files changed, 171 insertions(+), 70 deletions(-) diff --git a/src/gallium/drivers/ilo/core/ilo_builder_3d_top.h b/src/gallium/drivers/ilo/core/ilo_builder_3d_top.h index bb20c7fd87a..6a45d701f1d 100644 --- a/src/gallium/drivers/ilo/core/ilo_builder_3d_top.h +++ b/src/gallium/drivers/ilo/core/ilo_builder_3d_top.h @@ -437,102 +437,63 @@ gen6_3DSTATE_VERTEX_ELEMENTS(struct ilo_builder *builder, static inline void gen6_3DSTATE_INDEX_BUFFER(struct ilo_builder *builder, const struct ilo_state_vf *vf, - const struct ilo_ib_state *ib) + const struct ilo_state_index_buffer *ib) { const uint8_t cmd_len = 3; - struct ilo_buffer *buf = ilo_buffer(ib->hw_resource); - uint32_t start_offset, end_offset; - enum gen_index_format format; - uint32_t *dw; + uint32_t dw0, *dw; unsigned pos; ILO_DEV_ASSERT(builder->dev, 6, 7.5); - if (!buf) - return; - - switch (ib->hw_index_size) { - case 4: - format = GEN6_INDEX_DWORD; - break; - case 2: - format = GEN6_INDEX_WORD; - break; - case 1: - format = GEN6_INDEX_BYTE; - break; - default: - assert(!"unknown index size"); - format = GEN6_INDEX_BYTE; - break; - } + dw0 = GEN6_RENDER_CMD(3D, 3DSTATE_INDEX_BUFFER) | (cmd_len - 2) | + builder->mocs << GEN6_IB_DW0_MOCS__SHIFT; /* - * set start_offset to 0 here and adjust pipe_draw_info::start with - * ib->draw_start_offset in 3DPRIMITIVE + * see index_buffer_set_gen8_3DSTATE_INDEX_BUFFER() and + * vf_params_set_gen6_3dstate_index_buffer() */ - start_offset = 0; - end_offset = buf->bo_size; - - /* end_offset must also be aligned and is inclusive */ - end_offset -= (end_offset % ib->hw_index_size); - end_offset--; + dw0 |= ib->ib[0]; + if (ilo_dev_gen(builder->dev) <= ILO_GEN(7)) + dw0 |= vf->cut[0]; pos = ilo_builder_batch_pointer(builder, cmd_len, &dw); - dw[0] = GEN6_RENDER_CMD(3D, 3DSTATE_INDEX_BUFFER) | (cmd_len - 2) | - builder->mocs << GEN6_IB_DW0_MOCS__SHIFT | - format << GEN6_IB_DW0_FORMAT__SHIFT; - - /* see vf_params_set_gen6_3dstate_index_buffer() */ - if (ilo_dev_gen(builder->dev) <= ILO_GEN(7)) - dw[0] |= vf->cut[0]; - - ilo_builder_batch_reloc(builder, pos + 1, buf->bo, start_offset, 0); - ilo_builder_batch_reloc(builder, pos + 2, buf->bo, end_offset, 0); + dw[0] = dw0; + if (ib->need_bo) { + ilo_builder_batch_reloc(builder, pos + 1, ib->bo, ib->ib[1], 0); + ilo_builder_batch_reloc(builder, pos + 2, ib->bo, ib->ib[2], 0); + } else { + dw[1] = 0; + dw[2] = 0; + } } static inline void gen8_3DSTATE_INDEX_BUFFER(struct ilo_builder *builder, const struct ilo_state_vf *vf, - const struct ilo_ib_state *ib) + const struct ilo_state_index_buffer *ib) { const uint8_t cmd_len = 5; - struct ilo_buffer *buf = ilo_buffer(ib->hw_resource); - int format; uint32_t *dw; unsigned pos; ILO_DEV_ASSERT(builder->dev, 8, 8); - if (!buf) - return; - - switch (ib->hw_index_size) { - case 4: - format = GEN6_INDEX_DWORD; - break; - case 2: - format = GEN6_INDEX_WORD; - break; - case 1: - format = GEN6_INDEX_BYTE; - break; - default: - assert(!"unknown index size"); - format = GEN6_INDEX_BYTE; - break; - } - pos = ilo_builder_batch_pointer(builder, cmd_len, &dw); dw[0] = GEN6_RENDER_CMD(3D, 3DSTATE_INDEX_BUFFER) | (cmd_len - 2); - dw[1] = format << GEN8_IB_DW1_FORMAT__SHIFT | + /* see index_buffer_set_gen8_3DSTATE_INDEX_BUFFER() */ + dw[1] = ib->ib[0] | builder->mocs << GEN8_IB_DW1_MOCS__SHIFT; - dw[4] = buf->bo_size; - /* ignore ib->offset here in favor of adjusting 3DPRIMITIVE */ - ilo_builder_batch_reloc64(builder, pos + 2, buf->bo, 0, 0); + if (ib->need_bo) { + ilo_builder_batch_reloc64(builder, pos + 2, ib->bo, ib->ib[1], 0); + } else { + dw[2] = 0; + dw[3] = 0; + } + + dw[4] = ib->ib[2]; } static inline void diff --git a/src/gallium/drivers/ilo/core/ilo_state_vf.c b/src/gallium/drivers/ilo/core/ilo_state_vf.c index 92e0380e5c3..09e0f7f2293 100644 --- a/src/gallium/drivers/ilo/core/ilo_state_vf.c +++ b/src/gallium/drivers/ilo/core/ilo_state_vf.c @@ -555,6 +555,93 @@ vertex_buffer_set_gen8_vertex_buffer_state(struct ilo_state_vertex_buffer *vb, return true; } +static uint32_t +get_index_format_size(enum gen_index_format format) +{ + switch (format) { + case GEN6_INDEX_BYTE: return 1; + case GEN6_INDEX_WORD: return 2; + case GEN6_INDEX_DWORD: return 4; + default: + assert(!"unknown index format"); + return 1; + } +} + +static bool +index_buffer_validate_gen6(const struct ilo_dev *dev, + const struct ilo_state_index_buffer_info *info) +{ + const uint32_t format_size = get_index_format_size(info->format); + + ILO_DEV_ASSERT(dev, 6, 8); + + /* + * From the Sandy Bridge PRM, volume 2 part 1, page 79: + * + * "This field (Buffer Starting Address) contains the size-aligned (as + * specified by Index Format) Graphics Address of the first element of + * interest within the index buffer." + */ + assert(info->offset % format_size == 0); + + if (info->buf) + assert(info->offset < info->buf->bo_size && info->size); + + return true; +} + +static uint32_t +index_buffer_get_gen6_size(const struct ilo_dev *dev, + const struct ilo_state_index_buffer_info *info) +{ + uint32_t size; + + ILO_DEV_ASSERT(dev, 6, 8); + + if (!info->buf) + return 0; + + size = (info->offset + info->size <= info->buf->bo_size) ? info->size : + info->buf->bo_size - info->offset; + + if (ilo_dev_gen(dev) < ILO_GEN(8)) { + const uint32_t format_size = get_index_format_size(info->format); + size -= (size % format_size); + } + + return size; +} + +static bool +index_buffer_set_gen8_3DSTATE_INDEX_BUFFER(struct ilo_state_index_buffer *ib, + const struct ilo_dev *dev, + const struct ilo_state_index_buffer_info *info) +{ + const uint32_t size = index_buffer_get_gen6_size(dev, info); + + ILO_DEV_ASSERT(dev, 6, 8); + + if (!index_buffer_validate_gen6(dev, info)) + return false; + + STATIC_ASSERT(ARRAY_SIZE(ib->ib) >= 3); + if (ilo_dev_gen(dev) >= ILO_GEN(8)) { + ib->ib[0] = info->format << GEN8_IB_DW1_FORMAT__SHIFT; + ib->ib[1] = info->offset; + ib->ib[2] = size; + } else { + ib->ib[0] = info->format << GEN6_IB_DW0_FORMAT__SHIFT; + ib->ib[1] = info->offset; + /* address of the last valid byte, or 0 */ + ib->ib[2] = (size) ? info->offset + size - 1 : 0; + } + + ib->need_bo = (info->buf != NULL); + + return true; +} + bool ilo_state_vf_init(struct ilo_state_vf *vf, const struct ilo_dev *dev, @@ -752,3 +839,20 @@ ilo_state_vertex_buffer_set_info(struct ilo_state_vertex_buffer *vb, return ret; } + +/** + * No need to initialize first. + */ +bool +ilo_state_index_buffer_set_info(struct ilo_state_index_buffer *ib, + const struct ilo_dev *dev, + const struct ilo_state_index_buffer_info *info) +{ + bool ret = true; + + ret &= index_buffer_set_gen8_3DSTATE_INDEX_BUFFER(ib, dev, info); + + assert(ret); + + return ret; +} diff --git a/src/gallium/drivers/ilo/core/ilo_state_vf.h b/src/gallium/drivers/ilo/core/ilo_state_vf.h index 488f92f9b40..39750d8aafe 100644 --- a/src/gallium/drivers/ilo/core/ilo_state_vf.h +++ b/src/gallium/drivers/ilo/core/ilo_state_vf.h @@ -149,6 +149,23 @@ struct ilo_state_vertex_buffer { struct intel_bo *bo; }; +struct ilo_state_index_buffer_info { + const struct ilo_buffer *buf; + uint32_t offset; + uint32_t size; + + enum gen_index_format format; +}; + +struct ilo_state_index_buffer { + uint32_t ib[3]; + + bool need_bo; + + /* managed by users */ + struct intel_bo *bo; +}; + static inline size_t ilo_state_vf_data_size(const struct ilo_dev *dev, uint8_t element_count) { @@ -199,4 +216,9 @@ ilo_state_vertex_buffer_set_info(struct ilo_state_vertex_buffer *vb, const struct ilo_dev *dev, const struct ilo_state_vertex_buffer_info *info); +bool +ilo_state_index_buffer_set_info(struct ilo_state_index_buffer *ib, + const struct ilo_dev *dev, + const struct ilo_state_index_buffer_info *info); + #endif /* ILO_STATE_VF_H */ diff --git a/src/gallium/drivers/ilo/ilo_render_gen6.c b/src/gallium/drivers/ilo/ilo_render_gen6.c index 8415b136002..0623714c19f 100644 --- a/src/gallium/drivers/ilo/ilo_render_gen6.c +++ b/src/gallium/drivers/ilo/ilo_render_gen6.c @@ -415,7 +415,7 @@ gen6_draw_vf(struct ilo_render *r, /* 3DSTATE_INDEX_BUFFER */ if ((session->vf_delta.dirty & ILO_STATE_VF_3DSTATE_INDEX_BUFFER) || DIRTY(IB) || r->batch_bo_changed) - gen6_3DSTATE_INDEX_BUFFER(r->builder, &vec->ve->vf, &vec->ib); + gen6_3DSTATE_INDEX_BUFFER(r->builder, &vec->ve->vf, &vec->ib.ib); /* 3DSTATE_VF */ if (session->vf_delta.dirty & ILO_STATE_VF_3DSTATE_VF) @@ -424,7 +424,7 @@ gen6_draw_vf(struct ilo_render *r, /* 3DSTATE_INDEX_BUFFER */ if ((session->vf_delta.dirty & ILO_STATE_VF_3DSTATE_INDEX_BUFFER) || DIRTY(IB) || r->batch_bo_changed) - gen6_3DSTATE_INDEX_BUFFER(r->builder, &vec->ve->vf, &vec->ib); + gen6_3DSTATE_INDEX_BUFFER(r->builder, &vec->ve->vf, &vec->ib.ib); } /* 3DSTATE_VERTEX_BUFFERS */ diff --git a/src/gallium/drivers/ilo/ilo_render_gen8.c b/src/gallium/drivers/ilo/ilo_render_gen8.c index 4c1c08bbd25..8956e5f6b2e 100644 --- a/src/gallium/drivers/ilo/ilo_render_gen8.c +++ b/src/gallium/drivers/ilo/ilo_render_gen8.c @@ -202,7 +202,7 @@ gen8_draw_vf(struct ilo_render *r, /* 3DSTATE_INDEX_BUFFER */ if ((session->vf_delta.dirty & ILO_STATE_VF_3DSTATE_INDEX_BUFFER) || DIRTY(IB) || r->batch_bo_changed) - gen8_3DSTATE_INDEX_BUFFER(r->builder, &vec->ve->vf, &vec->ib); + gen8_3DSTATE_INDEX_BUFFER(r->builder, &vec->ve->vf, &vec->ib.ib); /* 3DSTATE_VF */ if (session->vf_delta.dirty & ILO_STATE_VF_3DSTATE_VF) diff --git a/src/gallium/drivers/ilo/ilo_state.c b/src/gallium/drivers/ilo/ilo_state.c index e24f8fa316f..966a6e0470c 100644 --- a/src/gallium/drivers/ilo/ilo_state.c +++ b/src/gallium/drivers/ilo/ilo_state.c @@ -379,11 +379,13 @@ finalize_constant_buffers(struct ilo_context *ilo) static void finalize_index_buffer(struct ilo_context *ilo) { + const struct ilo_dev *dev = ilo->dev; struct ilo_state_vector *vec = &ilo->state_vector; const bool need_upload = (vec->draw->indexed && (vec->ib.state.user_buffer || vec->ib.state.offset % vec->ib.state.index_size)); struct pipe_resource *current_hw_res = NULL; + struct ilo_state_index_buffer_info info; if (!(vec->dirty & ILO_DIRTY_IB) && !need_upload) return; @@ -435,6 +437,17 @@ finalize_index_buffer(struct ilo_context *ilo) vec->ib.hw_index_size = vec->ib.state.index_size; pipe_resource_reference(¤t_hw_res, NULL); + + memset(&info, 0, sizeof(info)); + if (vec->ib.hw_resource) { + info.buf = ilo_buffer(vec->ib.hw_resource); + info.size = info.buf->bo_size; + info.format = ilo_translate_index_size(vec->ib.hw_index_size); + + vec->ib.ib.bo = info.buf->bo; + } + + ilo_state_index_buffer_set_info(&vec->ib.ib, dev, &info); } static void diff --git a/src/gallium/drivers/ilo/ilo_state.h b/src/gallium/drivers/ilo/ilo_state.h index 2b3147fc355..d990269171b 100644 --- a/src/gallium/drivers/ilo/ilo_state.h +++ b/src/gallium/drivers/ilo/ilo_state.h @@ -167,6 +167,7 @@ struct ilo_ib_state { /* these are not valid until the state is finalized */ struct pipe_resource *hw_resource; unsigned hw_index_size; + struct ilo_state_index_buffer ib; /* an offset to be added to pipe_draw_info::start */ int64_t draw_start_offset; }; -- 2.30.2