layers: GH849: Defend against poorly-written applications
A test application was written that didn't properly call some count-based query
commands. In this particular case, they always hard-coded the count variable
to 1 the 2nd time the query was called. The swapchain layer was only recording
the 1st count value in this case, and this caused a seg fault when the
vkCreateSwapchainKHR command validation code was run.
This commit better defends against such poorly-written applications, so that
the vkCreateSwapchainKHR command validation code won't seg fault. This
includes looking for VK_INCOMPLETE as a successful return code from the ICD.
diff --git a/layers/swapchain.cpp b/layers/swapchain.cpp
index e301a5d..2449625 100644
--- a/layers/swapchain.cpp
+++ b/layers/swapchain.cpp
@@ -331,7 +331,12 @@
auto it = my_data->physicalDeviceMap.find(physicalDevice);
pPhysicalDevice = (it == my_data->physicalDeviceMap.end()) ? NULL : &it->second;
}
- if (pPhysicalDevice && pQueueFamilyPropertyCount && !pQueueFamilyProperties) {
+ // Note: for poorly-written applications (e.g. that don't call this command
+ // twice, the first time with pQueueFamilyProperties set to NULL, and the
+ // second time with a non-NULL pQueueFamilyProperties and with the same
+ // count as returned the first time), record the count when
+ // pQueueFamilyProperties is non-NULL:
+ if (pPhysicalDevice && pQueueFamilyPropertyCount && pQueueFamilyProperties) {
pPhysicalDevice->gotQueueFamilyPropertyCount = true;
pPhysicalDevice->numOfQueueFamilies = *pQueueFamilyPropertyCount;
}
@@ -1449,9 +1454,14 @@
if ((result == VK_SUCCESS) && pPhysicalDevice && !pSurfaceFormats && pSurfaceFormatCount) {
// Record the result of this preliminary query:
pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
- } else if ((result == VK_SUCCESS) && pPhysicalDevice && pSurfaceFormats && pSurfaceFormatCount &&
- (*pSurfaceFormatCount > 0)) {
+ } else if (((result == VK_SUCCESS) || (result == VK_INCOMPLETE)) && pPhysicalDevice && pSurfaceFormats &&
+ pSurfaceFormatCount && (*pSurfaceFormatCount > 0)) {
// Record the result of this query:
+
+ // Note: for poorly-written applications (e.g. that don't call this command
+ // twice, the first time with pSurfaceFormats set to NULL, and the second time
+ // with a non-NULL pSurfaceFormats and with the same count as returned the
+ // first time), record again the count when pSurfaceFormats is non-NULL:
pPhysicalDevice->surfaceFormatCount = *pSurfaceFormatCount;
pPhysicalDevice->pSurfaceFormats = (VkSurfaceFormatKHR *)malloc(*pSurfaceFormatCount * sizeof(VkSurfaceFormatKHR));
if (pPhysicalDevice->pSurfaceFormats) {
@@ -1527,8 +1537,14 @@
if ((result == VK_SUCCESS) && pPhysicalDevice && !pPresentModes && pPresentModeCount) {
// Record the result of this preliminary query:
pPhysicalDevice->presentModeCount = *pPresentModeCount;
- } else if ((result == VK_SUCCESS) && pPhysicalDevice && pPresentModes && pPresentModeCount && (*pPresentModeCount > 0)) {
+ } else if (((result == VK_SUCCESS) || (result == VK_INCOMPLETE)) && pPhysicalDevice &&
+ pPresentModes && pPresentModeCount && (*pPresentModeCount > 0)) {
// Record the result of this query:
+
+ // Note: for poorly-written applications (e.g. that don't call this command
+ // twice, the first time with pPresentModes set to NULL, and the second time
+ // with a non-NULL pPresentModes and with the same count as returned the
+ // first time), record again the count when pPresentModes is non-NULL:
pPhysicalDevice->presentModeCount = *pPresentModeCount;
pPhysicalDevice->pPresentModes = (VkPresentModeKHR *)malloc(*pPresentModeCount * sizeof(VkPresentModeKHR));
if (pPhysicalDevice->pPresentModes) {