From 4555211028394673f8ad68f3de9c12e9a1f93160 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Thu, 18 Jun 2015 14:26:29 +0800 Subject: [PATCH] ilo: add 3DSTATE_VF_INSTANCING to ilo_state_vf 3DSTATE_VF_INSTANCING specifies instancing enable and step rate. They are specified along with 3DSTATE_VERTEX_BUFFERS instead prior to Gen8. Both commands are added. --- .../drivers/ilo/core/ilo_builder_3d_top.h | 50 ++++---- src/gallium/drivers/ilo/core/ilo_state_vf.c | 117 +++++++++++++++--- src/gallium/drivers/ilo/core/ilo_state_vf.h | 26 ++-- .../drivers/ilo/genhw/gen_render_3d.xml.h | 4 +- src/gallium/drivers/ilo/ilo_blitter.h | 2 +- src/gallium/drivers/ilo/ilo_render_gen6.c | 7 +- src/gallium/drivers/ilo/ilo_render_gen8.c | 18 +-- src/gallium/drivers/ilo/ilo_state.c | 8 +- src/gallium/drivers/ilo/ilo_state.h | 3 +- 9 files changed, 168 insertions(+), 67 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 e4ee9cf3af4..782746591d9 100644 --- a/src/gallium/drivers/ilo/core/ilo_builder_3d_top.h +++ b/src/gallium/drivers/ilo/core/ilo_builder_3d_top.h @@ -264,7 +264,8 @@ gen8_3DSTATE_VF_TOPOLOGY(struct ilo_builder *builder, static inline void gen8_3DSTATE_VF_INSTANCING(struct ilo_builder *builder, - int vb_index, uint32_t step_rate) + const struct ilo_state_vf *vf, + uint32_t attr) { const uint8_t cmd_len = 3; uint32_t *dw; @@ -274,10 +275,15 @@ gen8_3DSTATE_VF_INSTANCING(struct ilo_builder *builder, ilo_builder_batch_pointer(builder, cmd_len, &dw); dw[0] = GEN8_RENDER_CMD(3D, 3DSTATE_VF_INSTANCING) | (cmd_len - 2); - dw[1] = vb_index; - if (step_rate) - dw[1] |= GEN8_INSTANCING_DW1_ENABLE; - dw[2] = step_rate; + dw[1] = attr << GEN8_INSTANCING_DW1_VE_INDEX__SHIFT; + dw[2] = 0; + /* see vf_set_gen8_3DSTATE_VF_INSTANCING() */ + if (attr >= vf->internal_ve_count) { + attr -= vf->internal_ve_count; + + dw[1] |= vf->user_instancing[attr][0]; + dw[2] |= vf->user_instancing[attr][1]; + } } static inline void @@ -298,9 +304,9 @@ gen8_3DSTATE_VF_SGVS(struct ilo_builder *builder, static inline void gen6_3DSTATE_VERTEX_BUFFERS(struct ilo_builder *builder, + const struct ilo_state_vf *vf, const struct ilo_vb_state *vb, const unsigned *vb_mapping, - const unsigned *instance_divisors, unsigned vb_count) { uint8_t cmd_len; @@ -327,9 +333,9 @@ gen6_3DSTATE_VERTEX_BUFFERS(struct ilo_builder *builder, pos++; for (hw_idx = 0; hw_idx < vb_count; hw_idx++) { - const unsigned instance_divisor = instance_divisors[hw_idx]; const unsigned pipe_idx = vb_mapping[hw_idx]; const struct pipe_vertex_buffer *cso = &vb->states[pipe_idx]; + const int8_t elem = vf->vb_to_first_elem[hw_idx]; dw[0] = hw_idx << GEN6_VB_DW0_INDEX__SHIFT; @@ -341,19 +347,19 @@ gen6_3DSTATE_VERTEX_BUFFERS(struct ilo_builder *builder, if (ilo_dev_gen(builder->dev) >= ILO_GEN(7)) dw[0] |= GEN7_VB_DW0_ADDR_MODIFIED; - if (instance_divisor) - dw[0] |= GEN6_VB_DW0_ACCESS_INSTANCEDATA; - else - dw[0] |= GEN6_VB_DW0_ACCESS_VERTEXDATA; + dw[1] = 0; + dw[2] = 0; + dw[3] = 0; - /* use null vb if there is no buffer or the stride is out of range */ - if (!cso->buffer || cso->stride > 2048) { - dw[0] |= GEN6_VB_DW0_IS_NULL; - dw[1] = 0; - dw[2] = 0; - dw[3] = (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) ? - 0 : instance_divisor; + /* see vf_set_gen6_vertex_buffer_state() */ + if (ilo_dev_gen(builder->dev) < ILO_GEN(8) && elem >= 0) { + dw[0] |= vf->user_instancing[elem][0]; + dw[3] |= vf->user_instancing[elem][1]; + } + /* use null vb if there is no VE/buffer or the stride is out of range */ + if (elem < 0 || !cso->buffer || cso->stride > 2048) { + dw[0] |= GEN6_VB_DW0_IS_NULL; continue; } @@ -371,8 +377,6 @@ gen6_3DSTATE_VERTEX_BUFFERS(struct ilo_builder *builder, const uint32_t start_offset = cso->buffer_offset; const uint32_t end_offset = buf->bo_size - 1; - dw[3] = instance_divisor; - ilo_builder_batch_reloc(builder, pos + 1, buf->bo, start_offset, 0); ilo_builder_batch_reloc(builder, pos + 2, buf->bo, end_offset, 0); } @@ -431,12 +435,16 @@ gen6_3DSTATE_VERTEX_ELEMENTS(struct ilo_builder *builder, dw[0] = GEN6_RENDER_CMD(3D, 3DSTATE_VERTEX_ELEMENTS) | (cmd_len - 2); dw++; - /* see vf_set_gen6_3DSTATE_VERTEX_ELEMENTS() */ + /* + * see vf_params_set_gen6_internal_ve() and + * vf_set_gen6_3DSTATE_VERTEX_ELEMENTS() + */ if (vf->internal_ve_count) { memcpy(dw, vf->internal_ve, sizeof(vf->internal_ve[0]) * vf->internal_ve_count); dw += 2 * vf->internal_ve_count; } + memcpy(dw, vf->user_ve, sizeof(vf->user_ve[0]) * vf->user_ve_count); } diff --git a/src/gallium/drivers/ilo/core/ilo_state_vf.c b/src/gallium/drivers/ilo/core/ilo_state_vf.c index 571af3d5aea..4126560aee9 100644 --- a/src/gallium/drivers/ilo/core/ilo_state_vf.c +++ b/src/gallium/drivers/ilo/core/ilo_state_vf.c @@ -221,6 +221,66 @@ vf_set_gen6_3DSTATE_VERTEX_ELEMENTS(struct ilo_state_vf *vf, return true; } +static bool +vf_set_gen6_vertex_buffer_state(struct ilo_state_vf *vf, + const struct ilo_dev *dev, + const struct ilo_state_vf_info *info) +{ + uint8_t i; + + ILO_DEV_ASSERT(dev, 6, 7.5); + + memset(vf->vb_to_first_elem, -1, sizeof(vf->vb_to_first_elem)); + + for (i = 0; i < info->element_count; i++) { + const struct ilo_state_vf_element_info *elem = &info->elements[i]; + + STATIC_ASSERT(ARRAY_SIZE(vf->user_instancing[i]) >= 2); + /* instancing enable only */ + vf->user_instancing[i][0] = (elem->instancing_enable) ? + GEN6_VB_DW0_ACCESS_INSTANCEDATA : + GEN6_VB_DW0_ACCESS_VERTEXDATA; + vf->user_instancing[i][1] = elem->instancing_step_rate; + + /* + * Instancing is per VB, not per VE, before Gen8. Set up a VB-to-VE + * mapping as well. + */ + if (vf->vb_to_first_elem[elem->buffer] < 0) { + vf->vb_to_first_elem[elem->buffer] = i; + } else { + const struct ilo_state_vf_element_info *first = + &info->elements[vf->vb_to_first_elem[elem->buffer]]; + + assert(elem->instancing_enable == first->instancing_enable && + elem->instancing_step_rate == first->instancing_step_rate); + } + } + + return true; +} + +static bool +vf_set_gen8_3DSTATE_VF_INSTANCING(struct ilo_state_vf *vf, + const struct ilo_dev *dev, + const struct ilo_state_vf_info *info) +{ + uint8_t i; + + ILO_DEV_ASSERT(dev, 8, 8); + + for (i = 0; i < info->element_count; i++) { + const struct ilo_state_vf_element_info *elem = &info->elements[i]; + + STATIC_ASSERT(ARRAY_SIZE(vf->user_instancing[i]) >= 2); + vf->user_instancing[i][0] = (elem->instancing_enable) ? + GEN8_INSTANCING_DW1_ENABLE : 0; + vf->user_instancing[i][1] = elem->instancing_step_rate; + } + + return true; +} + static uint32_t get_gen6_component_zeros(const struct ilo_dev *dev) { @@ -254,7 +314,9 @@ vf_params_set_gen6_internal_ve(struct ilo_state_vf *vf, { const bool prepend_ids = (params->prepend_vertexid || params->prepend_instanceid); - uint8_t internal_ve_count = 0; + uint8_t internal_ve_count = 0, i; + uint32_t dw1[2]; + ILO_DEV_ASSERT(dev, 6, 8); @@ -279,29 +341,23 @@ vf_params_set_gen6_internal_ve(struct ilo_state_vf *vf, * * - [DevILK+] Element[0] must be valid." */ - if (params->prepend_zeros || (!user_ve_count && !prepend_ids)) { - STATIC_ASSERT(ARRAY_SIZE(vf->internal_ve[internal_ve_count]) >= 2); - vf->internal_ve[internal_ve_count][0] = GEN6_VE_DW0_VALID; - vf->internal_ve[internal_ve_count][1] = get_gen6_component_zeros(dev); - internal_ve_count++; - } + if (params->prepend_zeros || (!user_ve_count && !prepend_ids)) + dw1[internal_ve_count++] = get_gen6_component_zeros(dev); if (prepend_ids) { - uint32_t dw1; - if (ilo_dev_gen(dev) >= ILO_GEN(8)) { /* placeholder for 3DSTATE_VF_SGVS */ - dw1 = get_gen6_component_zeros(dev); + dw1[internal_ve_count++] = get_gen6_component_zeros(dev); } else { - dw1 = get_gen6_component_ids(dev, - params->prepend_vertexid, - params->prepend_instanceid); + dw1[internal_ve_count++] = get_gen6_component_ids(dev, + params->prepend_vertexid, params->prepend_instanceid); } + } - STATIC_ASSERT(ARRAY_SIZE(vf->internal_ve[internal_ve_count]) >= 2); - vf->internal_ve[internal_ve_count][0] = GEN6_VE_DW0_VALID; - vf->internal_ve[internal_ve_count][1] = dw1; - internal_ve_count++; + for (i = 0; i < internal_ve_count; i++) { + STATIC_ASSERT(ARRAY_SIZE(vf->internal_ve[i]) >= 2); + vf->internal_ve[i][0] = GEN6_VE_DW0_VALID; + vf->internal_ve[i][1] = dw1[i]; } vf->internal_ve_count = internal_ve_count; @@ -440,9 +496,16 @@ ilo_state_vf_init(struct ilo_state_vf *vf, assert(ilo_state_vf_data_size(dev, info->element_count) <= info->data_size); vf->user_ve = (uint32_t (*)[2]) info->data; + vf->user_instancing = + (uint32_t (*)[2]) (vf->user_ve + info->element_count); ret &= vf_set_gen6_3DSTATE_VERTEX_ELEMENTS(vf, dev, info); + if (ilo_dev_gen(dev) >= ILO_GEN(8)) + ret &= vf_set_gen8_3DSTATE_VF_INSTANCING(vf, dev, info); + else + ret &= vf_set_gen6_vertex_buffer_state(vf, dev, info); + ret &= ilo_state_vf_set_params(vf, dev, &info->params); assert(ret); @@ -545,8 +608,12 @@ ilo_state_vf_full_delta(const struct ilo_state_vf *vf, { delta->dirty = ILO_STATE_VF_3DSTATE_VERTEX_ELEMENTS; - if (ilo_dev_gen(dev) >= ILO_GEN(8)) - delta->dirty |= ILO_STATE_VF_3DSTATE_VF_SGVS; + if (ilo_dev_gen(dev) >= ILO_GEN(8)) { + delta->dirty |= ILO_STATE_VF_3DSTATE_VF_SGVS | + ILO_STATE_VF_3DSTATE_VF_INSTANCING; + } else { + delta->dirty |= ILO_STATE_VF_3DSTATE_VERTEX_BUFFERS; + } if (ilo_dev_gen(dev) >= ILO_GEN(7.5)) delta->dirty |= ILO_STATE_VF_3DSTATE_VF; @@ -561,7 +628,8 @@ ilo_state_vf_get_delta(const struct ilo_state_vf *vf, struct ilo_state_vf_delta *delta) { /* no shallow copying */ - assert(vf->user_ve != old->user_ve); + assert(vf->user_ve != old->user_ve && + vf->user_instancing != old->user_instancing); delta->dirty = 0; @@ -573,6 +641,15 @@ ilo_state_vf_get_delta(const struct ilo_state_vf *vf, sizeof(vf->user_ve[0]) * vf->user_ve_count)) delta->dirty |= ILO_STATE_VF_3DSTATE_VERTEX_ELEMENTS; + if (vf->user_ve_count != old->user_ve_count || + memcmp(vf->user_instancing, old->user_instancing, + sizeof(vf->user_instancing[0]) * vf->user_ve_count)) { + if (ilo_dev_gen(dev) >= ILO_GEN(8)) + delta->dirty |= ILO_STATE_VF_3DSTATE_VF_INSTANCING; + else + delta->dirty |= ILO_STATE_VF_3DSTATE_VERTEX_BUFFERS; + } + if (ilo_dev_gen(dev) >= ILO_GEN(8)) { if (vf->sgvs[0] != old->sgvs[0]) delta->dirty |= ILO_STATE_VF_3DSTATE_VF_SGVS; diff --git a/src/gallium/drivers/ilo/core/ilo_state_vf.h b/src/gallium/drivers/ilo/core/ilo_state_vf.h index 49a0eb3aa14..c51da10270f 100644 --- a/src/gallium/drivers/ilo/core/ilo_state_vf.h +++ b/src/gallium/drivers/ilo/core/ilo_state_vf.h @@ -48,8 +48,10 @@ enum ilo_state_vf_dirty_bits { ILO_STATE_VF_3DSTATE_VERTEX_ELEMENTS = (1 << 0), ILO_STATE_VF_3DSTATE_VF_SGVS = (1 << 1), - ILO_STATE_VF_3DSTATE_VF = (1 << 2), - ILO_STATE_VF_3DSTATE_INDEX_BUFFER = (1 << 3), + ILO_STATE_VF_3DSTATE_VF_INSTANCING = (1 << 2), + ILO_STATE_VF_3DSTATE_VERTEX_BUFFERS = (1 << 3), + ILO_STATE_VF_3DSTATE_VF = (1 << 4), + ILO_STATE_VF_3DSTATE_INDEX_BUFFER = (1 << 5), }; /** @@ -64,6 +66,10 @@ struct ilo_state_vf_element_info { uint8_t component_count; bool is_integer; bool is_double; + + /* must be the same for those share the same buffer before Gen8 */ + bool instancing_enable; + uint32_t instancing_step_rate; }; /** @@ -100,17 +106,20 @@ struct ilo_state_vf_info { }; struct ilo_state_vf { + uint32_t (*user_ve)[2]; + uint32_t (*user_instancing)[2]; + int8_t vb_to_first_elem[ILO_STATE_VF_MAX_BUFFER_COUNT]; + uint8_t user_ve_count; + + bool edge_flag_supported; + uint32_t last_user_ve[2][2]; + /* two VEs are reserved for internal use */ uint32_t internal_ve[2][2]; - uint32_t (*user_ve)[2]; uint8_t internal_ve_count; - uint8_t user_ve_count; uint32_t sgvs[1]; - uint32_t last_user_ve[2][2]; - bool edge_flag_supported; - uint32_t cut[2]; }; @@ -122,7 +131,8 @@ static inline size_t ilo_state_vf_data_size(const struct ilo_dev *dev, uint8_t element_count) { const struct ilo_state_vf *vf = NULL; - return sizeof(vf->user_ve[0]) * element_count; + return (sizeof(vf->user_ve[0]) + + sizeof(vf->user_instancing[0])) * element_count; } bool diff --git a/src/gallium/drivers/ilo/genhw/gen_render_3d.xml.h b/src/gallium/drivers/ilo/genhw/gen_render_3d.xml.h index 60e3922e286..52173fe5d07 100644 --- a/src/gallium/drivers/ilo/genhw/gen_render_3d.xml.h +++ b/src/gallium/drivers/ilo/genhw/gen_render_3d.xml.h @@ -394,8 +394,8 @@ enum gen_msrast_mode { #define GEN8_INSTANCING_DW1_ENABLE (0x1 << 8) -#define GEN8_INSTANCING_DW1_VB_INDEX__MASK 0x0000003f -#define GEN8_INSTANCING_DW1_VB_INDEX__SHIFT 0 +#define GEN8_INSTANCING_DW1_VE_INDEX__MASK 0x0000003f +#define GEN8_INSTANCING_DW1_VE_INDEX__SHIFT 0 #define GEN8_3DSTATE_VF_SGVS__SIZE 2 diff --git a/src/gallium/drivers/ilo/ilo_blitter.h b/src/gallium/drivers/ilo/ilo_blitter.h index 08690f30378..6af6046e1a9 100644 --- a/src/gallium/drivers/ilo/ilo_blitter.h +++ b/src/gallium/drivers/ilo/ilo_blitter.h @@ -60,7 +60,7 @@ struct ilo_blitter { float vertices[3][2]; struct pipe_draw_info draw; - uint32_t vf_data[2]; + uint32_t vf_data[4]; struct ilo_state_vf vf; struct ilo_state_vs vs; diff --git a/src/gallium/drivers/ilo/ilo_render_gen6.c b/src/gallium/drivers/ilo/ilo_render_gen6.c index 89c87349b62..f997274397a 100644 --- a/src/gallium/drivers/ilo/ilo_render_gen6.c +++ b/src/gallium/drivers/ilo/ilo_render_gen6.c @@ -428,9 +428,10 @@ gen6_draw_vf(struct ilo_render *r, } /* 3DSTATE_VERTEX_BUFFERS */ - if (DIRTY(VB) || DIRTY(VE) || r->batch_bo_changed) { - gen6_3DSTATE_VERTEX_BUFFERS(r->builder, &vec->vb, vec->ve->vb_mapping, - vec->ve->instance_divisors, vec->ve->vb_count); + if ((session->vf_delta.dirty & ILO_STATE_VF_3DSTATE_VERTEX_BUFFERS) || + DIRTY(VB) || DIRTY(VE) || r->batch_bo_changed) { + gen6_3DSTATE_VERTEX_BUFFERS(r->builder, &vec->ve->vf, &vec->vb, + vec->ve->vb_mapping, vec->ve->vb_count); } /* 3DSTATE_VERTEX_ELEMENTS */ diff --git a/src/gallium/drivers/ilo/ilo_render_gen8.c b/src/gallium/drivers/ilo/ilo_render_gen8.c index 7e0d2060698..3b8589ce8f1 100644 --- a/src/gallium/drivers/ilo/ilo_render_gen8.c +++ b/src/gallium/drivers/ilo/ilo_render_gen8.c @@ -199,8 +199,6 @@ gen8_draw_vf(struct ilo_render *r, const struct ilo_state_vector *vec, struct ilo_render_draw_session *session) { - int i; - /* 3DSTATE_INDEX_BUFFER */ if ((session->vf_delta.dirty & ILO_STATE_VF_3DSTATE_INDEX_BUFFER) || DIRTY(IB) || r->batch_bo_changed) @@ -211,9 +209,10 @@ gen8_draw_vf(struct ilo_render *r, gen75_3DSTATE_VF(r->builder, &vec->ve->vf); /* 3DSTATE_VERTEX_BUFFERS */ - if (DIRTY(VB) || DIRTY(VE) || r->batch_bo_changed) { - gen6_3DSTATE_VERTEX_BUFFERS(r->builder, &vec->vb, vec->ve->vb_mapping, - vec->ve->instance_divisors, vec->ve->vb_count); + if ((session->vf_delta.dirty & ILO_STATE_VF_3DSTATE_VERTEX_BUFFERS) || + DIRTY(VB) || DIRTY(VE) || r->batch_bo_changed) { + gen6_3DSTATE_VERTEX_BUFFERS(r->builder, &vec->ve->vf, &vec->vb, + vec->ve->vb_mapping, vec->ve->vb_count); } /* 3DSTATE_VERTEX_ELEMENTS */ @@ -223,9 +222,12 @@ gen8_draw_vf(struct ilo_render *r, gen8_3DSTATE_VF_TOPOLOGY(r->builder, gen6_3d_translate_pipe_prim(vec->draw->mode)); - for (i = 0; i < vec->ve->vb_count; i++) { - gen8_3DSTATE_VF_INSTANCING(r->builder, i, - vec->ve->instance_divisors[i]); + if (session->vf_delta.dirty & ILO_STATE_VF_3DSTATE_VF_INSTANCING) { + const uint8_t attr_count = ilo_state_vf_get_attr_count(&vec->ve->vf); + uint8_t i; + + for (i = 0; i < attr_count; i++) + gen8_3DSTATE_VF_INSTANCING(r->builder, &vec->ve->vf, i); } if (session->vf_delta.dirty & ILO_STATE_VF_3DSTATE_VF_SGVS) diff --git a/src/gallium/drivers/ilo/ilo_state.c b/src/gallium/drivers/ilo/ilo_state.c index a01e9da69ec..d6144e4035f 100644 --- a/src/gallium/drivers/ilo/ilo_state.c +++ b/src/gallium/drivers/ilo/ilo_state.c @@ -1329,6 +1329,7 @@ ilo_create_vertex_elements_state(struct pipe_context *pipe, { const struct ilo_dev *dev = ilo_context(pipe)->dev; struct ilo_state_vf_element_info vf_elements[PIPE_MAX_ATTRIBS]; + unsigned instance_divisors[PIPE_MAX_ATTRIBS]; struct ilo_state_vf_info vf_info; struct ilo_ve_state *ve; unsigned i; @@ -1347,7 +1348,7 @@ ilo_create_vertex_elements_state(struct pipe_context *pipe, */ for (hw_idx = 0; hw_idx < ve->vb_count; hw_idx++) { if (ve->vb_mapping[hw_idx] == elem->vertex_buffer_index && - ve->instance_divisors[hw_idx] == elem->instance_divisor) + instance_divisors[hw_idx] == elem->instance_divisor) break; } @@ -1356,7 +1357,7 @@ ilo_create_vertex_elements_state(struct pipe_context *pipe, hw_idx = ve->vb_count++; ve->vb_mapping[hw_idx] = elem->vertex_buffer_index; - ve->instance_divisors[hw_idx] = elem->instance_divisor; + instance_divisors[hw_idx] = elem->instance_divisor; } attr->buffer = hw_idx; @@ -1367,6 +1368,9 @@ ilo_create_vertex_elements_state(struct pipe_context *pipe, attr->is_integer = util_format_is_pure_integer(elem->src_format); attr->is_double = (util_format_is_float(elem->src_format) && attr->format_size == attr->component_count * 8); + + attr->instancing_enable = (elem->instance_divisor != 0); + attr->instancing_step_rate = elem->instance_divisor; } memset(&vf_info, 0, sizeof(vf_info)); diff --git a/src/gallium/drivers/ilo/ilo_state.h b/src/gallium/drivers/ilo/ilo_state.h index 9ce7744948c..66c671a01e5 100644 --- a/src/gallium/drivers/ilo/ilo_state.h +++ b/src/gallium/drivers/ilo/ilo_state.h @@ -147,11 +147,10 @@ struct ilo_shader_state; struct ilo_ve_state { unsigned vb_mapping[PIPE_MAX_ATTRIBS]; - unsigned instance_divisors[PIPE_MAX_ATTRIBS]; unsigned vb_count; /* these are not valid until the state is finalized */ - uint32_t vf_data[PIPE_MAX_ATTRIBS][2]; + uint32_t vf_data[PIPE_MAX_ATTRIBS][4]; struct ilo_state_vf_params_info vf_params; struct ilo_state_vf vf; }; -- 2.30.2