From e4076d557fd086abb598edeff4781b45db6a4382 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Sun, 4 Oct 2020 12:10:17 -0400 Subject: [PATCH] zink: split out ubo descriptor updating now that we're doing incremental updates, we can refactor this to be much more readable by having separate functions for each type of descriptor update Reviewed-by: Bas Nieuwenhuizen Part-of: --- src/gallium/drivers/zink/zink_draw.c | 177 +++++++++++++++++++++++++---------- 1 file changed, 127 insertions(+), 50 deletions(-) diff --git a/src/gallium/drivers/zink/zink_draw.c b/src/gallium/drivers/zink/zink_draw.c index 0111a35..e92a3e4 100644 --- a/src/gallium/drivers/zink/zink_draw.c +++ b/src/gallium/drivers/zink/zink_draw.c @@ -351,6 +351,123 @@ write_descriptor_resource(struct zink_descriptor_resource *resource, struct zink (*num_resources)++; } +static bool +bind_descriptors(struct zink_context *ctx, struct zink_descriptor_set *zds, unsigned num_wds, VkWriteDescriptorSet *wds, + unsigned num_resources, struct zink_descriptor_resource *resources, + uint32_t *dynamic_offsets, unsigned dynamic_offset_idx, bool is_compute, bool cache_hit) +{ + bool need_flush = false; + struct zink_program *pg = zds->pg; + struct zink_batch *batch = is_compute ? &ctx->compute_batch : zink_curr_batch(ctx); + struct zink_screen *screen = zink_screen(ctx->base.screen); + assert(zds->desc_set); + unsigned check_flush_id = is_compute ? 0 : ZINK_COMPUTE_BATCH_ID; + for (int i = 0; i < num_resources; ++i) { + assert(num_resources <= zink_program_num_bindings_typed(pg, zds->type, is_compute)); + assert(num_resources <= zds->num_resources); + + struct zink_resource *res = resources[i].res; + if (res) { + need_flush |= zink_batch_reference_resource_rw(batch, res, resources[i].write) == check_flush_id; + } + } + if (!cache_hit && num_wds) + vkUpdateDescriptorSets(screen->dev, num_wds, wds, 0, NULL); + + vkCmdBindDescriptorSets(batch->cmdbuf, is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS, + pg->layout, zds->type, 1, &zds->desc_set, zds->type == ZINK_DESCRIPTOR_TYPE_UBO ? dynamic_offset_idx : 0, dynamic_offsets); + return need_flush; +} + +static bool +update_ubo_descriptors(struct zink_context *ctx, struct zink_descriptor_set *zds, struct zink_transition *transitions, int *num_transitions, + struct set *transition_hash, bool is_compute, bool cache_hit) +{ + struct zink_program *pg = zds->pg; + struct zink_screen *screen = zink_screen(ctx->base.screen); + unsigned num_descriptors = pg->num_descriptors[zds->type]; + unsigned num_bindings = zink_program_num_bindings_typed(pg, zds->type, is_compute); + VkWriteDescriptorSet wds[num_descriptors]; + struct zink_descriptor_resource resources[num_bindings]; + VkDescriptorBufferInfo buffer_infos[num_bindings]; + unsigned num_wds = 0; + unsigned num_buffer_info = 0; + unsigned num_resources = 0; + struct zink_shader **stages; + struct { + uint32_t binding; + uint32_t offset; + } dynamic_buffers[PIPE_MAX_CONSTANT_BUFFERS]; + uint32_t dynamic_offsets[PIPE_MAX_CONSTANT_BUFFERS]; + unsigned dynamic_offset_idx = 0; + + unsigned num_stages = is_compute ? 1 : ZINK_SHADER_COUNT; + if (is_compute) + stages = &ctx->curr_compute->shader; + else + stages = &ctx->gfx_stages[0]; + + for (int i = 0; i < num_stages; i++) { + struct zink_shader *shader = stages[i]; + if (!shader) + continue; + enum pipe_shader_type stage = pipe_shader_type_from_mesa(shader->nir->info.stage); + + for (int j = 0; j < shader->num_bindings[zds->type]; j++) { + int index = shader->bindings[zds->type][j].index; + assert(shader->bindings[zds->type][j].type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || + shader->bindings[zds->type][j].type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC); + assert(ctx->ubos[stage][index].buffer_size <= screen->info.props.limits.maxUniformBufferRange); + struct zink_resource *res = zink_resource(ctx->ubos[stage][index].buffer); + assert(!res || ctx->ubos[stage][index].buffer_size > 0); + assert(!res || ctx->ubos[stage][index].buffer); + assert(num_resources < num_bindings); + desc_set_res_add(zds, res, num_resources, cache_hit); + read_descriptor_resource(&resources[num_resources], res, &num_resources); + assert(num_buffer_info < num_bindings); + buffer_infos[num_buffer_info].buffer = res ? res->buffer : + (screen->info.rb2_feats.nullDescriptor ? + VK_NULL_HANDLE : + zink_resource(ctx->dummy_vertex_buffer)->buffer); + if (shader->bindings[zds->type][j].type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) { + buffer_infos[num_buffer_info].offset = 0; + /* we're storing this to qsort later */ + dynamic_buffers[dynamic_offset_idx].binding = shader->bindings[zds->type][j].binding; + dynamic_buffers[dynamic_offset_idx++].offset = res ? ctx->ubos[stage][index].buffer_offset : 0; + } else + buffer_infos[num_buffer_info].offset = res ? ctx->ubos[stage][index].buffer_offset : 0; + buffer_infos[num_buffer_info].range = res ? ctx->ubos[stage][index].buffer_size : VK_WHOLE_SIZE; + if (res) + add_transition(res, 0, VK_ACCESS_UNIFORM_READ_BIT, stage, &transitions[*num_transitions], num_transitions, transition_hash); + wds[num_wds].pBufferInfo = buffer_infos + num_buffer_info; + ++num_buffer_info; + + wds[num_wds].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + wds[num_wds].pNext = NULL; + wds[num_wds].dstBinding = shader->bindings[zds->type][j].binding; + wds[num_wds].dstArrayElement = 0; + wds[num_wds].descriptorCount = shader->bindings[zds->type][j].size; + wds[num_wds].descriptorType = shader->bindings[zds->type][j].type; + wds[num_wds].dstSet = zds->desc_set; + ++num_wds; + } + } + + /* Values are taken from pDynamicOffsets in an order such that all entries for set N come before set N+1; + * within a set, entries are ordered by the binding numbers in the descriptor set layouts + * - vkCmdBindDescriptorSets spec + * + * because of this, we have to sort all the dynamic offsets by their associated binding to ensure they + * match what the driver expects + */ + if (dynamic_offset_idx > 1) + qsort(dynamic_buffers, dynamic_offset_idx, sizeof(uint32_t) * 2, cmp_dynamic_offset_binding); + for (int i = 0; i < dynamic_offset_idx; i++) + dynamic_offsets[i] = dynamic_buffers[i].offset; + + return bind_descriptors(ctx, zds, num_wds, wds, num_resources, resources, dynamic_offsets, dynamic_offset_idx, is_compute, cache_hit); +} + static void update_descriptors(struct zink_context *ctx, struct zink_screen *screen, bool is_compute) { @@ -370,12 +487,6 @@ update_descriptors(struct zink_context *ctx, struct zink_screen *screen, bool is unsigned num_surface_refs = 0; unsigned num_resources[ZINK_DESCRIPTOR_TYPES] = {0}; struct zink_shader **stages; - struct { - uint32_t binding; - uint32_t offset; - } dynamic_buffers[PIPE_MAX_CONSTANT_BUFFERS]; - uint32_t dynamic_offsets[PIPE_MAX_CONSTANT_BUFFERS]; - unsigned dynamic_offset_idx = 0; unsigned num_stages = is_compute ? 1 : ZINK_SHADER_COUNT; if (is_compute) @@ -399,7 +510,12 @@ update_descriptors(struct zink_context *ctx, struct zink_screen *screen, bool is int num_transitions = 0; struct set *ht = _mesa_set_create(NULL, transition_hash, transition_equals); - for (int h = 0; h < ZINK_DESCRIPTOR_TYPES; h++) { + + bool need_flush = false; + if (zds[ZINK_DESCRIPTOR_TYPE_UBO]) + need_flush |= update_ubo_descriptors(ctx, zds[ZINK_DESCRIPTOR_TYPE_UBO], transitions, &num_transitions, ht, is_compute, cache_hit[ZINK_DESCRIPTOR_TYPE_UBO]); + assert(num_transitions <= num_bindings); + for (int h = 1; h < ZINK_DESCRIPTOR_TYPES; h++) { for (int i = 0; i < num_stages; i++) { struct zink_shader *shader = stages[i]; if (!shader) @@ -408,33 +524,7 @@ update_descriptors(struct zink_context *ctx, struct zink_screen *screen, bool is for (int j = 0; j < shader->num_bindings[h]; j++) { int index = shader->bindings[h][j].index; - if (shader->bindings[h][j].type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER || - shader->bindings[h][j].type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) { - assert(ctx->ubos[stage][index].buffer_size <= screen->info.props.limits.maxUniformBufferRange); - struct zink_resource *res = zink_resource(ctx->ubos[stage][index].buffer); - assert(!res || ctx->ubos[stage][index].buffer_size > 0); - assert(!res || ctx->ubos[stage][index].buffer); - assert(num_resources[h] < num_bindings); - desc_set_res_add(zds[h], res, num_resources[h], cache_hit[h]); - read_descriptor_resource(&resources[h][num_resources[h]], res, &num_resources[h]); - assert(num_buffer_info[h] < num_bindings); - buffer_infos[h][num_buffer_info[h]].buffer = res ? res->buffer : - (screen->info.rb2_feats.nullDescriptor ? - VK_NULL_HANDLE : - zink_resource(ctx->dummy_vertex_buffer)->buffer); - if (shader->bindings[h][j].type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) { - buffer_infos[h][num_buffer_info[h]].offset = 0; - /* we're storing this to qsort later */ - dynamic_buffers[dynamic_offset_idx].binding = shader->bindings[h][j].binding; - dynamic_buffers[dynamic_offset_idx++].offset = res ? ctx->ubos[stage][index].buffer_offset : 0; - } else - buffer_infos[h][num_buffer_info[h]].offset = res ? ctx->ubos[stage][index].buffer_offset : 0; - buffer_infos[h][num_buffer_info[h]].range = res ? ctx->ubos[stage][index].buffer_size : VK_WHOLE_SIZE; - if (res) - add_transition(res, 0, VK_ACCESS_UNIFORM_READ_BIT, stage, &transitions[num_transitions], &num_transitions, ht); - wds[h][num_wds[h]].pBufferInfo = buffer_infos[h] + num_buffer_info[h]; - ++num_buffer_info[h]; - } else if (shader->bindings[h][j].type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) { + if (shader->bindings[h][j].type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) { struct zink_resource *res = zink_resource(ctx->ssbos[stage][index].buffer); desc_set_res_add(zds[h], res, num_resources[h], cache_hit[h]); if (res) { @@ -582,21 +672,8 @@ update_descriptors(struct zink_context *ctx, struct zink_screen *screen, bool is } _mesa_set_destroy(ht, NULL); - /* Values are taken from pDynamicOffsets in an order such that all entries for set N come before set N+1; - * within a set, entries are ordered by the binding numbers in the descriptor set layouts - * - vkCmdBindDescriptorSets spec - * - * because of this, we have to sort all the dynamic offsets by their associated binding to ensure they - * match what the driver expects - */ - if (dynamic_offset_idx > 1) - qsort(dynamic_buffers, dynamic_offset_idx, sizeof(uint32_t) * 2, cmp_dynamic_offset_binding); - for (int i = 0; i < dynamic_offset_idx; i++) - dynamic_offsets[i] = dynamic_buffers[i].offset; - unsigned check_flush_id = is_compute ? 0 : ZINK_COMPUTE_BATCH_ID; - bool need_flush = false; - for (int h = 0; h < ZINK_DESCRIPTOR_TYPES; h++) { + for (int h = 1; h < ZINK_DESCRIPTOR_TYPES; h++) { if (!zds[h]) continue; assert(zds[h]->desc_set); @@ -616,10 +693,10 @@ update_descriptors(struct zink_context *ctx, struct zink_screen *screen, bool is if (is_compute) vkCmdBindDescriptorSets(batch->cmdbuf, VK_PIPELINE_BIND_POINT_COMPUTE, - ctx->curr_compute->base.layout, h, 1, &zds[h]->desc_set, h == ZINK_DESCRIPTOR_TYPE_UBO ? dynamic_offset_idx : 0, dynamic_offsets); + ctx->curr_compute->base.layout, h, 1, &zds[h]->desc_set, 0, NULL); else vkCmdBindDescriptorSets(batch->cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, - ctx->curr_program->base.layout, h, 1, &zds[h]->desc_set, h == ZINK_DESCRIPTOR_TYPE_UBO ? dynamic_offset_idx : 0, dynamic_offsets); + ctx->curr_program->base.layout, h, 1, &zds[h]->desc_set, 0, NULL); for (int i = 0; i < num_stages; i++) { struct zink_shader *shader = stages[i]; -- 2.7.4