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:
parent
3d4e6c641b
commit
817de3c776
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue