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_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;
}

View File

@@ -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);

View File

@@ -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

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;
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;

View File

@@ -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