summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJose Maria Casanova Crespo <[email protected]>2019-02-27 20:44:27 +0100
committerJosé Casanova Crespo <[email protected]>2019-03-06 22:19:08 +0000
commitffa9082c406d17680c0ceeeac921ace5e793e5af (patch)
treeadada651f6b8bf310e2120c8476df958d0c81b4d
parentc4d2da1f1471a742de7156e45ca52f83c75f0ba9 (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.h3
-rw-r--r--src/gallium/drivers/iris/iris_program.c9
-rw-r--r--src/gallium/drivers/iris/iris_state.c89
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;
}
}
}