ralloc_free(pool);
}
+static void
+multi_pool_destroy(struct zink_screen *screen, struct zink_descriptor_pool_multi *mpool)
+{
+ if (mpool->pool)
+ pool_destroy(screen, mpool->pool);
+ ralloc_free(mpool);
+}
+
static VkDescriptorPool
create_pool(struct zink_screen *screen, unsigned num_type_sizes, const VkDescriptorPoolSize *sizes, unsigned flags)
{
get_descriptor_pool(struct zink_context *ctx, struct zink_program *pg, enum zink_descriptor_type type, struct zink_batch_state *bs, bool is_compute);
static bool
-set_pool(struct zink_batch_state *bs, struct zink_program *pg, struct zink_descriptor_pool *pool, enum zink_descriptor_type type)
+set_pool(struct zink_batch_state *bs, struct zink_program *pg, struct zink_descriptor_pool_multi *mpool, enum zink_descriptor_type type)
{
assert(type != ZINK_DESCRIPTOR_TYPES);
+ assert(mpool);
const struct zink_descriptor_pool_key *pool_key = pg->dd.pool_key[type];
- if (pool) {
- size_t size = bs->dd.pools[type].capacity;
- if (!util_dynarray_resize(&bs->dd.pools[type], struct zink_descriptor_pool*, pool_key->id + 1))
- return false;
- if (size != bs->dd.pools[type].capacity) {
- uint8_t *data = bs->dd.pools[type].data;
- memset(data + size, 0, bs->dd.pools[type].capacity - size);
- }
- bs->dd.pool_size[type] = MAX2(bs->dd.pool_size[type], pool_key->id + 1);
+ size_t size = bs->dd.pools[type].capacity;
+ if (!util_dynarray_resize(&bs->dd.pools[type], struct zink_descriptor_pool*, pool_key->id + 1))
+ return false;
+ if (size != bs->dd.pools[type].capacity) {
+ uint8_t *data = bs->dd.pools[type].data;
+ memset(data + size, 0, bs->dd.pools[type].capacity - size);
}
- struct zink_descriptor_pool **ppool = util_dynarray_element(&bs->dd.pools[type], struct zink_descriptor_pool*, pool_key->id);
- *ppool = pool;
+ bs->dd.pool_size[type] = MAX2(bs->dd.pool_size[type], pool_key->id + 1);
+ struct zink_descriptor_pool_multi **mppool = util_dynarray_element(&bs->dd.pools[type], struct zink_descriptor_pool_multi*, pool_key->id);
+ *mppool = mpool;
return true;
}
static struct zink_descriptor_pool *
-check_pool_alloc(struct zink_context *ctx, struct zink_descriptor_pool *pool, struct zink_program *pg,
+alloc_new_pool(struct zink_screen *screen, struct zink_descriptor_pool_multi *mpool)
+{
+ struct zink_descriptor_pool *pool = rzalloc(mpool, struct zink_descriptor_pool);
+ if (!pool)
+ return NULL;
+ const unsigned num_type_sizes = mpool->pool_key->sizes[1].descriptorCount ? 2 : 1;
+ pool->pool = create_pool(screen, num_type_sizes, mpool->pool_key->sizes, 0);
+ if (!pool->pool) {
+ ralloc_free(pool);
+ return NULL;
+ }
+ return pool;
+}
+
+static struct zink_descriptor_pool *
+check_pool_alloc(struct zink_context *ctx, struct zink_descriptor_pool_multi *mpool, struct zink_program *pg,
enum zink_descriptor_type type, struct zink_batch_state *bs, bool is_compute)
{
struct zink_screen *screen = zink_screen(ctx->base.screen);
+ if (!mpool->pool) {
+ if (util_dynarray_contains(&mpool->overflowed_pools[!mpool->overflow_idx], struct zink_descriptor_pool*))
+ mpool->pool = util_dynarray_pop(&mpool->overflowed_pools[!mpool->overflow_idx], struct zink_descriptor_pool*);
+ else
+ mpool->pool = alloc_new_pool(screen, mpool);
+ }
+ struct zink_descriptor_pool *pool = mpool->pool;
/* allocate up to $current * 10, e.g., 10 -> 100 or 100 -> 1000 */
if (pool->set_idx == pool->sets_alloc) {
unsigned sets_to_alloc = MIN2(MIN2(MAX2(pool->sets_alloc * 10, 10), MAX_LAZY_DESCRIPTORS) - pool->sets_alloc, 100);
if (!sets_to_alloc) {
- /* overflowed pool: queue for deletion on next reset */
- util_dynarray_append(&bs->dd.overflowed_pools, struct zink_descriptor_pool*, pool);
- set_pool(bs, pg, NULL, type);
+ /* overflowed pool: store for reuse */
+ pool->set_idx = 0;
+ util_dynarray_append(&mpool->overflowed_pools[mpool->overflow_idx], struct zink_descriptor_pool*, pool);
+ mpool->pool = NULL;
return get_descriptor_pool(ctx, pg, type, bs, is_compute);
}
if (!zink_descriptor_util_alloc_sets(screen, pg->dsl[type + 1],
}
static struct zink_descriptor_pool *
-check_push_pool_alloc(struct zink_context *ctx, struct zink_descriptor_pool *pool, struct zink_batch_state *bs, bool is_compute)
+check_push_pool_alloc(struct zink_context *ctx, struct zink_descriptor_pool_multi *mpool, struct zink_batch_state *bs, bool is_compute)
{
struct zink_screen *screen = zink_screen(ctx->base.screen);
+ struct zink_descriptor_pool *pool = mpool->pool;
/* allocate up to $current * 10, e.g., 10 -> 100 or 100 -> 1000 */
if (pool->set_idx == pool->sets_alloc || unlikely(ctx->dd.has_fbfetch != bs->dd.has_fbfetch)) {
unsigned sets_to_alloc = MIN2(MIN2(MAX2(pool->sets_alloc * 10, 10), MAX_LAZY_DESCRIPTORS) - pool->sets_alloc, 100);
if (!sets_to_alloc || unlikely(ctx->dd.has_fbfetch != bs->dd.has_fbfetch)) {
- /* overflowed pool: queue for deletion on next reset */
- util_dynarray_append(&bs->dd.overflowed_pools, struct zink_descriptor_pool*, pool);
- bs->dd.push_pool[is_compute] = create_push_pool(screen, bs, is_compute, ctx->dd.has_fbfetch);
+ /* overflowed pool: store for reuse */
+ pool->set_idx = 0;
+ util_dynarray_append(&mpool->overflowed_pools[mpool->overflow_idx], struct zink_descriptor_pool*, pool);
+ if (util_dynarray_contains(&mpool->overflowed_pools[!mpool->overflow_idx], struct zink_descriptor_pool*))
+ bs->dd.push_pool[is_compute].pool = util_dynarray_pop(&mpool->overflowed_pools[!mpool->overflow_idx], struct zink_descriptor_pool*);
+ else
+ bs->dd.push_pool[is_compute].pool = create_push_pool(screen, bs, is_compute, ctx->dd.has_fbfetch);
+ if (unlikely(ctx->dd.has_fbfetch != bs->dd.has_fbfetch))
+ mpool->reinit_overflow = true;
bs->dd.has_fbfetch = ctx->dd.has_fbfetch;
- return check_push_pool_alloc(ctx, bs->dd.push_pool[is_compute], bs, is_compute);
+ return check_push_pool_alloc(ctx, &bs->dd.push_pool[is_compute], bs, is_compute);
}
if (!zink_descriptor_util_alloc_sets(screen, ctx->dd.push_dsl[is_compute]->layout,
pool->pool, &pool->sets[pool->sets_alloc], sets_to_alloc)) {
{
struct zink_screen *screen = zink_screen(ctx->base.screen);
const struct zink_descriptor_pool_key *pool_key = pg->dd.pool_key[type];
- struct zink_descriptor_pool **ppool = bs->dd.pool_size[type] > pool_key->id ?
- util_dynarray_element(&bs->dd.pools[type], struct zink_descriptor_pool *, pool_key->id) :
+ struct zink_descriptor_pool_multi **mppool = bs->dd.pool_size[type] > pool_key->id ?
+ util_dynarray_element(&bs->dd.pools[type], struct zink_descriptor_pool_multi *, pool_key->id) :
NULL;
- if (ppool && *ppool)
- return check_pool_alloc(ctx, *ppool, pg, type, bs, is_compute);
- struct zink_descriptor_pool *pool = rzalloc(bs, struct zink_descriptor_pool);
- if (!pool)
+ if (mppool && *mppool)
+ return check_pool_alloc(ctx, *mppool, pg, type, bs, is_compute);
+ struct zink_descriptor_pool_multi *mpool = rzalloc(bs, struct zink_descriptor_pool_multi);
+ if (!mpool)
return NULL;
- const unsigned num_type_sizes = pool_key->sizes[1].descriptorCount ? 2 : 1;
- pool->pool = create_pool(screen, num_type_sizes, pool_key->sizes, 0);
- pool->pool_key = pool_key;
- if (!pool->pool) {
- ralloc_free(pool);
- return NULL;
- }
- if (!set_pool(bs, pg, pool, type)) {
- pool_destroy(screen, pool);
+ util_dynarray_init(&mpool->overflowed_pools[0], mpool);
+ util_dynarray_init(&mpool->overflowed_pools[1], mpool);
+ mpool->pool_key = pool_key;
+ if (!set_pool(bs, pg, mpool, type)) {
+ multi_pool_destroy(screen, mpool);
return NULL;
}
assert(pool_key->id < bs->dd.pool_size[type]);
- return check_pool_alloc(ctx, pool, pg, type, bs, is_compute);
+ return check_pool_alloc(ctx, mpool, pg, type, bs, is_compute);
}
ALWAYS_INLINE static VkDescriptorSet
(ctx->dd.push_state_changed[is_compute] || batch_changed);
VkDescriptorSet push_set = VK_NULL_HANDLE;
if (need_push && !have_KHR_push_descriptor) {
- struct zink_descriptor_pool *pool = check_push_pool_alloc(ctx, bs->dd.push_pool[pg->is_compute], bs, pg->is_compute);
+ struct zink_descriptor_pool *pool = check_push_pool_alloc(ctx, &bs->dd.push_pool[pg->is_compute], bs, pg->is_compute);
push_set = get_descriptor_set(pool);
if (!push_set)
mesa_loge("ZINK: failed to get push descriptor set! prepare to crash!");
}
}
+static void
+clear_multi_pool_overflow(struct zink_screen *screen, struct util_dynarray *overflowed_pools)
+{
+ while (util_dynarray_num_elements(overflowed_pools, struct zink_descriptor_pool*)) {
+ struct zink_descriptor_pool *pool = util_dynarray_pop(overflowed_pools, struct zink_descriptor_pool*);
+ pool_destroy(screen, pool);
+ }
+}
+
+static void
+deinit_multi_pool_overflow(struct zink_screen *screen, struct zink_descriptor_pool_multi *mpool)
+{
+ for (unsigned i = 0; i < 2; i++) {
+ clear_multi_pool_overflow(screen, &mpool->overflowed_pools[i]);
+ util_dynarray_fini(&mpool->overflowed_pools[i]);
+ }
+}
+
void
zink_batch_descriptor_deinit(struct zink_screen *screen, struct zink_batch_state *bs)
{
for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++) {
- while (util_dynarray_contains(&bs->dd.pools[i], struct zink_descriptor_pool *)) {
- struct zink_descriptor_pool *pool = util_dynarray_pop(&bs->dd.pools[i], struct zink_descriptor_pool *);
- if (pool)
- VKSCR(DestroyDescriptorPool)(screen->dev, pool->pool, NULL);
+ while (util_dynarray_contains(&bs->dd.pools[i], struct zink_descriptor_pool_multi *)) {
+ struct zink_descriptor_pool_multi *mpool = util_dynarray_pop(&bs->dd.pools[i], struct zink_descriptor_pool_multi *);
+ if (mpool) {
+ deinit_multi_pool_overflow(screen, mpool);
+ multi_pool_destroy(screen, mpool);
+ }
}
util_dynarray_fini(&bs->dd.pools[i]);
}
- if (bs->dd.push_pool[0])
- VKSCR(DestroyDescriptorPool)(screen->dev, bs->dd.push_pool[0]->pool, NULL);
- if (bs->dd.push_pool[1])
- VKSCR(DestroyDescriptorPool)(screen->dev, bs->dd.push_pool[1]->pool, NULL);
+ for (unsigned i = 0; i < 2; i++) {
+ if (bs->dd.push_pool[0].pool)
+ pool_destroy(screen, bs->dd.push_pool[i].pool);
+ deinit_multi_pool_overflow(screen, &bs->dd.push_pool[i]);
+ }
}
void
zink_batch_descriptor_reset(struct zink_screen *screen, struct zink_batch_state *bs)
{
for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++) {
- struct zink_descriptor_pool **pools = bs->dd.pools[i].data;
- unsigned count = util_dynarray_num_elements(&bs->dd.pools[i], struct zink_descriptor_pool *);
+ struct zink_descriptor_pool_multi **mpools = bs->dd.pools[i].data;
+ unsigned count = util_dynarray_num_elements(&bs->dd.pools[i], struct zink_descriptor_pool_multi *);
for (unsigned j = 0; j < count; j++) {
- struct zink_descriptor_pool *pool = pools[j];
- if (!pool)
+ struct zink_descriptor_pool_multi *mpool = mpools[j];
+ if (!mpool)
continue;
- if (pool->pool_key->use_count)
- pool->set_idx = 0;
+ if (mpool->pool->set_idx)
+ mpool->overflow_idx = !mpool->overflow_idx;
+ if (mpool->pool_key->use_count)
+ mpool->pool->set_idx = 0;
else {
- pool_destroy(screen, pool);
- pools[j] = NULL;
+ multi_pool_destroy(screen, mpool);
+ mpools[j] = NULL;
}
}
}
for (unsigned i = 0; i < 2; i++) {
bs->dd.pg[i] = NULL;
- if (bs->dd.push_pool[i])
- bs->dd.push_pool[i]->set_idx = 0;
- }
- while (util_dynarray_num_elements(&bs->dd.overflowed_pools, struct zink_descriptor_pool*)) {
- struct zink_descriptor_pool *pool = util_dynarray_pop(&bs->dd.overflowed_pools, struct zink_descriptor_pool*);
- pool_destroy(screen, pool);
+ if (bs->dd.push_pool[i].reinit_overflow) {
+ /* these don't match current fbfetch usage and can never be used again */
+ clear_multi_pool_overflow(screen, &bs->dd.push_pool[i].overflowed_pools[bs->dd.push_pool[i].overflow_idx]);
+ } else if (bs->dd.push_pool[i].pool && bs->dd.push_pool[i].pool->set_idx) {
+ bs->dd.push_pool[i].overflow_idx = !bs->dd.push_pool[i].overflow_idx;
+ }
+ if (bs->dd.push_pool[i].pool)
+ bs->dd.push_pool[i].pool->set_idx = 0;
}
}
{
for (unsigned i = 0; i < ZINK_DESCRIPTOR_TYPES; i++)
util_dynarray_init(&bs->dd.pools[i], bs);
- util_dynarray_init(&bs->dd.overflowed_pools, bs);
if (!screen->info.have_KHR_push_descriptor) {
- bs->dd.push_pool[0] = create_push_pool(screen, bs, false, false);
- bs->dd.push_pool[1] = create_push_pool(screen, bs, true, false);
+ for (unsigned i = 0; i < 2; i++) {
+ bs->dd.push_pool[i].pool = create_push_pool(screen, bs, i, false);
+ util_dynarray_init(&bs->dd.push_pool[i].overflowed_pools[0], bs);
+ util_dynarray_init(&bs->dd.push_pool[i].overflowed_pools[1], bs);
+ }
}
return true;
}