mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-02 18:10:17 +01:00
v3dv: add reference counting for descriptor set layouts
The spec states that descriptor set layouts can be destroyed almost
at any time:
"VkDescriptorSetLayout objects may be accessed by commands that
operate on descriptor sets allocated using that layout, and those
descriptor sets must not be updated with vkUpdateDescriptorSets
after the descriptor set layout has been destroyed. Otherwise,
descriptor set layouts can be destroyed any time they are not in
use by an API command."
Based on a similar fix for RADV.
Gitlab: https://gitlab.freedesktop.org/mesa/mesa/-/issues/5893
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15634>
This commit is contained in:
parent
ca861bd6f4
commit
7f6ecb8667
2 changed files with 56 additions and 8 deletions
|
|
@ -314,8 +314,8 @@ v3dv_CreatePipelineLayout(VkDevice _device,
|
|||
for (uint32_t set = 0; set < pCreateInfo->setLayoutCount; set++) {
|
||||
V3DV_FROM_HANDLE(v3dv_descriptor_set_layout, set_layout,
|
||||
pCreateInfo->pSetLayouts[set]);
|
||||
v3dv_descriptor_set_layout_ref(set_layout);
|
||||
layout->set[set].layout = set_layout;
|
||||
|
||||
layout->set[set].dynamic_offset_start = dynamic_offset_count;
|
||||
for (uint32_t b = 0; b < set_layout->binding_count; b++) {
|
||||
dynamic_offset_count += set_layout->binding[b].array_size *
|
||||
|
|
@ -351,6 +351,10 @@ v3dv_DestroyPipelineLayout(VkDevice _device,
|
|||
|
||||
if (!pipeline_layout)
|
||||
return;
|
||||
|
||||
for (uint32_t i = 0; i < pipeline_layout->num_sets; i++)
|
||||
v3dv_descriptor_set_layout_unref(device, pipeline_layout->set[i].layout);
|
||||
|
||||
vk_object_free(&device->vk, pAllocator, pipeline_layout);
|
||||
}
|
||||
|
||||
|
|
@ -478,6 +482,8 @@ descriptor_set_destroy(struct v3dv_device *device,
|
|||
{
|
||||
assert(!pool->host_memory_base);
|
||||
|
||||
v3dv_descriptor_set_layout_unref(device, set->layout);
|
||||
|
||||
if (free_bo && !pool->host_memory_base) {
|
||||
for (uint32_t i = 0; i < pool->entry_count; i++) {
|
||||
if (pool->entries[i].set == set) {
|
||||
|
|
@ -543,6 +549,15 @@ v3dv_ResetDescriptorPool(VkDevice _device,
|
|||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
v3dv_descriptor_set_layout_destroy(struct v3dv_device *device,
|
||||
struct v3dv_descriptor_set_layout *set_layout)
|
||||
{
|
||||
assert(set_layout->ref_cnt == 0);
|
||||
vk_object_base_finish(&set_layout->base);
|
||||
vk_free2(&device->vk.alloc, NULL, set_layout);
|
||||
}
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL
|
||||
v3dv_CreateDescriptorSetLayout(VkDevice _device,
|
||||
const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
|
||||
|
|
@ -588,12 +603,18 @@ v3dv_CreateDescriptorSetLayout(VkDevice _device,
|
|||
uint32_t size = samplers_offset +
|
||||
immutable_sampler_count * sizeof(struct v3dv_sampler);
|
||||
|
||||
set_layout = vk_object_zalloc(&device->vk, pAllocator, size,
|
||||
VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT);
|
||||
|
||||
/* Descriptor set layouts are reference counted and therefore can survive
|
||||
* vkDestroyPipelineSetLayout, so they need to be allocated with a device
|
||||
* scope.
|
||||
*/
|
||||
set_layout =
|
||||
vk_zalloc(&device->vk.alloc, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
|
||||
if (!set_layout)
|
||||
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
vk_object_base_init(&device->vk, &set_layout->base,
|
||||
VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT);
|
||||
|
||||
struct v3dv_sampler *samplers = (void*) &set_layout->binding[num_bindings];
|
||||
|
||||
assert(pCreateInfo->bindingCount == 0 || num_bindings > 0);
|
||||
|
|
@ -602,7 +623,7 @@ v3dv_CreateDescriptorSetLayout(VkDevice _device,
|
|||
VkResult result = vk_create_sorted_bindings(pCreateInfo->pBindings,
|
||||
pCreateInfo->bindingCount, &bindings);
|
||||
if (result != VK_SUCCESS) {
|
||||
vk_object_free(&device->vk, pAllocator, set_layout);
|
||||
v3dv_descriptor_set_layout_destroy(device, set_layout);
|
||||
return vk_error(device, result);
|
||||
}
|
||||
|
||||
|
|
@ -610,6 +631,7 @@ v3dv_CreateDescriptorSetLayout(VkDevice _device,
|
|||
set_layout->flags = pCreateInfo->flags;
|
||||
set_layout->shader_stages = 0;
|
||||
set_layout->bo_size = 0;
|
||||
set_layout->ref_cnt = 1;
|
||||
|
||||
uint32_t descriptor_count = 0;
|
||||
uint32_t dynamic_offset_count = 0;
|
||||
|
|
@ -712,7 +734,7 @@ v3dv_DestroyDescriptorSetLayout(VkDevice _device,
|
|||
if (!set_layout)
|
||||
return;
|
||||
|
||||
vk_object_free(&device->vk, pAllocator, set_layout);
|
||||
v3dv_descriptor_set_layout_unref(device, set_layout);
|
||||
}
|
||||
|
||||
static inline VkResult
|
||||
|
|
@ -731,7 +753,7 @@ out_of_pool_memory(const struct v3dv_device *device,
|
|||
static VkResult
|
||||
descriptor_set_create(struct v3dv_device *device,
|
||||
struct v3dv_descriptor_pool *pool,
|
||||
const struct v3dv_descriptor_set_layout *layout,
|
||||
struct v3dv_descriptor_set_layout *layout,
|
||||
struct v3dv_descriptor_set **out_set)
|
||||
{
|
||||
struct v3dv_descriptor_set *set;
|
||||
|
|
@ -836,6 +858,7 @@ descriptor_set_create(struct v3dv_device *device,
|
|||
}
|
||||
}
|
||||
|
||||
v3dv_descriptor_set_layout_ref(layout);
|
||||
*out_set = set;
|
||||
|
||||
return VK_SUCCESS;
|
||||
|
|
|
|||
|
|
@ -1645,7 +1645,7 @@ struct v3dv_descriptor_set {
|
|||
|
||||
struct v3dv_descriptor_pool *pool;
|
||||
|
||||
const struct v3dv_descriptor_set_layout *layout;
|
||||
struct v3dv_descriptor_set_layout *layout;
|
||||
|
||||
/* Offset relative to the descriptor pool bo for this set */
|
||||
uint32_t base_offset;
|
||||
|
|
@ -1699,10 +1699,35 @@ struct v3dv_descriptor_set_layout {
|
|||
/* Number of dynamic offsets used by this descriptor set */
|
||||
uint16_t dynamic_offset_count;
|
||||
|
||||
/* Descriptor set layouts can be destroyed even if they are still being
|
||||
* used.
|
||||
*/
|
||||
uint32_t ref_cnt;
|
||||
|
||||
/* Bindings in this descriptor set */
|
||||
struct v3dv_descriptor_set_binding_layout binding[0];
|
||||
};
|
||||
|
||||
void
|
||||
v3dv_descriptor_set_layout_destroy(struct v3dv_device *device,
|
||||
struct v3dv_descriptor_set_layout *set_layout);
|
||||
|
||||
static inline void
|
||||
v3dv_descriptor_set_layout_ref(struct v3dv_descriptor_set_layout *set_layout)
|
||||
{
|
||||
assert(set_layout && set_layout->ref_cnt >= 1);
|
||||
p_atomic_inc(&set_layout->ref_cnt);
|
||||
}
|
||||
|
||||
static inline void
|
||||
v3dv_descriptor_set_layout_unref(struct v3dv_device *device,
|
||||
struct v3dv_descriptor_set_layout *set_layout)
|
||||
{
|
||||
assert(set_layout && set_layout->ref_cnt >= 1);
|
||||
if (p_atomic_dec_zero(&set_layout->ref_cnt))
|
||||
v3dv_descriptor_set_layout_destroy(device, set_layout);
|
||||
}
|
||||
|
||||
struct v3dv_pipeline_layout {
|
||||
struct vk_object_base base;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue