From f860c7bdf16440ada294a388969c21c371e94b7d Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Mon, 28 Jul 2025 14:50:16 -0400 Subject: [PATCH] panvk: Use write-back maps for descriptor sets Reviewed-by: Boris Brezillon Reviewed-by: Christoph Pillmayer Part-of: --- src/panfrost/vulkan/panvk_descriptor_set.h | 7 +++ src/panfrost/vulkan/panvk_vX_descriptor_set.c | 50 ++++++++++++++++++- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/src/panfrost/vulkan/panvk_descriptor_set.h b/src/panfrost/vulkan/panvk_descriptor_set.h index a28181a2b7e..4da2625315e 100644 --- a/src/panfrost/vulkan/panvk_descriptor_set.h +++ b/src/panfrost/vulkan/panvk_descriptor_set.h @@ -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 */ diff --git a/src/panfrost/vulkan/panvk_vX_descriptor_set.c b/src/panfrost/vulkan/panvk_vX_descriptor_set.c index 744f50c57ca..1d70920b0b8 100644 --- a/src/panfrost/vulkan/panvk_vX_descriptor_set.c +++ b/src/panfrost/vulkan/panvk_vX_descriptor_set.c @@ -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; }