layers: Validate descriptor pool with mutable types
diff --git a/layers/parameter_validation_utils.cpp b/layers/parameter_validation_utils.cpp
index abe346c..3af31f9 100644
--- a/layers/parameter_validation_utils.cpp
+++ b/layers/parameter_validation_utils.cpp
@@ -4827,6 +4827,69 @@
}
#endif // VK_USE_PLATFORM_WIN32_KHR
+static bool MutableDescriptorTypePartialOverlap(const VkDescriptorPoolCreateInfo *pCreateInfo, uint32_t i, uint32_t j) {
+ bool partial_overlap = false;
+
+ static const std::vector<VkDescriptorType> all_descriptor_types = {
+ VK_DESCRIPTOR_TYPE_SAMPLER,
+ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
+ VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
+ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
+ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
+ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,
+ VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
+ VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT,
+ VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR,
+ VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV,
+ };
+
+ const auto *mutable_descriptor_type = LvlFindInChain<VkMutableDescriptorTypeCreateInfoVALVE>(pCreateInfo->pNext);
+ if (mutable_descriptor_type) {
+ std::vector<VkDescriptorType> first_types, second_types;
+ if (mutable_descriptor_type->mutableDescriptorTypeListCount > i) {
+ for (uint32_t k = 0; k < mutable_descriptor_type->pMutableDescriptorTypeLists[i].descriptorTypeCount; ++k) {
+ first_types.push_back(mutable_descriptor_type->pMutableDescriptorTypeLists[i].pDescriptorTypes[k]);
+ }
+ } else {
+ first_types = all_descriptor_types;
+ }
+ if (mutable_descriptor_type->mutableDescriptorTypeListCount > j) {
+ for (uint32_t k = 0; k < mutable_descriptor_type->pMutableDescriptorTypeLists[j].descriptorTypeCount; ++k) {
+ second_types.push_back(mutable_descriptor_type->pMutableDescriptorTypeLists[j].pDescriptorTypes[k]);
+ }
+ } else {
+ second_types = all_descriptor_types;
+ }
+
+ bool complete_overlap = first_types.size() == second_types.size();
+ bool disjoint = true;
+ for (const auto first_type : first_types) {
+ bool found = false;
+ for (const auto second_type : second_types) {
+ if (first_type == second_type) {
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ disjoint = false;
+ } else {
+ complete_overlap = false;
+ }
+ if (!disjoint && !complete_overlap) {
+ partial_overlap = true;
+ break;
+ }
+ }
+ }
+
+ return partial_overlap;
+}
+
bool StatelessValidation::manual_PreCallValidateCreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkDescriptorPool *pDescriptorPool) const {
@@ -4838,6 +4901,11 @@
"vkCreateDescriptorPool(): pCreateInfo->maxSets is not greater than 0.");
}
+ const auto *mutable_descriptor_type_features =
+ LvlFindInChain<VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE>(device_createinfo_pnext);
+ bool mutable_descriptor_type_enabled =
+ mutable_descriptor_type_features && mutable_descriptor_type_features->mutableDescriptorType == VK_TRUE;
+
if (pCreateInfo->pPoolSizes) {
for (uint32_t i = 0; i < pCreateInfo->poolSizeCount; ++i) {
if (pCreateInfo->pPoolSizes[i].descriptorCount <= 0) {
@@ -4853,9 +4921,37 @@
" and pCreateInfo->pPoolSizes[%" PRIu32 "].descriptorCount is not a multiple of 4.",
i, i);
}
+ if (pCreateInfo->pPoolSizes[i].type == VK_DESCRIPTOR_TYPE_MUTABLE_VALVE && !mutable_descriptor_type_enabled) {
+ skip |=
+ LogError(device, "VUID-VkDescriptorPoolCreateInfo-mutableDescriptorType-04608",
+ "vkCreateDescriptorPool(): pCreateInfo->pPoolSizes[%" PRIu32
+ "].type is VK_DESCRIPTOR_TYPE_MUTABLE_VALVE "
+ ", but VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE::mutableDescriptorType is not enabled.",
+ i);
+ }
+ if (pCreateInfo->pPoolSizes[i].type == VK_DESCRIPTOR_TYPE_MUTABLE_VALVE) {
+ for (uint32_t j = i + 1; j < pCreateInfo->poolSizeCount; ++j) {
+ if (pCreateInfo->pPoolSizes[j].type == VK_DESCRIPTOR_TYPE_MUTABLE_VALVE) {
+ if (MutableDescriptorTypePartialOverlap(pCreateInfo, i, j)) {
+ skip |= LogError(device, "VUID-VkDescriptorPoolCreateInfo-pPoolSizes-04787",
+ "vkCreateDescriptorPool(): pCreateInfo->pPoolSizes[%" PRIu32
+ "].type and pCreateInfo->pPoolSizes[%" PRIu32
+ "].type are both VK_DESCRIPTOR_TYPE_MUTABLE_VALVE "
+ " and have sets which partially overlap.",
+ i, j);
+ }
+ }
+ }
+ }
}
}
+ if (pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE && (!mutable_descriptor_type_enabled)) {
+ skip |=
+ LogError(device, "VUID-VkDescriptorPoolCreateInfo-flags-04609",
+ "vkCreateDescriptorPool(): pCreateInfo->flags contains VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE, "
+ "but VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE::mutableDescriptorType is not enabled.");
+ }
if ((pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_VALVE) &&
(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT)) {
skip |= LogError(device, "VUID-VkDescriptorPoolCreateInfo-flags-04607",