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 <kenneth@whitecape.org>
This commit is contained in:
Jose Maria Casanova Crespo 2019-02-26 14:37:23 +01:00 committed by Kenneth Graunke
parent 1c9fdcefd4
commit 4122665dd9
5 changed files with 212 additions and 4 deletions

View File

@ -448,6 +448,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];
@ -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;

View File

@ -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;
}
}
/**

View File

@ -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;
}
}

View File

@ -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:

View File

@ -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));
}