diff options
author | Jason Ekstrand <[email protected]> | 2019-02-20 18:14:56 -0600 |
---|---|---|
committer | Jason Ekstrand <[email protected]> | 2019-04-19 19:56:42 +0000 |
commit | a7d48718466978bd5a6ae73d9cf1c2ea566d772c (patch) | |
tree | aebf303c8636cda2aea589aa07263327f92b752f | |
parent | a5a0dc08f18928a080e3393ebc694bc7053216fb (diff) |
anv/pipeline: Sort bindings by most used first
This commit just sorts the bindings by how often they're used vs the
array size of the binding. This will let us make more nuanced decisions
about what goes in the binding table vs. what to make bindless.
Reviewed-by: Lionel Landwerlin <[email protected]>
Reviewed-by: Caio Marcelo de Oliveira Filho <[email protected]>
-rw-r--r-- | src/intel/vulkan/anv_nir_apply_pipeline_layout.c | 135 |
1 files changed, 95 insertions, 40 deletions
diff --git a/src/intel/vulkan/anv_nir_apply_pipeline_layout.c b/src/intel/vulkan/anv_nir_apply_pipeline_layout.c index 3448e753842..74f70806586 100644 --- a/src/intel/vulkan/anv_nir_apply_pipeline_layout.c +++ b/src/intel/vulkan/anv_nir_apply_pipeline_layout.c @@ -41,7 +41,7 @@ struct apply_pipeline_layout_state { bool desc_buffer_used; uint8_t desc_offset; - BITSET_WORD *used; + uint8_t *use_count; uint8_t *surface_offsets; uint8_t *sampler_offsets; } set[MAX_SETS]; @@ -54,7 +54,8 @@ add_binding(struct apply_pipeline_layout_state *state, const struct anv_descriptor_set_binding_layout *bind_layout = &state->layout->set[set].layout->binding[binding]; - BITSET_SET(state->set[set].used, binding); + if (state->set[set].use_count[binding] < UINT8_MAX) + state->set[set].use_count[binding]++; /* Only flag the descriptor buffer as used if there's actually data for * this binding. This lets us be lazy and call this function constantly @@ -505,6 +506,25 @@ apply_pipeline_layout_block(nir_block *block, } } +struct binding_info { + uint32_t binding; + uint8_t set; + uint16_t score; +}; + +static int +compare_binding_infos(const void *_a, const void *_b) +{ + const struct binding_info *a = _a, *b = _b; + if (a->score != b->score) + return b->score - a->score; + + if (a->set != b->set) + return a->set - b->set; + + return a->binding - b->binding; +} + void anv_nir_apply_pipeline_layout(const struct anv_physical_device *pdevice, bool robust_buffer_access, @@ -524,8 +544,7 @@ anv_nir_apply_pipeline_layout(const struct anv_physical_device *pdevice, for (unsigned s = 0; s < layout->num_sets; s++) { const unsigned count = layout->set[s].layout->binding_count; - const unsigned words = BITSET_WORDS(count); - state.set[s].used = rzalloc_array(mem_ctx, BITSET_WORD, words); + state.set[s].use_count = rzalloc_array(mem_ctx, uint8_t, count); state.set[s].surface_offsets = rzalloc_array(mem_ctx, uint8_t, count); state.set[s].sampler_offsets = rzalloc_array(mem_ctx, uint8_t, count); } @@ -557,49 +576,85 @@ anv_nir_apply_pipeline_layout(const struct anv_physical_device *pdevice, map->surface_count++; } + unsigned used_binding_count = 0; for (uint32_t set = 0; set < layout->num_sets; set++) { struct anv_descriptor_set_layout *set_layout = layout->set[set].layout; + for (unsigned b = 0; b < set_layout->binding_count; b++) { + if (state.set[set].use_count[b] == 0) + continue; - BITSET_WORD b, _tmp; - BITSET_FOREACH_SET(b, _tmp, state.set[set].used, - set_layout->binding_count) { - struct anv_descriptor_set_binding_layout *binding = - &set_layout->binding[b]; + used_binding_count++; + } + } - if (binding->array_size == 0) + struct binding_info *infos = + rzalloc_array(mem_ctx, struct binding_info, used_binding_count); + used_binding_count = 0; + for (uint32_t set = 0; set < layout->num_sets; set++) { + struct anv_descriptor_set_layout *set_layout = layout->set[set].layout; + for (unsigned b = 0; b < set_layout->binding_count; b++) { + if (state.set[set].use_count[b] == 0) continue; - if (binding->data & ANV_DESCRIPTOR_SURFACE_STATE) { - state.set[set].surface_offsets[b] = map->surface_count; - struct anv_sampler **samplers = binding->immutable_samplers; - for (unsigned i = 0; i < binding->array_size; i++) { - uint8_t planes = samplers ? samplers[i]->n_planes : 1; - for (uint8_t p = 0; p < planes; p++) { - map->surface_to_descriptor[map->surface_count++] = - (struct anv_pipeline_binding) { - .set = set, - .binding = b, - .index = i, - .plane = p, - }; - } + struct anv_descriptor_set_binding_layout *binding = + &layout->set[set].layout->binding[b]; + + /* Do a fixed-point calculation to generate a score based on the + * number of uses and the binding array size. + */ + uint16_t score = ((uint16_t)state.set[set].use_count[b] << 7) / + binding->array_size; + + infos[used_binding_count++] = (struct binding_info) { + .set = set, + .binding = b, + .score = score, + }; + } + } + + /* Order the binding infos based on score with highest scores first. If + * scores are equal we then order by set and binding. + */ + qsort(infos, used_binding_count, sizeof(struct binding_info), + compare_binding_infos); + + for (unsigned i = 0; i < used_binding_count; i++) { + unsigned set = infos[i].set, b = infos[i].binding; + struct anv_descriptor_set_binding_layout *binding = + &layout->set[set].layout->binding[b]; + + if (binding->data & ANV_DESCRIPTOR_SURFACE_STATE) { + state.set[set].surface_offsets[b] = map->surface_count; + struct anv_sampler **samplers = binding->immutable_samplers; + for (unsigned i = 0; i < binding->array_size; i++) { + uint8_t planes = samplers ? samplers[i]->n_planes : 1; + for (uint8_t p = 0; p < planes; p++) { + map->surface_to_descriptor[map->surface_count++] = + (struct anv_pipeline_binding) { + .set = set, + .binding = b, + .index = i, + .plane = p, + }; } } - - if (binding->data & ANV_DESCRIPTOR_SAMPLER_STATE) { - state.set[set].sampler_offsets[b] = map->sampler_count; - struct anv_sampler **samplers = binding->immutable_samplers; - for (unsigned i = 0; i < binding->array_size; i++) { - uint8_t planes = samplers ? samplers[i]->n_planes : 1; - for (uint8_t p = 0; p < planes; p++) { - map->sampler_to_descriptor[map->sampler_count++] = - (struct anv_pipeline_binding) { - .set = set, - .binding = b, - .index = i, - .plane = p, - }; - } + } + assert(map->surface_count <= MAX_BINDING_TABLE_SIZE); + + if (binding->data & ANV_DESCRIPTOR_SAMPLER_STATE) { + state.set[set].sampler_offsets[b] = map->sampler_count; + struct anv_sampler **samplers = binding->immutable_samplers; + for (unsigned i = 0; i < binding->array_size; i++) { + uint8_t planes = samplers ? samplers[i]->n_planes : 1; + for (uint8_t p = 0; p < planes; p++) { + map->sampler_to_descriptor[map->sampler_count++] = + (struct anv_pipeline_binding) { + .set = set, + .binding = b, + .index = i, + .plane = p, + }; } } } @@ -618,7 +673,7 @@ anv_nir_apply_pipeline_layout(const struct anv_physical_device *pdevice, const uint32_t array_size = layout->set[set].layout->binding[binding].array_size; - if (!BITSET_TEST(state.set[set].used, binding)) + if (state.set[set].use_count[binding] == 0) continue; struct anv_pipeline_binding *pipe_binding = |