diff --git a/src/gallium/drivers/zink/zink_batch.c b/src/gallium/drivers/zink/zink_batch.c index 6be245c4faa..841c2d9a894 100644 --- a/src/gallium/drivers/zink/zink_batch.c +++ b/src/gallium/drivers/zink/zink_batch.c @@ -414,13 +414,20 @@ zink_batch_bind_db(struct zink_context *ctx) struct zink_screen *screen = zink_screen(ctx->base.screen); struct zink_batch *batch = &ctx->batch; unsigned count = screen->compact_descriptors ? 3 : 5; - VkDescriptorBufferBindingInfoEXT infos[ZINK_DESCRIPTOR_NON_BINDLESS_TYPES] = {0}; + VkDescriptorBufferBindingInfoEXT infos[ZINK_DESCRIPTOR_ALL_TYPES] = {0}; for (unsigned i = 0; i < count; i++) { infos[i].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT; infos[i].address = batch->state->dd.db[i]->obj->bda; infos[i].usage = batch->state->dd.db[i]->obj->vkusage; assert(infos[i].usage); } + if (ctx->dd.bindless_layout) { + infos[ZINK_DESCRIPTOR_BINDLESS].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT; + infos[ZINK_DESCRIPTOR_BINDLESS].address = ctx->dd.db.bindless_db->obj->bda; + infos[ZINK_DESCRIPTOR_BINDLESS].usage = ctx->dd.db.bindless_db->obj->vkusage; + assert(infos[ZINK_DESCRIPTOR_BINDLESS].usage); + count++; + } VKSCR(CmdBindDescriptorBuffersEXT)(batch->state->cmdbuf, count, infos); batch->state->db_bound = true; } diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index fa20a2146db..8a12466c45b 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -154,7 +154,10 @@ zink_context_destroy(struct pipe_context *pctx) for (unsigned i = 0; i < 2; i++) { util_idalloc_fini(&ctx->di.bindless[i].tex_slots); util_idalloc_fini(&ctx->di.bindless[i].img_slots); - free(ctx->di.bindless[i].t.buffer_infos); + if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) + free(ctx->di.bindless[i].db.buffer_infos); + else + free(ctx->di.bindless[i].t.buffer_infos); free(ctx->di.bindless[i].img_infos); util_dynarray_fini(&ctx->di.bindless[i].updates); util_dynarray_fini(&ctx->di.bindless[i].resident); @@ -2027,10 +2030,18 @@ zink_create_texture_handle(struct pipe_context *pctx, struct pipe_sampler_view * } bd->ds.is_buffer = res->base.b.target == PIPE_BUFFER; - if (res->base.b.target == PIPE_BUFFER) - zink_buffer_view_reference(zink_screen(pctx->screen), &bd->ds.bufferview, sv->buffer_view); - else + if (res->base.b.target == PIPE_BUFFER) { + if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) { + pipe_resource_reference(&bd->ds.db.pres, view->texture); + bd->ds.db.format = view->format; + bd->ds.db.offset = view->u.buf.offset; + bd->ds.db.size = view->u.buf.size; + } else { + zink_buffer_view_reference(zink_screen(pctx->screen), &bd->ds.bufferview, sv->buffer_view); + } + } else { zink_surface_reference(zink_screen(pctx->screen), &bd->ds.surface, sv->image_view); + } uint64_t handle = util_idalloc_alloc(&ctx->di.bindless[bd->ds.is_buffer].tex_slots); if (bd->ds.is_buffer) handle += ZINK_MAX_BINDLESS_HANDLES; @@ -2053,7 +2064,11 @@ zink_delete_texture_handle(struct pipe_context *pctx, uint64_t handle) util_dynarray_append(&ctx->batch.state->bindless_releases[0], uint32_t, h); if (ds->is_buffer) { - zink_buffer_view_reference(zink_screen(pctx->screen), &ds->bufferview, NULL); + if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) { + pipe_resource_reference(&ds->db.pres, NULL); + } else { + zink_buffer_view_reference(zink_screen(pctx->screen), &ds->bufferview, NULL); + } } else { zink_surface_reference(zink_screen(pctx->screen), &ds->surface, NULL); pctx->delete_sampler_state(pctx, bd->sampler); @@ -2064,6 +2079,9 @@ zink_delete_texture_handle(struct pipe_context *pctx, uint64_t handle) static void rebind_bindless_bufferview(struct zink_context *ctx, struct zink_resource *res, struct zink_descriptor_surface *ds) { + /* descriptor buffer is unaffected by this */ + if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) + return; /* if this resource has been rebound while it wasn't set here, * its backing resource will have changed and thus we need to update * the bufferview @@ -2081,17 +2099,27 @@ zero_bindless_descriptor(struct zink_context *ctx, uint32_t handle, bool is_buff { if (likely(zink_screen(ctx->base.screen)->info.rb2_feats.nullDescriptor)) { if (is_buffer) { - VkBufferView *bv = &ctx->di.bindless[is_image].t.buffer_infos[handle]; - *bv = VK_NULL_HANDLE; + if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) { + ctx->di.bindless[is_image].db.buffer_infos[handle].address = 0; + ctx->di.bindless[is_image].db.buffer_infos[handle].range = 0; + } else { + VkBufferView *bv = &ctx->di.bindless[is_image].t.buffer_infos[handle]; + *bv = VK_NULL_HANDLE; + } } else { VkDescriptorImageInfo *ii = &ctx->di.bindless[is_image].img_infos[handle]; memset(ii, 0, sizeof(*ii)); } } else { if (is_buffer) { - VkBufferView *bv = &ctx->di.bindless[is_image].t.buffer_infos[handle]; - struct zink_buffer_view *null_bufferview = ctx->dummy_bufferview; - *bv = null_bufferview->buffer_view; + if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) { + ctx->di.bindless[is_image].db.buffer_infos[handle].address = zink_resource(ctx->dummy_bufferview->pres)->obj->bda; + ctx->di.bindless[is_image].db.buffer_infos[handle].range = 1; + } else { + VkBufferView *bv = &ctx->di.bindless[is_image].t.buffer_infos[handle]; + struct zink_buffer_view *null_bufferview = ctx->dummy_bufferview; + *bv = null_bufferview->buffer_view; + } } else { struct zink_surface *null_surface = zink_get_dummy_surface(ctx, 0); VkDescriptorImageInfo *ii = &ctx->di.bindless[is_image].img_infos[handle]; @@ -2119,10 +2147,16 @@ zink_make_texture_handle_resident(struct pipe_context *pctx, uint64_t handle, bo update_res_bind_count(ctx, res, true, false); res->bindless[0]++; if (is_buffer) { - if (ds->bufferview->bvci.buffer != res->obj->buffer) - rebind_bindless_bufferview(ctx, res, ds); - VkBufferView *bv = &ctx->di.bindless[0].t.buffer_infos[handle]; - *bv = ds->bufferview->buffer_view; + if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) { + ctx->di.bindless[0].db.buffer_infos[handle].address = res->obj->bda + ds->db.offset; + ctx->di.bindless[0].db.buffer_infos[handle].range = ds->db.size; + ctx->di.bindless[0].db.buffer_infos[handle].format = ds->db.format; + } else { + if (ds->bufferview->bvci.buffer != res->obj->buffer) + rebind_bindless_bufferview(ctx, res, ds); + VkBufferView *bv = &ctx->di.bindless[0].t.buffer_infos[handle]; + *bv = ds->bufferview->buffer_view; + } zink_screen(ctx->base.screen)->buffer_barrier(ctx, res, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); zink_batch_resource_usage_set(&ctx->batch, res, false, true); } else { @@ -2171,7 +2205,14 @@ zink_create_image_handle(struct pipe_context *pctx, const struct pipe_image_view bd->ds.is_buffer = res->base.b.target == PIPE_BUFFER; if (res->base.b.target == PIPE_BUFFER) - bd->ds.bufferview = create_image_bufferview(ctx, view); + if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) { + pipe_resource_reference(&bd->ds.db.pres, view->resource); + bd->ds.db.format = view->format; + bd->ds.db.offset = view->u.buf.offset; + bd->ds.db.size = view->u.buf.size; + } else { + bd->ds.bufferview = create_image_bufferview(ctx, view); + } else bd->ds.surface = create_image_surface(ctx, view, false); uint64_t handle = util_idalloc_alloc(&ctx->di.bindless[bd->ds.is_buffer].img_slots); @@ -2195,7 +2236,11 @@ zink_delete_image_handle(struct pipe_context *pctx, uint64_t handle) util_dynarray_append(&ctx->batch.state->bindless_releases[1], uint32_t, h); if (ds->is_buffer) { - zink_buffer_view_reference(zink_screen(pctx->screen), &ds->bufferview, NULL); + if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) { + pipe_resource_reference(&ds->db.pres, NULL); + } else { + zink_buffer_view_reference(zink_screen(pctx->screen), &ds->bufferview, NULL); + } } else { zink_surface_reference(zink_screen(pctx->screen), &ds->surface, NULL); } @@ -2236,10 +2281,16 @@ zink_make_image_handle_resident(struct pipe_context *pctx, uint64_t handle, unsi res->image_bind_count[1]++; res->bindless[1]++; if (is_buffer) { - if (ds->bufferview->bvci.buffer != res->obj->buffer) - rebind_bindless_bufferview(ctx, res, ds); - VkBufferView *bv = &ctx->di.bindless[1].t.buffer_infos[handle]; - *bv = ds->bufferview->buffer_view; + if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) { + ctx->di.bindless[0].db.buffer_infos[handle].address = res->obj->bda + ds->db.offset; + ctx->di.bindless[0].db.buffer_infos[handle].range = ds->db.size; + ctx->di.bindless[0].db.buffer_infos[handle].format = ds->db.format; + } else { + if (ds->bufferview->bvci.buffer != res->obj->buffer) + rebind_bindless_bufferview(ctx, res, ds); + VkBufferView *bv = &ctx->di.bindless[1].t.buffer_infos[handle]; + *bv = ds->bufferview->buffer_view; + } zink_screen(ctx->base.screen)->buffer_barrier(ctx, res, access, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); zink_batch_resource_usage_set(&ctx->batch, res, zink_resource_access_is_write(access), true); } else { @@ -5044,7 +5095,15 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) util_idalloc_alloc(&ctx->di.bindless[i].tex_slots); util_idalloc_init(&ctx->di.bindless[i].img_slots, ZINK_MAX_BINDLESS_HANDLES); util_idalloc_alloc(&ctx->di.bindless[i].img_slots); - ctx->di.bindless[i].t.buffer_infos = malloc(sizeof(VkBufferView) * ZINK_MAX_BINDLESS_HANDLES); + if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) { + ctx->di.bindless[i].db.buffer_infos = malloc(sizeof(VkDescriptorAddressInfoEXT) * ZINK_MAX_BINDLESS_HANDLES); + for (unsigned j = 0; j < ZINK_MAX_BINDLESS_HANDLES; j++) { + ctx->di.bindless[i].db.buffer_infos[j].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_ADDRESS_INFO_EXT; + ctx->di.bindless[i].db.buffer_infos[j].pNext = NULL; + } + } else { + ctx->di.bindless[i].t.buffer_infos = malloc(sizeof(VkBufferView) * ZINK_MAX_BINDLESS_HANDLES); + } ctx->di.bindless[i].img_infos = malloc(sizeof(VkDescriptorImageInfo) * ZINK_MAX_BINDLESS_HANDLES); util_dynarray_init(&ctx->di.bindless[i].updates, NULL); util_dynarray_init(&ctx->di.bindless[i].resident, NULL); diff --git a/src/gallium/drivers/zink/zink_context.h b/src/gallium/drivers/zink/zink_context.h index 62546db7f07..50d1bf33762 100644 --- a/src/gallium/drivers/zink/zink_context.h +++ b/src/gallium/drivers/zink/zink_context.h @@ -53,7 +53,9 @@ struct zink_vertex_elements_state; static inline struct zink_resource * zink_descriptor_surface_resource(struct zink_descriptor_surface *ds) { - return ds->is_buffer ? (struct zink_resource*)ds->bufferview->pres : (struct zink_resource*)ds->surface->base.texture; + return ds->is_buffer ? + zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB ? (struct zink_resource*)ds->bufferview->pres : zink_resource(ds->db.pres) : + (struct zink_resource*)ds->surface->base.texture; } static inline bool diff --git a/src/gallium/drivers/zink/zink_descriptors.c b/src/gallium/drivers/zink/zink_descriptors.c index 81087e11a9e..8e628556ef2 100644 --- a/src/gallium/drivers/zink/zink_descriptors.c +++ b/src/gallium/drivers/zink/zink_descriptors.c @@ -1118,6 +1118,9 @@ zink_descriptors_update(struct zink_context *ctx, bool is_compute) */ uint8_t bind_sets = bs->dd.pg[is_compute] && bs->dd.compat_id[is_compute] == pg->compat_id ? 0 : pg->dd.binding_usage; + if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB && !bs->db_bound) + zink_batch_bind_db(ctx); + if (pg->dd.push_usage && (ctx->dd.push_state_changed[is_compute] || bind_sets)) { if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) { uint32_t index = ZINK_DESCRIPTOR_TYPE_UNIFORMS; @@ -1184,9 +1187,20 @@ zink_descriptors_update(struct zink_context *ctx, bool is_compute) zink_descriptors_update_masked(ctx, is_compute, changed_sets, bind_sets); /* bindless descriptors are context-based and get updated elsewhere */ if (pg->dd.bindless && unlikely(!ctx->dd.bindless_bound)) { - VKCTX(CmdBindDescriptorSets)(ctx->batch.state->cmdbuf, is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS, - pg->layout, ZINK_DESCRIPTOR_BINDLESS, 1, &ctx->dd.bindless_set, - 0, NULL); + if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) { + unsigned index = ZINK_DESCRIPTOR_BINDLESS; + VkDeviceSize offset = 0; + VKCTX(CmdSetDescriptorBufferOffsetsEXT)(bs->cmdbuf, + is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS, + pg->layout, + ZINK_DESCRIPTOR_BINDLESS, 1, + &index, + &offset); + } else { + VKCTX(CmdBindDescriptorSets)(ctx->batch.state->cmdbuf, is_compute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS, + pg->layout, ZINK_DESCRIPTOR_BINDLESS, 1, &ctx->dd.t.bindless_set, + 0, NULL); + } ctx->dd.bindless_bound = true; } bs->dd.pg[is_compute] = pg; @@ -1473,7 +1487,7 @@ type_from_bindless_index(unsigned idx) void zink_descriptors_init_bindless(struct zink_context *ctx) { - if (ctx->dd.bindless_set) + if (ctx->dd.bindless_layout) return; struct zink_screen *screen = zink_screen(ctx->base.screen); @@ -1485,12 +1499,17 @@ zink_descriptors_init_bindless(struct zink_context *ctx) VkDescriptorSetLayoutBindingFlagsCreateInfo fci = {0}; VkDescriptorBindingFlags flags[4]; dcslci.pNext = &fci; - dcslci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT; + if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) + dcslci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_DESCRIPTOR_BUFFER_BIT_EXT; + else + dcslci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT; fci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO; fci.bindingCount = num_bindings; fci.pBindingFlags = flags; for (unsigned i = 0; i < num_bindings; i++) { - flags[i] = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT | VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT; + flags[i] = VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT; + if (zink_descriptor_mode != ZINK_DESCRIPTOR_MODE_DB) + flags[i] |= VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT; } /* there is exactly 1 bindless descriptor set per context, and it has 4 bindings, 1 for each descriptor type */ for (unsigned i = 0; i < num_bindings; i++) { @@ -1509,24 +1528,39 @@ zink_descriptors_init_bindless(struct zink_context *ctx) return; } - VkDescriptorPoolCreateInfo dpci = {0}; - VkDescriptorPoolSize sizes[4]; - for (unsigned i = 0; i < 4; i++) { - sizes[i].type = type_from_bindless_index(i); - sizes[i].descriptorCount = ZINK_MAX_BINDLESS_HANDLES; - } - dpci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - dpci.pPoolSizes = sizes; - dpci.poolSizeCount = 4; - dpci.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT; - dpci.maxSets = 1; - result = VKSCR(CreateDescriptorPool)(screen->dev, &dpci, 0, &ctx->dd.bindless_pool); - if (result != VK_SUCCESS) { - mesa_loge("ZINK: vkCreateDescriptorPool failed (%s)", vk_Result_to_str(result)); - return; - } + if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) { + unsigned bind = ZINK_BIND_RESOURCE_DESCRIPTOR | ZINK_BIND_SAMPLER_DESCRIPTOR; + VkDeviceSize size; + VKSCR(GetDescriptorSetLayoutSizeEXT)(screen->dev, ctx->dd.bindless_layout, &size); + struct pipe_resource *pres = pipe_buffer_create(&screen->base, bind, 0, size); + ctx->dd.db.bindless_db = zink_resource(pres); + ctx->dd.db.bindless_db_map = pipe_buffer_map(&ctx->base, pres, PIPE_MAP_READ | PIPE_MAP_WRITE, &ctx->dd.db.bindless_db_xfer); + zink_batch_bind_db(ctx); + for (unsigned i = 0; i < num_bindings; i++) { + VkDeviceSize offset; + VKSCR(GetDescriptorSetLayoutBindingOffsetEXT)(screen->dev, ctx->dd.bindless_layout, i, &offset); + ctx->dd.db.db_offsets[i] = offset; + } + } else { + VkDescriptorPoolCreateInfo dpci = {0}; + VkDescriptorPoolSize sizes[4]; + for (unsigned i = 0; i < 4; i++) { + sizes[i].type = type_from_bindless_index(i); + sizes[i].descriptorCount = ZINK_MAX_BINDLESS_HANDLES; + } + dpci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + dpci.pPoolSizes = sizes; + dpci.poolSizeCount = 4; + dpci.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT; + dpci.maxSets = 1; + result = VKSCR(CreateDescriptorPool)(screen->dev, &dpci, 0, &ctx->dd.t.bindless_pool); + if (result != VK_SUCCESS) { + mesa_loge("ZINK: vkCreateDescriptorPool failed (%s)", vk_Result_to_str(result)); + return; + } - zink_descriptor_util_alloc_sets(screen, ctx->dd.bindless_layout, ctx->dd.bindless_pool, &ctx->dd.bindless_set, 1); + zink_descriptor_util_alloc_sets(screen, ctx->dd.bindless_layout, ctx->dd.t.bindless_pool, &ctx->dd.t.bindless_set, 1); + } } /* called on context destroy */ @@ -1536,8 +1570,17 @@ zink_descriptors_deinit_bindless(struct zink_context *ctx) struct zink_screen *screen = zink_screen(ctx->base.screen); if (ctx->dd.bindless_layout) VKSCR(DestroyDescriptorSetLayout)(screen->dev, ctx->dd.bindless_layout, NULL); - if (ctx->dd.bindless_pool) - VKSCR(DestroyDescriptorPool)(screen->dev, ctx->dd.bindless_pool, NULL); + if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) { + if (ctx->dd.db.bindless_db_xfer) + pipe_buffer_unmap(&ctx->base, ctx->dd.db.bindless_db_xfer); + if (ctx->dd.db.bindless_db) { + struct pipe_resource *pres = &ctx->dd.db.bindless_db->base.b; + pipe_resource_reference(&pres, NULL); + } + } else { + if (ctx->dd.t.bindless_pool) + VKSCR(DestroyDescriptorPool)(screen->dev, ctx->dd.t.bindless_pool, NULL); + } } /* entrypoint for updating bindless descriptors: called from draw/dispatch */ @@ -1545,6 +1588,9 @@ void zink_descriptors_update_bindless(struct zink_context *ctx) { struct zink_screen *screen = zink_screen(ctx->base.screen); + VkDescriptorGetInfoEXT info; + info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_GET_INFO_EXT; + info.pNext = NULL; /* bindless descriptors are split between images and buffers */ for (unsigned i = 0; i < 2; i++) { if (!ctx->di.bindless_dirty[i]) @@ -1553,21 +1599,53 @@ zink_descriptors_update_bindless(struct zink_context *ctx) /* updates are tracked by handle */ uint32_t handle = util_dynarray_pop(&ctx->di.bindless[i].updates, uint32_t); bool is_buffer = ZINK_BINDLESS_IS_BUFFER(handle); - VkWriteDescriptorSet wd; - wd.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - wd.pNext = NULL; - wd.dstSet = ctx->dd.bindless_set; - wd.dstBinding = is_buffer ? i * 2 + 1: i * 2; - /* buffer handle ids are offset by ZINK_MAX_BINDLESS_HANDLES for internal tracking */ - wd.dstArrayElement = is_buffer ? handle - ZINK_MAX_BINDLESS_HANDLES : handle; - wd.descriptorCount = 1; - wd.descriptorType = type_from_bindless_index(wd.dstBinding); - if (is_buffer) - wd.pTexelBufferView = &ctx->di.bindless[i].t.buffer_infos[wd.dstArrayElement]; - else - wd.pImageInfo = &ctx->di.bindless[i].img_infos[handle]; - /* this sucks, but sets must be singly updated to be handled correctly */ - VKSCR(UpdateDescriptorSets)(screen->dev, 1, &wd, 0, NULL); + unsigned binding = i * 2 + !!is_buffer; + if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) { + if (is_buffer) { + size_t size = i ? screen->info.db_props.robustStorageTexelBufferDescriptorSize : screen->info.db_props.robustUniformTexelBufferDescriptorSize; + info.type = i ? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; + info.data.pSampler = (void*)&ctx->di.bindless[i].db.buffer_infos[handle]; + VKSCR(GetDescriptorEXT)(screen->dev, &info, size, ctx->dd.db.bindless_db_map + ctx->dd.db.db_offsets[binding] + handle * size); + } else { + info.type = i ? VK_DESCRIPTOR_TYPE_STORAGE_IMAGE : VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + if (screen->info.db_props.combinedImageSamplerDescriptorSingleArray || i) { + size_t size = i ? screen->info.db_props.storageImageDescriptorSize : screen->info.db_props.combinedImageSamplerDescriptorSize; + info.data.pSampler = (void*)&ctx->di.bindless[i].img_infos[handle]; + VKSCR(GetDescriptorEXT)(screen->dev, &info, size, ctx->dd.db.bindless_db_map + ctx->dd.db.db_offsets[binding] + handle * size); + } else { + /* drivers that don't support combinedImageSamplerDescriptorSingleArray must have sampler arrays written in memory as + * + * | array_of_samplers[] | array_of_sampled_images[] | + * + * which means each descriptor's data must be split + */ + uint8_t buf[1024]; + size_t size = screen->info.db_props.combinedImageSamplerDescriptorSize; + info.data.pSampler = (void*)&ctx->di.bindless[i].img_infos[handle]; + VKSCR(GetDescriptorEXT)(screen->dev, &info, size, buf); + memcpy(ctx->dd.db.bindless_db_map + ctx->dd.db.db_offsets[binding] + handle * screen->info.db_props.samplerDescriptorSize, buf, screen->info.db_props.samplerDescriptorSize); + size_t offset = screen->info.db_props.samplerDescriptorSize * ZINK_MAX_BINDLESS_HANDLES; + offset += handle * screen->info.db_props.sampledImageDescriptorSize; + memcpy(ctx->dd.db.bindless_db_map + ctx->dd.db.db_offsets[binding] + offset, &buf[screen->info.db_props.samplerDescriptorSize], screen->info.db_props.sampledImageDescriptorSize); + } + } + } else { + VkWriteDescriptorSet wd; + wd.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + wd.pNext = NULL; + wd.dstSet = ctx->dd.t.bindless_set; + wd.dstBinding = binding; + /* buffer handle ids are offset by ZINK_MAX_BINDLESS_HANDLES for internal tracking */ + wd.dstArrayElement = is_buffer ? handle - ZINK_MAX_BINDLESS_HANDLES : handle; + wd.descriptorCount = 1; + wd.descriptorType = type_from_bindless_index(wd.dstBinding); + if (is_buffer) + wd.pTexelBufferView = &ctx->di.bindless[i].t.buffer_infos[wd.dstArrayElement]; + else + wd.pImageInfo = &ctx->di.bindless[i].img_infos[handle]; + /* this sucks, but sets must be singly updated to be handled correctly */ + VKSCR(UpdateDescriptorSets)(screen->dev, 1, &wd, 0, NULL); + } } } ctx->di.any_bindless_dirty = 0; diff --git a/src/gallium/drivers/zink/zink_types.h b/src/gallium/drivers/zink/zink_types.h index 0812d6269fd..6e33f2243ff 100644 --- a/src/gallium/drivers/zink/zink_types.h +++ b/src/gallium/drivers/zink/zink_types.h @@ -394,8 +394,18 @@ struct zink_descriptor_data { struct zink_descriptor_layout *dummy_dsl; VkDescriptorSetLayout bindless_layout; - VkDescriptorPool bindless_pool; - VkDescriptorSet bindless_set; + union { + struct { + VkDescriptorPool bindless_pool; + VkDescriptorSet bindless_set; + } t; + struct { + struct zink_resource *bindless_db; + uint8_t *bindless_db_map; + struct pipe_transfer *bindless_db_xfer; + uint32_t db_offsets[4]; + } db; + }; struct zink_program *pg[2]; //gfx, compute @@ -1510,11 +1520,18 @@ struct zink_viewport_state { uint8_t num_viewports; }; +struct zink_descriptor_db_info { + unsigned offset; + unsigned size; + enum pipe_format format; + struct pipe_resource *pres; +}; struct zink_descriptor_surface { union { struct zink_surface *surface; struct zink_buffer_view *bufferview; + struct zink_descriptor_db_info db; }; bool is_buffer; }; @@ -1735,6 +1752,9 @@ struct zink_context { struct { VkBufferView *buffer_infos; //tex, img } t; + struct { + VkDescriptorAddressInfoEXT *buffer_infos; + } db; }; VkDescriptorImageInfo *img_infos; //tex, img struct util_dynarray updates; //texture, img