It serves the same purpose as ilo_state_vertex_buffer does.
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
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,
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;
+}
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)
{
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 */
/* 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)
/* 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 */
/* 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)
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;
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
/* 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;
};