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:
parent
1c9fdcefd4
commit
4122665dd9
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue