layers: Add support for VK_EXT_descriptor_indexing
authorJeff Bolz <jbolz@nvidia.com>
Tue, 10 Apr 2018 19:32:18 +0000 (14:32 -0500)
committerMark Lobodzinski <mark@lunarg.com>
Fri, 13 Apr 2018 19:09:51 +0000 (13:09 -0600)
Change-Id: Ieeaf9cbdff1c9b383d4f47ef678fe4a7467113cb

layers/core_validation.cpp
layers/core_validation_types.h
layers/descriptor_sets.cpp
layers/descriptor_sets.h
layers/shader_validation.cpp
layers/vk_validation_error_database.txt
tests/layer_validation_tests.cpp
tests/vkrenderframework.cpp
tests/vkrenderframework.h
tests/vktestbinding.cpp
tests/vktestbinding.h

index beaf3fb..614eeb9 100644 (file)
@@ -207,6 +207,8 @@ struct layer_data {
     // Device extension properties -- storing properties gathered from VkPhysicalDeviceProperties2KHR::pNext chain
     struct DeviceExtensionProperties {
         uint32_t max_push_descriptors;  // from VkPhysicalDevicePushDescriptorPropertiesKHR::maxPushDescriptors
+        VkPhysicalDeviceDescriptorIndexingPropertiesEXT descriptor_indexing_props;
+        VkPhysicalDeviceDescriptorIndexingFeaturesEXT descriptor_indexing_features;
     };
     DeviceExtensionProperties phys_dev_ext_props = {};
     bool external_sync_warning = false;
@@ -2282,6 +2284,18 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDevice
         instance_data->dispatch_table.GetPhysicalDeviceProperties2KHR(gpu, &prop2);
         device_data->phys_dev_ext_props.max_push_descriptors = push_descriptor_prop.maxPushDescriptors;
     }
+    if (device_data->extensions.vk_ext_descriptor_indexing) {
+        // Get the needed descriptor_indexing limits
+        auto descriptor_indexing_props = lvl_init_struct<VkPhysicalDeviceDescriptorIndexingPropertiesEXT>();
+        auto prop2 = lvl_init_struct<VkPhysicalDeviceProperties2KHR>(&descriptor_indexing_props);
+        instance_data->dispatch_table.GetPhysicalDeviceProperties2KHR(gpu, &prop2);
+        device_data->phys_dev_ext_props.descriptor_indexing_props = descriptor_indexing_props;
+    }
+
+    const auto *descriptor_indexing_features = lvl_find_in_chain<VkPhysicalDeviceDescriptorIndexingFeaturesEXT>(pCreateInfo->pNext);
+    if (descriptor_indexing_features) {
+        device_data->phys_dev_ext_props.descriptor_indexing_features = *descriptor_indexing_features;
+    }
 
     lock.unlock();
 
@@ -4725,6 +4739,10 @@ const PHYS_DEV_PROPERTIES_NODE *GetPhysDevProperties(const layer_data *device_da
 
 const VkPhysicalDeviceFeatures *GetEnabledFeatures(const layer_data *device_data) { return &device_data->enabled_features; }
 
+const VkPhysicalDeviceDescriptorIndexingFeaturesEXT *GetEnabledDescriptorIndexingFeatures(const layer_data *device_data) {
+    return &device_data->phys_dev_ext_props.descriptor_indexing_features;
+}
+
 const DeviceExtensions *GetDeviceExtensions(const layer_data *device_data) { return &device_data->extensions; }
 
 VKAPI_ATTR VkResult VKAPI_CALL CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
@@ -4998,9 +5016,10 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateSampler(VkDevice device, const VkSamplerCre
 
 static bool PreCallValidateCreateDescriptorSetLayout(layer_data *dev_data, const VkDescriptorSetLayoutCreateInfo *create_info) {
     if (dev_data->instance_data->disabled.create_descriptor_set_layout) return false;
-    return cvdescriptorset::DescriptorSetLayout::ValidateCreateInfo(dev_data->report_data, create_info,
-                                                                    dev_data->extensions.vk_khr_push_descriptor,
-                                                                    dev_data->phys_dev_ext_props.max_push_descriptors);
+    return cvdescriptorset::DescriptorSetLayout::ValidateCreateInfo(
+        dev_data->report_data, create_info, dev_data->extensions.vk_khr_push_descriptor,
+        dev_data->phys_dev_ext_props.max_push_descriptors, dev_data->extensions.vk_ext_descriptor_indexing,
+        &dev_data->phys_dev_ext_props.descriptor_indexing_features);
 }
 
 static void PostCallRecordCreateDescriptorSetLayout(layer_data *dev_data, const VkDescriptorSetLayoutCreateInfo *create_info,
@@ -5137,7 +5156,8 @@ enum DSL_DESCRIPTOR_GROUPS {
 // Used by PreCallValiateCreatePipelineLayout.
 // Returns an array of size DSL_NUM_DESCRIPTOR_GROUPS of the maximum number of descriptors used in any single pipeline stage
 std::valarray<uint32_t> GetDescriptorCountMaxPerStage(
-    const layer_data *dev_data, const std::vector<std::shared_ptr<cvdescriptorset::DescriptorSetLayout const>> set_layouts) {
+    const layer_data *dev_data, const std::vector<std::shared_ptr<cvdescriptorset::DescriptorSetLayout const>> set_layouts,
+    bool skip_update_after_bind) {
     // Identify active pipeline stages
     std::vector<VkShaderStageFlags> stage_flags = {VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_FRAGMENT_BIT,
                                                    VK_SHADER_STAGE_COMPUTE_BIT};
@@ -5158,6 +5178,11 @@ std::valarray<uint32_t> GetDescriptorCountMaxPerStage(
     for (auto stage : stage_flags) {
         std::valarray<uint32_t> stage_sum(0U, DSL_NUM_DESCRIPTOR_GROUPS);  // per-stage sums
         for (auto dsl : set_layouts) {
+            if (skip_update_after_bind &&
+                (dsl->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT)) {
+                continue;
+            }
+
             for (uint32_t binding_idx = 0; binding_idx < dsl->GetBindingCount(); binding_idx++) {
                 const VkDescriptorSetLayoutBinding *binding = dsl->GetDescriptorSetLayoutBindingPtrFromIndex(binding_idx);
                 if (0 != (stage & binding->stageFlags)) {
@@ -5205,9 +5230,14 @@ std::valarray<uint32_t> GetDescriptorCountMaxPerStage(
 // Returns an array of size VK_DESCRIPTOR_TYPE_RANGE_SIZE of the summed descriptors by type.
 // Note: descriptors only count against the limit once even if used by multiple stages.
 std::valarray<uint32_t> GetDescriptorSum(
-    const layer_data *dev_data, const std::vector<std::shared_ptr<cvdescriptorset::DescriptorSetLayout const>> &set_layouts) {
+    const layer_data *dev_data, const std::vector<std::shared_ptr<cvdescriptorset::DescriptorSetLayout const>> &set_layouts,
+    bool skip_update_after_bind) {
     std::valarray<uint32_t> sum_by_type(0U, VK_DESCRIPTOR_TYPE_RANGE_SIZE);
     for (auto dsl : set_layouts) {
+        if (skip_update_after_bind && (dsl->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT)) {
+            continue;
+        }
+
         for (uint32_t binding_idx = 0; binding_idx < dsl->GetBindingCount(); binding_idx++) {
             const VkDescriptorSetLayoutBinding *binding = dsl->GetDescriptorSetLayoutBindingPtrFromIndex(binding_idx);
             sum_by_type[binding->descriptorType] += binding->descriptorCount;
@@ -5268,7 +5298,7 @@ static bool PreCallValiateCreatePipelineLayout(const layer_data *dev_data, const
     }
 
     // Max descriptors by type, within a single pipeline stage
-    std::valarray<uint32_t> max_descriptors_per_stage = GetDescriptorCountMaxPerStage(dev_data, set_layouts);
+    std::valarray<uint32_t> max_descriptors_per_stage = GetDescriptorCountMaxPerStage(dev_data, set_layouts, true);
     // Samplers
     if (max_descriptors_per_stage[DSL_TYPE_SAMPLERS] > dev_data->phys_dev_props.limits.maxPerStageDescriptorSamplers) {
         skip |=
@@ -5332,16 +5362,15 @@ static bool PreCallValiateCreatePipelineLayout(const layer_data *dev_data, const
 
     // Total descriptors by type
     //
-    std::valarray<uint32_t> sum_all_stages = GetDescriptorSum(dev_data, set_layouts);
+    std::valarray<uint32_t> sum_all_stages = GetDescriptorSum(dev_data, set_layouts, true);
     // Samplers
-    if ((sum_all_stages[VK_DESCRIPTOR_TYPE_SAMPLER] + sum_all_stages[VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER]) >
-        dev_data->phys_dev_props.limits.maxDescriptorSetSamplers) {
+    uint32_t sum = sum_all_stages[VK_DESCRIPTOR_TYPE_SAMPLER] + sum_all_stages[VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER];
+    if (sum > dev_data->phys_dev_props.limits.maxDescriptorSetSamplers) {
         skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
                         VALIDATION_ERROR_0fe00d1a,
                         "vkCreatePipelineLayout(): sum of sampler bindings among all stages (%d) exceeds device "
                         "maxDescriptorSetSamplers limit (%d).",
-                        sum_all_stages[VK_DESCRIPTOR_TYPE_SAMPLER] + sum_all_stages[VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER],
-                        dev_data->phys_dev_props.limits.maxDescriptorSetSamplers);
+                        sum, dev_data->phys_dev_props.limits.maxDescriptorSetSamplers);
     }
 
     // Uniform buffers
@@ -5387,27 +5416,24 @@ static bool PreCallValiateCreatePipelineLayout(const layer_data *dev_data, const
     }
 
     //  Sampled images
-    if ((sum_all_stages[VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE] + sum_all_stages[VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER] +
-         sum_all_stages[VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER]) > dev_data->phys_dev_props.limits.maxDescriptorSetSampledImages) {
-        skip |=
-            log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
-                    VALIDATION_ERROR_0fe00d24,
-                    "vkCreatePipelineLayout(): sum of sampled image bindings among all stages (%d) exceeds device "
-                    "maxDescriptorSetSampledImages limit (%d).",
-                    sum_all_stages[VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE] + sum_all_stages[VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER] +
-                        sum_all_stages[VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER],
-                    dev_data->phys_dev_props.limits.maxDescriptorSetSampledImages);
+    sum = sum_all_stages[VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE] + sum_all_stages[VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER] +
+          sum_all_stages[VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER];
+    if (sum > dev_data->phys_dev_props.limits.maxDescriptorSetSampledImages) {
+        skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                        VALIDATION_ERROR_0fe00d24,
+                        "vkCreatePipelineLayout(): sum of sampled image bindings among all stages (%d) exceeds device "
+                        "maxDescriptorSetSampledImages limit (%d).",
+                        sum, dev_data->phys_dev_props.limits.maxDescriptorSetSampledImages);
     }
 
     //  Storage images
-    if ((sum_all_stages[VK_DESCRIPTOR_TYPE_STORAGE_IMAGE] + sum_all_stages[VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER]) >
-        dev_data->phys_dev_props.limits.maxDescriptorSetStorageImages) {
+    sum = sum_all_stages[VK_DESCRIPTOR_TYPE_STORAGE_IMAGE] + sum_all_stages[VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER];
+    if (sum > dev_data->phys_dev_props.limits.maxDescriptorSetStorageImages) {
         skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
                         VALIDATION_ERROR_0fe00d26,
                         "vkCreatePipelineLayout(): sum of storage image bindings among all stages (%d) exceeds device "
                         "maxDescriptorSetStorageImages limit (%d).",
-                        sum_all_stages[VK_DESCRIPTOR_TYPE_STORAGE_IMAGE] + sum_all_stages[VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER],
-                        dev_data->phys_dev_props.limits.maxDescriptorSetStorageImages);
+                        sum, dev_data->phys_dev_props.limits.maxDescriptorSetStorageImages);
     }
 
     // Input attachments
@@ -5420,6 +5446,179 @@ static bool PreCallValiateCreatePipelineLayout(const layer_data *dev_data, const
                         dev_data->phys_dev_props.limits.maxDescriptorSetInputAttachments);
     }
 
+    if (dev_data->extensions.vk_ext_descriptor_indexing) {
+        // XXX TODO: replace with correct VU messages
+
+        // Max descriptors by type, within a single pipeline stage
+        std::valarray<uint32_t> max_descriptors_per_stage_update_after_bind =
+            GetDescriptorCountMaxPerStage(dev_data, set_layouts, false);
+        // Samplers
+        if (max_descriptors_per_stage_update_after_bind[DSL_TYPE_SAMPLERS] >
+            dev_data->phys_dev_ext_props.descriptor_indexing_props.maxPerStageDescriptorUpdateAfterBindSamplers) {
+            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                            VALIDATION_ERROR_0fe0179c,
+                            "vkCreatePipelineLayout(): max per-stage sampler bindings count (%d) exceeds device "
+                            "maxPerStageDescriptorUpdateAfterBindSamplers limit (%d).",
+                            max_descriptors_per_stage_update_after_bind[DSL_TYPE_SAMPLERS],
+                            dev_data->phys_dev_ext_props.descriptor_indexing_props.maxPerStageDescriptorUpdateAfterBindSamplers);
+        }
+
+        // Uniform buffers
+        if (max_descriptors_per_stage_update_after_bind[DSL_TYPE_UNIFORM_BUFFERS] >
+            dev_data->phys_dev_ext_props.descriptor_indexing_props.maxPerStageDescriptorUpdateAfterBindUniformBuffers) {
+            skip |=
+                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                        VALIDATION_ERROR_0fe0179e,
+                        "vkCreatePipelineLayout(): max per-stage uniform buffer bindings count (%d) exceeds device "
+                        "maxPerStageDescriptorUpdateAfterBindUniformBuffers limit (%d).",
+                        max_descriptors_per_stage_update_after_bind[DSL_TYPE_UNIFORM_BUFFERS],
+                        dev_data->phys_dev_ext_props.descriptor_indexing_props.maxPerStageDescriptorUpdateAfterBindUniformBuffers);
+        }
+
+        // Storage buffers
+        if (max_descriptors_per_stage_update_after_bind[DSL_TYPE_STORAGE_BUFFERS] >
+            dev_data->phys_dev_ext_props.descriptor_indexing_props.maxPerStageDescriptorUpdateAfterBindStorageBuffers) {
+            skip |=
+                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                        VALIDATION_ERROR_0fe017a0,
+                        "vkCreatePipelineLayout(): max per-stage storage buffer bindings count (%d) exceeds device "
+                        "maxPerStageDescriptorUpdateAfterBindStorageBuffers limit (%d).",
+                        max_descriptors_per_stage_update_after_bind[DSL_TYPE_STORAGE_BUFFERS],
+                        dev_data->phys_dev_ext_props.descriptor_indexing_props.maxPerStageDescriptorUpdateAfterBindStorageBuffers);
+        }
+
+        // Sampled images
+        if (max_descriptors_per_stage_update_after_bind[DSL_TYPE_SAMPLED_IMAGES] >
+            dev_data->phys_dev_ext_props.descriptor_indexing_props.maxPerStageDescriptorUpdateAfterBindSampledImages) {
+            skip |=
+                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                        VALIDATION_ERROR_0fe017a2,
+                        "vkCreatePipelineLayout(): max per-stage sampled image bindings count (%d) exceeds device "
+                        "maxPerStageDescriptorUpdateAfterBindSampledImages limit (%d).",
+                        max_descriptors_per_stage_update_after_bind[DSL_TYPE_SAMPLED_IMAGES],
+                        dev_data->phys_dev_ext_props.descriptor_indexing_props.maxPerStageDescriptorUpdateAfterBindSampledImages);
+        }
+
+        // Storage images
+        if (max_descriptors_per_stage_update_after_bind[DSL_TYPE_STORAGE_IMAGES] >
+            dev_data->phys_dev_ext_props.descriptor_indexing_props.maxPerStageDescriptorUpdateAfterBindStorageImages) {
+            skip |=
+                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                        VALIDATION_ERROR_0fe017a4,
+                        "vkCreatePipelineLayout(): max per-stage storage image bindings count (%d) exceeds device "
+                        "maxPerStageDescriptorUpdateAfterBindStorageImages limit (%d).",
+                        max_descriptors_per_stage_update_after_bind[DSL_TYPE_STORAGE_IMAGES],
+                        dev_data->phys_dev_ext_props.descriptor_indexing_props.maxPerStageDescriptorUpdateAfterBindStorageImages);
+        }
+
+        // Input attachments
+        if (max_descriptors_per_stage_update_after_bind[DSL_TYPE_INPUT_ATTACHMENTS] >
+            dev_data->phys_dev_ext_props.descriptor_indexing_props.maxPerStageDescriptorUpdateAfterBindInputAttachments) {
+            skip |= log_msg(
+                dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                VALIDATION_ERROR_0fe017a6,
+                "vkCreatePipelineLayout(): max per-stage input attachment bindings count (%d) exceeds device "
+                "maxPerStageDescriptorUpdateAfterBindInputAttachments limit (%d).",
+                max_descriptors_per_stage_update_after_bind[DSL_TYPE_INPUT_ATTACHMENTS],
+                dev_data->phys_dev_ext_props.descriptor_indexing_props.maxPerStageDescriptorUpdateAfterBindInputAttachments);
+        }
+
+        // Total descriptors by type, summed across all pipeline stages
+        //
+        std::valarray<uint32_t> sum_all_stages_update_after_bind = GetDescriptorSum(dev_data, set_layouts, false);
+        // Samplers
+        sum = sum_all_stages_update_after_bind[VK_DESCRIPTOR_TYPE_SAMPLER] +
+              sum_all_stages_update_after_bind[VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER];
+        if (sum > dev_data->phys_dev_ext_props.descriptor_indexing_props.maxDescriptorSetUpdateAfterBindSamplers) {
+            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                            VALIDATION_ERROR_0fe017b8,
+                            "vkCreatePipelineLayout(): sum of sampler bindings among all stages (%d) exceeds device "
+                            "maxDescriptorSetUpdateAfterBindSamplers limit (%d).",
+                            sum, dev_data->phys_dev_ext_props.descriptor_indexing_props.maxDescriptorSetUpdateAfterBindSamplers);
+        }
+
+        // Uniform buffers
+        if (sum_all_stages_update_after_bind[VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER] >
+            dev_data->phys_dev_ext_props.descriptor_indexing_props.maxDescriptorSetUpdateAfterBindUniformBuffers) {
+            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                            VALIDATION_ERROR_0fe017ba,
+                            "vkCreatePipelineLayout(): sum of uniform buffer bindings among all stages (%d) exceeds device "
+                            "maxDescriptorSetUpdateAfterBindUniformBuffers limit (%d).",
+                            sum_all_stages_update_after_bind[VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER],
+                            dev_data->phys_dev_ext_props.descriptor_indexing_props.maxDescriptorSetUpdateAfterBindUniformBuffers);
+        }
+
+        // Dynamic uniform buffers
+        if (sum_all_stages_update_after_bind[VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC] >
+            dev_data->phys_dev_ext_props.descriptor_indexing_props.maxDescriptorSetUpdateAfterBindUniformBuffersDynamic) {
+            skip |= log_msg(
+                dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                VALIDATION_ERROR_0fe017bc,
+                "vkCreatePipelineLayout(): sum of dynamic uniform buffer bindings among all stages (%d) exceeds device "
+                "maxDescriptorSetUpdateAfterBindUniformBuffersDynamic limit (%d).",
+                sum_all_stages_update_after_bind[VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC],
+                dev_data->phys_dev_ext_props.descriptor_indexing_props.maxDescriptorSetUpdateAfterBindUniformBuffersDynamic);
+        }
+
+        // Storage buffers
+        if (sum_all_stages_update_after_bind[VK_DESCRIPTOR_TYPE_STORAGE_BUFFER] >
+            dev_data->phys_dev_ext_props.descriptor_indexing_props.maxDescriptorSetUpdateAfterBindStorageBuffers) {
+            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                            VALIDATION_ERROR_0fe017be,
+                            "vkCreatePipelineLayout(): sum of storage buffer bindings among all stages (%d) exceeds device "
+                            "maxDescriptorSetUpdateAfterBindStorageBuffers limit (%d).",
+                            sum_all_stages_update_after_bind[VK_DESCRIPTOR_TYPE_STORAGE_BUFFER],
+                            dev_data->phys_dev_ext_props.descriptor_indexing_props.maxDescriptorSetUpdateAfterBindStorageBuffers);
+        }
+
+        // Dynamic storage buffers
+        if (sum_all_stages_update_after_bind[VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC] >
+            dev_data->phys_dev_ext_props.descriptor_indexing_props.maxDescriptorSetUpdateAfterBindStorageBuffersDynamic) {
+            skip |= log_msg(
+                dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                VALIDATION_ERROR_0fe017c0,
+                "vkCreatePipelineLayout(): sum of dynamic storage buffer bindings among all stages (%d) exceeds device "
+                "maxDescriptorSetUpdateAfterBindStorageBuffersDynamic limit (%d).",
+                sum_all_stages_update_after_bind[VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC],
+                dev_data->phys_dev_ext_props.descriptor_indexing_props.maxDescriptorSetUpdateAfterBindStorageBuffersDynamic);
+        }
+
+        //  Sampled images
+        sum = sum_all_stages_update_after_bind[VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE] +
+              sum_all_stages_update_after_bind[VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER] +
+              sum_all_stages_update_after_bind[VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER];
+        if (sum > dev_data->phys_dev_ext_props.descriptor_indexing_props.maxDescriptorSetUpdateAfterBindSampledImages) {
+            skip |=
+                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                        VALIDATION_ERROR_0fe017c2,
+                        "vkCreatePipelineLayout(): sum of sampled image bindings among all stages (%d) exceeds device "
+                        "maxDescriptorSetUpdateAfterBindSampledImages limit (%d).",
+                        sum, dev_data->phys_dev_ext_props.descriptor_indexing_props.maxDescriptorSetUpdateAfterBindSampledImages);
+        }
+
+        //  Storage images
+        sum = sum_all_stages_update_after_bind[VK_DESCRIPTOR_TYPE_STORAGE_IMAGE] +
+              sum_all_stages_update_after_bind[VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER];
+        if (sum > dev_data->phys_dev_ext_props.descriptor_indexing_props.maxDescriptorSetUpdateAfterBindStorageImages) {
+            skip |=
+                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                        VALIDATION_ERROR_0fe017c4,
+                        "vkCreatePipelineLayout(): sum of storage image bindings among all stages (%d) exceeds device "
+                        "maxDescriptorSetUpdateAfterBindStorageImages limit (%d).",
+                        sum, dev_data->phys_dev_ext_props.descriptor_indexing_props.maxDescriptorSetUpdateAfterBindStorageImages);
+        }
+
+        // Input attachments
+        if (sum_all_stages_update_after_bind[VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT] >
+            dev_data->phys_dev_ext_props.descriptor_indexing_props.maxDescriptorSetUpdateAfterBindInputAttachments) {
+            skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                            VALIDATION_ERROR_0fe017c6,
+                            "vkCreatePipelineLayout(): sum of input attachment bindings among all stages (%d) exceeds device "
+                            "maxDescriptorSetUpdateAfterBindInputAttachments limit (%d).",
+                            sum_all_stages_update_after_bind[VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT],
+                            dev_data->phys_dev_ext_props.descriptor_indexing_props.maxDescriptorSetUpdateAfterBindInputAttachments);
+        }
+    }
     return skip;
 }
 
@@ -6454,7 +6653,7 @@ static void PreCallRecordCmdPushDescriptorSetKHR(layer_data *device_data, GLOBAL
     const auto &pipeline_layout = getPipelineLayout(device_data, layout);
     if (!pipeline_layout) return;
     std::unique_ptr<cvdescriptorset::DescriptorSet> new_desc{
-        new cvdescriptorset::DescriptorSet(0, 0, pipeline_layout->set_layouts[set], device_data)};
+        new cvdescriptorset::DescriptorSet(0, 0, pipeline_layout->set_layouts[set], 0, device_data)};
 
     std::vector<cvdescriptorset::DescriptorSet *> descriptor_sets = {new_desc.get()};
     UpdateLastBoundDescriptorSets(device_data, cb_state, pipelineBindPoint, pipeline_layout, set, 1, descriptor_sets, 0, nullptr);
index 8497130..8cf2d0f 100644 (file)
@@ -892,6 +892,7 @@ shader_module const *GetShaderModuleState(layer_data const *dev_data, VkShaderMo
 const PHYS_DEV_PROPERTIES_NODE *GetPhysDevProperties(const layer_data *device_data);
 const VkPhysicalDeviceFeatures *GetEnabledFeatures(const layer_data *device_data);
 const DeviceExtensions *GetEnabledExtensions(const layer_data *device_data);
+const VkPhysicalDeviceDescriptorIndexingFeaturesEXT *GetEnabledDescriptorIndexingFeatures(const layer_data *device_data);
 
 void invalidateCommandBuffers(const layer_data *, std::unordered_set<GLOBAL_CB_NODE *> const &, VK_OBJECT);
 bool ValidateMemoryIsBoundToBuffer(const layer_data *, const BUFFER_STATE *, const char *, UNIQUE_VALIDATION_ERROR_CODE);
index d0a56b8..57f3034 100644 (file)
 #include "hash_vk_types.h"
 #include "vk_enum_string_helper.h"
 #include "vk_safe_struct.h"
+#include "vk_typemap_helper.h"
 #include "buffer_validation.h"
 #include <sstream>
 #include <algorithm>
 #include <memory>
 
+// ExtendedBinding collects a VkDescriptorSetLayoutBinding and any extended
+// state that comes from a different array/structure so they can stay together
+// while being sorted by binding number.
+struct ExtendedBinding {
+    ExtendedBinding(const VkDescriptorSetLayoutBinding *l, VkDescriptorBindingFlagsEXT f) : layout_binding(l), binding_flags(f) {}
+
+    const VkDescriptorSetLayoutBinding *layout_binding;
+    VkDescriptorBindingFlagsEXT binding_flags;
+};
+
 struct BindingNumCmp {
-    bool operator()(const VkDescriptorSetLayoutBinding *a, const VkDescriptorSetLayoutBinding *b) const {
-        return a->binding < b->binding;
+    bool operator()(const ExtendedBinding &a, const ExtendedBinding &b) const {
+        return a.layout_binding->binding < b.layout_binding->binding;
     }
 };
 
@@ -51,12 +62,18 @@ DescriptorSetLayoutId get_canonical_id(const VkDescriptorSetLayoutCreateInfo *p_
 // Proactively reserve and resize as possible, as the reallocation was visible in profiling
 cvdescriptorset::DescriptorSetLayoutDef::DescriptorSetLayoutDef(const VkDescriptorSetLayoutCreateInfo *p_create_info)
     : flags_(p_create_info->flags), binding_count_(0), descriptor_count_(0), dynamic_descriptor_count_(0) {
+    const auto *flags_create_info = lvl_find_in_chain<VkDescriptorSetLayoutBindingFlagsCreateInfoEXT>(p_create_info->pNext);
+
     binding_type_stats_ = {0, 0, 0};
-    std::set<const VkDescriptorSetLayoutBinding *, BindingNumCmp> sorted_bindings;
+    std::set<ExtendedBinding, BindingNumCmp> sorted_bindings;
     const uint32_t input_bindings_count = p_create_info->bindingCount;
     // Sort the input bindings in binding number order, eliminating duplicates
     for (uint32_t i = 0; i < input_bindings_count; i++) {
-        sorted_bindings.insert(p_create_info->pBindings + i);
+        VkDescriptorBindingFlagsEXT flags = 0;
+        if (flags_create_info && flags_create_info->bindingCount == p_create_info->bindingCount) {
+            flags = flags_create_info->pBindingFlags[i];
+        }
+        sorted_bindings.insert(ExtendedBinding(p_create_info->pBindings + i, flags));
     }
 
     // Store the create info in the sorted order from above
@@ -64,13 +81,15 @@ cvdescriptorset::DescriptorSetLayoutDef::DescriptorSetLayoutDef(const VkDescript
     uint32_t index = 0;
     binding_count_ = static_cast<uint32_t>(sorted_bindings.size());
     bindings_.reserve(binding_count_);
+    binding_flags_.reserve(binding_count_);
     binding_to_index_map_.reserve(binding_count_);
     for (auto input_binding : sorted_bindings) {
         // Add to binding and map, s.t. it is robust to invalid duplication of binding_num
-        const auto binding_num = input_binding->binding;
+        const auto binding_num = input_binding.layout_binding->binding;
         binding_to_index_map_[binding_num] = index++;
-        bindings_.emplace_back(input_binding);
+        bindings_.emplace_back(input_binding.layout_binding);
         auto &binding_info = bindings_.back();
+        binding_flags_.emplace_back(input_binding.binding_flags);
 
         descriptor_count_ += binding_info.descriptorCount;
         if (binding_info.descriptorCount > 0) {
@@ -90,6 +109,7 @@ cvdescriptorset::DescriptorSetLayoutDef::DescriptorSetLayoutDef(const VkDescript
         }
     }
     assert(bindings_.size() == binding_count_);
+    assert(binding_flags_.size() == binding_count_);
     uint32_t global_index = 0;
     binding_to_global_index_range_map_.reserve(binding_count_);
     // Vector order is finalized so create maps of bindings to descriptors and descriptors to indices
@@ -150,6 +170,12 @@ VkShaderStageFlags cvdescriptorset::DescriptorSetLayoutDef::GetStageFlagsFromInd
     if (index < bindings_.size()) return bindings_[index].stageFlags;
     return VkShaderStageFlags(0);
 }
+// Return binding flags for given index, 0 if index is unavailable
+VkDescriptorBindingFlagsEXT cvdescriptorset::DescriptorSetLayoutDef::GetDescriptorBindingFlagsFromIndex(
+    const uint32_t index) const {
+    if (index >= binding_flags_.size()) return 0;
+    return binding_flags_[index];
+}
 
 // For the given global index, return index
 uint32_t cvdescriptorset::DescriptorSetLayoutDef::GetIndexFromGlobalIndex(const uint32_t global_index) const {
@@ -274,9 +300,11 @@ bool cvdescriptorset::DescriptorSetLayoutDef::IsNextBindingConsistent(const uint
             auto type = bindings_[bi_itr->second].descriptorType;
             auto stage_flags = bindings_[bi_itr->second].stageFlags;
             auto immut_samp = bindings_[bi_itr->second].pImmutableSamplers ? true : false;
+            auto flags = binding_flags_[bi_itr->second];
             if ((type != bindings_[next_bi_itr->second].descriptorType) ||
                 (stage_flags != bindings_[next_bi_itr->second].stageFlags) ||
-                (immut_samp != (bindings_[next_bi_itr->second].pImmutableSamplers ? true : false))) {
+                (immut_samp != (bindings_[next_bi_itr->second].pImmutableSamplers ? true : false)) ||
+                (flags != binding_flags_[next_bi_itr->second])) {
                 return false;
             }
             return true;
@@ -328,14 +356,17 @@ cvdescriptorset::DescriptorSetLayout::DescriptorSetLayout(const VkDescriptorSetL
     : layout_(layout), layout_destroyed_(false), layout_id_(get_canonical_id(p_create_info)) {}
 
 // Validate descriptor set layout create info
-bool cvdescriptorset::DescriptorSetLayout::ValidateCreateInfo(const debug_report_data *report_data,
-                                                              const VkDescriptorSetLayoutCreateInfo *create_info,
-                                                              const bool push_descriptor_ext, const uint32_t max_push_descriptors) {
+bool cvdescriptorset::DescriptorSetLayout::ValidateCreateInfo(
+    const debug_report_data *report_data, const VkDescriptorSetLayoutCreateInfo *create_info, const bool push_descriptor_ext,
+    const uint32_t max_push_descriptors, const bool descriptor_indexing_ext,
+    const VkPhysicalDeviceDescriptorIndexingFeaturesEXT *descriptor_indexing_features) {
     bool skip = false;
     std::unordered_set<uint32_t> bindings;
     uint64_t total_descriptors = 0;
 
-    const bool push_descriptor_set = create_info->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR;
+    const auto *flags_create_info = lvl_find_in_chain<VkDescriptorSetLayoutBindingFlagsCreateInfoEXT>(create_info->pNext);
+
+    const bool push_descriptor_set = !!(create_info->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR);
     if (push_descriptor_set && !push_descriptor_ext) {
         skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
                         DRAWSTATE_EXTENSION_NOT_ENABLED,
@@ -344,13 +375,26 @@ bool cvdescriptorset::DescriptorSetLayout::ValidateCreateInfo(const debug_report
                         VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
     }
 
+    const bool update_after_bind_set = !!(create_info->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT);
+    if (update_after_bind_set && !descriptor_indexing_ext) {
+        skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                        DRAWSTATE_EXTENSION_NOT_ENABLED,
+                        "Attemped to use %s in %s but its required extension %s has not been enabled.\n",
+                        "VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT", "VkDescriptorSetLayoutCreateInfo::flags",
+                        VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
+    }
+
     auto valid_type = [push_descriptor_set](const VkDescriptorType type) {
         return !push_descriptor_set ||
                ((type != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) && (type != VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC));
     };
 
+    uint32_t max_binding = 0;
+
     for (uint32_t i = 0; i < create_info->bindingCount; ++i) {
         const auto &binding_info = create_info->pBindings[i];
+        max_binding = std::max(max_binding, binding_info.binding);
+
         if (!bindings.insert(binding_info.binding).second) {
             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
                             VALIDATION_ERROR_0500022e, "duplicated binding number in VkDescriptorSetLayoutBinding.");
@@ -364,6 +408,120 @@ bool cvdescriptorset::DescriptorSetLayout::ValidateCreateInfo(const debug_report
         total_descriptors += binding_info.descriptorCount;
     }
 
+    if (flags_create_info) {
+        if (flags_create_info->bindingCount != 0 && flags_create_info->bindingCount != create_info->bindingCount) {
+            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                            VALIDATION_ERROR_46a01774,
+                            "VkDescriptorSetLayoutCreateInfo::bindingCount (%d) != "
+                            "VkDescriptorSetLayoutBindingFlagsCreateInfoEXT::bindingCount (%d)",
+                            create_info->bindingCount, flags_create_info->bindingCount);
+        }
+
+        if (flags_create_info->bindingCount == create_info->bindingCount) {
+            for (uint32_t i = 0; i < create_info->bindingCount; ++i) {
+                const auto &binding_info = create_info->pBindings[i];
+
+                if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT) {
+                    if (!update_after_bind_set) {
+                        skip |=
+                            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                                    VALIDATION_ERROR_05001770, "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
+                    }
+
+                    if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER &&
+                        !descriptor_indexing_features->descriptorBindingUniformBufferUpdateAfterBind) {
+                        skip |=
+                            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                                    VALIDATION_ERROR_46a0177a, "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
+                    }
+                    if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
+                         binding_info.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
+                         binding_info.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) &&
+                        !descriptor_indexing_features->descriptorBindingSampledImageUpdateAfterBind) {
+                        skip |=
+                            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                                    VALIDATION_ERROR_46a0177c, "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
+                    }
+                    if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE &&
+                        !descriptor_indexing_features->descriptorBindingStorageImageUpdateAfterBind) {
+                        skip |=
+                            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                                    VALIDATION_ERROR_46a0177e, "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
+                    }
+                    if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER &&
+                        !descriptor_indexing_features->descriptorBindingStorageBufferUpdateAfterBind) {
+                        skip |=
+                            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                                    VALIDATION_ERROR_46a01780, "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
+                    }
+                    if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER &&
+                        !descriptor_indexing_features->descriptorBindingUniformTexelBufferUpdateAfterBind) {
+                        skip |=
+                            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                                    VALIDATION_ERROR_46a01782, "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
+                    }
+                    if (binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER &&
+                        !descriptor_indexing_features->descriptorBindingStorageTexelBufferUpdateAfterBind) {
+                        skip |=
+                            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                                    VALIDATION_ERROR_46a01784, "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
+                    }
+                    if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT ||
+                         binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
+                         binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
+                        skip |=
+                            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                                    VALIDATION_ERROR_46a01786, "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
+                    }
+                }
+
+                if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT) {
+                    if (!descriptor_indexing_features->descriptorBindingUpdateUnusedWhilePending) {
+                        skip |=
+                            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                                    VALIDATION_ERROR_46a01788, "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
+                    }
+                }
+
+                if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT) {
+                    if (!descriptor_indexing_features->descriptorBindingPartiallyBound) {
+                        skip |=
+                            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                                    VALIDATION_ERROR_46a0178a, "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
+                    }
+                }
+
+                if (flags_create_info->pBindingFlags[i] & VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT) {
+                    if (binding_info.binding != max_binding) {
+                        skip |=
+                            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                                    VALIDATION_ERROR_46a01778, "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
+                    }
+
+                    if (!descriptor_indexing_features->descriptorBindingVariableDescriptorCount) {
+                        skip |=
+                            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                                    VALIDATION_ERROR_46a0178c, "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
+                    }
+                    if ((binding_info.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
+                         binding_info.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
+                        skip |=
+                            log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                                    VALIDATION_ERROR_46a0178e, "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
+                    }
+                }
+
+                if (push_descriptor_set &&
+                    (flags_create_info->pBindingFlags[i] &
+                     (VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT |
+                      VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT))) {
+                    skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+                                    VALIDATION_ERROR_46a01776, "Invalid flags for VkDescriptorSetLayoutBinding entry %" PRIu32, i);
+                }
+            }
+        }
+    }
+
     if ((push_descriptor_set) && (total_descriptors > max_push_descriptors)) {
         const char *undefined = push_descriptor_ext ? "" : " -- undefined";
         skip |= log_msg(
@@ -380,13 +538,15 @@ cvdescriptorset::AllocateDescriptorSetsData::AllocateDescriptorSetsData(uint32_t
     : required_descriptors_by_type{}, layout_nodes(count, nullptr) {}
 
 cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const VkDescriptorPool pool,
-                                              const std::shared_ptr<DescriptorSetLayout const> &layout, layer_data *dev_data)
+                                              const std::shared_ptr<DescriptorSetLayout const> &layout, uint32_t variable_count,
+                                              layer_data *dev_data)
     : some_update_(false),
       set_(set),
       pool_state_(nullptr),
       p_layout_(layout),
       device_data_(dev_data),
-      limits_(GetPhysDevProperties(dev_data)->properties.limits) {
+      limits_(GetPhysDevProperties(dev_data)->properties.limits),
+      variable_count_(variable_count) {
     pool_state_ = GetDescriptorPoolState(dev_data, pool);
     // Foreach binding, create default descriptors of given type
     descriptors_.reserve(p_layout_->GetTotalDescriptorCount());
@@ -480,8 +640,18 @@ bool cvdescriptorset::DescriptorSet::ValidateDrawState(const std::map<uint32_t,
         }
         IndexRange index_range = p_layout_->GetGlobalIndexRangeFromBinding(binding);
         auto array_idx = 0;  // Track array idx if we're dealing with array descriptors
+
+        if (IsVariableDescriptorCount(binding)) {
+            // Only validate the first N descriptors if it uses variable_count
+            index_range.end = index_range.start + GetVariableDescriptorCount();
+        }
+
         for (uint32_t i = index_range.start; i < index_range.end; ++i, ++array_idx) {
-            if (!descriptors_[i]->updated) {
+            if (p_layout_->GetDescriptorBindingFlagsFromBinding(binding) & VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT) {
+                // Can't validate the descriptor because it may not have been updated,
+                // or the view could have been destroyed
+                continue;
+            } else if (!descriptors_[i]->updated) {
                 std::stringstream error_str;
                 error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i
                           << " is being used in draw but has not been updated.";
@@ -707,7 +877,10 @@ void cvdescriptorset::DescriptorSet::PerformWriteUpdate(const VkWriteDescriptorS
     }
     if (update->descriptorCount) some_update_ = true;
 
-    InvalidateBoundCmdBuffers();
+    if (!(p_layout_->GetDescriptorBindingFlagsFromBinding(update->dstBinding) &
+          (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT))) {
+        InvalidateBoundCmdBuffers();
+    }
 }
 // Validate Copy update
 bool cvdescriptorset::DescriptorSet::ValidateCopyUpdate(const debug_report_data *report_data, const VkCopyDescriptorSet *update,
@@ -734,16 +907,6 @@ bool cvdescriptorset::DescriptorSet::ValidateCopyUpdate(const debug_report_data
         return false;
     }
 
-    // Verify idle ds
-    if (in_use.load()) {
-        // TODO : Re-using Free Idle error code, need copy update idle error code
-        *error_code = VALIDATION_ERROR_2860026a;
-        std::stringstream error_str;
-        error_str << "Cannot call vkUpdateDescriptorSets() to perform copy update on descriptor set " << set_
-                  << " that is in use by a command buffer";
-        *error_msg = error_str.str();
-        return false;
-    }
     if (!p_layout_->HasBinding(update->dstBinding)) {
         *error_code = VALIDATION_ERROR_032002b6;
         std::stringstream error_str;
@@ -758,6 +921,18 @@ bool cvdescriptorset::DescriptorSet::ValidateCopyUpdate(const debug_report_data
         *error_msg = error_str.str();
         return false;
     }
+    // Verify idle ds
+    if (in_use.load() &&
+        !(p_layout_->GetDescriptorBindingFlagsFromBinding(update->dstBinding) &
+          (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT))) {
+        // TODO : Re-using Free Idle error code, need copy update idle error code
+        *error_code = VALIDATION_ERROR_2860026a;
+        std::stringstream error_str;
+        error_str << "Cannot call vkUpdateDescriptorSets() to perform copy update on descriptor set " << set_
+                  << " that is in use by a command buffer";
+        *error_msg = error_str.str();
+        return false;
+    }
     // src & dst set bindings are valid
     // Check bounds of src & dst
     auto src_start_idx = src_set->GetGlobalIndexRangeFromBinding(update->srcBinding).start + update->srcArrayElement;
@@ -805,6 +980,67 @@ bool cvdescriptorset::DescriptorSet::ValidateCopyUpdate(const debug_report_data
                                              set_, error_msg))) {
         return false;
     }
+
+    if ((src_set->GetLayout()->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT) &&
+        !(GetLayout()->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT)) {
+        *error_code = VALIDATION_ERROR_03200efc;
+        std::stringstream error_str;
+        error_str << "If pname:srcSet's (" << update->srcSet
+                  << ") layout was created with the "
+                     "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag "
+                     "set, then pname:dstSet's ("
+                  << update->dstSet
+                  << ") layout must: also have been created with the "
+                     "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag set";
+        *error_msg = error_str.str();
+        return false;
+    }
+
+    if (!(src_set->GetLayout()->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT) &&
+        (GetLayout()->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT)) {
+        *error_code = VALIDATION_ERROR_03200efe;
+        std::stringstream error_str;
+        error_str << "If pname:srcSet's (" << update->srcSet
+                  << ") layout was created without the "
+                     "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag "
+                     "set, then pname:dstSet's ("
+                  << update->dstSet
+                  << ") layout must: also have been created without the "
+                     "ename:VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag set";
+        *error_msg = error_str.str();
+        return false;
+    }
+
+    if ((src_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT) &&
+        !(GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT)) {
+        *error_code = VALIDATION_ERROR_03200f00;
+        std::stringstream error_str;
+        error_str << "If the descriptor pool from which pname:srcSet (" << update->srcSet
+                  << ") was allocated was created "
+                     "with the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag "
+                     "set, then the descriptor pool from which pname:dstSet ("
+                  << update->dstSet
+                  << ") was allocated must: "
+                     "also have been created with the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag set";
+        *error_msg = error_str.str();
+        return false;
+    }
+
+    if (!(src_set->GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT) &&
+        (GetPoolState()->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT)) {
+        *error_code = VALIDATION_ERROR_03200f02;
+        std::stringstream error_str;
+        error_str << "If the descriptor pool from which pname:srcSet (" << update->srcSet
+                  << ") was allocated was created "
+                     "without the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag "
+                     "set, then the descriptor pool from which pname:dstSet ("
+                  << update->dstSet
+                  << ") was allocated must: "
+                     "also have been created without the ename:VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag set";
+        *error_msg = error_str.str();
+        return false;
+    }
+
     // Update parameters all look good and descriptor updated so verify update contents
     if (!VerifyCopyUpdateContents(update, src_set, src_type, src_start_idx, error_code, error_msg)) return false;
 
@@ -827,7 +1063,10 @@ void cvdescriptorset::DescriptorSet::PerformCopyUpdate(const VkCopyDescriptorSet
         }
     }
 
-    InvalidateBoundCmdBuffers();
+    if (!(p_layout_->GetDescriptorBindingFlagsFromBinding(update->dstBinding) &
+          (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT))) {
+        InvalidateBoundCmdBuffers();
+    }
 }
 
 // Bind cb_node to this set and this set to cb_node.
@@ -1429,16 +1668,6 @@ bool cvdescriptorset::DescriptorSet::ValidateWriteUpdate(const debug_report_data
                        HandleToUint64(set_), HandleToUint64(p_layout_->GetDescriptorSetLayout()));
         return false;
     }
-    // Verify idle ds
-    if (in_use.load()) {
-        // TODO : Re-using Free Idle error code, need write update idle error code
-        *error_code = VALIDATION_ERROR_2860026a;
-        std::stringstream error_str;
-        error_str << "Cannot call vkUpdateDescriptorSets() to perform write update on descriptor set " << set_
-                  << " that is in use by a command buffer";
-        *error_msg = error_str.str();
-        return false;
-    }
     // Verify dst binding exists
     if (!p_layout_->HasBinding(update->dstBinding)) {
         *error_code = VALIDATION_ERROR_15c00276;
@@ -1456,6 +1685,18 @@ bool cvdescriptorset::DescriptorSet::ValidateWriteUpdate(const debug_report_data
             return false;
         }
     }
+    // Verify idle ds
+    if (in_use.load() &&
+        !(p_layout_->GetDescriptorBindingFlagsFromBinding(update->dstBinding) &
+          (VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT))) {
+        // TODO : Re-using Free Idle error code, need write update idle error code
+        *error_code = VALIDATION_ERROR_2860026a;
+        std::stringstream error_str;
+        error_str << "Cannot call vkUpdateDescriptorSets() to perform write update on descriptor set " << set_
+                  << " that is in use by a command buffer";
+        *error_msg = error_str.str();
+        return false;
+    }
     // We know that binding is valid, verify update and do update on each descriptor
     auto start_idx = p_layout_->GetGlobalIndexRangeFromBinding(update->dstBinding).start + update->dstArrayElement;
     auto type = p_layout_->GetTypeFromBinding(update->dstBinding);
@@ -1865,6 +2106,7 @@ bool cvdescriptorset::ValidateAllocateDescriptorSets(const core_validation::laye
                                                      const AllocateDescriptorSetsData *ds_data) {
     bool skip = false;
     auto report_data = core_validation::GetReportData(dev_data);
+    auto pool_state = GetDescriptorPoolState(dev_data, p_alloc_info->descriptorPool);
 
     for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
         auto layout = GetDescriptorSetLayout(dev_data, p_alloc_info->pSetLayouts[i]);
@@ -1877,10 +2119,15 @@ bool cvdescriptorset::ValidateAllocateDescriptorSets(const core_validation::laye
                                 HandleToUint64(p_alloc_info->pSetLayouts[i]), i,
                                 "VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR");
             }
+            if (layout->GetCreateFlags() & VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT &&
+                !(pool_state->createInfo.flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT)) {
+                skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT,
+                                0, VALIDATION_ERROR_04c017c8,
+                                "Descriptor set layout create flags and pool create flags mismatch for index (%d)", i);
+            }
         }
     }
     if (!GetDeviceExtensions(dev_data)->vk_khr_maintenance1) {
-        auto pool_state = GetDescriptorPoolState(dev_data, p_alloc_info->descriptorPool);
         // Track number of descriptorSets allowable in this pool
         if (pool_state->availableSets < p_alloc_info->descriptorSetCount) {
             skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
@@ -1902,6 +2149,30 @@ bool cvdescriptorset::ValidateAllocateDescriptorSets(const core_validation::laye
         }
     }
 
+    const auto *count_allocate_info = lvl_find_in_chain<VkDescriptorSetVariableDescriptorCountAllocateInfoEXT>(p_alloc_info->pNext);
+
+    if (count_allocate_info) {
+        if (count_allocate_info->descriptorSetCount != 0 &&
+            count_allocate_info->descriptorSetCount != p_alloc_info->descriptorSetCount) {
+            skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, 0,
+                            VALIDATION_ERROR_46c017ca,
+                            "VkDescriptorSetAllocateInfo::descriptorSetCount (%d) != "
+                            "VkDescriptorSetVariableDescriptorCountAllocateInfoEXT::descriptorSetCount (%d)",
+                            p_alloc_info->descriptorSetCount, count_allocate_info->descriptorSetCount);
+        }
+        if (count_allocate_info->descriptorSetCount == p_alloc_info->descriptorSetCount) {
+            for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
+                auto layout = GetDescriptorSetLayout(dev_data, p_alloc_info->pSetLayouts[i]);
+                if (count_allocate_info->pDescriptorCounts[i] > layout->GetDescriptorCountFromBinding(layout->GetMaxBinding())) {
+                    skip |= log_msg(
+                        report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, 0,
+                        VALIDATION_ERROR_46c017cc, "pDescriptorCounts[%d] = (%d), binding's descriptorCount = (%d)", i,
+                        count_allocate_info->pDescriptorCounts[i], layout->GetDescriptorCountFromBinding(layout->GetMaxBinding()));
+                }
+            }
+        }
+    }
+
     return skip;
 }
 // Decrement allocated sets from the pool and insert new sets into set_map
@@ -1917,10 +2188,16 @@ void cvdescriptorset::PerformAllocateDescriptorSets(const VkDescriptorSetAllocat
     for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) {
         pool_state->availableDescriptorTypeCount[i] -= ds_data->required_descriptors_by_type[i];
     }
+
+    const auto *variable_count_info = lvl_find_in_chain<VkDescriptorSetVariableDescriptorCountAllocateInfoEXT>(p_alloc_info->pNext);
+    bool variable_count_valid = variable_count_info && variable_count_info->descriptorSetCount == p_alloc_info->descriptorSetCount;
+
     // Create tracking object for each descriptor set; insert into global map and the pool's set.
     for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
+        uint32_t variable_count = variable_count_valid ? variable_count_info->pDescriptorCounts[i] : 0;
+
         auto new_ds = new cvdescriptorset::DescriptorSet(descriptor_sets[i], p_alloc_info->descriptorPool, ds_data->layout_nodes[i],
-                                                         dev_data);
+                                                         variable_count, dev_data);
 
         pool_state->sets.insert(new_ds);
         new_ds->in_use.store(0);
index 133657a..8e90b0d 100644 (file)
@@ -127,6 +127,10 @@ class DescriptorSetLayoutDef {
     VkShaderStageFlags GetStageFlagsFromBinding(const uint32_t binding) const {
         return GetStageFlagsFromIndex(GetIndexFromBinding(binding));
     }
+    VkDescriptorBindingFlagsEXT GetDescriptorBindingFlagsFromIndex(const uint32_t) const;
+    VkDescriptorBindingFlagsEXT GetDescriptorBindingFlagsFromBinding(const uint32_t binding) const {
+        return GetDescriptorBindingFlagsFromIndex(GetIndexFromBinding(binding));
+    }
     uint32_t GetIndexFromGlobalIndex(const uint32_t global_index) const;
     VkDescriptorType GetTypeFromGlobalIndex(const uint32_t global_index) const {
         return GetTypeFromIndex(GetIndexFromGlobalIndex(global_index));
@@ -165,6 +169,7 @@ class DescriptorSetLayoutDef {
     // to speed up the various lookups/queries/validations
     VkDescriptorSetLayoutCreateFlags flags_;
     std::vector<safe_VkDescriptorSetLayoutBinding> bindings_;
+    std::vector<VkDescriptorBindingFlagsEXT> binding_flags_;
 
     // Convenience data structures for rapid lookup of various descriptor set layout properties
     std::set<uint32_t> non_empty_bindings_;  // Containing non-emtpy bindings in numerical order
@@ -175,7 +180,7 @@ class DescriptorSetLayoutDef {
     // For a given binding map to associated index in the dynamic offset array
     std::unordered_map<uint32_t, uint32_t> binding_to_dynamic_array_idx_map_;
 
-    uint32_t binding_count_;  // # of bindings in this layout
+    uint32_t binding_count_;     // # of bindings in this layout
     uint32_t descriptor_count_;  // total # descriptors in this layout
     uint32_t dynamic_descriptor_count_;
     BindingTypeStats binding_type_stats_;
@@ -194,7 +199,8 @@ class DescriptorSetLayout {
     // Constructors and destructor
     DescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo *p_create_info, const VkDescriptorSetLayout layout);
     // Validate create info - should be called prior to creation
-    static bool ValidateCreateInfo(const debug_report_data *, const VkDescriptorSetLayoutCreateInfo *, const bool, const uint32_t);
+    static bool ValidateCreateInfo(const debug_report_data *, const VkDescriptorSetLayoutCreateInfo *, const bool, const uint32_t,
+                                   const bool, const VkPhysicalDeviceDescriptorIndexingFeaturesEXT *descriptor_indexing_features);
     bool HasBinding(const uint32_t binding) const { return layout_id_->HasBinding(binding); }
     // Return true if this layout is compatible with passed in layout from a pipelineLayout,
     //   else return false and update error_msg with description of incompatibility
@@ -231,6 +237,12 @@ class DescriptorSetLayout {
     VkShaderStageFlags GetStageFlagsFromBinding(const uint32_t binding) const {
         return layout_id_->GetStageFlagsFromBinding(binding);
     }
+    VkDescriptorBindingFlagsEXT GetDescriptorBindingFlagsFromIndex(const uint32_t index) const {
+        return layout_id_->GetDescriptorBindingFlagsFromIndex(index);
+    }
+    VkDescriptorBindingFlagsEXT GetDescriptorBindingFlagsFromBinding(const uint32_t binding) const {
+        return layout_id_->GetDescriptorBindingFlagsFromBinding(binding);
+    }
     uint32_t GetIndexFromGlobalIndex(const uint32_t global_index) const {
         return layout_id_->GetIndexFromGlobalIndex(global_index);
     }
@@ -435,7 +447,7 @@ void PerformAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *, const Vk
 class DescriptorSet : public BASE_NODE {
    public:
     DescriptorSet(const VkDescriptorSet, const VkDescriptorPool, const std::shared_ptr<DescriptorSetLayout const> &,
-                  core_validation::layer_data *);
+                  uint32_t variable_count, core_validation::layer_data *);
     ~DescriptorSet();
     // A number of common Get* functions that return data based on layout from which this set was created
     uint32_t GetTotalDescriptorCount() const { return p_layout_->GetTotalDescriptorCount(); };
@@ -509,6 +521,12 @@ class DescriptorSet : public BASE_NODE {
     // Return true if any part of set has ever been updated
     bool IsUpdated() const { return some_update_; };
     bool IsPushDescriptor() const { return p_layout_->IsPushDescriptor(); };
+    bool IsVariableDescriptorCount(uint32_t binding) const {
+        return !!(p_layout_->GetDescriptorBindingFlagsFromBinding(binding) &
+                  VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT);
+    }
+    uint32_t GetVariableDescriptorCount() const { return variable_count_; }
+    DESCRIPTOR_POOL_STATE *GetPoolState() const { return pool_state_; }
 
    private:
     bool VerifyWriteUpdateContents(const VkWriteDescriptorSet *, const uint32_t, UNIQUE_VALIDATION_ERROR_CODE *,
@@ -528,6 +546,7 @@ class DescriptorSet : public BASE_NODE {
     // Ptr to device data used for various data look-ups
     core_validation::layer_data *const device_data_;
     const VkPhysicalDeviceLimits limits_;
+    uint32_t variable_count_;
 
     // Cached binding and validation support:
     //
index 368c3d2..2943044 100644 (file)
@@ -1086,8 +1086,11 @@ static bool descriptor_type_match(shader_module const *module, uint32_t type_id,
     descriptor_count = 1;
 
     // Strip off any array or ptrs. Where we remove array levels, adjust the  descriptor count for each dimension.
-    while (type.opcode() == spv::OpTypeArray || type.opcode() == spv::OpTypePointer) {
-        if (type.opcode() == spv::OpTypeArray) {
+    while (type.opcode() == spv::OpTypeArray || type.opcode() == spv::OpTypePointer || type.opcode() == spv::OpTypeRuntimeArray) {
+        if (type.opcode() == spv::OpTypeRuntimeArray) {
+            descriptor_count = 0;
+            type = module->get_def(type.word(2));
+        } else if (type.opcode() == spv::OpTypeArray) {
             descriptor_count *= get_constant_value(module, type.word(3));
             type = module->get_def(type.word(2));
         } else {
@@ -1166,8 +1169,7 @@ static bool descriptor_type_match(shader_module const *module, uint32_t type_id,
 static bool require_feature(debug_report_data const *report_data, VkBool32 feature, char const *feature_name) {
     if (!feature) {
         if (log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
-                    SHADER_CHECKER_FEATURE_NOT_ENABLED,
-                    "Shader requires VkPhysicalDeviceFeatures::%s but is not enabled on the device", feature_name)) {
+                    SHADER_CHECKER_FEATURE_NOT_ENABLED, "Shader requires %s but is not enabled on the device", feature_name)) {
             return true;
         }
     }
@@ -1194,16 +1196,14 @@ static bool validate_shader_capabilities(layer_data *dev_data, shader_module con
     auto report_data = GetReportData(dev_data);
     auto const &enabledFeatures = GetEnabledFeatures(dev_data);
     auto const &extensions = GetEnabledExtensions(dev_data);
+    auto const &descriptorIndexingFeatures = GetEnabledDescriptorIndexingFeatures(dev_data);
 
     struct CapabilityInfo {
         char const *name;
-        VkBool32 const VkPhysicalDeviceFeatures::*feature;
-        bool const DeviceExtensions::*extension;
+        VkBool32 const *feature;
+        bool const *extension;
     };
 
-    using F = VkPhysicalDeviceFeatures;
-    using E = DeviceExtensions;
-
     // clang-format off
     static const std::unordered_multimap<uint32_t, CapabilityInfo> capabilities = {
         // Capabilities always supported by a Vulkan 1.0 implementation -- no
@@ -1219,41 +1219,67 @@ static bool validate_shader_capabilities(layer_data *dev_data, shader_module con
 
         // Capabilities that are optionally supported, but require a feature to
         // be enabled on the device
-        {spv::CapabilityGeometry, {"geometryShader", &F::geometryShader}},
-        {spv::CapabilityTessellation, {"tessellationShader", &F::tessellationShader}},
-        {spv::CapabilityFloat64, {"shaderFloat64", &F::shaderFloat64}},
-        {spv::CapabilityInt64, {"shaderInt64", &F::shaderInt64}},
-        {spv::CapabilityTessellationPointSize, {"shaderTessellationAndGeometryPointSize", &F::shaderTessellationAndGeometryPointSize}},
-        {spv::CapabilityGeometryPointSize, {"shaderTessellationAndGeometryPointSize", &F::shaderTessellationAndGeometryPointSize}},
-        {spv::CapabilityImageGatherExtended, {"shaderImageGatherExtended", &F::shaderImageGatherExtended}},
-        {spv::CapabilityStorageImageMultisample, {"shaderStorageImageMultisample", &F::shaderStorageImageMultisample}},
-        {spv::CapabilityUniformBufferArrayDynamicIndexing, {"shaderUniformBufferArrayDynamicIndexing", &F::shaderUniformBufferArrayDynamicIndexing}},
-        {spv::CapabilitySampledImageArrayDynamicIndexing, {"shaderSampledImageArrayDynamicIndexing", &F::shaderSampledImageArrayDynamicIndexing}},
-        {spv::CapabilityStorageBufferArrayDynamicIndexing, {"shaderStorageBufferArrayDynamicIndexing", &F::shaderStorageBufferArrayDynamicIndexing}},
-        {spv::CapabilityStorageImageArrayDynamicIndexing, {"shaderStorageImageArrayDynamicIndexing", &F::shaderStorageBufferArrayDynamicIndexing}},
-        {spv::CapabilityClipDistance, {"shaderClipDistance", &F::shaderClipDistance}},
-        {spv::CapabilityCullDistance, {"shaderCullDistance", &F::shaderCullDistance}},
-        {spv::CapabilityImageCubeArray, {"imageCubeArray", &F::imageCubeArray}},
-        {spv::CapabilitySampleRateShading, {"sampleRateShading", &F::sampleRateShading}},
-        {spv::CapabilitySparseResidency, {"shaderResourceResidency", &F::shaderResourceResidency}},
-        {spv::CapabilityMinLod, {"shaderResourceMinLod", &F::shaderResourceMinLod}},
-        {spv::CapabilitySampledCubeArray, {"imageCubeArray", &F::imageCubeArray}},
-        {spv::CapabilityImageMSArray, {"shaderStorageImageMultisample", &F::shaderStorageImageMultisample}},
-        {spv::CapabilityStorageImageExtendedFormats, {"shaderStorageImageExtendedFormats", &F::shaderStorageImageExtendedFormats}},
-        {spv::CapabilityInterpolationFunction, {"sampleRateShading", &F::sampleRateShading}},
-        {spv::CapabilityStorageImageReadWithoutFormat, {"shaderStorageImageReadWithoutFormat", &F::shaderStorageImageReadWithoutFormat}},
-        {spv::CapabilityStorageImageWriteWithoutFormat, {"shaderStorageImageWriteWithoutFormat", &F::shaderStorageImageWriteWithoutFormat}},
-        {spv::CapabilityMultiViewport, {"multiViewport", &F::multiViewport}},
+        {spv::CapabilityGeometry, {"VkPhysicalDeviceFeatures::geometryShader", &enabledFeatures->geometryShader}},
+        {spv::CapabilityTessellation, {"VkPhysicalDeviceFeatures::tessellationShader", &enabledFeatures->tessellationShader}},
+        {spv::CapabilityFloat64, {"VkPhysicalDeviceFeatures::shaderFloat64", &enabledFeatures->shaderFloat64}},
+        {spv::CapabilityInt64, {"VkPhysicalDeviceFeatures::shaderInt64", &enabledFeatures->shaderInt64}},
+        {spv::CapabilityTessellationPointSize, {"VkPhysicalDeviceFeatures::shaderTessellationAndGeometryPointSize", &enabledFeatures->shaderTessellationAndGeometryPointSize}},
+        {spv::CapabilityGeometryPointSize, {"VkPhysicalDeviceFeatures::shaderTessellationAndGeometryPointSize", &enabledFeatures->shaderTessellationAndGeometryPointSize}},
+        {spv::CapabilityImageGatherExtended, {"VkPhysicalDeviceFeatures::shaderImageGatherExtended", &enabledFeatures->shaderImageGatherExtended}},
+        {spv::CapabilityStorageImageMultisample, {"VkPhysicalDeviceFeatures::shaderStorageImageMultisample", &enabledFeatures->shaderStorageImageMultisample}},
+        {spv::CapabilityUniformBufferArrayDynamicIndexing, {"VkPhysicalDeviceFeatures::shaderUniformBufferArrayDynamicIndexing", &enabledFeatures->shaderUniformBufferArrayDynamicIndexing}},
+        {spv::CapabilitySampledImageArrayDynamicIndexing, {"VkPhysicalDeviceFeatures::shaderSampledImageArrayDynamicIndexing", &enabledFeatures->shaderSampledImageArrayDynamicIndexing}},
+        {spv::CapabilityStorageBufferArrayDynamicIndexing, {"VkPhysicalDeviceFeatures::shaderStorageBufferArrayDynamicIndexing", &enabledFeatures->shaderStorageBufferArrayDynamicIndexing}},
+        {spv::CapabilityStorageImageArrayDynamicIndexing, {"VkPhysicalDeviceFeatures::shaderStorageImageArrayDynamicIndexing", &enabledFeatures->shaderStorageBufferArrayDynamicIndexing}},
+        {spv::CapabilityClipDistance, {"VkPhysicalDeviceFeatures::shaderClipDistance", &enabledFeatures->shaderClipDistance}},
+        {spv::CapabilityCullDistance, {"VkPhysicalDeviceFeatures::shaderCullDistance", &enabledFeatures->shaderCullDistance}},
+        {spv::CapabilityImageCubeArray, {"VkPhysicalDeviceFeatures::imageCubeArray", &enabledFeatures->imageCubeArray}},
+        {spv::CapabilitySampleRateShading, {"VkPhysicalDeviceFeatures::sampleRateShading", &enabledFeatures->sampleRateShading}},
+        {spv::CapabilitySparseResidency, {"VkPhysicalDeviceFeatures::shaderResourceResidency", &enabledFeatures->shaderResourceResidency}},
+        {spv::CapabilityMinLod, {"VkPhysicalDeviceFeatures::shaderResourceMinLod", &enabledFeatures->shaderResourceMinLod}},
+        {spv::CapabilitySampledCubeArray, {"VkPhysicalDeviceFeatures::imageCubeArray", &enabledFeatures->imageCubeArray}},
+        {spv::CapabilityImageMSArray, {"VkPhysicalDeviceFeatures::shaderStorageImageMultisample", &enabledFeatures->shaderStorageImageMultisample}},
+        {spv::CapabilityStorageImageExtendedFormats, {"VkPhysicalDeviceFeatures::shaderStorageImageExtendedFormats", &enabledFeatures->shaderStorageImageExtendedFormats}},
+        {spv::CapabilityInterpolationFunction, {"VkPhysicalDeviceFeatures::sampleRateShading", &enabledFeatures->sampleRateShading}},
+        {spv::CapabilityStorageImageReadWithoutFormat, {"VkPhysicalDeviceFeatures::shaderStorageImageReadWithoutFormat", &enabledFeatures->shaderStorageImageReadWithoutFormat}},
+        {spv::CapabilityStorageImageWriteWithoutFormat, {"VkPhysicalDeviceFeatures::shaderStorageImageWriteWithoutFormat", &enabledFeatures->shaderStorageImageWriteWithoutFormat}},
+        {spv::CapabilityMultiViewport, {"VkPhysicalDeviceFeatures::multiViewport", &enabledFeatures->multiViewport}},
+
+        // XXX TODO: Descriptor indexing capability enums are not yet available in the spirv-tools we fetch.
+#define CapabilityShaderNonUniformEXT 5301
+#define CapabilityRuntimeDescriptorArrayEXT 5302
+#define CapabilityInputAttachmentArrayDynamicIndexingEXT 5303
+#define CapabilityUniformTexelBufferArrayDynamicIndexingEXT 5304
+#define CapabilityStorageTexelBufferArrayDynamicIndexingEXT 5305
+#define CapabilityUniformBufferArrayNonUniformIndexingEXT 5306
+#define CapabilitySampledImageArrayNonUniformIndexingEXT 5307
+#define CapabilityStorageBufferArrayNonUniformIndexingEXT 5308
+#define CapabilityStorageImageArrayNonUniformIndexingEXT 5309
+#define CapabilityInputAttachmentArrayNonUniformIndexingEXT 5310
+#define CapabilityUniformTexelBufferArrayNonUniformIndexingEXT 5311
+#define CapabilityStorageTexelBufferArrayNonUniformIndexingEXT 5312
+        {CapabilityShaderNonUniformEXT, {VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME, nullptr, &extensions->vk_ext_descriptor_indexing}},
+        {CapabilityRuntimeDescriptorArrayEXT, {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::runtimeDescriptorArray", &descriptorIndexingFeatures->runtimeDescriptorArray}},
+        {CapabilityInputAttachmentArrayDynamicIndexingEXT, {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderInputAttachmentArrayDynamicIndexing", &descriptorIndexingFeatures->shaderInputAttachmentArrayDynamicIndexing}},
+        {CapabilityUniformTexelBufferArrayDynamicIndexingEXT, {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderUniformTexelBufferArrayDynamicIndexing", &descriptorIndexingFeatures->shaderUniformTexelBufferArrayDynamicIndexing}},
+        {CapabilityStorageTexelBufferArrayDynamicIndexingEXT, {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderStorageTexelBufferArrayDynamicIndexing", &descriptorIndexingFeatures->shaderStorageTexelBufferArrayDynamicIndexing}},
+        {CapabilityUniformBufferArrayNonUniformIndexingEXT, {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderUniformBufferArrayNonUniformIndexing", &descriptorIndexingFeatures->shaderUniformBufferArrayNonUniformIndexing}},
+        {CapabilitySampledImageArrayNonUniformIndexingEXT, {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderSampledImageArrayNonUniformIndexing", &descriptorIndexingFeatures->shaderSampledImageArrayNonUniformIndexing}},
+        {CapabilityStorageBufferArrayNonUniformIndexingEXT, {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderStorageBufferArrayNonUniformIndexing", &descriptorIndexingFeatures->shaderStorageBufferArrayNonUniformIndexing}},
+        {CapabilityStorageImageArrayNonUniformIndexingEXT, {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderStorageImageArrayNonUniformIndexing", &descriptorIndexingFeatures->shaderStorageImageArrayNonUniformIndexing}},
+        {CapabilityInputAttachmentArrayNonUniformIndexingEXT, {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderInputAttachmentArrayNonUniformIndexing", &descriptorIndexingFeatures->shaderInputAttachmentArrayNonUniformIndexing}},
+        {CapabilityUniformTexelBufferArrayNonUniformIndexingEXT, {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderUniformTexelBufferArrayNonUniformIndexing", &descriptorIndexingFeatures->shaderUniformTexelBufferArrayNonUniformIndexing}},
+        {CapabilityStorageTexelBufferArrayNonUniformIndexingEXT , {"VkPhysicalDeviceDescriptorIndexingFeaturesEXT::shaderStorageTexelBufferArrayNonUniformIndexing", &descriptorIndexingFeatures->shaderStorageTexelBufferArrayNonUniformIndexing}},
 
         // Capabilities that require an extension
-        {spv::CapabilityDrawParameters, {VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, nullptr, &E::vk_khr_shader_draw_parameters}},
-        {spv::CapabilityGeometryShaderPassthroughNV, {VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME, nullptr, &E::vk_nv_geometry_shader_passthrough}},
-        {spv::CapabilitySampleMaskOverrideCoverageNV, {VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME, nullptr, &E::vk_nv_sample_mask_override_coverage}},
-        {spv::CapabilityShaderViewportIndexLayerEXT, {VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME, nullptr, &E::vk_ext_shader_viewport_index_layer}},
-        {spv::CapabilityShaderViewportIndexLayerNV, {VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME, nullptr, &E::vk_nv_viewport_array2}},
-        {spv::CapabilityShaderViewportMaskNV, {VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME, nullptr, &E::vk_nv_viewport_array2}},
-        {spv::CapabilitySubgroupBallotKHR, {VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME, nullptr, &E::vk_ext_shader_subgroup_ballot }},
-        {spv::CapabilitySubgroupVoteKHR, {VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME, nullptr, &E::vk_ext_shader_subgroup_vote }},
+        {spv::CapabilityDrawParameters, {VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, nullptr, &extensions->vk_khr_shader_draw_parameters}},
+        {spv::CapabilityGeometryShaderPassthroughNV, {VK_NV_GEOMETRY_SHADER_PASSTHROUGH_EXTENSION_NAME, nullptr, &extensions->vk_nv_geometry_shader_passthrough}},
+        {spv::CapabilitySampleMaskOverrideCoverageNV, {VK_NV_SAMPLE_MASK_OVERRIDE_COVERAGE_EXTENSION_NAME, nullptr, &extensions->vk_nv_sample_mask_override_coverage}},
+        {spv::CapabilityShaderViewportIndexLayerEXT, {VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME, nullptr, &extensions->vk_ext_shader_viewport_index_layer}},
+        {spv::CapabilityShaderViewportIndexLayerNV, {VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME, nullptr, &extensions->vk_nv_viewport_array2}},
+        {spv::CapabilityShaderViewportMaskNV, {VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME, nullptr, &extensions->vk_nv_viewport_array2}},
+        {spv::CapabilitySubgroupBallotKHR, {VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME, nullptr, &extensions->vk_ext_shader_subgroup_ballot }},
+        {spv::CapabilitySubgroupVoteKHR, {VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME, nullptr, &extensions->vk_ext_shader_subgroup_vote }},
     };
     // clang-format on
 
@@ -1264,10 +1290,10 @@ static bool validate_shader_capabilities(layer_data *dev_data, shader_module con
                 auto it = capabilities.find(insn.word(1));
                 if (it != capabilities.end()) {
                     if (it->second.feature) {
-                        skip |= require_feature(report_data, enabledFeatures->*(it->second.feature), it->second.name);
+                        skip |= require_feature(report_data, *(it->second.feature), it->second.name);
                     }
                     if (it->second.extension) {
-                        skip |= require_extension(report_data, extensions->*(it->second.extension), it->second.name);
+                        skip |= require_extension(report_data, *(it->second.extension), it->second.name);
                     }
                 }
             } else if (1 < n) {  // key occurs multiple times, at least one must be enabled
@@ -1279,13 +1305,13 @@ static bool validate_shader_capabilities(layer_data *dev_data, shader_module con
                 for (auto it = caps.first; it != caps.second; ++it) {
                     if (it->second.feature) {
                         needs_feature = true;
-                        has_feature = has_feature || enabledFeatures->*(it->second.feature);
+                        has_feature = has_feature || *(it->second.feature);
                         feature_names += it->second.name;
                         feature_names += " ";
                     }
                     if (it->second.extension) {
                         needs_ext = true;
-                        has_ext = has_ext || extensions->*(it->second.extension);
+                        has_ext = has_ext || *(it->second.extension);
                         extension_names += it->second.name;
                         extension_names += " ";
                     }
index 4fe0e08..ccb2ee0 100644 (file)
@@ -270,10 +270,10 @@ VALIDATION_ERROR_032002b4~^~Y~^~Unknown~^~VkCopyDescriptorSet~^~VUID-VkCopyDescr
 VALIDATION_ERROR_032002b6~^~Y~^~Unknown~^~VkCopyDescriptorSet~^~VUID-VkCopyDescriptorSet-dstBinding-00347~^~core~^~The spec valid usage text states 'dstBinding must be a valid binding within dstSet' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkCopyDescriptorSet-dstBinding-00347)~^~
 VALIDATION_ERROR_032002b8~^~Y~^~Unknown~^~VkCopyDescriptorSet~^~VUID-VkCopyDescriptorSet-dstArrayElement-00348~^~core~^~The spec valid usage text states 'The sum of dstArrayElement and descriptorCount must be less than or equal to the number of array elements in the descriptor set binding specified by dstBinding, and all applicable consecutive bindings, as described by descriptorsets-updates-consecutive' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkCopyDescriptorSet-dstArrayElement-00348)~^~
 VALIDATION_ERROR_032002ba~^~Y~^~Unknown~^~VkCopyDescriptorSet~^~VUID-VkCopyDescriptorSet-srcSet-00349~^~core~^~The spec valid usage text states 'If srcSet is equal to dstSet, then the source and destination ranges of descriptors must not overlap, where the ranges may include array elements from consecutive bindings as described by descriptorsets-updates-consecutive' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkCopyDescriptorSet-srcSet-00349)~^~
-VALIDATION_ERROR_03200efc~^~N~^~None~^~VkCopyDescriptorSet~^~VUID-VkCopyDescriptorSet-srcSet-01918~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If srcSet's layout was created with the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag set, then dstSet's layout must also have been created with the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkCopyDescriptorSet-srcSet-01918)~^~
-VALIDATION_ERROR_03200efe~^~N~^~None~^~VkCopyDescriptorSet~^~VUID-VkCopyDescriptorSet-srcSet-01919~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If srcSet's layout was created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag set, then dstSet's layout must also have been created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkCopyDescriptorSet-srcSet-01919)~^~
-VALIDATION_ERROR_03200f00~^~N~^~None~^~VkCopyDescriptorSet~^~VUID-VkCopyDescriptorSet-srcSet-01920~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If the descriptor pool from which srcSet was allocated was created with the VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag set, then the descriptor pool from which dstSet was allocated must also have been created with the VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkCopyDescriptorSet-srcSet-01920)~^~
-VALIDATION_ERROR_03200f02~^~N~^~None~^~VkCopyDescriptorSet~^~VUID-VkCopyDescriptorSet-srcSet-01921~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If the descriptor pool from which srcSet was allocated was created without the VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag set, then the descriptor pool from which dstSet was allocated must also have been created without the VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkCopyDescriptorSet-srcSet-01921)~^~
+VALIDATION_ERROR_03200efc~^~Y~^~None~^~VkCopyDescriptorSet~^~VUID-VkCopyDescriptorSet-srcSet-01918~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If srcSet's layout was created with the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag set, then dstSet's layout must also have been created with the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkCopyDescriptorSet-srcSet-01918)~^~
+VALIDATION_ERROR_03200efe~^~Y~^~None~^~VkCopyDescriptorSet~^~VUID-VkCopyDescriptorSet-srcSet-01919~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If srcSet's layout was created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag set, then dstSet's layout must also have been created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT flag set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkCopyDescriptorSet-srcSet-01919)~^~
+VALIDATION_ERROR_03200f00~^~Y~^~None~^~VkCopyDescriptorSet~^~VUID-VkCopyDescriptorSet-srcSet-01920~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If the descriptor pool from which srcSet was allocated was created with the VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag set, then the descriptor pool from which dstSet was allocated must also have been created with the VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkCopyDescriptorSet-srcSet-01920)~^~
+VALIDATION_ERROR_03200f02~^~Y~^~None~^~VkCopyDescriptorSet~^~VUID-VkCopyDescriptorSet-srcSet-01921~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If the descriptor pool from which srcSet was allocated was created without the VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag set, then the descriptor pool from which dstSet was allocated must also have been created without the VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkCopyDescriptorSet-srcSet-01921)~^~
 VALIDATION_ERROR_03207601~^~Y~^~UpdateDestroyDescriptorSetLayout~^~VkCopyDescriptorSet~^~VUID-VkCopyDescriptorSet-dstSet-parameter~^~core~^~The spec valid usage text states 'dstSet must be a valid VkDescriptorSet handle' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkCopyDescriptorSet-dstSet-parameter)~^~implicit
 VALIDATION_ERROR_0321c40d~^~Y~^~Unknown~^~VkCopyDescriptorSet~^~VUID-VkCopyDescriptorSet-pNext-pNext~^~core~^~The spec valid usage text states 'pNext must be NULL' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkCopyDescriptorSet-pNext-pNext)~^~implicit, TBD in parameter validation layer.
 VALIDATION_ERROR_0322b00b~^~N~^~Unknown~^~VkCopyDescriptorSet~^~VUID-VkCopyDescriptorSet-sType-sType~^~core~^~The spec valid usage text states 'sType must be VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkCopyDescriptorSet-sType-sType)~^~implicit, TBD in parameter validation layer.
@@ -339,7 +339,7 @@ VALIDATION_ERROR_04c00009~^~Y~^~Unknown~^~VkDescriptorSetAllocateInfo~^~VUID-VkD
 VALIDATION_ERROR_04c00264~^~Y~^~AllocDescriptorFromEmptyPool~^~VkDescriptorSetAllocateInfo~^~VUID-VkDescriptorSetAllocateInfo-descriptorSetCount-00306~^~!(VK_VERSION_1_1,VK_KHR_maintenance1)~^~The spec valid usage text states 'descriptorSetCount must not be greater than the number of sets that are currently available for allocation in descriptorPool' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkDescriptorSetAllocateInfo-descriptorSetCount-00306)~^~
 VALIDATION_ERROR_04c00266~^~Y~^~AllocDescriptorFromEmptyPool~^~VkDescriptorSetAllocateInfo~^~VUID-VkDescriptorSetAllocateInfo-descriptorPool-00307~^~!(VK_VERSION_1_1,VK_KHR_maintenance1)~^~The spec valid usage text states 'descriptorPool must have enough free descriptor capacity remaining to allocate the descriptor sets of the specified layouts' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkDescriptorSetAllocateInfo-descriptorPool-00307)~^~
 VALIDATION_ERROR_04c00268~^~Y~^~AllocatePushDescriptorSet~^~VkDescriptorSetAllocateInfo~^~VUID-VkDescriptorSetAllocateInfo-pSetLayouts-00308~^~(VK_KHR_push_descriptor)~^~The spec valid usage text states 'Each element of pSetLayouts must not have been created with VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetAllocateInfo-pSetLayouts-00308)~^~
-VALIDATION_ERROR_04c017c8~^~N~^~None~^~VkDescriptorSetAllocateInfo~^~VUID-VkDescriptorSetAllocateInfo-pSetLayouts-03044~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If any element of pSetLayouts was created with the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT bit set, descriptorPool must have been created with the VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetAllocateInfo-pSetLayouts-03044)~^~
+VALIDATION_ERROR_04c017c8~^~Y~^~DescriptorIndexingSetLayout~^~VkDescriptorSetAllocateInfo~^~VUID-VkDescriptorSetAllocateInfo-pSetLayouts-03044~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If any element of pSetLayouts was created with the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT bit set, descriptorPool must have been created with the VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT flag set' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetAllocateInfo-pSetLayouts-03044)~^~
 VALIDATION_ERROR_04c04601~^~Y~^~None~^~VkDescriptorSetAllocateInfo~^~VUID-VkDescriptorSetAllocateInfo-descriptorPool-parameter~^~core~^~The spec valid usage text states 'descriptorPool must be a valid VkDescriptorPool handle' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkDescriptorSetAllocateInfo-descriptorPool-parameter)~^~implicit
 VALIDATION_ERROR_04c04a1b~^~N~^~Unknown~^~VkDescriptorSetAllocateInfo~^~VUID-VkDescriptorSetAllocateInfo-descriptorSetCount-arraylength~^~core~^~The spec valid usage text states 'descriptorSetCount must be greater than 0' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkDescriptorSetAllocateInfo-descriptorSetCount-arraylength)~^~implicit
 VALIDATION_ERROR_04c1c40d~^~Y~^~Unknown~^~VkDescriptorSetAllocateInfo~^~VUID-VkDescriptorSetAllocateInfo-pNext-pNext~^~core~^~The spec valid usage text states 'pNext must be NULL or a pointer to a valid instance of VkDescriptorSetVariableDescriptorCountAllocateInfoEXT' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkDescriptorSetAllocateInfo-pNext-pNext)~^~implicit, TBD in parameter validation layer.
@@ -352,7 +352,7 @@ VALIDATION_ERROR_04e04e01~^~Y~^~Unknown~^~VkDescriptorSetLayoutBinding~^~VUID-Vk
 VALIDATION_ERROR_0500022e~^~Y~^~DuplicateDescriptorBinding~^~VkDescriptorSetLayoutCreateInfo~^~VUID-VkDescriptorSetLayoutCreateInfo-binding-00279~^~core~^~The spec valid usage text states 'The VkDescriptorSetLayoutBinding::binding members of the elements of the pBindings array must each have different values.' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkDescriptorSetLayoutCreateInfo-binding-00279)~^~
 VALIDATION_ERROR_05000230~^~Y~^~InvalidPushDescriptorSetLayout~^~VkDescriptorSetLayoutCreateInfo~^~VUID-VkDescriptorSetLayoutCreateInfo-flags-00280~^~(VK_KHR_push_descriptor)~^~The spec valid usage text states 'If flags contains VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR, then all elements of pBindings must not have a descriptorType of VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutCreateInfo-flags-00280)~^~
 VALIDATION_ERROR_05000232~^~Y~^~InvalidPushDescriptorSetLayout~^~VkDescriptorSetLayoutCreateInfo~^~VUID-VkDescriptorSetLayoutCreateInfo-flags-00281~^~(VK_KHR_push_descriptor)~^~The spec valid usage text states 'If flags contains VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR, then the total number of elements of all bindings must be less than or equal to VkPhysicalDevicePushDescriptorPropertiesKHR::maxPushDescriptors' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutCreateInfo-flags-00281)~^~
-VALIDATION_ERROR_05001770~^~N~^~None~^~VkDescriptorSetLayoutCreateInfo~^~VUID-VkDescriptorSetLayoutCreateInfo-flags-03000~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If any binding has the VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT bit set, flags must include VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutCreateInfo-flags-03000)~^~
+VALIDATION_ERROR_05001770~^~Y~^~DescriptorIndexingSetLayout~^~VkDescriptorSetLayoutCreateInfo~^~VUID-VkDescriptorSetLayoutCreateInfo-flags-03000~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If any binding has the VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT bit set, flags must include VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutCreateInfo-flags-03000)~^~
 VALIDATION_ERROR_05001772~^~N~^~None~^~VkDescriptorSetLayoutCreateInfo~^~VUID-VkDescriptorSetLayoutCreateInfo-descriptorType-03001~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If any binding has the VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT bit set, then all bindings must not have descriptorType of VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutCreateInfo-descriptorType-03001)~^~
 VALIDATION_ERROR_05009001~^~Y~^~Unknown~^~VkDescriptorSetLayoutCreateInfo~^~VUID-VkDescriptorSetLayoutCreateInfo-flags-parameter~^~core~^~The spec valid usage text states 'flags must be a valid combination of VkDescriptorSetLayoutCreateFlagBits values' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkDescriptorSetLayoutCreateInfo-flags-parameter)~^~implicit
 VALIDATION_ERROR_0500fc01~^~Y~^~Unknown~^~VkDescriptorSetLayoutCreateInfo~^~VUID-VkDescriptorSetLayoutCreateInfo-pBindings-parameter~^~core~^~The spec valid usage text states 'If bindingCount is not 0, pBindings must be a valid pointer to an array of bindingCount valid VkDescriptorSetLayoutBinding structures' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkDescriptorSetLayoutCreateInfo-pBindings-parameter)~^~implicit
@@ -1129,12 +1129,12 @@ VALIDATION_ERROR_0fe01794~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipel
 VALIDATION_ERROR_0fe01796~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-descriptorType-03019~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, and VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits::maxPerStageDescriptorSampledImages' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-descriptorType-03019)~^~
 VALIDATION_ERROR_0fe01798~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-descriptorType-03020~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, and VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits::maxPerStageDescriptorStorageImages' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-descriptorType-03020)~^~
 VALIDATION_ERROR_0fe0179a~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-descriptorType-03021~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits::maxPerStageDescriptorInputAttachments' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-descriptorType-03021)~^~
-VALIDATION_ERROR_0fe0179c~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-descriptorType-03022~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors with a descriptorType of VK_DESCRIPTOR_TYPE_SAMPLER and VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxPerStageDescriptorUpdateAfterBindSamplers' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-descriptorType-03022)~^~
-VALIDATION_ERROR_0fe0179e~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-descriptorType-03023~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors with a descriptorType of VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER and VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxPerStageDescriptorUpdateAfterBindUniformBuffers' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-descriptorType-03023)~^~
-VALIDATION_ERROR_0fe017a0~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-descriptorType-03024~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors with a descriptorType of VK_DESCRIPTOR_TYPE_STORAGE_BUFFER and VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxPerStageDescriptorUpdateAfterBindStorageBuffers' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-descriptorType-03024)~^~
-VALIDATION_ERROR_0fe017a2~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-descriptorType-03025~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors with a descriptorType of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, and VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxPerStageDescriptorUpdateAfterBindSampledImages' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-descriptorType-03025)~^~
-VALIDATION_ERROR_0fe017a4~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-descriptorType-03026~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors with a descriptorType of VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, and VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxPerStageDescriptorUpdateAfterBindStorageImages' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-descriptorType-03026)~^~
-VALIDATION_ERROR_0fe017a6~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-descriptorType-03027~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors with a descriptorType of VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxPerStageDescriptorUpdateAfterBindInputAttachments' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-descriptorType-03027)~^~
+VALIDATION_ERROR_0fe0179c~^~Y~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-descriptorType-03022~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors with a descriptorType of VK_DESCRIPTOR_TYPE_SAMPLER and VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxPerStageDescriptorUpdateAfterBindSamplers' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-descriptorType-03022)~^~
+VALIDATION_ERROR_0fe0179e~^~Y~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-descriptorType-03023~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors with a descriptorType of VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER and VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxPerStageDescriptorUpdateAfterBindUniformBuffers' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-descriptorType-03023)~^~
+VALIDATION_ERROR_0fe017a0~^~Y~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-descriptorType-03024~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors with a descriptorType of VK_DESCRIPTOR_TYPE_STORAGE_BUFFER and VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxPerStageDescriptorUpdateAfterBindStorageBuffers' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-descriptorType-03024)~^~
+VALIDATION_ERROR_0fe017a2~^~Y~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-descriptorType-03025~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors with a descriptorType of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, and VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxPerStageDescriptorUpdateAfterBindSampledImages' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-descriptorType-03025)~^~
+VALIDATION_ERROR_0fe017a4~^~Y~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-descriptorType-03026~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors with a descriptorType of VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, and VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxPerStageDescriptorUpdateAfterBindStorageImages' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-descriptorType-03026)~^~
+VALIDATION_ERROR_0fe017a6~^~Y~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-descriptorType-03027~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors with a descriptorType of VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT accessible to any given shader stage across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxPerStageDescriptorUpdateAfterBindInputAttachments' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-descriptorType-03027)~^~
 VALIDATION_ERROR_0fe017a8~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-descriptorType-03028~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_SAMPLER and VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits::maxDescriptorSetSamplers' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-descriptorType-03028)~^~
 VALIDATION_ERROR_0fe017aa~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-descriptorType-03029~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER accessible across all shader stagess and and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits::maxDescriptorSetUniformBuffers' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-descriptorType-03029)~^~
 VALIDATION_ERROR_0fe017ac~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-descriptorType-03030~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits::maxDescriptorSetUniformBuffersDynamic' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-descriptorType-03030)~^~
@@ -1143,14 +1143,14 @@ VALIDATION_ERROR_0fe017b0~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipel
 VALIDATION_ERROR_0fe017b2~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-descriptorType-03033~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, and VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits::maxDescriptorSetSampledImages' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-descriptorType-03033)~^~
 VALIDATION_ERROR_0fe017b4~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-descriptorType-03034~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, and VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits::maxDescriptorSetStorageImages' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-descriptorType-03034)~^~
 VALIDATION_ERROR_0fe017b6~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-descriptorType-03035~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors in descriptor set layouts created without the VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT bit set with a descriptorType of VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceLimits::maxDescriptorSetInputAttachments' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-descriptorType-03035)~^~
-VALIDATION_ERROR_0fe017b8~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03036~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors of the type VK_DESCRIPTOR_TYPE_SAMPLER and VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxDescriptorSetUpdateAfterBindSamplers' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03036)~^~
-VALIDATION_ERROR_0fe017ba~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03037~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors of the type VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER accessible across all shader stagess and and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxDescriptorSetUpdateAfterBindUniformBuffers' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03037)~^~
-VALIDATION_ERROR_0fe017bc~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03038~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors of the type VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxDescriptorSetUpdateAfterBindUniformBuffersDynamic' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03038)~^~
-VALIDATION_ERROR_0fe017be~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03039~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors of the type VK_DESCRIPTOR_TYPE_STORAGE_BUFFER accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxDescriptorSetUpdateAfterBindStorageBuffers' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03039)~^~
-VALIDATION_ERROR_0fe017c0~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03040~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors of the type VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxDescriptorSetUpdateAfterBindStorageBuffersDynamic' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03040)~^~
-VALIDATION_ERROR_0fe017c2~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03041~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors of the type VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, and VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxDescriptorSetUpdateAfterBindSampledImages' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03041)~^~
-VALIDATION_ERROR_0fe017c4~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03042~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors of the type VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, and VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxDescriptorSetUpdateAfterBindStorageImages' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03042)~^~
-VALIDATION_ERROR_0fe017c6~^~N~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03043~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors of the type VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxDescriptorSetUpdateAfterBindInputAttachments' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03043)~^~
+VALIDATION_ERROR_0fe017b8~^~Y~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03036~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors of the type VK_DESCRIPTOR_TYPE_SAMPLER and VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxDescriptorSetUpdateAfterBindSamplers' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03036)~^~
+VALIDATION_ERROR_0fe017ba~^~Y~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03037~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors of the type VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER accessible across all shader stagess and and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxDescriptorSetUpdateAfterBindUniformBuffers' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03037)~^~
+VALIDATION_ERROR_0fe017bc~^~Y~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03038~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors of the type VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxDescriptorSetUpdateAfterBindUniformBuffersDynamic' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03038)~^~
+VALIDATION_ERROR_0fe017be~^~Y~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03039~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors of the type VK_DESCRIPTOR_TYPE_STORAGE_BUFFER accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxDescriptorSetUpdateAfterBindStorageBuffers' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03039)~^~
+VALIDATION_ERROR_0fe017c0~^~Y~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03040~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors of the type VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxDescriptorSetUpdateAfterBindStorageBuffersDynamic' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03040)~^~
+VALIDATION_ERROR_0fe017c2~^~Y~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03041~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors of the type VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, and VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxDescriptorSetUpdateAfterBindSampledImages' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03041)~^~
+VALIDATION_ERROR_0fe017c4~^~Y~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03042~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors of the type VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, and VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxDescriptorSetUpdateAfterBindStorageImages' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03042)~^~
+VALIDATION_ERROR_0fe017c6~^~Y~^~None~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03043~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'The total number of descriptors of the type VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT accessible across all shader stages and across all elements of pSetLayouts must be less than or equal to VkPhysicalDeviceDescriptorIndexingPropertiesEXT::maxDescriptorSetUpdateAfterBindInputAttachments' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-pSetLayouts-03043)~^~
 VALIDATION_ERROR_0fe09005~^~Y~^~Unknown~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-flags-zerobitmask~^~core~^~The spec valid usage text states 'flags must be 0' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-flags-zerobitmask)~^~implicit, TBD in parameter validation layer.
 VALIDATION_ERROR_0fe1c40d~^~Y~^~Unknown~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-pNext-pNext~^~core~^~The spec valid usage text states 'pNext must be NULL' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-pNext-pNext)~^~implicit, TBD in parameter validation layer.
 VALIDATION_ERROR_0fe1f801~^~Y~^~Unknown~^~VkPipelineLayoutCreateInfo~^~VUID-VkPipelineLayoutCreateInfo-pPushConstantRanges-parameter~^~core~^~The spec valid usage text states 'If pushConstantRangeCount is not 0, pPushConstantRanges must be a valid pointer to an array of pushConstantRangeCount valid VkPushConstantRange structures' (https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#VUID-VkPipelineLayoutCreateInfo-pPushConstantRanges-parameter)~^~implicit
@@ -3913,25 +3913,25 @@ VALIDATION_ERROR_46605601~^~N~^~None~^~vkSetDebugUtilsObjectNameEXT~^~VUID-vkSet
 VALIDATION_ERROR_4661c201~^~N~^~None~^~vkSetDebugUtilsObjectNameEXT~^~VUID-vkSetDebugUtilsObjectNameEXT-pNameInfo-parameter~^~(VK_EXT_debug_utils)~^~The spec valid usage text states 'pNameInfo must be a valid pointer to a valid VkDebugUtilsObjectNameInfoEXT structure' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-vkSetDebugUtilsObjectNameEXT-pNameInfo-parameter)~^~implicit
 VALIDATION_ERROR_46805601~^~N~^~None~^~vkSetDebugUtilsObjectTagEXT~^~VUID-vkSetDebugUtilsObjectTagEXT-device-parameter~^~(VK_EXT_debug_utils)~^~The spec valid usage text states 'device must be a valid VkDevice handle' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-vkSetDebugUtilsObjectTagEXT-device-parameter)~^~implicit
 VALIDATION_ERROR_46825c01~^~N~^~None~^~vkSetDebugUtilsObjectTagEXT~^~VUID-vkSetDebugUtilsObjectTagEXT-pTagInfo-parameter~^~(VK_EXT_debug_utils)~^~The spec valid usage text states 'pTagInfo must be a valid pointer to a valid VkDebugUtilsObjectTagInfoEXT structure' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-vkSetDebugUtilsObjectTagEXT-pTagInfo-parameter)~^~implicit
-VALIDATION_ERROR_46a01774~^~N~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-bindingCount-03002~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If bindingCount is not zero, bindingCount must equal VkDescriptorSetLayoutCreateInfo::bindingCount' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-bindingCount-03002)~^~
-VALIDATION_ERROR_46a01776~^~N~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-flags-03003~^~(VK_EXT_descriptor_indexing)+(VK_KHR_push_descriptor)~^~The spec valid usage text states 'If VkDescriptorSetLayoutCreateInfo::flags includes VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR, then all elements of pBindingFlags must not include VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT, VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT, or VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-flags-03003)~^~
-VALIDATION_ERROR_46a01778~^~N~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-pBindingFlags-03004~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If an element of pBindingFlags includes VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT, then all other elements of VkDescriptorSetLayoutCreateInfo::pBindings must have a smaller value of binding' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-pBindingFlags-03004)~^~
-VALIDATION_ERROR_46a0177a~^~N~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingUniformBufferUpdateAfterBind-03005~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If VkPhysicalDeviceDescriptorIndexingFeaturesEXT::descriptorBindingUniformBufferUpdateAfterBind is not enabled, all bindings with descriptor type VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER must not use VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingUniformBufferUpdateAfterBind-03005)~^~
-VALIDATION_ERROR_46a0177c~^~N~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingSampledImageUpdateAfterBind-03006~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If VkPhysicalDeviceDescriptorIndexingFeaturesEXT::descriptorBindingSampledImageUpdateAfterBind is not enabled, all bindings with descriptor type VK_DESCRIPTOR_TYPE_SAMPLER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, or VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE must not use VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingSampledImageUpdateAfterBind-03006)~^~
-VALIDATION_ERROR_46a0177e~^~N~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingStorageImageUpdateAfterBind-03007~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If VkPhysicalDeviceDescriptorIndexingFeaturesEXT::descriptorBindingStorageImageUpdateAfterBind is not enabled, all bindings with descriptor type VK_DESCRIPTOR_TYPE_STORAGE_IMAGE must not use VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingStorageImageUpdateAfterBind-03007)~^~
-VALIDATION_ERROR_46a01780~^~N~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingStorageBufferUpdateAfterBind-03008~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If VkPhysicalDeviceDescriptorIndexingFeaturesEXT::descriptorBindingStorageBufferUpdateAfterBind is not enabled, all bindings with descriptor type VK_DESCRIPTOR_TYPE_STORAGE_BUFFER must not use VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingStorageBufferUpdateAfterBind-03008)~^~
-VALIDATION_ERROR_46a01782~^~N~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingUniformTexelBufferUpdateAfterBind-03009~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If VkPhysicalDeviceDescriptorIndexingFeaturesEXT::descriptorBindingUniformTexelBufferUpdateAfterBind is not enabled, all bindings with descriptor type VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER must not use VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingUniformTexelBufferUpdateAfterBind-03009)~^~
-VALIDATION_ERROR_46a01784~^~N~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingStorageTexelBufferUpdateAfterBind-03010~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If VkPhysicalDeviceDescriptorIndexingFeaturesEXT::descriptorBindingStorageTexelBufferUpdateAfterBind is not enabled, all bindings with descriptor type VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER must not use VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingStorageTexelBufferUpdateAfterBind-03010)~^~
-VALIDATION_ERROR_46a01786~^~N~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-None-03011~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'All bindings with descriptor type VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC must not use VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-None-03011)~^~
-VALIDATION_ERROR_46a01788~^~N~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingUpdateUnusedWhilePending-03012~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If VkPhysicalDeviceDescriptorIndexingFeaturesEXT::descriptorBindingUpdateUnusedWhilePending is not enabled, all elements of pBindingFlags must not include VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingUpdateUnusedWhilePending-03012)~^~
-VALIDATION_ERROR_46a0178a~^~N~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingPartiallyBound-03013~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If VkPhysicalDeviceDescriptorIndexingFeaturesEXT::descriptorBindingPartiallyBound is not enabled, all elements of pBindingFlags must not include VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingPartiallyBound-03013)~^~
-VALIDATION_ERROR_46a0178c~^~N~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingVariableDescriptorCount-03014~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If VkPhysicalDeviceDescriptorIndexingFeaturesEXT::descriptorBindingVariableDescriptorCount is not enabled, all elements of pBindingFlags must not include VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingVariableDescriptorCount-03014)~^~
-VALIDATION_ERROR_46a0178e~^~N~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-pBindingFlags-03015~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If an element of pBindingFlags includes VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT, that element's descriptorType must not be VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-pBindingFlags-03015)~^~
+VALIDATION_ERROR_46a01774~^~Y~^~DescriptorIndexingSetLayout~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-bindingCount-03002~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If bindingCount is not zero, bindingCount must equal VkDescriptorSetLayoutCreateInfo::bindingCount' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-bindingCount-03002)~^~
+VALIDATION_ERROR_46a01776~^~Y~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-flags-03003~^~(VK_EXT_descriptor_indexing)+(VK_KHR_push_descriptor)~^~The spec valid usage text states 'If VkDescriptorSetLayoutCreateInfo::flags includes VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR, then all elements of pBindingFlags must not include VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT, VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT, or VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-flags-03003)~^~
+VALIDATION_ERROR_46a01778~^~Y~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-pBindingFlags-03004~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If an element of pBindingFlags includes VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT, then all other elements of VkDescriptorSetLayoutCreateInfo::pBindings must have a smaller value of binding' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-pBindingFlags-03004)~^~
+VALIDATION_ERROR_46a0177a~^~Y~^~DescriptorIndexingSetLayout~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingUniformBufferUpdateAfterBind-03005~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If VkPhysicalDeviceDescriptorIndexingFeaturesEXT::descriptorBindingUniformBufferUpdateAfterBind is not enabled, all bindings with descriptor type VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER must not use VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingUniformBufferUpdateAfterBind-03005)~^~
+VALIDATION_ERROR_46a0177c~^~Y~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingSampledImageUpdateAfterBind-03006~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If VkPhysicalDeviceDescriptorIndexingFeaturesEXT::descriptorBindingSampledImageUpdateAfterBind is not enabled, all bindings with descriptor type VK_DESCRIPTOR_TYPE_SAMPLER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, or VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE must not use VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingSampledImageUpdateAfterBind-03006)~^~
+VALIDATION_ERROR_46a0177e~^~Y~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingStorageImageUpdateAfterBind-03007~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If VkPhysicalDeviceDescriptorIndexingFeaturesEXT::descriptorBindingStorageImageUpdateAfterBind is not enabled, all bindings with descriptor type VK_DESCRIPTOR_TYPE_STORAGE_IMAGE must not use VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingStorageImageUpdateAfterBind-03007)~^~
+VALIDATION_ERROR_46a01780~^~Y~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingStorageBufferUpdateAfterBind-03008~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If VkPhysicalDeviceDescriptorIndexingFeaturesEXT::descriptorBindingStorageBufferUpdateAfterBind is not enabled, all bindings with descriptor type VK_DESCRIPTOR_TYPE_STORAGE_BUFFER must not use VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingStorageBufferUpdateAfterBind-03008)~^~
+VALIDATION_ERROR_46a01782~^~Y~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingUniformTexelBufferUpdateAfterBind-03009~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If VkPhysicalDeviceDescriptorIndexingFeaturesEXT::descriptorBindingUniformTexelBufferUpdateAfterBind is not enabled, all bindings with descriptor type VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER must not use VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingUniformTexelBufferUpdateAfterBind-03009)~^~
+VALIDATION_ERROR_46a01784~^~Y~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingStorageTexelBufferUpdateAfterBind-03010~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If VkPhysicalDeviceDescriptorIndexingFeaturesEXT::descriptorBindingStorageTexelBufferUpdateAfterBind is not enabled, all bindings with descriptor type VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER must not use VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingStorageTexelBufferUpdateAfterBind-03010)~^~
+VALIDATION_ERROR_46a01786~^~Y~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-None-03011~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'All bindings with descriptor type VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC must not use VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-None-03011)~^~
+VALIDATION_ERROR_46a01788~^~Y~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingUpdateUnusedWhilePending-03012~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If VkPhysicalDeviceDescriptorIndexingFeaturesEXT::descriptorBindingUpdateUnusedWhilePending is not enabled, all elements of pBindingFlags must not include VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingUpdateUnusedWhilePending-03012)~^~
+VALIDATION_ERROR_46a0178a~^~Y~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingPartiallyBound-03013~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If VkPhysicalDeviceDescriptorIndexingFeaturesEXT::descriptorBindingPartiallyBound is not enabled, all elements of pBindingFlags must not include VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingPartiallyBound-03013)~^~
+VALIDATION_ERROR_46a0178c~^~Y~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingVariableDescriptorCount-03014~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If VkPhysicalDeviceDescriptorIndexingFeaturesEXT::descriptorBindingVariableDescriptorCount is not enabled, all elements of pBindingFlags must not include VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-descriptorBindingVariableDescriptorCount-03014)~^~
+VALIDATION_ERROR_46a0178e~^~Y~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-pBindingFlags-03015~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If an element of pBindingFlags includes VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT, that element's descriptorType must not be VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-pBindingFlags-03015)~^~
 VALIDATION_ERROR_46a2b00b~^~N~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-sType-sType~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'sType must be VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-sType-sType)~^~implicit
 VALIDATION_ERROR_46a42a01~^~N~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-pBindingFlags-parameter~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If bindingCount is not 0, pBindingFlags must be a valid pointer to an array of bindingCount valid combinations of VkDescriptorBindingFlagBitsEXT values' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-pBindingFlags-parameter)~^~implicit
 VALIDATION_ERROR_46a42a03~^~N~^~None~^~VkDescriptorSetLayoutBindingFlagsCreateInfoEXT~^~VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-pBindingFlags-requiredbitmask~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'Each element of pBindingFlags must not be 0' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfoEXT-pBindingFlags-requiredbitmask)~^~implicit
-VALIDATION_ERROR_46c017ca~^~N~^~None~^~VkDescriptorSetVariableDescriptorCountAllocateInfoEXT~^~VUID-VkDescriptorSetVariableDescriptorCountAllocateInfoEXT-descriptorSetCount-03045~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If descriptorSetCount is not zero, descriptorSetCount must equal VkDescriptorSetAllocateInfo::descriptorSetCount' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetVariableDescriptorCountAllocateInfoEXT-descriptorSetCount-03045)~^~
-VALIDATION_ERROR_46c017cc~^~N~^~None~^~VkDescriptorSetVariableDescriptorCountAllocateInfoEXT~^~VUID-VkDescriptorSetVariableDescriptorCountAllocateInfoEXT-pSetLayouts-03046~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If VkDescriptorSetAllocateInfo::pSetLayouts[i] has a variable descriptor count binding, then pDescriptorCounts[i] must be less than or equal to the descriptor count specified for that binding when the descriptor set layout was created.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetVariableDescriptorCountAllocateInfoEXT-pSetLayouts-03046)~^~
+VALIDATION_ERROR_46c017ca~^~Y~^~None~^~VkDescriptorSetVariableDescriptorCountAllocateInfoEXT~^~VUID-VkDescriptorSetVariableDescriptorCountAllocateInfoEXT-descriptorSetCount-03045~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If descriptorSetCount is not zero, descriptorSetCount must equal VkDescriptorSetAllocateInfo::descriptorSetCount' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetVariableDescriptorCountAllocateInfoEXT-descriptorSetCount-03045)~^~
+VALIDATION_ERROR_46c017cc~^~Y~^~DescriptorIndexingSetLayout~^~VkDescriptorSetVariableDescriptorCountAllocateInfoEXT~^~VUID-VkDescriptorSetVariableDescriptorCountAllocateInfoEXT-pSetLayouts-03046~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If VkDescriptorSetAllocateInfo::pSetLayouts[i] has a variable descriptor count binding, then pDescriptorCounts[i] must be less than or equal to the descriptor count specified for that binding when the descriptor set layout was created.' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetVariableDescriptorCountAllocateInfoEXT-pSetLayouts-03046)~^~
 VALIDATION_ERROR_46c2b00b~^~N~^~None~^~VkDescriptorSetVariableDescriptorCountAllocateInfoEXT~^~VUID-VkDescriptorSetVariableDescriptorCountAllocateInfoEXT-sType-sType~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'sType must be VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetVariableDescriptorCountAllocateInfoEXT-sType-sType)~^~implicit
 VALIDATION_ERROR_46c42c01~^~N~^~None~^~VkDescriptorSetVariableDescriptorCountAllocateInfoEXT~^~VUID-VkDescriptorSetVariableDescriptorCountAllocateInfoEXT-pDescriptorCounts-parameter~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'If descriptorSetCount is not 0, pDescriptorCounts must be a valid pointer to an array of descriptorSetCount uint32_t values' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetVariableDescriptorCountAllocateInfoEXT-pDescriptorCounts-parameter)~^~implicit
 VALIDATION_ERROR_46e2b00b~^~N~^~None~^~VkDescriptorSetVariableDescriptorCountLayoutSupportEXT~^~VUID-VkDescriptorSetVariableDescriptorCountLayoutSupportEXT-sType-sType~^~(VK_EXT_descriptor_indexing)~^~The spec valid usage text states 'sType must be VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT_EXT' (https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VUID-VkDescriptorSetVariableDescriptorCountLayoutSupportEXT-sType-sType)~^~implicit
index 2111c15..0d80cd9 100644 (file)
@@ -462,9 +462,10 @@ class VkLayerTest : public VkRenderFramework {
     void GenericDrawPreparation(VkCommandBufferObj *commandBuffer, VkPipelineObj &pipelineobj, VkDescriptorSetObj &descriptorSet,
                                 BsoFailSelect failCase);
 
-    void Init(VkPhysicalDeviceFeatures *features = nullptr, const VkCommandPoolCreateFlags flags = 0) {
+    void Init(VkPhysicalDeviceFeatures *features = nullptr, VkPhysicalDeviceFeatures2 *features2 = nullptr,
+              const VkCommandPoolCreateFlags flags = 0) {
         InitFramework(myDbgFunc, m_errorMonitor);
-        InitState(features, flags);
+        InitState(features, features2, flags);
     }
 
    protected:
@@ -3247,7 +3248,7 @@ TEST_F(VkLayerTest, CreatePipelineBadVertexAttributeFormat) {
 
 TEST_F(VkLayerTest, ImageSampleCounts) {
     TEST_DESCRIPTION("Use bad sample counts in image transfer calls to trigger validation errors.");
-    ASSERT_NO_FATAL_FAILURE(Init(nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
+    ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
 
     VkMemoryPropertyFlags reqs = 0;
     VkImageCreateInfo image_create_info = {};
@@ -3596,7 +3597,7 @@ TEST_F(VkLayerTest, BlitImageFilters) {
 TEST_F(VkLayerTest, BlitImageLayout) {
     TEST_DESCRIPTION("Incorrect vkCmdBlitImage layouts");
 
-    ASSERT_NO_FATAL_FAILURE(Init(nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
+    ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
 
     VkResult err;
     VkFormat fmt = VK_FORMAT_R8G8B8A8_UNORM;
@@ -7717,7 +7718,7 @@ TEST_F(VkLayerTest, InvalidCmdBufferDescriptorSetImageSamplerDestroyed) {
         "Attempt to draw with a command buffer that is invalid due to a bound descriptor sets with a combined image sampler having "
         "their image, sampler, and descriptor set each respectively destroyed and then attempting to submit associated cmd "
         "buffers. Attempt to destroy a DescriptorSet that is in use.");
-    ASSERT_NO_FATAL_FAILURE(Init(nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
+    ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
     ASSERT_NO_FATAL_FAILURE(InitViewport());
     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
 
@@ -8010,7 +8011,7 @@ TEST_F(VkLayerTest, InvalidCmdBufferDescriptorSetImageSamplerDestroyed) {
 
 TEST_F(VkLayerTest, InvalidDescriptorSetSamplerDestroyed) {
     TEST_DESCRIPTION("Attempt to draw with a bound descriptor sets with a combined image sampler where sampler has been deleted.");
-    ASSERT_NO_FATAL_FAILURE(Init(nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
+    ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
     ASSERT_NO_FATAL_FAILURE(InitViewport());
     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
 
@@ -8108,7 +8109,7 @@ TEST_F(VkLayerTest, InvalidDescriptorSetSamplerDestroyed) {
 
 TEST_F(VkLayerTest, ImageDescriptorLayoutMismatch) {
     TEST_DESCRIPTION("Update an image sampler with a layout that doesn't match the actual image layout at the image is used.");
-    ASSERT_NO_FATAL_FAILURE(Init(nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
+    ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
     ASSERT_NO_FATAL_FAILURE(InitViewport());
     ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
 
@@ -11874,7 +11875,7 @@ static void ValidOwnershipTransfer(ErrorMonitor *monitor, VkCommandBufferObj *cb
 
 TEST_F(VkPositiveLayerTest, OwnershipTranfersImage) {
     TEST_DESCRIPTION("Valid image ownership transfers that shouldn't create errors");
-    ASSERT_NO_FATAL_FAILURE(Init(nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
+    ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
 
     uint32_t no_gfx = m_device->QueueFamilyWithoutCapabilities(VK_QUEUE_GRAPHICS_BIT);
     if (no_gfx == UINT32_MAX) {
@@ -11916,7 +11917,7 @@ TEST_F(VkPositiveLayerTest, OwnershipTranfersImage) {
 
 TEST_F(VkPositiveLayerTest, OwnershipTranfersBuffer) {
     TEST_DESCRIPTION("Valid buffer ownership transfers that shouldn't create errors");
-    ASSERT_NO_FATAL_FAILURE(Init(nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
+    ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
 
     uint32_t no_gfx = m_device->QueueFamilyWithoutCapabilities(VK_QUEUE_GRAPHICS_BIT);
     if (no_gfx == UINT32_MAX) {
@@ -12017,7 +12018,7 @@ class BarrierQueueFamilyTestHelper {
 
 TEST_F(VkLayerTest, InvalidBarrierQueueFamily) {
     TEST_DESCRIPTION("Create and submit barriers with invalid queue families");
-    ASSERT_NO_FATAL_FAILURE(Init(nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
+    ASSERT_NO_FATAL_FAILURE(Init(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
 
     // Find queues of two families
     const uint32_t submit_family = m_device->graphics_queue_node_index_;
@@ -12082,7 +12083,7 @@ TEST_F(VkLayerTest, InvalidBarrierQueueFamilyWithMemExt) {
         return;
     }
 
-    ASSERT_NO_FATAL_FAILURE(InitState(nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
+    ASSERT_NO_FATAL_FAILURE(InitState(nullptr, nullptr, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
 
     // Find queues of two families
     const uint32_t submit_family = m_device->graphics_queue_node_index_;
@@ -22888,6 +22889,327 @@ TEST_F(VkLayerTest, PushDescriptorSetLayoutWithoutExtension) {
     vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr);
 }
 
+TEST_F(VkLayerTest, DescriptorIndexingSetLayoutWithoutExtension) {
+    TEST_DESCRIPTION("Create an update_after_bind set layout without loading the needed extension.");
+    ASSERT_NO_FATAL_FAILURE(Init());
+
+    auto ds_layout_ci = lvl_init_struct<VkDescriptorSetLayoutCreateInfo>();
+    ds_layout_ci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT;
+
+    std::string error = "Attemped to use VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT in ";
+    error = error + "VkDescriptorSetLayoutCreateInfo::flags but its required extension ";
+    error = error + VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME;
+    error = error + " has not been enabled.";
+
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, error.c_str());
+    VkDescriptorSetLayout ds_layout = VK_NULL_HANDLE;
+    vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout);
+    m_errorMonitor->VerifyFound();
+    vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr);
+}
+
+TEST_F(VkLayerTest, DescriptorIndexingSetLayout) {
+    TEST_DESCRIPTION("Exercise various create/allocate-time errors related to VK_EXT_descriptor_indexing.");
+
+    ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
+    if (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME)) {
+        m_device_extension_names.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
+    } else {
+        printf("             %s Extension not supported, skipping tests\n", VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
+        return;
+    }
+
+    // Create a device that enables all supported indexing features except descriptorBindingUniformBufferUpdateAfterBind
+    auto indexingFeatures = lvl_init_struct<VkPhysicalDeviceDescriptorIndexingFeaturesEXT>();
+    auto features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&indexingFeatures);
+    vkGetPhysicalDeviceFeatures2(gpu(), &features2);
+
+    indexingFeatures.descriptorBindingUniformBufferUpdateAfterBind = VK_FALSE;
+
+    ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2));
+
+    VkDescriptorBindingFlagsEXT flags = VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT;
+    auto flags_create_info = lvl_init_struct<VkDescriptorSetLayoutBindingFlagsCreateInfoEXT>();
+    flags_create_info.bindingCount = 1;
+    flags_create_info.pBindingFlags = &flags;
+
+    VkDescriptorSetLayoutBinding binding = {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr};
+    auto ds_layout_ci = lvl_init_struct<VkDescriptorSetLayoutCreateInfo>(&flags_create_info);
+    ds_layout_ci.bindingCount = 1;
+    ds_layout_ci.pBindings = &binding;
+    VkDescriptorSetLayout ds_layout = VK_NULL_HANDLE;
+
+    // VU for VkDescriptorSetLayoutBindingFlagsCreateInfoEXT::bindingCount
+    flags_create_info.bindingCount = 2;
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_46a01774);
+    VkResult err = vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout);
+    m_errorMonitor->VerifyFound();
+    vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr);
+
+    flags_create_info.bindingCount = 1;
+
+    // set is missing UPDATE_AFTER_BIND_POOL flag.
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_05001770);
+    // binding uses a feature we disabled
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_46a0177a);
+    err = vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout);
+    m_errorMonitor->VerifyFound();
+    vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr);
+
+    ds_layout_ci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT;
+    ds_layout_ci.bindingCount = 0;
+    flags_create_info.bindingCount = 0;
+    err = vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout);
+    ASSERT_VK_SUCCESS(err);
+
+    VkDescriptorPoolSize pool_size = {binding.descriptorType, binding.descriptorCount};
+    auto dspci = lvl_init_struct<VkDescriptorPoolCreateInfo>();
+    dspci.poolSizeCount = 1;
+    dspci.pPoolSizes = &pool_size;
+    dspci.maxSets = 1;
+    VkDescriptorPool pool;
+    err = vkCreateDescriptorPool(m_device->handle(), &dspci, nullptr, &pool);
+    ASSERT_VK_SUCCESS(err);
+
+    auto ds_alloc_info = lvl_init_struct<VkDescriptorSetAllocateInfo>();
+    ds_alloc_info.descriptorPool = pool;
+    ds_alloc_info.descriptorSetCount = 1;
+    ds_alloc_info.pSetLayouts = &ds_layout;
+
+    VkDescriptorSet ds = VK_NULL_HANDLE;
+    // mismatch between descriptor set and pool
+    m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_04c017c8);
+    vkAllocateDescriptorSets(m_device->handle(), &ds_alloc_info, &ds);
+    m_errorMonitor->VerifyFound();
+
+    vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr);
+    vkDestroyDescriptorPool(m_device->handle(), pool, nullptr);
+
+    if (indexingFeatures.descriptorBindingVariableDescriptorCount) {
+        ds_layout_ci.flags = 0;
+        ds_layout_ci.bindingCount = 1;
+        flags_create_info.bindingCount = 1;
+        flags = VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT;
+        err = vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout);
+        ASSERT_VK_SUCCESS(err);
+
+        pool_size = {binding.descriptorType, binding.descriptorCount};
+        dspci = lvl_init_struct<VkDescriptorPoolCreateInfo>();
+        dspci.poolSizeCount = 1;
+        dspci.pPoolSizes = &pool_size;
+        dspci.maxSets = 1;
+        err = vkCreateDescriptorPool(m_device->handle(), &dspci, nullptr, &pool);
+        ASSERT_VK_SUCCESS(err);
+
+        auto count_alloc_info = lvl_init_struct<VkDescriptorSetVariableDescriptorCountAllocateInfoEXT>();
+        count_alloc_info.descriptorSetCount = 1;
+        // Set variable count larger than what was in the descriptor binding
+        uint32_t variable_count = 2;
+        count_alloc_info.pDescriptorCounts = &variable_count;
+
+        ds_alloc_info = lvl_init_struct<VkDescriptorSetAllocateInfo>(&count_alloc_info);
+        ds_alloc_info.descriptorPool = pool;
+        ds_alloc_info.descriptorSetCount = 1;
+        ds_alloc_info.pSetLayouts = &ds_layout;
+
+        ds = VK_NULL_HANDLE;
+        m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, VALIDATION_ERROR_46c017cc);
+        vkAllocateDescriptorSets(m_device->handle(), &ds_alloc_info, &ds);
+        m_errorMonitor->VerifyFound();
+
+        vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr);
+        vkDestroyDescriptorPool(m_device->handle(), pool, nullptr);
+    }
+}
+
+TEST_F(VkLayerTest, DescriptorIndexingUpdateAfterBind) {
+    TEST_DESCRIPTION("Exercise errors for updating a descriptor set after it is bound.");
+
+    ASSERT_NO_FATAL_FAILURE(InitFramework(myDbgFunc, m_errorMonitor));
+    if (DeviceExtensionSupported(gpu(), nullptr, VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME)) {
+        m_device_extension_names.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
+    } else {
+        printf("             %s Extension not supported, skipping tests\n", VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
+        return;
+    }
+
+    // Create a device that enables all supported indexing features except descriptorBindingUniformBufferUpdateAfterBind
+    auto indexingFeatures = lvl_init_struct<VkPhysicalDeviceDescriptorIndexingFeaturesEXT>();
+    auto features2 = lvl_init_struct<VkPhysicalDeviceFeatures2KHR>(&indexingFeatures);
+    vkGetPhysicalDeviceFeatures2(gpu(), &features2);
+
+    indexingFeatures.descriptorBindingUniformBufferUpdateAfterBind = VK_FALSE;
+
+    if (!indexingFeatures.descriptorBindingStorageBufferUpdateAfterBind) {
+        printf("             Test requires (unsupported) descriptorBindingStorageBufferUpdateAfterBind, skipping\n");
+        return;
+    }
+
+    ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &features2, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
+    ASSERT_NO_FATAL_FAILURE(InitViewport());
+    ASSERT_NO_FATAL_FAILURE(InitRenderTarget());
+
+    VkDescriptorBindingFlagsEXT flags[2] = {0, VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT};
+    auto flags_create_info = lvl_init_struct<VkDescriptorSetLayoutBindingFlagsCreateInfoEXT>();
+    flags_create_info.bindingCount = 2;
+    flags_create_info.pBindingFlags = &flags[0];
+
+    // Descriptor set has two bindings - only the second is update_after_bind
+    VkDescriptorSetLayoutBinding binding[2] = {
+        {0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr},
+        {1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT, nullptr},
+    };
+    auto ds_layout_ci = lvl_init_struct<VkDescriptorSetLayoutCreateInfo>(&flags_create_info);
+    ds_layout_ci.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT;
+    ds_layout_ci.bindingCount = 2;
+    ds_layout_ci.pBindings = &binding[0];
+    VkDescriptorSetLayout ds_layout = VK_NULL_HANDLE;
+
+    VkResult err = vkCreateDescriptorSetLayout(m_device->handle(), &ds_layout_ci, nullptr, &ds_layout);
+
+    VkDescriptorPoolSize pool_sizes[2] = {
+        {binding[0].descriptorType, binding[0].descriptorCount},
+        {binding[1].descriptorType, binding[1].descriptorCount},
+    };
+    auto dspci = lvl_init_struct<VkDescriptorPoolCreateInfo>();
+    dspci.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT;
+    dspci.poolSizeCount = 2;
+    dspci.pPoolSizes = &pool_sizes[0];
+    dspci.maxSets = 1;
+    VkDescriptorPool pool;
+    err = vkCreateDescriptorPool(m_device->handle(), &dspci, nullptr, &pool);
+    ASSERT_VK_SUCCESS(err);
+
+    auto ds_alloc_info = lvl_init_struct<VkDescriptorSetAllocateInfo>();
+    ds_alloc_info.descriptorPool = pool;
+    ds_alloc_info.descriptorSetCount = 1;
+    ds_alloc_info.pSetLayouts = &ds_layout;
+
+    VkDescriptorSet ds = VK_NULL_HANDLE;
+    vkAllocateDescriptorSets(m_device->handle(), &ds_alloc_info, &ds);
+    ASSERT_VK_SUCCESS(err);
+
+    VkBufferCreateInfo buffCI = {};
+    buffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+    buffCI.size = 1024;
+    buffCI.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
+
+    VkBuffer dyub;
+    err = vkCreateBuffer(m_device->device(), &buffCI, NULL, &dyub);
+    ASSERT_VK_SUCCESS(err);
+
+    VkDeviceMemory mem;
+    VkMemoryRequirements mem_reqs;
+    vkGetBufferMemoryRequirements(m_device->device(), dyub, &mem_reqs);
+
+    VkMemoryAllocateInfo mem_alloc_info = {};
+    mem_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+    mem_alloc_info.allocationSize = mem_reqs.size;
+    m_device->phy().set_memory_type(mem_reqs.memoryTypeBits, &mem_alloc_info, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
+    err = vkAllocateMemory(m_device->device(), &mem_alloc_info, NULL, &mem);
+    ASSERT_VK_SUCCESS(err);
+
+    err = vkBindBufferMemory(m_device->device(), dyub, mem, 0);
+    ASSERT_VK_SUCCESS(err);
+
+    VkDescriptorBufferInfo buffInfo[2] = {};
+    buffInfo[0].buffer = dyub;
+    buffInfo[0].offset = 0;
+    buffInfo[0].range = 1024;
+
+    VkWriteDescriptorSet descriptor_write[2] = {};
+    descriptor_write[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+    descriptor_write[0].dstSet = ds;
+    descriptor_write[0].dstBinding = 0;
+    descriptor_write[0].descriptorCount = 1;
+    descriptor_write[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+    descriptor_write[0].pBufferInfo = buffInfo;
+    descriptor_write[1] = descriptor_write[0];
+    descriptor_write[1].dstBinding = 1;
+    descriptor_write[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+
+    VkPipelineLayout pipeline_layout;
+    VkPipelineLayoutCreateInfo pipeline_layout_ci = {};
+    pipeline_layout_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+    pipeline_layout_ci.setLayoutCount = 1;
+    pipeline_layout_ci.pSetLayouts = &ds_layout;
+
+    vkCreatePipelineLayout(m_device->device(), &pipeline_layout_ci, NULL, &pipeline_layout);
+
+    // Create a dummy pipeline, since LVL inspects which bindings are
+    // actually used at draw time
+    char const *vsSource =
+        "#version 450\n"
+        "void main(){\n"
+        "   gl_Position = vec4(0);\n"
+        "}\n";
+    char const *fsSource =
+        "#version 450\n"
+        "\n"
+        "layout(location=0) out vec4 color;\n"
+        "layout(set=0, binding=0) uniform foo0 { float x0; } bar0;\n"
+        "layout(set=0, binding=1) buffer  foo1 { float x1; } bar1;\n"
+        "void main(){\n"
+        "   color = vec4(bar0.x0 + bar1.x1);\n"
+        "}\n";
+
+    VkShaderObj vs(m_device, vsSource, VK_SHADER_STAGE_VERTEX_BIT, this);
+    VkShaderObj fs(m_device, fsSource, VK_SHADER_STAGE_FRAGMENT_BIT, this);
+
+    VkPipelineObj pipe(m_device);
+    pipe.SetViewport(m_viewports);
+    pipe.SetScissor(m_scissors);
+    pipe.AddDefaultColorAttachment();
+    pipe.AddShader(&vs);
+    pipe.AddShader(&fs);
+    pipe.CreateVKPipeline(pipeline_layout, m_renderPass);
+
+    // Make both bindings valid before binding to the command buffer
+    vkUpdateDescriptorSets(m_device->device(), 2, &descriptor_write[0], 0, NULL);
+    m_errorMonitor->VerifyNotFound();
+
+    // Two subtests. First only updates the update_after_bind binding and expects
+    // no error. Second updates the other binding and expects an error when the
+    // command buffer is ended.
+    for (uint32_t i = 0; i < 2; ++i) {
+        m_commandBuffer->begin();
+
+        vkCmdBindDescriptorSets(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &ds, 0, NULL);
+
+        m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
+        vkCmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
+        vkCmdDraw(m_commandBuffer->handle(), 0, 0, 0, 0);
+        vkCmdEndRenderPass(m_commandBuffer->handle());
+
+        m_errorMonitor->VerifyNotFound();
+        // Valid to update binding 1 after being bound
+        vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write[1], 0, NULL);
+        m_errorMonitor->VerifyNotFound();
+
+        if (i == 0) {
+            // expect no errors
+            m_commandBuffer->end();
+            m_errorMonitor->VerifyNotFound();
+        } else {
+            // Invalid to update binding 0 after being bound. But the error is actually
+            // generated during vkEndCommandBuffer
+            vkUpdateDescriptorSets(m_device->device(), 1, &descriptor_write[0], 0, NULL);
+            m_errorMonitor->VerifyNotFound();
+
+            m_errorMonitor->SetDesiredFailureMsg(VK_DEBUG_REPORT_ERROR_BIT_EXT, "is invalid because bound DescriptorSet");
+
+            vkEndCommandBuffer(m_commandBuffer->handle());
+            m_errorMonitor->VerifyFound();
+        }
+    }
+
+    vkDestroyDescriptorSetLayout(m_device->handle(), ds_layout, nullptr);
+    vkDestroyDescriptorPool(m_device->handle(), pool, nullptr);
+    vkDestroyBuffer(m_device->handle(), dyub, NULL);
+    vkFreeMemory(m_device->handle(), mem, NULL);
+    vkDestroyPipelineLayout(m_device->handle(), pipeline_layout, NULL);
+}
+
 TEST_F(VkLayerTest, AllocatePushDescriptorSet) {
     TEST_DESCRIPTION("Attempt to allocate a push descriptor set.");
     if (InstanceExtensionSupported(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
index 9d2fd12..c8bc793 100644 (file)
@@ -294,7 +294,8 @@ void VkRenderFramework::GetPhysicalDeviceFeatures(VkPhysicalDeviceFeatures *feat
     }
 }
 
-void VkRenderFramework::InitState(VkPhysicalDeviceFeatures *features, const VkCommandPoolCreateFlags flags) {
+void VkRenderFramework::InitState(VkPhysicalDeviceFeatures *features, VkPhysicalDeviceFeatures2 *features2,
+                                  const VkCommandPoolCreateFlags flags) {
     // Remove any unsupported device extension names from list
     for (auto ext = m_device_extension_names.begin(); ext != m_device_extension_names.end();) {
         if (!DeviceExtensionSupported(objs[0], nullptr, *ext)) {
@@ -316,7 +317,7 @@ void VkRenderFramework::InitState(VkPhysicalDeviceFeatures *features, const VkCo
         }
     }
 
-    m_device = new VkDeviceObj(0, objs[0], m_device_extension_names, features);
+    m_device = new VkDeviceObj(0, objs[0], m_device_extension_names, features, features2);
     m_device->SetDeviceQueue();
 
     m_depthStencil = new VkDepthStencilObj(m_device);
@@ -530,9 +531,9 @@ VkDeviceObj::VkDeviceObj(uint32_t id, VkPhysicalDevice obj) : vk_testing::Device
 }
 
 VkDeviceObj::VkDeviceObj(uint32_t id, VkPhysicalDevice obj, std::vector<const char *> &extension_names,
-                         VkPhysicalDeviceFeatures *features)
+                         VkPhysicalDeviceFeatures *features, VkPhysicalDeviceFeatures2 *features2)
     : vk_testing::Device(obj), id(id) {
-    init(extension_names, features);
+    init(extension_names, features, features2);
 
     props = phy().properties();
     queue_props = phy().queue_properties();
index 43d9c72..bb54b0d 100644 (file)
@@ -52,7 +52,7 @@ class VkDeviceObj : public vk_testing::Device {
    public:
     VkDeviceObj(uint32_t id, VkPhysicalDevice obj);
     VkDeviceObj(uint32_t id, VkPhysicalDevice obj, std::vector<const char *> &extension_names,
-                VkPhysicalDeviceFeatures *features = nullptr);
+                VkPhysicalDeviceFeatures *features = nullptr, VkPhysicalDeviceFeatures2KHR *features2 = nullptr);
 
     uint32_t QueueFamilyMatching(VkQueueFlags with, VkQueueFlags without, bool all_bits = true);
     uint32_t QueueFamilyWithoutCapabilities(VkQueueFlags capabilities) {
@@ -97,7 +97,8 @@ class VkRenderFramework : public VkTestFramework {
 
     void ShutdownFramework();
     void GetPhysicalDeviceFeatures(VkPhysicalDeviceFeatures *features);
-    void InitState(VkPhysicalDeviceFeatures *features = nullptr, const VkCommandPoolCreateFlags flags = 0);
+    void InitState(VkPhysicalDeviceFeatures *features = nullptr, VkPhysicalDeviceFeatures2 *features2 = nullptr,
+                   const VkCommandPoolCreateFlags flags = 0);
 
     const VkRenderPassBeginInfo &renderPassBeginInfo() const { return m_renderPassBeginInfo; }
 
index 70058b6..30c4272 100644 (file)
@@ -242,7 +242,7 @@ Device::~Device() {
     vkDestroyDevice(handle(), NULL);
 }
 
-void Device::init(std::vector<const char *> &extensions, VkPhysicalDeviceFeatures *features) {
+void Device::init(std::vector<const char *> &extensions, VkPhysicalDeviceFeatures *features, VkPhysicalDeviceFeatures2 *features2) {
     // request all queues
     const std::vector<VkQueueFamilyProperties> queue_props = phy_.queue_properties();
     QueueCreateInfoArray queue_info(phy_.queue_properties());
@@ -273,7 +273,11 @@ void Device::init(std::vector<const char *> &extensions, VkPhysicalDeviceFeature
     dev_info.ppEnabledExtensionNames = extensions.data();
 
     VkPhysicalDeviceFeatures all_features;
-    if (features) {
+    // Let VkPhysicalDeviceFeatures2 take priority over VkPhysicalDeviceFeatures,
+    // since it supports extensions
+    if (features2) {
+        dev_info.pNext = features2;
+    } else if (features) {
         dev_info.pEnabledFeatures = features;
     } else {
         // request all supportable features enabled
index 3e73aba..d1ea1de 100644 (file)
@@ -195,8 +195,8 @@ class Device : public internal::Handle<VkDevice> {
 
     // vkCreateDevice()
     void init(const VkDeviceCreateInfo &info);
-    void init(std::vector<const char *> &extensions,
-              VkPhysicalDeviceFeatures *features = nullptr);  // all queues, all extensions, etc
+    void init(std::vector<const char *> &extensions, VkPhysicalDeviceFeatures *features = nullptr,
+              VkPhysicalDeviceFeatures2 *features2 = nullptr);  // all queues, all extensions, etc
     void init() {
         std::vector<const char *> extensions;
         init(extensions);