panvk: Use write-back maps for descriptor sets

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Christoph Pillmayer <christoph.pillmayer@arm.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36385>
This commit is contained in:
Faith Ekstrand 2025-07-28 14:50:16 -04:00 committed by Boris Brezillon
parent e84f804a6d
commit f860c7bdf1
2 changed files with 56 additions and 1 deletions

View file

@ -24,6 +24,7 @@
struct panvk_priv_bo;
struct panvk_sysvals;
struct panvk_descriptor_pool;
struct panvk_descriptor_set_layout;
struct panvk_opaque_desc {
@ -40,10 +41,14 @@ struct panvk_ssbo_addr {
struct panvk_descriptor_set {
struct vk_object_base base;
struct panvk_descriptor_pool *pool;
const struct panvk_descriptor_set_layout *layout;
struct {
uint64_t dev;
void *host;
/* Dirty range, or SIZE_MAX, 0 for clean */
size_t dirty_min, dirty_max;
} descs;
struct {
@ -84,4 +89,6 @@ void panvk_per_arch(descriptor_set_write_template)(
const struct vk_descriptor_update_template *template, const void *data,
bool write_immutable_samplers);
void panvk_per_arch(descriptor_set_flush)(struct panvk_descriptor_set *set);
#endif /* PANVK_VX_DESCRIPTOR_SET_H */

View file

@ -65,6 +65,9 @@ write_desc_data(struct panvk_descriptor_set *set, uint32_t binding,
uint32_t offset_B = desc_offset + index * PANVK_DESCRIPTOR_SIZE;
memcpy((char *)set->descs.host + offset_B, desc_data, desc_size);
set->descs.dirty_min = MIN2(set->descs.dirty_min, offset_B);
set->descs.dirty_max = MAX2(set->descs.dirty_max, offset_B + desc_size);
}
#define write_desc(set, binding, elem, desc, subdesc) \
@ -319,7 +322,9 @@ panvk_init_pool_memory(struct panvk_device *device,
const VkAllocationCallbacks *pAllocator)
{
if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT)) {
VkResult result = panvk_priv_bo_create(device, pool_size, 0,
uint32_t bo_flags =
panvk_device_adjust_bo_flags(device, PAN_KMOD_BO_FLAG_WB_MMAP);
VkResult result = panvk_priv_bo_create(device, pool_size, bo_flags,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT,
&pool->desc_bo);
if (result != VK_SUCCESS)
@ -538,6 +543,7 @@ panvk_desc_pool_allocate_set(struct panvk_descriptor_pool *pool,
vk_object_base_init(pool->base.device, &set->base,
VK_OBJECT_TYPE_DESCRIPTOR_SET);
vk_descriptor_set_layout_ref(&layout->vk);
set->pool = pool;
set->layout = layout;
set->desc_count = num_descs;
if (pool->desc_bo) {
@ -549,6 +555,8 @@ panvk_desc_pool_allocate_set(struct panvk_descriptor_pool *pool,
* pointer in case of a host only pool. */
set->descs.host = (void *)(uintptr_t)descs_dev_addr;
}
set->descs.dirty_min = SIZE_MAX;
set->descs.dirty_max = 0;
desc_set_write_immutable_samplers(set, variable_count);
BITSET_CLEAR(pool->free_sets, first_free_set - 1);
@ -794,6 +802,21 @@ panvk_per_arch(UpdateDescriptorSets)(
for (uint32_t i = 0; i < descriptorCopyCount; i++)
panvk_descriptor_set_copy(&pDescriptorCopies[i]);
/* Flush at the end so we call into the kernel as few times as possible.
* Note that redundant flushes do nothing.
*/
for (uint32_t i = 0; i < descriptorWriteCount; i++) {
VK_FROM_HANDLE(panvk_descriptor_set, set, pDescriptorWrites[i].dstSet);
panvk_per_arch(descriptor_set_flush)(set);
}
for (uint32_t i = 0; i < descriptorCopyCount; i++) {
VK_FROM_HANDLE(panvk_descriptor_set, set, pDescriptorCopies[i].dstSet);
panvk_per_arch(descriptor_set_flush)(set);
}
}
void
@ -895,4 +918,29 @@ panvk_per_arch(UpdateDescriptorSetWithTemplate)(
descriptorUpdateTemplate);
panvk_per_arch(descriptor_set_write_template)(set, template, pData, false);
panvk_per_arch(descriptor_set_flush)(set);
}
void panvk_per_arch(descriptor_set_flush)(struct panvk_descriptor_set *set)
{
if (set->descs.dirty_max <= set->descs.dirty_min) {
assert(set->descs.dirty_max == 0);
assert(set->descs.dirty_min == SIZE_MAX);
return;
}
if (set->pool->desc_bo) {
assert(set->descs.dev >= set->pool->desc_bo->addr.dev);
uint64_t set_offset = set->descs.dev - set->pool->desc_bo->addr.dev;
assert(set_offset < set->pool->desc_bo->bo->size);
assert(set_offset + set->descs.dirty_max <= set->pool->desc_bo->bo->size);
size_t offset = set_offset + set->descs.dirty_min;
size_t range = set->descs.dirty_max - set->descs.dirty_min;
panvk_priv_bo_flush(set->pool->desc_bo, offset, range);
}
set->descs.dirty_min = SIZE_MAX;
set->descs.dirty_max = 0;
}