radv: Use sorted bindings for set layout creation.
authorBas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Mon, 9 Apr 2018 21:16:55 +0000 (23:16 +0200)
committerBas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Wed, 18 Apr 2018 20:56:54 +0000 (22:56 +0200)
Previously we did not care about havin the set storage in order,
but for variable descriptor count we want the highest binding
at the end of the storage.

Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
src/amd/vulkan/radv_descriptor_set.c

index 0915f5c35520a63f51e4143c79ec8b73ed551ea2..1100ca182b1e6e954e028ffb066195889c991b5f 100644 (file)
@@ -45,6 +45,27 @@ static bool has_equal_immutable_samplers(const VkSampler *samplers, uint32_t cou
        return true;
 }
 
+static int binding_compare(const void* av, const void *bv)
+{
+       const VkDescriptorSetLayoutBinding *a = (const VkDescriptorSetLayoutBinding*)av;
+       const VkDescriptorSetLayoutBinding *b = (const VkDescriptorSetLayoutBinding*)bv;
+
+       return (a->binding < b->binding) ? -1 : (a->binding > b->binding) ? 1 : 0;
+}
+
+static VkDescriptorSetLayoutBinding *
+create_sorted_bindings(const VkDescriptorSetLayoutBinding *bindings, unsigned count) {
+       VkDescriptorSetLayoutBinding *sorted_bindings = malloc(count * sizeof(VkDescriptorSetLayoutBinding));
+       if (!sorted_bindings)
+               return NULL;
+
+       memcpy(sorted_bindings, bindings, count * sizeof(VkDescriptorSetLayoutBinding));
+
+       qsort(sorted_bindings, count, sizeof(VkDescriptorSetLayoutBinding), binding_compare);
+
+       return sorted_bindings;
+}
+
 VkResult radv_CreateDescriptorSetLayout(
        VkDevice                                    _device,
        const VkDescriptorSetLayoutCreateInfo*      pCreateInfo,
@@ -78,6 +99,13 @@ VkResult radv_CreateDescriptorSetLayout(
        /* We just allocate all the samplers at the end of the struct */
        uint32_t *samplers = (uint32_t*)&set_layout->binding[max_binding + 1];
 
+       VkDescriptorSetLayoutBinding *bindings = create_sorted_bindings(pCreateInfo->pBindings,
+                                                                       pCreateInfo->bindingCount);
+       if (!bindings) {
+               vk_free2(&device->alloc, pAllocator, set_layout);
+               return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+       }
+
        set_layout->binding_count = max_binding + 1;
        set_layout->shader_stages = 0;
        set_layout->dynamic_shader_stages = 0;
@@ -89,7 +117,7 @@ VkResult radv_CreateDescriptorSetLayout(
        uint32_t dynamic_offset_count = 0;
 
        for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {
-               const VkDescriptorSetLayoutBinding *binding = &pCreateInfo->pBindings[j];
+               const VkDescriptorSetLayoutBinding *binding = bindings + j;
                uint32_t b = binding->binding;
                uint32_t alignment;
 
@@ -163,6 +191,8 @@ VkResult radv_CreateDescriptorSetLayout(
                set_layout->shader_stages |= binding->stageFlags;
        }
 
+       free(bindings);
+
        set_layout->dynamic_offset_count = dynamic_offset_count;
 
        *pSetLayout = radv_descriptor_set_layout_to_handle(set_layout);
@@ -188,10 +218,17 @@ void radv_GetDescriptorSetLayoutSupport(VkDevice device,
                                         const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
                                         VkDescriptorSetLayoutSupport* pSupport)
 {
+       VkDescriptorSetLayoutBinding *bindings = create_sorted_bindings(pCreateInfo->pBindings,
+                                                                       pCreateInfo->bindingCount);
+       if (!bindings) {
+               pSupport->supported = false;
+               return;
+       }
+
        bool supported = true;
        uint64_t size = 0;
        for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
-               const VkDescriptorSetLayoutBinding *binding = &pCreateInfo->pBindings[i];
+               const VkDescriptorSetLayoutBinding *binding = bindings + i;
 
                if (binding->descriptorCount == 0)
                        continue;
@@ -244,6 +281,8 @@ void radv_GetDescriptorSetLayoutSupport(VkDevice device,
                size += binding->descriptorCount * descriptor_size;
        }
 
+       free(bindings);
+
        pSupport->supported = supported;
 }