zink: implement descriptor buffer handling of bindless texture

pretty straightforward, just lazily allocating the context-based db
and then writing updates to it on-demand

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21085>
This commit is contained in:
Mike Blumenkrantz 2023-02-02 17:14:36 -05:00 committed by Marge Bot
parent 6b49dec675
commit 99ba529fee
5 changed files with 231 additions and 65 deletions

View file

@ -414,13 +414,20 @@ zink_batch_bind_db(struct zink_context *ctx)
struct zink_screen *screen = zink_screen(ctx->base.screen); struct zink_screen *screen = zink_screen(ctx->base.screen);
struct zink_batch *batch = &ctx->batch; struct zink_batch *batch = &ctx->batch;
unsigned count = screen->compact_descriptors ? 3 : 5; 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++) { for (unsigned i = 0; i < count; i++) {
infos[i].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT; infos[i].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_BUFFER_BINDING_INFO_EXT;
infos[i].address = batch->state->dd.db[i]->obj->bda; infos[i].address = batch->state->dd.db[i]->obj->bda;
infos[i].usage = batch->state->dd.db[i]->obj->vkusage; infos[i].usage = batch->state->dd.db[i]->obj->vkusage;
assert(infos[i].usage); 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); VKSCR(CmdBindDescriptorBuffersEXT)(batch->state->cmdbuf, count, infos);
batch->state->db_bound = true; batch->state->db_bound = true;
} }

View file

