diff options
author | Jose Maria Casanova Crespo <[email protected]> | 2019-02-27 20:44:27 +0100 |
---|---|---|
committer | José Casanova Crespo <[email protected]> | 2019-03-06 22:19:08 +0000 |
commit | ffa9082c406d17680c0ceeeac921ace5e793e5af (patch) | |
tree | adada651f6b8bf310e2120c8476df958d0c81b4d | |
parent | c4d2da1f1471a742de7156e45ca52f83c75f0ba9 (diff) |
iris: setup EdgeFlag Vertex Element when needed.
If Vertex Shader uses EdgeFlag the hardware request that it is setup
as the last VERTEX_ELEMENT_STATE. If SGVS are add at draw time we
need to also reconfigure the last 3DSTATE_VF_INSTANCING so its
VertexElementIndex points to the new Vertex Element that contains
the EdgeFlag.
So if draw parameters or edgeflag are not used the CSO generated at
iris_create_vertex_element is sent directly in the batches. But if
edge flag is used we adjust last VERTEX_ELEMENT_STATE and
last 3DSTATE_VF_INSTANCING using their alternative edge flag version
we generate at iris_create_vertex_element and store at the CSO.
Reviewed-by: Kenneth Graunke <[email protected]>
-rw-r--r-- | src/gallium/drivers/iris/iris_context.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/iris/iris_program.c | 9 | ||||
-rw-r--r-- | src/gallium/drivers/iris/iris_state.c | 89 |
3 files changed, 86 insertions, 15 deletions
diff --git a/src/gallium/drivers/iris/iris_context.h b/src/gallium/drivers/iris/iris_context.h index fe06fd935af..87439718a94 100644 --- a/src/gallium/drivers/iris/iris_context.h +++ b/src/gallium/drivers/iris/iris_context.h @@ -571,6 +571,9 @@ struct iris_context { bool vs_uses_derived_draw_params; bool vs_needs_sgvs_element; + /** Do vertex shader uses edge flag ? */ + bool vs_needs_edge_flag; + /** Do any samplers (for any stage) need border color? */ bool need_border_colors; diff --git a/src/gallium/drivers/iris/iris_program.c b/src/gallium/drivers/iris/iris_program.c index ad3eab6d8ce..2feb43a367f 100644 --- a/src/gallium/drivers/iris/iris_program.c +++ b/src/gallium/drivers/iris/iris_program.c @@ -626,15 +626,22 @@ iris_update_compiled_vs(struct iris_context *ice) const bool needs_sgvs_element = uses_draw_params || vs_prog_data->uses_instanceid || vs_prog_data->uses_vertexid; + bool needs_edge_flag = false; + nir_foreach_variable(var, &ish->nir->inputs) { + if (var->data.location == VERT_ATTRIB_EDGEFLAG) + needs_edge_flag = true; + } if (ice->state.vs_uses_draw_params != uses_draw_params || - ice->state.vs_uses_derived_draw_params != uses_derived_draw_params) { + ice->state.vs_uses_derived_draw_params != uses_derived_draw_params || + ice->state.vs_needs_edge_flag != needs_edge_flag) { ice->state.dirty |= IRIS_DIRTY_VERTEX_BUFFERS | IRIS_DIRTY_VERTEX_ELEMENTS; } ice->state.vs_uses_draw_params = uses_draw_params; ice->state.vs_uses_derived_draw_params = uses_derived_draw_params; ice->state.vs_needs_sgvs_element = needs_sgvs_element; + ice->state.vs_needs_edge_flag = needs_edge_flag; } } diff --git a/src/gallium/drivers/iris/iris_state.c b/src/gallium/drivers/iris/iris_state.c index 464f81f17bf..327a3888ed3 100644 --- a/src/gallium/drivers/iris/iris_state.c +++ b/src/gallium/drivers/iris/iris_state.c @@ -2586,6 +2586,8 @@ iris_set_vertex_buffers(struct pipe_context *ctx, struct iris_vertex_element_state { uint32_t vertex_elements[1 + 33 * GENX(VERTEX_ELEMENT_STATE_length)]; uint32_t vf_instancing[33 * GENX(3DSTATE_VF_INSTANCING_length)]; + uint32_t edgeflag_ve[GENX(VERTEX_ELEMENT_STATE_length)]; + uint32_t edgeflag_vfi[GENX(3DSTATE_VF_INSTANCING_length)]; unsigned count; }; @@ -2593,7 +2595,12 @@ struct iris_vertex_element_state { * The pipe->create_vertex_elements() driver hook. * * This translates pipe_vertex_element to our 3DSTATE_VERTEX_ELEMENTS - * and 3DSTATE_VF_INSTANCING commands. SGVs are handled at draw time. + * and 3DSTATE_VF_INSTANCING commands. The vertex_elements and vf_instancing + * arrays are ready to be emitted at draw time if no EdgeFlag or SGVs are + * needed. In these cases we will need information available at draw time. + * We setup edgeflag_ve and edgeflag_vfi as alternatives last + * 3DSTATE_VERTEX_ELEMENT and 3DSTATE_VF_INSTANCING that can be used at + * draw time if we detect that EdgeFlag is needed by the Vertex Shader. */ static void * iris_create_vertex_elements(struct pipe_context *ctx, @@ -2607,11 +2614,6 @@ iris_create_vertex_elements(struct pipe_context *ctx, cso->count = count; - /* TODO: - * - create edge flag one - * - create SGV ones - * - if those are necessary, use count + 1/2/3... OR in the length - */ iris_pack_command(GENX(3DSTATE_VERTEX_ELEMENTS), cso->vertex_elements, ve) { ve.DWordLength = 1 + GENX(VERTEX_ELEMENT_STATE_length) * MAX2(count, 1) - 2; @@ -2650,6 +2652,7 @@ iris_create_vertex_elements(struct pipe_context *ctx, break; } iris_pack_state(GENX(VERTEX_ELEMENT_STATE), ve_pack_dest, ve) { + ve.EdgeFlagEnable = false; ve.VertexBufferIndex = state[i].vertex_buffer_index; ve.Valid = true; ve.SourceElementOffset = state[i].src_offset; @@ -2670,6 +2673,33 @@ iris_create_vertex_elements(struct pipe_context *ctx, vfi_pack_dest += GENX(3DSTATE_VF_INSTANCING_length); } + /* An alternative version of the last VE and VFI is stored so it + * can be used at draw time in case Vertex Shader uses EdgeFlag + */ + if (count) { + const unsigned edgeflag_index = count - 1; + const struct iris_format_info fmt = + iris_format_for_usage(devinfo, state[edgeflag_index].src_format, 0); + iris_pack_state(GENX(VERTEX_ELEMENT_STATE), cso->edgeflag_ve, ve) { + ve.EdgeFlagEnable = true ; + ve.VertexBufferIndex = state[edgeflag_index].vertex_buffer_index; + ve.Valid = true; + ve.SourceElementOffset = state[edgeflag_index].src_offset; + ve.SourceElementFormat = fmt.fmt; + ve.Component0Control = VFCOMP_STORE_SRC; + ve.Component1Control = VFCOMP_STORE_0; + ve.Component2Control = VFCOMP_STORE_0; + ve.Component3Control = VFCOMP_STORE_0; + } + iris_pack_command(GENX(3DSTATE_VF_INSTANCING), cso->edgeflag_vfi, vi) { + /* The vi.VertexElementIndex of the EdgeFlag Vertex Element is filled + * at draw time, as it should change if SGVs are emitted. + */ + vi.InstancingEnable = state[edgeflag_index].instance_divisor > 0; + vi.InstanceDataStepRate = state[edgeflag_index].instance_divisor; + } + } + return cso; } @@ -4774,12 +4804,13 @@ iris_upload_dirty_render_state(struct iris_context *ice, struct iris_vertex_element_state *cso = ice->state.cso_vertex_elements; const unsigned entries = MAX2(cso->count, 1); if (!(ice->state.vs_needs_sgvs_element || - ice->state.vs_uses_derived_draw_params)) { + ice->state.vs_uses_derived_draw_params || + ice->state.vs_needs_edge_flag)) { iris_batch_emit(batch, cso->vertex_elements, sizeof(uint32_t) * (1 + entries * GENX(VERTEX_ELEMENT_STATE_length))); } else { uint32_t dynamic_ves[1 + 33 * GENX(VERTEX_ELEMENT_STATE_length)]; - const int dyn_count = cso->count + + const unsigned dyn_count = cso->count + ice->state.vs_needs_sgvs_element + ice->state.vs_uses_derived_draw_params; @@ -4788,10 +4819,12 @@ iris_upload_dirty_render_state(struct iris_context *ice, ve.DWordLength = 1 + GENX(VERTEX_ELEMENT_STATE_length) * dyn_count - 2; } - memcpy(&dynamic_ves[1], &cso->vertex_elements[1], cso->count * + memcpy(&dynamic_ves[1], &cso->vertex_elements[1], + (cso->count - ice->state.vs_needs_edge_flag) * GENX(VERTEX_ELEMENT_STATE_length) * sizeof(uint32_t)); uint32_t *ve_pack_dest = - &dynamic_ves[1 + cso->count * GENX(VERTEX_ELEMENT_STATE_length)]; + &dynamic_ves[1 + (cso->count - ice->state.vs_needs_edge_flag) * + GENX(VERTEX_ELEMENT_STATE_length)]; if (ice->state.vs_needs_sgvs_element) { uint32_t base_ctrl = ice->state.vs_uses_draw_params ? @@ -4822,12 +4855,38 @@ iris_upload_dirty_render_state(struct iris_context *ice, } ve_pack_dest += GENX(VERTEX_ELEMENT_STATE_length); } + if (ice->state.vs_needs_edge_flag) { + for (int i = 0; i < GENX(VERTEX_ELEMENT_STATE_length); i++) + ve_pack_dest[i] = cso->edgeflag_ve[i]; + } + iris_batch_emit(batch, &dynamic_ves, sizeof(uint32_t) * (1 + dyn_count * GENX(VERTEX_ELEMENT_STATE_length))); } - iris_batch_emit(batch, cso->vf_instancing, sizeof(uint32_t) * - entries * GENX(3DSTATE_VF_INSTANCING_length)); + if (!ice->state.vs_needs_edge_flag) { + iris_batch_emit(batch, cso->vf_instancing, sizeof(uint32_t) * + entries * GENX(3DSTATE_VF_INSTANCING_length)); + } else { + assert(cso->count > 0); + const unsigned edgeflag_index = cso->count - 1; + uint32_t dynamic_vfi[33 * GENX(3DSTATE_VF_INSTANCING_length)]; + memcpy(&dynamic_vfi[0], cso->vf_instancing, edgeflag_index * + GENX(3DSTATE_VF_INSTANCING_length) * sizeof(uint32_t)); + + uint32_t *vfi_pack_dest = &dynamic_vfi[0] + + edgeflag_index * GENX(3DSTATE_VF_INSTANCING_length); + iris_pack_command(GENX(3DSTATE_VF_INSTANCING), vfi_pack_dest, vi) { + vi.VertexElementIndex = edgeflag_index + + ice->state.vs_needs_sgvs_element + + ice->state.vs_uses_derived_draw_params; + } + for (int i = 0; i < GENX(3DSTATE_VF_INSTANCING_length); i++) + vfi_pack_dest[i] |= cso->edgeflag_vfi[i]; + + iris_batch_emit(batch, &dynamic_vfi[0], sizeof(uint32_t) * + entries * GENX(3DSTATE_VF_INSTANCING_length)); + } } if (dirty & IRIS_DIRTY_VF_SGVS) { @@ -4839,13 +4898,15 @@ iris_upload_dirty_render_state(struct iris_context *ice, if (vs_prog_data->uses_vertexid) { sgv.VertexIDEnable = true; sgv.VertexIDComponentNumber = 2; - sgv.VertexIDElementOffset = cso->count; + sgv.VertexIDElementOffset = + cso->count - ice->state.vs_needs_edge_flag; } if (vs_prog_data->uses_instanceid) { sgv.InstanceIDEnable = true; sgv.InstanceIDComponentNumber = 3; - sgv.InstanceIDElementOffset = cso->count; + sgv.InstanceIDElementOffset = + cso->count - ice->state.vs_needs_edge_flag; } } } |