diff options
author | Jose Maria Casanova Crespo <[email protected]> | 2019-02-26 14:37:23 +0100 |
---|---|---|
committer | Kenneth Graunke <[email protected]> | 2019-02-26 13:28:38 -0800 |
commit | 4122665dd90dc8997840194094bbd8cbefd7a4c3 (patch) | |
tree | b4697ecd08b1ab4840f24cfe665210fe2c488caa /src | |
parent | 1c9fdcefd4bf589128bce4ab3bbfdaa4f6faa600 (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')
-rw-r--r-- | src/gallium/drivers/iris/iris_context.h | 48 | ||||
-rw-r--r-- | src/gallium/drivers/iris/iris_draw.c | 34 | ||||
-rw-r--r-- | src/gallium/drivers/iris/iris_program.c | 18 | ||||
-rw-r--r-- | src/gallium/drivers/iris/iris_screen.c | 1 | ||||
-rw-r--r-- | src/gallium/drivers/iris/iris_state.c | 115 |
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)); } |