layers: LX450, Tighten up queueFamilyIndex validation, fix crash

For CreateBuffer and CreateImage the QFIs should be ignored unless
sharingMode is set to CONCURRENT.  Also added QFI validation to
CreateCommandPool and added a special case for when an index is
incorrectly set to QUEUE_FAMILY_IGNORED.

Change-Id: I17639230ea7aa58ab89b9b0dc33e55927e9f1c84
diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index 4ea26ba..6250790 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -6293,30 +6293,11 @@
     loader_platform_thread_unlock_mutex(&globalLock);
 }
 
-VkBool32 validate_queue_family_indices(layer_data *dev_data, const char *function_name, const uint32_t count,
-                                       const uint32_t *indices) {
-    VkBool32 skipCall = VK_FALSE;
-    for (auto i = 0; i < count; i++) {
-        if (indices[i] >= dev_data->physDevProperties.queue_family_properties.size()) {
-            skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
-                                DRAWSTATE_INVALID_QUEUE_INDEX, "DS",
-                                "%s has QueueFamilyIndex greater than the number of QueueFamilies (" PRINTF_SIZE_T_SPECIFIER
-                                ") for this device.",
-                                function_name, dev_data->physDevProperties.queue_family_properties.size());
-        }
-    }
-    return skipCall;
-}
-
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) {
-    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
+VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
+                                                              const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) {
     layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
-    bool skipCall = validate_queue_family_indices(dev_data, "vkCreateBuffer", pCreateInfo->queueFamilyIndexCount,
-                                                  pCreateInfo->pQueueFamilyIndices);
-    if (!skipCall) {
-        result = dev_data->device_dispatch_table->CreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
-    }
+
+    VkResult result = dev_data->device_dispatch_table->CreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
 
     if (VK_SUCCESS == result) {
         loader_platform_thread_lock_mutex(&globalLock);
@@ -6350,15 +6331,11 @@
     return result;
 }
 
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
-    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
+VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
+                                                             const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
     layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
-    bool skipCall = validate_queue_family_indices(dev_data, "vkCreateImage", pCreateInfo->queueFamilyIndexCount,
-                                                  pCreateInfo->pQueueFamilyIndices);
-    if (!skipCall) {
-        result = dev_data->device_dispatch_table->CreateImage(device, pCreateInfo, pAllocator, pImage);
-    }
+
+    VkResult result = dev_data->device_dispatch_table->CreateImage(device, pCreateInfo, pAllocator, pImage);
 
     if (VK_SUCCESS == result) {
         loader_platform_thread_lock_mutex(&globalLock);
diff --git a/layers/parameter_validation.cpp b/layers/parameter_validation.cpp
index 4302e9c..e66a117 100644
--- a/layers/parameter_validation.cpp
+++ b/layers/parameter_validation.cpp
@@ -1275,6 +1275,30 @@
     return enumeratorString;
 }
 
+static bool validate_queue_family_indices(VkDevice device, const char *function_name, const uint32_t count,
+                                          const uint32_t *indices) {
+    bool skipCall = false;
+    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+
+    for (auto i = 0u; i < count; i++) {
+        if (indices[i] == VK_QUEUE_FAMILY_IGNORED) {
+            skipCall |=
+                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
+                        "%s: the specified queueFamilyIndex cannot be VK_QUEUE_FAMILY_IGNORED.", function_name);
+        } else {
+            const auto &queue_data = my_device_data->queueFamilyIndexMap.find(indices[i]);
+            if (queue_data == my_device_data->queueFamilyIndexMap.end()) {
+                skipCall |= log_msg(
+                    mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
+                    "VkGetDeviceQueue parameter, uint32_t queueFamilyIndex %d, must have been given when the device was created.",
+                    indices[i]);
+                return false;
+            }
+        }
+    }
+    return skipCall;
+}
+
 static bool ValidateEnumerator(VkQueryControlFlagBits const &enumerator) {
     VkQueryControlFlagBits allFlags = (VkQueryControlFlagBits)(VK_QUERY_CONTROL_PRECISE_BIT);
     if (enumerator & (~allFlags)) {
@@ -1756,15 +1780,9 @@
     layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
     assert(my_device_data != nullptr);
 
+    validate_queue_family_indices(device, "vkGetDeviceQueue", 1, &queueFamilyIndex);
+
     const auto &queue_data = my_device_data->queueFamilyIndexMap.find(queueFamilyIndex);
-
-    if (queue_data == my_device_data->queueFamilyIndexMap.end()) {
-        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
-                "VkGetDeviceQueue parameter, uint32_t queueFamilyIndex %d, must have been given when the device was created.",
-                queueFamilyIndex);
-        return false;
-    }
-
     if (queue_data->second <= queueIndex) {
         log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
                 "VkGetDeviceQueue parameter, uint32_t queueIndex %d, must be less than the number of queues given when the device "
@@ -2552,6 +2570,9 @@
             log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
                     "vkCreateBuffer parameter, VkSharingMode pCreateInfo->sharingMode, is an unrecognized enumerator");
             return false;
+        } else if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {
+            validate_queue_family_indices(device, "vkCreateBuffer", pCreateInfo->queueFamilyIndexCount,
+                                          pCreateInfo->pQueueFamilyIndices);
         }
     }
 
@@ -2679,6 +2700,9 @@
             log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
                     "vkCreateImage parameter, VkSharingMode pCreateInfo->sharingMode, is an unrecognized enumerator");
             return false;
+        } else if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {
+            validate_queue_family_indices(device, "vkCreateImage", pCreateInfo->queueFamilyIndexCount,
+                                          pCreateInfo->pQueueFamilyIndices);
         }
     }
 
@@ -3935,10 +3959,12 @@
                                                                    const VkAllocationCallbacks *pAllocator,
                                                                    VkCommandPool *pCommandPool) {
     VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
-    VkBool32 skipCall = VK_FALSE;
+    bool skipCall = false;
     layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
     assert(my_data != NULL);
 
+    skipCall |= validate_queue_family_indices(device, "vkCreateCommandPool", 1, &(pCreateInfo->queueFamilyIndex));
+
     skipCall |= parameter_validation_vkCreateCommandPool(my_data->report_data, pCreateInfo, pAllocator, pCommandPool);
 
     if (skipCall == VK_FALSE) {