summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/iris
diff options
context:
space:
mode:
authorJose Maria Casanova Crespo <[email protected]>2019-02-26 14:37:23 +0100
committerKenneth Graunke <[email protected]>2019-02-26 13:28:38 -0800
commit4122665dd90dc8997840194094bbd8cbefd7a4c3 (patch)
treeb4697ecd08b1ab4840f24cfe665210fe2c488caa /src/gallium/drivers/iris
parent1c9fdcefd4bf589128bce4ab3bbfdaa4f6faa600 (diff)
iris: Enable ARB_shader_draw_parameters support
Additional VERTEX_ELEMENT_STATE are used to store basevertex and baseinstance and drawid updating the DWordLength of the 3DSTATE_VERTEX_ELEMENTS command. This passes all piglit tests for spec.*draw_parameters.* tests and VK-GL-CTS KHR-GL45.shader_draw_parameters_tests.* tests. Now we only mark a dirty_update when parameters are changed or when we have an indirect draw. We enable PIPE_CAP_DRAW_PARAMETERS on Iris. There is no edge flag support in the Vertex Elements setup. Reviewed-by: Kenneth Graunke <[email protected]>
Diffstat (limited to 'src/gallium/drivers/iris')
-rw-r--r--src/gallium/drivers/iris/iris_context.h48
-rw-r--r--src/gallium/drivers/iris/iris_draw.c34
-rw-r--r--src/gallium/drivers/iris/iris_program.c18
-rw-r--r--src/gallium/drivers/iris/iris_screen.c1
-rw-r--r--src/gallium/drivers/iris/iris_state.c115
5 files changed, 212 insertions, 4 deletions
diff --git a/src/gallium/drivers/iris/iris_context.h b/src/gallium/drivers/iris/iris_context.h
index 8453e8c8d9e..fe06fd935af 100644
--- a/src/gallium/drivers/iris/iris_context.h
+++ b/src/gallium/drivers/iris/iris_context.h
@@ -449,6 +449,49 @@ struct iris_context {
struct u_upload_mgr *query_buffer_uploader;
struct {
+ struct {
+ /**
+ * Either the value of BaseVertex for indexed draw calls or the value
+ * of the argument <first> for non-indexed draw calls.
+ */
+ int firstvertex;
+ int baseinstance;
+ } params;
+
+ /**
+ * Resource and offset that stores draw_parameters from the indirect
+ * buffer or to the buffer that stures the previous values for non
+ * indirect draws.
+ */
+ struct pipe_resource *draw_params_res;
+ uint32_t draw_params_offset;
+
+ struct {
+ /**
+ * The value of DrawID. This always comes in from it's own vertex
+ * buffer since it's not part of the indirect draw parameters.
+ */
+ int drawid;
+
+ /**
+ * Stores if an indexed or non-indexed draw (~0/0). Useful to
+ * calculate BaseVertex as an AND of firstvertex and is_indexed_draw.
+ */
+ int is_indexed_draw;
+ } derived_params;
+
+ /**
+ * Resource and offset used for GL_ARB_shader_draw_parameters which
+ * contains parameters that are not present in the indirect buffer as
+ * drawid and is_indexed_draw. They will go in their own vertex element.
+ */
+ struct pipe_resource *derived_draw_params_res;
+ uint32_t derived_draw_params_offset;
+
+ bool is_indirect;
+ } draw;
+
+ struct {
struct iris_uncompiled_shader *uncompiled[MESA_SHADER_STAGES];
struct iris_compiled_shader *prog[MESA_SHADER_STAGES];
struct brw_vue_map *last_vue_map;
@@ -523,6 +566,11 @@ struct iris_context {
struct iris_shader_state shaders[MESA_SHADER_STAGES];
+ /** Do vertex shader uses shader draw parameters ? */
+ bool vs_uses_draw_params;
+ bool vs_uses_derived_draw_params;
+ bool vs_needs_sgvs_element;
+
/** Do any samplers (for any stage) need border color? */
bool need_border_colors;
diff --git a/src/gallium/drivers/iris/iris_draw.c b/src/gallium/drivers/iris/iris_draw.c
index 9dc102d2b70..e30f12974fb 100644
--- a/src/gallium/drivers/iris/iris_draw.c
+++ b/src/gallium/drivers/iris/iris_draw.c
@@ -73,6 +73,40 @@ iris_update_draw_info(struct iris_context *ice,
ice->state.primitive_restart = info->primitive_restart;
ice->state.cut_index = info->restart_index;
}
+
+ if (info->indirect) {
+ pipe_resource_reference(&ice->draw.draw_params_res,
+ info->indirect->buffer);
+ ice->draw.draw_params_offset = info->indirect->offset +
+ (info->index_size ? 12 : 8);
+ ice->draw.params.firstvertex = 0;
+ ice->draw.params.baseinstance = 0;
+ ice->state.dirty |= IRIS_DIRTY_VERTEX_BUFFERS |
+ IRIS_DIRTY_VERTEX_ELEMENTS |
+ IRIS_DIRTY_VF_SGVS;
+ } else if (ice->draw.is_indirect ||
+ ice->draw.params.firstvertex !=
+ (info->index_size ? info->index_bias : info->start) ||
+ (ice->draw.params.baseinstance != info->start_instance)) {
+ pipe_resource_reference(&ice->draw.draw_params_res, NULL);
+ ice->draw.draw_params_offset = 0;
+ ice->draw.params.firstvertex =
+ info->index_size ? info->index_bias : info->start;
+ ice->draw.params.baseinstance = info->start_instance;
+ ice->state.dirty |= IRIS_DIRTY_VERTEX_BUFFERS |
+ IRIS_DIRTY_VERTEX_ELEMENTS |
+ IRIS_DIRTY_VF_SGVS;
+ }
+ ice->draw.is_indirect = info->indirect;
+
+ if (ice->draw.derived_params.drawid != info->drawid ||
+ ice->draw.derived_params.is_indexed_draw != (info->index_size ? ~0 : 0)) {
+ ice->draw.derived_params.drawid = info->drawid;
+ ice->draw.derived_params.is_indexed_draw = info->index_size ? ~0 : 0;
+ ice->state.dirty |= IRIS_DIRTY_VERTEX_BUFFERS |
+ IRIS_DIRTY_VERTEX_ELEMENTS |
+ IRIS_DIRTY_VF_SGVS;
+ }
}
/**
diff --git a/src/gallium/drivers/iris/iris_program.c b/src/gallium/drivers/iris/iris_program.c
index 7f92c4a7998..28864c4f016 100644
--- a/src/gallium/drivers/iris/iris_program.c
+++ b/src/gallium/drivers/iris/iris_program.c
@@ -617,6 +617,24 @@ iris_update_compiled_vs(struct iris_context *ice)
IRIS_DIRTY_BINDINGS_VS |
IRIS_DIRTY_CONSTANTS_VS |
IRIS_DIRTY_VF_SGVS;
+ const struct brw_vs_prog_data *vs_prog_data =
+ (void *) shader->prog_data;
+ const bool uses_draw_params = vs_prog_data->uses_firstvertex ||
+ vs_prog_data->uses_baseinstance;
+ const bool uses_derived_draw_params = vs_prog_data->uses_drawid ||
+ vs_prog_data->uses_is_indexed_draw;
+ const bool needs_sgvs_element = uses_draw_params ||
+ vs_prog_data->uses_instanceid ||
+ vs_prog_data->uses_vertexid;
+
+ if (ice->state.vs_uses_draw_params != uses_draw_params ||
+ ice->state.vs_uses_derived_draw_params != uses_derived_draw_params) {
+ 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;
}
}
diff --git a/src/gallium/drivers/iris/iris_screen.c b/src/gallium/drivers/iris/iris_screen.c
index d831ffbc0a2..54c395c759f 100644
--- a/src/gallium/drivers/iris/iris_screen.c
+++ b/src/gallium/drivers/iris/iris_screen.c
@@ -172,6 +172,7 @@ iris_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_GLSL_TESS_LEVELS_AS_INPUTS:
case PIPE_CAP_LOAD_CONSTBUF:
case PIPE_CAP_NIR_COMPACT_ARRAYS:
+ case PIPE_CAP_DRAW_PARAMETERS:
return true;
case PIPE_CAP_TGSI_FS_FBFETCH:
case PIPE_CAP_POST_DEPTH_COVERAGE:
diff --git a/src/gallium/drivers/iris/iris_state.c b/src/gallium/drivers/iris/iris_state.c
index 578a61292e5..464f81f17bf 100644
--- a/src/gallium/drivers/iris/iris_state.c
+++ b/src/gallium/drivers/iris/iris_state.c
@@ -4651,6 +4651,62 @@ iris_upload_dirty_render_state(struct iris_context *ice,
if (dirty & IRIS_DIRTY_VERTEX_BUFFERS) {
int count = util_bitcount64(ice->state.bound_vertex_buffers);
+ int dynamic_bound = ice->state.bound_vertex_buffers;
+
+ if (ice->state.vs_uses_draw_params) {
+ if (ice->draw.draw_params_offset == 0) {
+ u_upload_data(ice->state.dynamic_uploader, 0, sizeof(ice->draw.params),
+ 4, &ice->draw.params, &ice->draw.draw_params_offset,
+ &ice->draw.draw_params_res);
+ }
+ assert(ice->draw.draw_params_res);
+
+ struct iris_vertex_buffer_state *state =
+ &(ice->state.genx->vertex_buffers[count]);
+ pipe_resource_reference(&state->resource, ice->draw.draw_params_res);
+ struct iris_resource *res = (void *) state->resource;
+
+ iris_pack_state(GENX(VERTEX_BUFFER_STATE), state->state, vb) {
+ vb.VertexBufferIndex = count;
+ vb.AddressModifyEnable = true;
+ vb.BufferPitch = 0;
+ vb.BufferSize = res->bo->size - ice->draw.draw_params_offset;
+ vb.BufferStartingAddress =
+ ro_bo(NULL, res->bo->gtt_offset +
+ (int) ice->draw.draw_params_offset);
+ vb.MOCS = mocs(res->bo);
+ }
+ dynamic_bound |= 1ull << count;
+ count++;
+ }
+
+ if (ice->state.vs_uses_derived_draw_params) {
+ u_upload_data(ice->state.dynamic_uploader, 0,
+ sizeof(ice->draw.derived_params), 4,
+ &ice->draw.derived_params,
+ &ice->draw.derived_draw_params_offset,
+ &ice->draw.derived_draw_params_res);
+
+ struct iris_vertex_buffer_state *state =
+ &(ice->state.genx->vertex_buffers[count]);
+ pipe_resource_reference(&state->resource,
+ ice->draw.derived_draw_params_res);
+ struct iris_resource *res = (void *) ice->draw.derived_draw_params_res;
+
+ iris_pack_state(GENX(VERTEX_BUFFER_STATE), state->state, vb) {
+ vb.VertexBufferIndex = count;
+ vb.AddressModifyEnable = true;
+ vb.BufferPitch = 0;
+ vb.BufferSize =
+ res->bo->size - ice->draw.derived_draw_params_offset;
+ vb.BufferStartingAddress =
+ ro_bo(NULL, res->bo->gtt_offset +
+ (int) ice->draw.derived_draw_params_offset);
+ vb.MOCS = mocs(res->bo);
+ }
+ dynamic_bound |= 1ull << count;
+ count++;
+ }
if (count) {
/* The VF cache designers cut corners, and made the cache key's
@@ -4664,7 +4720,7 @@ iris_upload_dirty_render_state(struct iris_context *ice,
*/
unsigned flush_flags = 0;
- uint64_t bound = ice->state.bound_vertex_buffers;
+ uint64_t bound = dynamic_bound;
while (bound) {
const int i = u_bit_scan64(&bound);
uint16_t high_bits = 0;
@@ -4704,7 +4760,7 @@ iris_upload_dirty_render_state(struct iris_context *ice,
}
map += 1;
- bound = ice->state.bound_vertex_buffers;
+ bound = dynamic_bound;
while (bound) {
const int i = u_bit_scan64(&bound);
memcpy(map, genx->vertex_buffers[i].state,
@@ -4717,8 +4773,59 @@ iris_upload_dirty_render_state(struct iris_context *ice,
if (dirty & IRIS_DIRTY_VERTEX_ELEMENTS) {
struct iris_vertex_element_state *cso = ice->state.cso_vertex_elements;
const unsigned entries = MAX2(cso->count, 1);
- iris_batch_emit(batch, cso->vertex_elements, sizeof(uint32_t) *
- (1 + entries * GENX(VERTEX_ELEMENT_STATE_length)));
+ if (!(ice->state.vs_needs_sgvs_element ||
+ ice->state.vs_uses_derived_draw_params)) {
+ 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 +
+ ice->state.vs_needs_sgvs_element +
+ ice->state.vs_uses_derived_draw_params;
+
+ iris_pack_command(GENX(3DSTATE_VERTEX_ELEMENTS),
+ &dynamic_ves, ve) {
+ ve.DWordLength =
+ 1 + GENX(VERTEX_ELEMENT_STATE_length) * dyn_count - 2;
+ }
+ memcpy(&dynamic_ves[1], &cso->vertex_elements[1], cso->count *
+ GENX(VERTEX_ELEMENT_STATE_length) * sizeof(uint32_t));
+ uint32_t *ve_pack_dest =
+ &dynamic_ves[1 + cso->count * GENX(VERTEX_ELEMENT_STATE_length)];
+
+ if (ice->state.vs_needs_sgvs_element) {
+ uint32_t base_ctrl = ice->state.vs_uses_draw_params ?
+ VFCOMP_STORE_SRC : VFCOMP_STORE_0;
+ iris_pack_state(GENX(VERTEX_ELEMENT_STATE), ve_pack_dest, ve) {
+ ve.Valid = true;
+ ve.VertexBufferIndex =
+ util_bitcount64(ice->state.bound_vertex_buffers);
+ ve.SourceElementFormat = ISL_FORMAT_R32G32_UINT;
+ ve.Component0Control = base_ctrl;
+ ve.Component1Control = base_ctrl;
+ ve.Component2Control = VFCOMP_STORE_0;
+ ve.Component3Control = VFCOMP_STORE_0;
+ }
+ ve_pack_dest += GENX(VERTEX_ELEMENT_STATE_length);
+ }
+ if (ice->state.vs_uses_derived_draw_params) {
+ iris_pack_state(GENX(VERTEX_ELEMENT_STATE), ve_pack_dest, ve) {
+ ve.Valid = true;
+ ve.VertexBufferIndex =
+ util_bitcount64(ice->state.bound_vertex_buffers) +
+ ice->state.vs_uses_draw_params;
+ ve.SourceElementFormat = ISL_FORMAT_R32G32_UINT;
+ ve.Component0Control = VFCOMP_STORE_SRC;
+ ve.Component1Control = VFCOMP_STORE_SRC;
+ ve.Component2Control = VFCOMP_STORE_0;
+ ve.Component3Control = VFCOMP_STORE_0;
+ }
+ ve_pack_dest += GENX(VERTEX_ELEMENT_STATE_length);
+ }
+ 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));
}