@ -154,7 +154,10 @@ zink_context_destroy(struct pipe_context *pctx)
for (unsigned i = 0; i < 2; i++) { for (unsigned i = 0; i < 2; i++) {
util_idalloc_fini(&ctx->di.bindless[i].tex_slots); util_idalloc_fini(&ctx->di.bindless[i].tex_slots);
util_idalloc_fini(&ctx->di.bindless[i].img_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); free(ctx->di.bindless[i].img_infos);
util_dynarray_fini(&ctx->di.bindless[i].updates); util_dynarray_fini(&ctx->di.bindless[i].updates);
util_dynarray_fini(&ctx->di.bindless[i].resident); 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; bd->ds.is_buffer = res->base.b.target == PIPE_BUFFER;
if (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); if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
else 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); 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); uint64_t handle = util_idalloc_alloc(&ctx->di.bindless[bd->ds.is_buffer].tex_slots);
if (bd->ds.is_buffer) if (bd->ds.is_buffer)
handle += ZINK_MAX_BINDLESS_HANDLES; 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); util_dynarray_append(&ctx->batch.state->bindless_releases[0], uint32_t, h);
if (ds->is_buffer) { 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 { } else {
zink_surface_reference(zink_screen(pctx->screen), &ds->surface, NULL); zink_surface_reference(zink_screen(pctx->screen), &ds->surface, NULL);
pctx->delete_sampler_state(pctx, bd->sampler); pctx->delete_sampler_state(pctx, bd->sampler);
@ -2064,6 +2079,9 @@ zink_delete_texture_handle(struct pipe_context *pctx, uint64_t handle)
static void static void
rebind_bindless_bufferview(struct zink_context *ctx, struct zink_resource *res, struct zink_descriptor_surface *ds) 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, /* if this resource has been rebound while it wasn't set here,
* its backing resource will have changed and thus we need to update * its backing resource will have changed and thus we need to update
* the bufferview * 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 (likely(zink_screen(ctx->base.screen)->info.rb2_feats.nullDescriptor)) {
if (is_buffer) { if (is_buffer) {
VkBufferView *bv = &ctx->di.bindless[is_image].t.buffer_infos[handle]; if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
*bv = VK_NULL_HANDLE; 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 { } else {
VkDescriptorImageInfo *ii = &ctx->di.bindless[is_image].img_infos[handle]; VkDescriptorImageInfo *ii = &ctx->di.bindless[is_image].img_infos[handle];
memset(ii, 0, sizeof(*ii)); memset(ii, 0, sizeof(*ii));
} }
} else { } else {
if (is_buffer) { if (is_buffer) {
VkBufferView *bv = &ctx->di.bindless[is_image].t.buffer_infos[handle]; if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
struct zink_buffer_view *null_bufferview = ctx->dummy_bufferview; ctx->di.bindless[is_image].db.buffer_infos[handle].address = zink_resource(ctx->dummy_bufferview->pres)->obj->bda;
*bv = null_bufferview->buffer_view; 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 { } else {
struct zink_surface *null_surface = zink_get_dummy_surface(ctx, 0); struct zink_surface *null_surface = zink_get_dummy_surface(ctx, 0);
VkDescriptorImageInfo *ii = &ctx->di.bindless[is_image].img_infos[handle]; 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); update_res_bind_count(ctx, res, true, false);
res->bindless[0]++; res->bindless[0]++;
if (is_buffer) { if (is_buffer) {
if (ds->bufferview->bvci.buffer != res->obj->buffer) if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
rebind_bindless_bufferview(ctx, res, ds); ctx->di.bindless[0].db.buffer_infos[handle].address = res->obj->bda + ds->db.offset;
VkBufferView *bv = &ctx->di.bindless[0].t.buffer_infos[handle]; ctx->di.bindless[0].db.buffer_infos[handle].range = ds->db.size;
*bv = ds->bufferview->buffer_view; 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_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); zink_batch_resource_usage_set(&ctx->batch, res, false, true);
} else { } 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; bd->ds.is_buffer = res->base.b.target == PIPE_BUFFER;
if (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 else
bd->ds.surface = create_image_surface(ctx, view, false); bd->ds.surface = create_image_surface(ctx, view, false);
uint64_t handle = util_idalloc_alloc(&ctx->di.bindless[bd->ds.is_buffer].img_slots); 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); util_dynarray_append(&ctx->batch.state->bindless_releases[1], uint32_t, h);
if (ds->is_buffer) { 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 { } else {
zink_surface_reference(zink_screen(pctx->screen), &ds->surface, NULL); 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->image_bind_count[1]++;
res->bindless[1]++; res->bindless[1]++;
if (is_buffer) { if (is_buffer) {
if (ds->bufferview->bvci.buffer != res->obj->buffer) if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
rebind_bindless_bufferview(ctx, res, ds); ctx->di.bindless[0].db.buffer_infos[handle].address = res->obj->bda + ds->db.offset;
VkBufferView *bv = &ctx->di.bindless[1].t.buffer_infos[handle]; ctx->di.bindless[0].db.buffer_infos[handle].range = ds->db.size;
*bv = ds->bufferview->buffer_view; 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_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); zink_batch_resource_usage_set(&ctx->batch, res, zink_resource_access_is_write(access), true);
} else { } 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_alloc(&ctx->di.bindless[i].tex_slots);
util_idalloc_init(&ctx->di.bindless[i].img_slots, ZINK_MAX_BINDLESS_HANDLES); util_idalloc_init(&ctx->di.bindless[i].img_slots, ZINK_MAX_BINDLESS_HANDLES);
util_idalloc_alloc(&ctx->di.bindless[i].img_slots); 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); 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].updates, NULL);
util_dynarray_init(&ctx->di.bindless[i].resident, NULL); util_dynarray_init(&ctx->di.bindless[i].resident, NULL);

View file

@ -53,7 +53,9 @@ struct zink_vertex_elements_state;
static inline struct zink_resource * static inline struct zink_resource *
zink_descriptor_surface_resource(struct zink_descriptor_surface *ds) 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 static inline bool

View file

@ -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; 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 (pg->dd.push_usage && (ctx->dd.push_state_changed[is_compute] || bind_sets)) {
if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) { if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
uint32_t index = ZINK_DESCRIPTOR_TYPE_UNIFORMS; 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); zink_descriptors_update_masked(ctx, is_compute, changed_sets, bind_sets);
/* bindless descriptors are context-based and get updated elsewhere */ /* bindless descriptors are context-based and get updated elsewhere */
if (pg->dd.bindless && unlikely(!ctx->dd.bindless_bound)) { 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, if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
pg->layout, ZINK_DESCRIPTOR_BINDLESS, 1, &ctx->dd.bindless_set, unsigned index = ZINK_DESCRIPTOR_BINDLESS;
0, NULL); 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; ctx->dd.bindless_bound = true;
} }
bs->dd.pg[is_compute] = pg; bs->dd.pg[is_compute] = pg;
@ -1473,7 +1487,7 @@ type_from_bindless_index(unsigned idx)
void void
zink_descriptors_init_bindless(struct zink_context *ctx) zink_descriptors_init_bindless(struct zink_context *ctx)
{ {
if (ctx->dd.bindless_set) if (ctx->dd.bindless_layout)
return; return;
struct zink_screen *screen = zink_screen(ctx->base.screen); struct zink_screen *screen = zink_screen(ctx->base.screen);
@ -1485,12 +1499,17 @@ zink_descriptors_init_bindless(struct zink_context *ctx)
VkDescriptorSetLayoutBindingFlagsCreateInfo fci = {0}; VkDescriptorSetLayoutBindingFlagsCreateInfo fci = {0};
VkDescriptorBindingFlags flags[4]; VkDescriptorBindingFlags flags[4];
dcslci.pNext = &fci; 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.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO;
fci.bindingCount = num_bindings; fci.bindingCount = num_bindings;
fci.pBindingFlags = flags; fci.pBindingFlags = flags;
for (unsigned i = 0; i < num_bindings; i++) { 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 */ /* 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++) { for (unsigned i = 0; i < num_bindings; i++) {
@ -1509,24 +1528,39 @@ zink_descriptors_init_bindless(struct zink_context *ctx)
return; return;
} }
VkDescriptorPoolCreateInfo dpci = {0}; if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
VkDescriptorPoolSize sizes[4]; unsigned bind = ZINK_BIND_RESOURCE_DESCRIPTOR | ZINK_BIND_SAMPLER_DESCRIPTOR;
for (unsigned i = 0; i < 4; i++) { VkDeviceSize size;
sizes[i].type = type_from_bindless_index(i); VKSCR(GetDescriptorSetLayoutSizeEXT)(screen->dev, ctx->dd.bindless_layout, &size);
sizes[i].descriptorCount = ZINK_MAX_BINDLESS_HANDLES; struct pipe_resource *pres = pipe_buffer_create(&screen->base, bind, 0, size);
} ctx->dd.db.bindless_db = zink_resource(pres);
dpci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; ctx->dd.db.bindless_db_map = pipe_buffer_map(&ctx->base, pres, PIPE_MAP_READ | PIPE_MAP_WRITE, &ctx->dd.db.bindless_db_xfer);
dpci.pPoolSizes = sizes; zink_batch_bind_db(ctx);
dpci.poolSizeCount = 4; for (unsigned i = 0; i < num_bindings; i++) {
dpci.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT; VkDeviceSize offset;
dpci.maxSets = 1; VKSCR(GetDescriptorSetLayoutBindingOffsetEXT)(screen->dev, ctx->dd.bindless_layout, i, &offset);
result = VKSCR(CreateDescriptorPool)(screen->dev, &dpci, 0, &ctx->dd.bindless_pool); ctx->dd.db.db_offsets[i] = offset;
if (result != VK_SUCCESS) { }
mesa_loge("ZINK: vkCreateDescriptorPool failed (%s)", vk_Result_to_str(result)); } else {
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.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 */ /* 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); struct zink_screen *screen = zink_screen(ctx->base.screen);
if (ctx->dd.bindless_layout) if (ctx->dd.bindless_layout)
VKSCR(DestroyDescriptorSetLayout)(screen->dev, ctx->dd.bindless_layout, NULL); VKSCR(DestroyDescriptorSetLayout)(screen->dev, ctx->dd.bindless_layout, NULL);
if (ctx->dd.bindless_pool) if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
VKSCR(DestroyDescriptorPool)(screen->dev, ctx->dd.bindless_pool, NULL); 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 */ /* entrypoint for updating bindless descriptors: called from draw/dispatch */
@ -1545,6 +1588,9 @@ void
zink_descriptors_update_bindless(struct zink_context *ctx) zink_descriptors_update_bindless(struct zink_context *ctx)
{ {
struct zink_screen *screen = zink_screen(ctx->base.screen); 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 */ /* bindless descriptors are split between images and buffers */
for (unsigned i = 0; i < 2; i++) { for (unsigned i = 0; i < 2; i++) {
if (!ctx->di.bindless_dirty[i]) if (!ctx->di.bindless_dirty[i])
@ -1553,21 +1599,53 @@ zink_descriptors_update_bindless(struct zink_context *ctx)
/* updates are tracked by handle */ /* updates are tracked by handle */
uint32_t handle = util_dynarray_pop(&ctx->di.bindless[i].updates, uint32_t); uint32_t handle = util_dynarray_pop(&ctx->di.bindless[i].updates, uint32_t);
bool is_buffer = ZINK_BINDLESS_IS_BUFFER(handle); bool is_buffer = ZINK_BINDLESS_IS_BUFFER(handle);
VkWriteDescriptorSet wd; unsigned binding = i * 2 + !!is_buffer;
wd.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; if (zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB) {
wd.pNext = NULL; if (is_buffer) {
wd.dstSet = ctx->dd.bindless_set; size_t size = i ? screen->info.db_props.robustStorageTexelBufferDescriptorSize : screen->info.db_props.robustUniformTexelBufferDescriptorSize;
wd.dstBinding = is_buffer ? i * 2 + 1: i * 2; info.type = i ? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER : VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
/* buffer handle ids are offset by ZINK_MAX_BINDLESS_HANDLES for internal tracking */ info.data.pSampler = (void*)&ctx->di.bindless[i].db.buffer_infos[handle];
wd.dstArrayElement = is_buffer ? handle - ZINK_MAX_BINDLESS_HANDLES : handle; VKSCR(GetDescriptorEXT)(screen->dev, &info, size, ctx->dd.db.bindless_db_map + ctx->dd.db.db_offsets[binding] + handle * size);
wd.descriptorCount = 1; } else {
wd.descriptorType = type_from_bindless_index(wd.dstBinding); info.type = i ? VK_DESCRIPTOR_TYPE_STORAGE_IMAGE : VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
if (is_buffer) if (screen->info.db_props.combinedImageSamplerDescriptorSingleArray || i) {
wd.pTexelBufferView = &ctx->di.bindless[i].t.buffer_infos[wd.dstArrayElement]; size_t size = i ? screen->info.db_props.storageImageDescriptorSize : screen->info.db_props.combinedImageSamplerDescriptorSize;
else info.data.pSampler = (void*)&ctx->di.bindless[i].img_infos[handle];
wd.pImageInfo = &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);
/* this sucks, but sets must be singly updated to be handled correctly */ } else {
VKSCR(UpdateDescriptorSets)(screen->dev, 1, &wd, 0, NULL); /* 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; ctx->di.any_bindless_dirty = 0;

View file

@ -394,8 +394,18 @@ struct zink_descriptor_data {
struct zink_descriptor_layout *dummy_dsl; struct zink_descriptor_layout *dummy_dsl;
VkDescriptorSetLayout bindless_layout; VkDescriptorSetLayout bindless_layout;
VkDescriptorPool bindless_pool; union {
VkDescriptorSet bindless_set; 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 struct zink_program *pg[2]; //gfx, compute
@ -1510,11 +1520,18 @@ struct zink_viewport_state {
uint8_t num_viewports; 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 { struct zink_descriptor_surface {
union { union {
struct zink_surface *surface; struct zink_surface *surface;
struct zink_buffer_view *bufferview; struct zink_buffer_view *bufferview;
struct zink_descriptor_db_info db;
}; };
bool is_buffer; bool is_buffer;
}; };
@ -1735,6 +1752,9 @@ struct zink_context {
struct { struct {
VkBufferView *buffer_infos; //tex, img VkBufferView *buffer_infos; //tex, img
} t; } t;
struct {
VkDescriptorAddressInfoEXT *buffer_infos;
} db;
}; };
VkDescriptorImageInfo *img_infos; //tex, img VkDescriptorImageInfo *img_infos; //tex, img
struct util_dynarray updates; //texture, img struct util_dynarray updates; //texture, img