zink: break out all the descriptor pool/layout stuff into a new struct

by pushing these into a separate struct, we can eventually reuse them between
programs to make the descriptor set caches even more valuable

Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9348>
This commit is contained in:
Mike Blumenkrantz 2020-10-05 21:29:02 -04:00 committed by Marge Bot
parent 3d4e6c641b
commit 817de3c776
5 changed files with 214 additions and 215 deletions

View File

@ -33,6 +33,83 @@
#include "zink_resource.h"
#include "zink_screen.h"
static bool
desc_state_equal(const void *a, const void *b)
{
const struct zink_descriptor_state_key *a_k = (void*)a;
const struct zink_descriptor_state_key *b_k = (void*)b;
for (unsigned i = 0; i < ZINK_SHADER_COUNT; i++) {
if (a_k->exists[i] != b_k->exists[i])
return false;
if (a_k->exists[i] && b_k->exists[i] &&
a_k->state[i] != b_k->state[i])
return false;
}
return true;
}
static uint32_t
desc_state_hash(const void *key)
{
const struct zink_descriptor_state_key *d_key = (void*)key;
uint32_t hash = 0;
/* this is a compute shader */
if (!d_key->exists[PIPE_SHADER_FRAGMENT])
return d_key->state[0];
for (unsigned i = 0; i < ZINK_SHADER_COUNT; i++) {
if (d_key->exists[i])
hash = XXH32(&d_key->state[i], sizeof(uint32_t), hash);
}
return hash;
}
static struct zink_descriptor_pool *
descriptor_pool_create(struct zink_screen *screen, VkDescriptorSetLayoutBinding *bindings, unsigned num_bindings, VkDescriptorPoolSize *sizes, unsigned num_type_sizes)
{
struct zink_descriptor_pool *pool = rzalloc(NULL, struct zink_descriptor_pool);
if (!pool)
return NULL;
pool->num_descriptors = num_bindings;
pool->desc_sets = _mesa_hash_table_create(NULL, desc_state_hash, desc_state_equal);
if (!pool->desc_sets)
goto fail;
pool->free_desc_sets = _mesa_hash_table_create(NULL, desc_state_hash, desc_state_equal);
if (!pool->free_desc_sets)
goto fail;
util_dynarray_init(&pool->alloc_desc_sets, NULL);
VkDescriptorSetLayoutCreateInfo dcslci = {};
dcslci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
dcslci.pNext = NULL;
dcslci.flags = 0;
dcslci.bindingCount = num_bindings;
dcslci.pBindings = bindings;
if (vkCreateDescriptorSetLayout(screen->dev, &dcslci, 0, &pool->dsl) != VK_SUCCESS) {
debug_printf("vkCreateDescriptorSetLayout failed\n");
goto fail;
}
VkDescriptorPoolCreateInfo dpci = {};
dpci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
dpci.pPoolSizes = sizes;
dpci.poolSizeCount = num_type_sizes;
dpci.flags = 0;
dpci.maxSets = ZINK_DEFAULT_MAX_DESCS;
if (vkCreateDescriptorPool(screen->dev, &dpci, 0, &pool->descpool) != VK_SUCCESS) {
debug_printf("vkCreateDescriptorPool failed\n");
goto fail;
}
return pool;
fail:
zink_descriptor_pool_free(screen, pool);
return NULL;
}
static bool
get_invalidated_desc_set(struct zink_descriptor_set *zds)
{
@ -45,9 +122,10 @@ static struct zink_descriptor_set *
allocate_desc_set(struct zink_screen *screen, struct zink_program *pg, enum zink_descriptor_type type, unsigned descs_used, bool is_compute)
{
VkDescriptorSetAllocateInfo dsai;
struct zink_descriptor_pool *pool = pg->pool[type];
#define DESC_BUCKET_FACTOR 10
unsigned bucket_size = pg->num_descriptors[type] ? DESC_BUCKET_FACTOR : 1;
if (pg->num_descriptors[type]) {
unsigned bucket_size = pool->num_descriptors ? DESC_BUCKET_FACTOR : 1;
if (pool->num_descriptors) {
for (unsigned desc_factor = DESC_BUCKET_FACTOR; desc_factor < descs_used; desc_factor *= DESC_BUCKET_FACTOR)
bucket_size = desc_factor;
}
@ -55,10 +133,10 @@ allocate_desc_set(struct zink_screen *screen, struct zink_program *pg, enum zink
memset((void *)&dsai, 0, sizeof(dsai));
dsai.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
dsai.pNext = NULL;
dsai.descriptorPool = pg->descpool[type];
dsai.descriptorPool = pool->descpool;
dsai.descriptorSetCount = bucket_size;
for (unsigned i = 0; i < bucket_size; i ++)
layouts[i] = pg->dsl[type];
layouts[i] = pool->dsl;
dsai.pSetLayouts = layouts;
VkDescriptorSet desc_set[bucket_size];
@ -67,14 +145,14 @@ allocate_desc_set(struct zink_screen *screen, struct zink_program *pg, enum zink
return VK_NULL_HANDLE;
}
struct zink_descriptor_set *alloc = ralloc_array(pg, struct zink_descriptor_set, bucket_size);
struct zink_descriptor_set *alloc = ralloc_array(pool, struct zink_descriptor_set, bucket_size);
assert(alloc);
unsigned num_resources = zink_program_num_bindings_typed(pg, type, is_compute);
struct zink_resource **resources = rzalloc_array(pg, struct zink_resource*, num_resources * bucket_size);
struct zink_resource **resources = rzalloc_array(pool, struct zink_resource*, num_resources * bucket_size);
assert(resources);
void **samplers = NULL;
if (type == ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW) {
samplers = rzalloc_array(pg, void*, num_resources * bucket_size);
samplers = rzalloc_array(pool, void*, num_resources * bucket_size);
assert(samplers);
}
for (unsigned i = 0; i < bucket_size; i ++) {
@ -89,13 +167,13 @@ allocate_desc_set(struct zink_screen *screen, struct zink_program *pg, enum zink
zds->num_resources = num_resources;
#endif
if (type == ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW) {
zds->sampler_views = (struct zink_sampler_view**)&resources[i * pg->num_descriptors[type]];
zds->sampler_states = (struct zink_sampler_state**)&samplers[i * pg->num_descriptors[type]];
zds->sampler_views = (struct zink_sampler_view**)&resources[i * pool->num_descriptors];
zds->sampler_states = (struct zink_sampler_state**)&samplers[i * pool->num_descriptors];
} else
zds->resources = (struct zink_resource**)&resources[i * pg->num_descriptors[type]];
zds->resources = (struct zink_resource**)&resources[i * pool->num_descriptors];
zds->desc_set = desc_set[i];
if (i > 0)
util_dynarray_append(&pg->alloc_desc_sets[type], struct zink_descriptor_set *, zds);
util_dynarray_append(&pool->alloc_desc_sets, struct zink_descriptor_set *, zds);
}
return alloc;
}
@ -127,25 +205,26 @@ zink_descriptor_set_get(struct zink_context *ctx,
*cache_hit = false;
struct zink_descriptor_set *zds;
struct zink_screen *screen = zink_screen(ctx->base.screen);
struct zink_descriptor_pool *pool = pg->pool[type];
unsigned descs_used = 1;
assert(type < ZINK_DESCRIPTOR_TYPES);
uint32_t hash = pg->num_descriptors[type] ? ctx->descriptor_states[is_compute].state[type] : 0;
uint32_t hash = pool->num_descriptors ? ctx->descriptor_states[is_compute].state[type] : 0;
struct zink_descriptor_state_key key;
populate_zds_key(ctx, type, is_compute, &key);
if (pg->last_set[type] && pg->last_set[type]->hash == hash &&
zink_desc_state_equal(&pg->last_set[type]->key, &key)) {
desc_state_equal(&pg->last_set[type]->key, &key)) {
zds = pg->last_set[type];
*cache_hit = !zds->invalid;
if (pg->num_descriptors[type] && zds->recycled) {
struct hash_entry *he = _mesa_hash_table_search_pre_hashed(pg->free_desc_sets[type], hash, &key);
if (pool->num_descriptors && zds->recycled) {
struct hash_entry *he = _mesa_hash_table_search_pre_hashed(pool->free_desc_sets, hash, &key);
if (he)
_mesa_hash_table_remove(pg->free_desc_sets[type], he);
_mesa_hash_table_remove(pool->free_desc_sets, he);
}
goto out;
}
if (pg->num_descriptors[type]) {
struct hash_entry *he = _mesa_hash_table_search_pre_hashed(pg->desc_sets[type], hash, &key);
if (pool->num_descriptors) {
struct hash_entry *he = _mesa_hash_table_search_pre_hashed(pool->desc_sets, hash, &key);
bool recycled = false;
if (he) {
zds = (void*)he->data;
@ -155,7 +234,7 @@ zink_descriptor_set_get(struct zink_context *ctx,
assert(!zds->invalid);
}
if (!he) {
he = _mesa_hash_table_search_pre_hashed(pg->free_desc_sets[type], hash, &key);
he = _mesa_hash_table_search_pre_hashed(pool->free_desc_sets, hash, &key);
recycled = true;
}
if (he) {
@ -163,35 +242,35 @@ zink_descriptor_set_get(struct zink_context *ctx,
*cache_hit = !zds->invalid;
if (recycled) {
/* need to migrate this entry back to the in-use hash */
_mesa_hash_table_remove(pg->free_desc_sets[type], he);
_mesa_hash_table_remove(pool->free_desc_sets, he);
goto out;
}
goto quick_out;
}
if (util_dynarray_num_elements(&pg->alloc_desc_sets[type], struct zink_descriptor_set *)) {
if (util_dynarray_num_elements(&pool->alloc_desc_sets, struct zink_descriptor_set *)) {
/* grab one off the allocated array */
zds = util_dynarray_pop(&pg->alloc_desc_sets[type], struct zink_descriptor_set *);
zds = util_dynarray_pop(&pool->alloc_desc_sets, struct zink_descriptor_set *);
goto out;
}
if (_mesa_hash_table_num_entries(pg->free_desc_sets[type])) {
if (_mesa_hash_table_num_entries(pool->free_desc_sets)) {
/* try for an invalidated set first */
unsigned count = 0;
hash_table_foreach(pg->free_desc_sets[type], he) {
hash_table_foreach(pool->free_desc_sets, he) {
struct zink_descriptor_set *tmp = he->data;
if ((count++ >= 100 && tmp->reference.count == 1) || get_invalidated_desc_set(he->data)) {
zds = tmp;
assert(p_atomic_read(&zds->reference.count) == 1);
zink_descriptor_set_invalidate(zds);
_mesa_hash_table_remove(pg->free_desc_sets[type], he);
_mesa_hash_table_remove(pool->free_desc_sets, he);
goto out;
}
}
}
descs_used = _mesa_hash_table_num_entries(pg->desc_sets[type]) + _mesa_hash_table_num_entries(pg->free_desc_sets[type]);
if (descs_used + pg->num_descriptors[type] > ZINK_DEFAULT_MAX_DESCS) {
descs_used = _mesa_hash_table_num_entries(pool->desc_sets) + _mesa_hash_table_num_entries(pool->free_desc_sets);
if (descs_used + pool->num_descriptors > ZINK_DEFAULT_MAX_DESCS) {
batch = zink_flush_batch(ctx, batch);
zink_batch_reference_program(batch, pg);
return zink_descriptor_set_get(ctx, batch, pg, type, is_compute, cache_hit);
@ -209,19 +288,19 @@ out:
zds->hash = hash;
populate_zds_key(ctx, type, is_compute, &zds->key);
zds->recycled = false;
if (pg->num_descriptors[type])
_mesa_hash_table_insert_pre_hashed(pg->desc_sets[type], hash, &zds->key, zds);
if (pool->num_descriptors)
_mesa_hash_table_insert_pre_hashed(pool->desc_sets, hash, &zds->key, zds);
else {
/* we can safely apply the null set to all the slots which will need it here */
for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++) {
if (!pg->num_descriptors[i])
if (pg->pool[i] && !pg->pool[i]->num_descriptors)
pg->last_set[i] = zds;
}
}
quick_out:
zds->invalid = false;
if (zink_batch_add_desc_set(batch, zds))
batch->descs_used += pg->num_descriptors[type];
batch->descs_used += pool->num_descriptors;
pg->last_set[type] = zds;
return zds;
}
@ -230,28 +309,29 @@ void
zink_descriptor_set_recycle(struct zink_descriptor_set *zds)
{
struct zink_program *pg = zds->pg;
struct zink_descriptor_pool *pool = pg->pool[zds->type];
/* if desc set is still in use by a batch, don't recache */
uint32_t refcount = p_atomic_read(&zds->reference.count);
if (refcount != 1)
return;
/* this is a null set */
if (!zds->hash && !pg->num_descriptors[zds->type])
if (!pool->num_descriptors)
return;
struct hash_entry *he = _mesa_hash_table_search_pre_hashed(pg->desc_sets[zds->type], zds->hash, &zds->key);
struct hash_entry *he = _mesa_hash_table_search_pre_hashed(pool->desc_sets, zds->hash, &zds->key);
if (!he)
/* desc sets can be used multiple times in the same batch */
return;
_mesa_hash_table_remove(pg->desc_sets[zds->type], he);
_mesa_hash_table_remove(pool->desc_sets, he);
if (zds->invalid) {
if (pg->last_set[zds->type] == zds)
pg->last_set[zds->type] = NULL;
zink_descriptor_set_invalidate(zds);
util_dynarray_append(&pg->alloc_desc_sets[zds->type], struct zink_descriptor_set *, zds);
util_dynarray_append(&pool->alloc_desc_sets, struct zink_descriptor_set *, zds);
} else {
zds->recycled = true;
_mesa_hash_table_insert_pre_hashed(pg->free_desc_sets[zds->type], zds->hash, &zds->key, zds);
_mesa_hash_table_insert_pre_hashed(pool->free_desc_sets, zds->hash, &zds->key, zds);
}
}
@ -302,7 +382,7 @@ zink_descriptor_set_refs_clear(struct zink_descriptor_refs *refs, void *ptr)
}
bool
zink_descriptor_program_init(VkDevice dev,
zink_descriptor_program_init(struct zink_screen *screen,
struct zink_shader *stages[ZINK_SHADER_COUNT],
struct zink_program *pg)
{
@ -340,7 +420,6 @@ zink_descriptor_program_init(VkDevice dev,
unsigned total_descs = 0;
for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++) {
pg->num_descriptors[i] = num_bindings[i];
total_descs += num_bindings[i];;
}
if (!total_descs)
@ -349,55 +428,27 @@ zink_descriptor_program_init(VkDevice dev,
for (int i = 0; i < num_types; i++)
sizes[i].descriptorCount *= ZINK_DEFAULT_MAX_DESCS;
VkDescriptorSetLayout null_set = VK_NULL_HANDLE;
VkDescriptorPool null_pool = VK_NULL_HANDLE;
bool found_descriptors = false;
for (unsigned i = ZINK_DESCRIPTOR_TYPES - 1; i < ZINK_DESCRIPTOR_TYPES; i--) {
VkDescriptorSetLayoutCreateInfo dcslci = {};
dcslci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
dcslci.pNext = NULL;
dcslci.flags = 0;
if (!num_bindings[i]) {
if (!found_descriptors)
continue;
if (!null_set) {
dcslci.bindingCount = 1;
VkDescriptorSetLayoutBinding null_binding;
null_binding.binding = 1;
null_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
null_binding.descriptorCount = 1;
null_binding.pImmutableSamplers = NULL;
null_binding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT |
VK_SHADER_STAGE_GEOMETRY_BIT | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | VK_SHADER_STAGE_COMPUTE_BIT;
dcslci.pBindings = &null_binding;
if (vkCreateDescriptorSetLayout(dev, &dcslci, 0, &null_set) != VK_SUCCESS) {
debug_printf("vkCreateDescriptorSetLayout failed\n");
return false;
}
VkDescriptorPoolCreateInfo dpci = {};
VkDescriptorPoolSize null_size = {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, ZINK_DESCRIPTOR_TYPES};
dpci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
dpci.pPoolSizes = &null_size;
dpci.poolSizeCount = 1;
dpci.flags = 0;
dpci.maxSets = 1;
if (vkCreateDescriptorPool(dev, &dpci, 0, &null_pool) != VK_SUCCESS)
return false;
}
pg->dsl[i] = null_set;
pg->descpool[i] = null_pool;
VkDescriptorSetLayoutBinding null_binding;
null_binding.binding = 1;
null_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
null_binding.descriptorCount = 1;
null_binding.pImmutableSamplers = NULL;
null_binding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT |
VK_SHADER_STAGE_GEOMETRY_BIT | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT |
VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | VK_SHADER_STAGE_COMPUTE_BIT;
VkDescriptorPoolSize null_size = {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, ZINK_DESCRIPTOR_TYPES};
pg->pool[i] = descriptor_pool_create(screen, &null_binding, 1, &null_size, 1);
if (!pg->pool[i])
return false;
continue;
}
dcslci.bindingCount = num_bindings[i];
dcslci.pBindings = bindings[i];
found_descriptors = true;
if (vkCreateDescriptorSetLayout(dev, &dcslci, 0, &pg->dsl[i]) != VK_SUCCESS) {
debug_printf("vkCreateDescriptorSetLayout failed\n");
return false;
}
VkDescriptorPoolSize type_sizes[2] = {};
int num_type_sizes = 0;
switch (i) {
@ -438,15 +489,9 @@ zink_descriptor_program_init(VkDevice dev,
}
break;
}
VkDescriptorPoolCreateInfo dpci = {};
dpci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
dpci.pPoolSizes = type_sizes;
dpci.poolSizeCount = num_type_sizes;
dpci.flags = 0;
dpci.maxSets = ZINK_DEFAULT_MAX_DESCS;
if (vkCreateDescriptorPool(dev, &dpci, 0, &pg->descpool[i]) != VK_SUCCESS) {
pg->pool[i] = descriptor_pool_create(screen, bindings[i], num_bindings[i], type_sizes, num_type_sizes);
if (!pg->pool[i])
return false;
}
}
return true;
}
@ -456,3 +501,40 @@ zink_descriptor_set_invalidate(struct zink_descriptor_set *zds)
{
zds->invalid = true;
}
#ifndef NDEBUG
static void
descriptor_pool_clear(struct hash_table *ht)
{
hash_table_foreach(ht, entry) {
struct zink_descriptor_set *zds = entry->data;
zink_descriptor_set_invalidate(zds);
}
_mesa_hash_table_clear(ht, NULL);
}
#endif
void
zink_descriptor_pool_free(struct zink_screen *screen, struct zink_descriptor_pool *pool)
{
if (!pool)
return;
if (pool->dsl)
vkDestroyDescriptorSetLayout(screen->dev, pool->dsl, NULL);
if (pool->descpool)
vkDestroyDescriptorPool(screen->dev, pool->descpool, NULL);
#ifndef NDEBUG
if (pool->desc_sets)
descriptor_pool_clear(pool->desc_sets);
if (pool->free_desc_sets)
descriptor_pool_clear(pool->free_desc_sets);
#endif
if (pool->desc_sets)
_mesa_hash_table_destroy(pool->desc_sets, NULL);
if (pool->free_desc_sets)
_mesa_hash_table_destroy(pool->free_desc_sets, NULL);
util_dynarray_fini(&pool->alloc_desc_sets);
ralloc_free(pool);
}

View File

@ -57,21 +57,14 @@ struct zink_descriptor_state_key {
uint32_t state[ZINK_SHADER_COUNT];
};
static inline bool
zink_desc_state_equal(const void *a, const void *b)
{
const struct zink_descriptor_state_key *a_k = (void*)a;
const struct zink_descriptor_state_key *b_k = (void*)b;
for (unsigned i = 0; i < ZINK_SHADER_COUNT; i++) {
if (a_k->exists[i] != b_k->exists[i])
return false;
if (a_k->exists[i] && b_k->exists[i] &&
a_k->state[i] != b_k->state[i])
return false;
}
return true;
}
struct zink_descriptor_pool {
struct hash_table *desc_sets;
struct hash_table *free_desc_sets;
struct util_dynarray alloc_desc_sets;
VkDescriptorPool descpool;
VkDescriptorSetLayout dsl;
unsigned num_descriptors;
};
struct zink_descriptor_set {
struct zink_program *pg;
@ -124,10 +117,14 @@ void
zink_descriptor_set_recycle(struct zink_descriptor_set *zds);
bool
zink_descriptor_program_init(VkDevice dev,
zink_descriptor_program_init(struct zink_screen *screen,
struct zink_shader *stages[ZINK_SHADER_COUNT],
struct zink_program *pg);
void
zink_descriptor_set_invalidate(struct zink_descriptor_set *zds);
void
zink_descriptor_pool_free(struct zink_screen *screen, struct zink_descriptor_pool *pool);
#endif

View File

@ -398,7 +398,7 @@ update_ubo_descriptors(struct zink_context *ctx, struct zink_descriptor_set *zds
{
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_descriptors = pg->pool[zds->type]->num_descriptors;
unsigned num_bindings = zink_program_num_bindings_typed(pg, zds->type, is_compute);
VkWriteDescriptorSet wds[num_descriptors];
struct zink_descriptor_resource resources[num_bindings];
@ -480,7 +480,7 @@ update_ssbo_descriptors(struct zink_context *ctx, struct zink_descriptor_set *zd
{
struct zink_program *pg = zds->pg;
ASSERTED struct zink_screen *screen = zink_screen(ctx->base.screen);
unsigned num_descriptors = pg->num_descriptors[zds->type];
unsigned num_descriptors = pg->pool[zds->type]->num_descriptors;
unsigned num_bindings = zink_program_num_bindings_typed(pg, zds->type, is_compute);
VkWriteDescriptorSet wds[num_descriptors];
struct zink_descriptor_resource resources[num_bindings];
@ -584,7 +584,7 @@ update_sampler_descriptors(struct zink_context *ctx, struct zink_descriptor_set
{
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_descriptors = pg->pool[zds->type]->num_descriptors;
unsigned num_bindings = zink_program_num_bindings(pg, is_compute);
VkWriteDescriptorSet wds[num_descriptors];
struct zink_descriptor_resource resources[num_bindings];
@ -657,7 +657,7 @@ update_image_descriptors(struct zink_context *ctx, struct zink_descriptor_set *z
{
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_descriptors = pg->pool[zds->type]->num_descriptors;
unsigned num_bindings = zink_program_num_bindings(pg, is_compute);
VkWriteDescriptorSet wds[num_descriptors];
struct zink_descriptor_resource resources[num_bindings];
@ -742,7 +742,7 @@ update_descriptors(struct zink_context *ctx, struct zink_screen *screen, bool is
bool cache_hit[ZINK_DESCRIPTOR_TYPES];
struct zink_descriptor_set *zds[ZINK_DESCRIPTOR_TYPES];
for (int h = 0; h < ZINK_DESCRIPTOR_TYPES; h++) {
if (pg->dsl[h])
if (pg->pool[h])
zds[h] = get_descriptor_set(ctx, is_compute, h, &cache_hit[h]);
else
zds[h] = NULL;
@ -970,7 +970,7 @@ zink_draw_vbo(struct pipe_context *pctx,
}
}
if (gfx_program->base.num_descriptors)
if (zink_program_num_descriptors(&gfx_program->base))
update_descriptors(ctx, screen, false);
struct zink_batch *batch = zink_batch_rp(ctx);
@ -1179,7 +1179,7 @@ zink_launch_grid(struct pipe_context *pctx, const struct pipe_grid_info *info)
VkPipeline pipeline = zink_get_compute_pipeline(screen, comp_program,
&ctx->compute_pipeline_state);
if (comp_program->base.num_descriptors)
if (zink_program_num_descriptors(&comp_program->base))
update_descriptors(ctx, screen, true);

View File

@ -125,8 +125,10 @@ create_gfx_pipeline_layout(VkDevice dev, struct zink_gfx_program *prog)
unsigned num_descriptors = zink_program_num_descriptors(&prog->base);
if (num_descriptors) {
for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++) {
layouts[num_layouts] = prog->base.dsl[i];
num_layouts += !!layouts[num_layouts];
if (prog->base.pool[i]) {
layouts[num_layouts] = prog->base.pool[i]->dsl;
num_layouts++;
}
}
}
@ -164,8 +166,10 @@ create_compute_pipeline_layout(VkDevice dev, struct zink_compute_program *comp)
unsigned num_descriptors = zink_program_num_descriptors(&comp->base);
if (num_descriptors) {
for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++) {
layouts[num_layouts] = comp->base.dsl[i];
num_layouts += !!layouts[num_layouts];
if (comp->base.pool[i]) {
layouts[num_layouts] = comp->base.pool[i]->dsl;
num_layouts++;
}
}
}
@ -479,22 +483,6 @@ zink_update_gfx_program(struct zink_context *ctx, struct zink_gfx_program *prog)
update_shader_modules(ctx, ctx->gfx_stages, prog, true);
}
static uint32_t
desc_state_hash(const void *key)
{
const struct zink_descriptor_state_key *d_key = (void*)key;
uint32_t hash = 0;
/* this is a compute shader */
if (!d_key->exists[PIPE_SHADER_FRAGMENT])
return d_key->state[0];
for (unsigned i = 0; i < ZINK_SHADER_COUNT; i++) {
if (d_key->exists[i])
hash = XXH32(&d_key->state[i], sizeof(uint32_t), hash);
}
return hash;
}
struct zink_gfx_program *
zink_create_gfx_program(struct zink_context *ctx,
struct zink_shader *stages[ZINK_SHADER_COUNT])
@ -525,27 +513,13 @@ zink_create_gfx_program(struct zink_context *ctx,
}
}
if (!zink_descriptor_program_init(screen->dev, stages, (struct zink_program*)prog))
if (!zink_descriptor_program_init(screen, stages, (struct zink_program*)prog))
goto fail;
prog->base.layout = create_gfx_pipeline_layout(screen->dev, prog);
if (!prog->base.layout)
goto fail;
for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++) {
if (!prog->base.num_descriptors[i])
continue;
prog->base.desc_sets[i] = _mesa_hash_table_create(NULL, desc_state_hash, zink_desc_state_equal);
if (!prog->base.desc_sets[i])
goto fail;
prog->base.free_desc_sets[i] = _mesa_hash_table_create(NULL, desc_state_hash, zink_desc_state_equal);
if (!prog->base.free_desc_sets[i])
goto fail;
util_dynarray_init(&prog->base.alloc_desc_sets[i], NULL);
}
return prog;
fail:
@ -637,27 +611,13 @@ zink_create_compute_program(struct zink_context *ctx, struct zink_shader *shader
struct zink_shader *stages[ZINK_SHADER_COUNT] = {};
stages[0] = shader;
if (!zink_descriptor_program_init(screen->dev, stages, (struct zink_program*)comp))
if (!zink_descriptor_program_init(screen, stages, (struct zink_program*)comp))
goto fail;
comp->base.layout = create_compute_pipeline_layout(screen->dev, comp);
if (!comp->base.layout)
goto fail;
for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++) {
if (!comp->base.num_descriptors[i])
continue;
comp->base.desc_sets[i] = _mesa_hash_table_create(NULL, desc_state_hash, zink_desc_state_equal);
if (!comp->base.desc_sets[i])
goto fail;
comp->base.free_desc_sets[i] = _mesa_hash_table_create(NULL, desc_state_hash, zink_desc_state_equal);
if (!comp->base.free_desc_sets[i])
goto fail;
util_dynarray_init(&comp->base.alloc_desc_sets[i], NULL);
}
return comp;
fail:
@ -666,16 +626,6 @@ fail:
return NULL;
}
static void
zink_program_clear_desc_sets(struct zink_program *pg, struct hash_table *ht)
{
hash_table_foreach(ht, entry) {
struct zink_descriptor_set *zds = entry->data;
zink_descriptor_set_invalidate(zds);
}
_mesa_hash_table_clear(ht, NULL);
}
uint32_t
zink_program_get_descriptor_usage(struct zink_context *ctx, enum pipe_shader_type stage, enum zink_descriptor_type type)
{
@ -753,6 +703,15 @@ zink_program_num_bindings(const struct zink_program *pg, bool is_compute)
return num_bindings;
}
unsigned
zink_program_num_descriptors(const struct zink_program *pg)
{
unsigned num_descriptors = 0;
for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++)
num_descriptors += pg->pool[i] ? pg->pool[i]->num_descriptors : 0;
return num_descriptors;
}
static void
gfx_program_remove_shader(struct zink_gfx_program *prog, struct zink_shader *shader)
{
@ -788,22 +747,8 @@ zink_destroy_gfx_program(struct zink_screen *screen,
}
zink_shader_cache_reference(screen, &prog->shader_cache, NULL);
bool null_destroy = false;
for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++) {
if (prog->base.num_descriptors[i] || !null_destroy) {
vkDestroyDescriptorSetLayout(screen->dev, prog->base.dsl[i], NULL);
vkDestroyDescriptorPool(screen->dev, prog->base.descpool[i], NULL);
}
null_destroy |= !prog->base.num_descriptors[i];
zink_program_clear_desc_sets(&prog->base, prog->base.desc_sets[i]);
_mesa_hash_table_destroy(prog->base.desc_sets[i], NULL);
zink_program_clear_desc_sets(&prog->base, prog->base.free_desc_sets[i]);
_mesa_hash_table_destroy(prog->base.free_desc_sets[i], NULL);
util_dynarray_fini(&prog->base.alloc_desc_sets[i]);
}
for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++)
zink_descriptor_pool_free(screen, prog->base.pool[i]);
ralloc_free(prog);
}
@ -829,22 +774,8 @@ zink_destroy_compute_program(struct zink_screen *screen,
_mesa_hash_table_destroy(comp->pipelines, NULL);
zink_shader_cache_reference(screen, &comp->shader_cache, NULL);
bool null_destroy = false;
for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++) {
if (comp->base.num_descriptors[i] || !null_destroy) {
vkDestroyDescriptorSetLayout(screen->dev, comp->base.dsl[i], NULL);
vkDestroyDescriptorPool(screen->dev, comp->base.descpool[i], NULL);
}
null_destroy |= !comp->base.num_descriptors[i];
zink_program_clear_desc_sets((struct zink_program*)comp, comp->base.desc_sets[i]);
_mesa_hash_table_destroy(comp->base.desc_sets[i], NULL);
zink_program_clear_desc_sets((struct zink_program*)comp, comp->base.free_desc_sets[i]);
_mesa_hash_table_destroy(comp->base.free_desc_sets[i], NULL);
util_dynarray_fini(&comp->base.alloc_desc_sets[i]);
}
for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++)
zink_descriptor_pool_free(screen, comp->base.pool[i]);
ralloc_free(comp);
}

View File

@ -70,12 +70,7 @@ struct zink_shader_cache {
struct zink_program {
struct pipe_reference reference;
struct hash_table *desc_sets[ZINK_DESCRIPTOR_TYPES];
struct hash_table *free_desc_sets[ZINK_DESCRIPTOR_TYPES];
struct util_dynarray alloc_desc_sets[ZINK_DESCRIPTOR_TYPES];
VkDescriptorPool descpool[ZINK_DESCRIPTOR_TYPES];
VkDescriptorSetLayout dsl[ZINK_DESCRIPTOR_TYPES];
unsigned num_descriptors[ZINK_DESCRIPTOR_TYPES];
struct zink_descriptor_pool *pool[ZINK_DESCRIPTOR_TYPES];
struct zink_descriptor_set *last_set[ZINK_DESCRIPTOR_TYPES];
VkPipelineLayout layout;
@ -123,14 +118,8 @@ zink_desc_type_from_vktype(VkDescriptorType type)
}
static inline unsigned
zink_program_num_descriptors(const struct zink_program *pg)
{
unsigned num_descriptors = 0;
for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++)
num_descriptors += pg->num_descriptors[i];
return num_descriptors;
}
unsigned
zink_program_num_descriptors(const struct zink_program *pg);
unsigned
zink_program_num_bindings_typed(const struct zink_program *pg, enum zink_descriptor_type type, bool is_compute);