nvk: Support VkDescriptorSetVariableDescriptorCountLayoutSupport

On cases with variable descriptor counts we need to calculate the
maximum supported variable count while taking into account the other existing
descriptors and their alignments in the set.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>
This commit is contained in:
George Ouzounoudis 2023-04-26 21:37:23 +03:00 committed by Marge Bot
parent 81bec8b63b
commit 6a74b3e311

View file

@ -256,6 +256,9 @@ nvk_GetDescriptorSetLayoutSupport(VkDevice _device,
const VkMutableDescriptorTypeCreateInfoEXT *mutable_info = const VkMutableDescriptorTypeCreateInfoEXT *mutable_info =
vk_find_struct_const(pCreateInfo->pNext, vk_find_struct_const(pCreateInfo->pNext,
MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT); MUTABLE_DESCRIPTOR_TYPE_CREATE_INFO_EXT);
const VkDescriptorSetLayoutBindingFlagsCreateInfo *binding_flags =
vk_find_struct_const(pCreateInfo->pNext,
DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO);
/* Figure out the maximum alignment up-front. Otherwise, we need to sort /* Figure out the maximum alignment up-front. Otherwise, we need to sort
* the list of descriptors by binding number in order to get the size * the list of descriptors by binding number in order to get the size
@ -274,11 +277,18 @@ nvk_GetDescriptorSetLayoutSupport(VkDevice _device,
max_align = MAX2(max_align, align); max_align = MAX2(max_align, align);
} }
uint32_t buffer_size = 0; uint64_t non_variable_size = 0;
uint32_t variable_stride = 0;
uint32_t variable_count = 0;
uint8_t dynamic_buffer_count = 0; uint8_t dynamic_buffer_count = 0;
for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) { for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
const VkDescriptorSetLayoutBinding *binding = &pCreateInfo->pBindings[i]; const VkDescriptorSetLayoutBinding *binding = &pCreateInfo->pBindings[i];
VkDescriptorBindingFlags flags = 0;
if (binding_flags != NULL && binding_flags->bindingCount > 0)
flags = binding_flags->pBindingFlags[i];
if (binding->descriptorCount == 0) if (binding->descriptorCount == 0)
continue; continue;
@ -303,23 +313,59 @@ nvk_GetDescriptorSetLayoutSupport(VkDevice _device,
assert(stride <= UINT8_MAX); assert(stride <= UINT8_MAX);
assert(util_is_power_of_two_nonzero(align)); assert(util_is_power_of_two_nonzero(align));
/* Since we're aligning to the maximum and since this is just a if (flags & VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT) {
* check for whether or not the max buffer size is big enough, we /* From the Vulkan 1.3.256 spec:
* keep buffer_size aligned to max_align. *
*/ * "For the purposes of this command, a variable-sized
buffer_size += stride * binding->descriptorCount; * descriptor binding with a descriptorCount of zero is treated
buffer_size = ALIGN_POT(buffer_size, max_align); * as if the descriptorCount is one"
*/
variable_count = MAX2(1, binding->descriptorCount);
variable_stride = stride;
} else {
/* Since we're aligning to the maximum and since this is just a
* check for whether or not the max buffer size is big enough, we
* keep non_variable_size aligned to max_align.
*/
non_variable_size += stride * binding->descriptorCount;
non_variable_size = ALIGN_POT(non_variable_size, max_align);
}
} }
} }
pSupport->supported = dynamic_buffer_count <= NVK_MAX_DYNAMIC_BUFFERS; uint64_t buffer_size = non_variable_size;
if (variable_stride > 0) {
buffer_size += variable_stride * variable_count;
buffer_size = ALIGN_POT(buffer_size, max_align);
}
uint32_t max_buffer_size;
if (pCreateInfo->flags & if (pCreateInfo->flags &
VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR) { VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR)
if (buffer_size > NVK_PUSH_DESCRIPTOR_SET_SIZE) max_buffer_size = NVK_PUSH_DESCRIPTOR_SET_SIZE;
pSupport->supported = false; else
} else { max_buffer_size = NVK_MAX_DESCRIPTOR_SET_SIZE;
if (buffer_size > NVK_MAX_DESCRIPTOR_SET_SIZE)
pSupport->supported = false; pSupport->supported = dynamic_buffer_count <= NVK_MAX_DYNAMIC_BUFFERS &&
buffer_size <= max_buffer_size;
vk_foreach_struct(ext, pSupport->pNext) {
switch (ext->sType) {
case VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT: {
VkDescriptorSetVariableDescriptorCountLayoutSupport *vs = (void *)ext;
if (variable_stride > 0) {
vs->maxVariableDescriptorCount =
(max_buffer_size - non_variable_size) / variable_stride;
} else {
vs->maxVariableDescriptorCount = 0;
}
break;
}
default:
nvk_debug_ignored_stype(ext->sType);
break;
}
} }
} }