demos: Minor cube/tri updates
authorDustin Graves <dustin@lunarg.com>
Wed, 27 Jan 2016 20:48:06 +0000 (13:48 -0700)
committerDustin Graves <dustin@lunarg.com>
Wed, 3 Feb 2016 22:45:31 +0000 (15:45 -0700)
Minor updates/fixes for cube and tri:
 - Break from demo_check_layers search loop when finding a match.
 - Skip memory allocation and layer/extension processing when 0
   layers/extensions are enumerated.
 - Fix potential NULL pointer dereference and exit with message when
   no accessible devices are available.
 - Fix device_extensions memory leak.
 - Remove trailing whitespace.

demos/cube.c
demos/tri.c

index 14b360a..d611f1e 100644 (file)
@@ -2102,6 +2102,7 @@ static VkBool32 demo_check_layers(uint32_t check_count, char **check_names,
         for (uint32_t j = 0; j < layer_count; j++) {
             if (!strcmp(check_names[i], layers[j].layerName)) {
                 found = 1;
+                break;
             }
         }
         if (!found) {
@@ -2115,10 +2116,6 @@ static VkBool32 demo_check_layers(uint32_t check_count, char **check_names,
 static void demo_init_vk(struct demo *demo) {
     VkResult err;
     char *extension_names[64];
-    VkExtensionProperties *instance_extensions;
-    VkPhysicalDevice *physical_devices;
-    VkLayerProperties *instance_layers;
-    VkLayerProperties *device_layers;
     uint32_t instance_extension_count = 0;
     uint32_t instance_layer_count = 0;
     uint32_t device_validation_layer_count = 0;
@@ -2149,68 +2146,83 @@ static void demo_init_vk(struct demo *demo) {
     err = vkEnumerateInstanceLayerProperties(&instance_layer_count, NULL);
     assert(!err);
 
-    instance_layers = malloc(sizeof(VkLayerProperties) * instance_layer_count);
-    err = vkEnumerateInstanceLayerProperties(&instance_layer_count,
-                                             instance_layers);
-    assert(!err);
+    if (instance_layer_count > 0) {
+        VkLayerProperties *instance_layers =
+            malloc(sizeof(VkLayerProperties) * instance_layer_count);
+        err = vkEnumerateInstanceLayerProperties(&instance_layer_count,
+                                                 instance_layers);
+        assert(!err);
 
-    if (demo->validate) {
-        validation_found = demo_check_layers(
-            ARRAY_SIZE(instance_validation_layers), instance_validation_layers,
-            instance_layer_count, instance_layers);
-        if (!validation_found) {
-            ERR_EXIT("vkEnumerateInstanceLayerProperties failed to find"
-                     "required validation layer.\n\n"
-                     "Please look at the Getting Started guide for additional "
-                     "information.\n",
-                     "vkCreateInstance Failure");
+        if (demo->validate) {
+            validation_found = demo_check_layers(
+                ARRAY_SIZE(instance_validation_layers),
+                instance_validation_layers, instance_layer_count,
+                instance_layers);
+
+            enabled_layer_count = ARRAY_SIZE(instance_validation_layers);
         }
-        enabled_layer_count = ARRAY_SIZE(instance_validation_layers);
+
+        free(instance_layers);
     }
 
-    err = vkEnumerateInstanceExtensionProperties(
-        NULL, &instance_extension_count, NULL);
-    assert(!err);
+    if (demo->validate && !validation_found) {
+        ERR_EXIT("vkEnumerateInstanceLayerProperties failed to find"
+                 "required validation layer.\n\n"
+                 "Please look at the Getting Started guide for additional "
+                 "information.\n",
+                 "vkCreateInstance Failure");
+    }
 
+    /* Look for instance extensions */
     VkBool32 surfaceExtFound = 0;
     VkBool32 platformSurfaceExtFound = 0;
     memset(extension_names, 0, sizeof(extension_names));
-    instance_extensions =
-        malloc(sizeof(VkExtensionProperties) * instance_extension_count);
+
     err = vkEnumerateInstanceExtensionProperties(
-        NULL, &instance_extension_count, instance_extensions);
+        NULL, &instance_extension_count, NULL);
     assert(!err);
-    for (uint32_t i = 0; i < instance_extension_count; i++) {
-        if (!strcmp(VK_KHR_SURFACE_EXTENSION_NAME,
-                    instance_extensions[i].extensionName)) {
-            surfaceExtFound = 1;
-            extension_names[enabled_extension_count++] =
-                VK_KHR_SURFACE_EXTENSION_NAME;
-        }
+
+    if (instance_extension_count > 0) {
+        VkExtensionProperties *instance_extensions =
+            malloc(sizeof(VkExtensionProperties) * instance_extension_count);
+        err = vkEnumerateInstanceExtensionProperties(
+            NULL, &instance_extension_count, instance_extensions);
+        assert(!err);
+        for (uint32_t i = 0; i < instance_extension_count; i++) {
+            if (!strcmp(VK_KHR_SURFACE_EXTENSION_NAME,
+                        instance_extensions[i].extensionName)) {
+                surfaceExtFound = 1;
+                extension_names[enabled_extension_count++] =
+                    VK_KHR_SURFACE_EXTENSION_NAME;
+            }
 #ifdef _WIN32
-        if (!strcmp(VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
-                    instance_extensions[i].extensionName)) {
-            platformSurfaceExtFound = 1;
-            extension_names[enabled_extension_count++] =
-                VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
-        }
+            if (!strcmp(VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
+                        instance_extensions[i].extensionName)) {
+                platformSurfaceExtFound = 1;
+                extension_names[enabled_extension_count++] =
+                    VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
+            }
 #else  // _WIN32
-        if (!strcmp(VK_KHR_XCB_SURFACE_EXTENSION_NAME,
-                    instance_extensions[i].extensionName)) {
-            platformSurfaceExtFound = 1;
-            extension_names[enabled_extension_count++] =
-                VK_KHR_XCB_SURFACE_EXTENSION_NAME;
-        }
-#endif // _WIN32
-        if (!strcmp(VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
-                    instance_extensions[i].extensionName)) {
-            if (demo->validate) {
+            if (!strcmp(VK_KHR_XCB_SURFACE_EXTENSION_NAME,
+                        instance_extensions[i].extensionName)) {
+                platformSurfaceExtFound = 1;
                 extension_names[enabled_extension_count++] =
-                    VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
+                    VK_KHR_XCB_SURFACE_EXTENSION_NAME;
             }
+#endif // _WIN32
+            if (!strcmp(VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
+                        instance_extensions[i].extensionName)) {
+                if (demo->validate) {
+                    extension_names[enabled_extension_count++] =
+                        VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
+                }
+            }
+            assert(enabled_extension_count < 64);
         }
-        assert(enabled_extension_count < 64);
+
+        free(instance_extensions);
     }
+
     if (!surfaceExtFound) {
         ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find "
                  "the " VK_KHR_SURFACE_EXTENSION_NAME
@@ -2270,7 +2282,7 @@ static void demo_init_vk(struct demo *demo) {
                  "vkCreateInstance Failure");
     } else if (err == VK_ERROR_EXTENSION_NOT_PRESENT) {
         ERR_EXIT("Cannot find a specified extension library"
-                 ".\nMake sure your layers path is set appropriately\n",
+                 ".\nMake sure your layers path is set appropriately.\n",
                  "vkCreateInstance Failure");
     } else if (err) {
         ERR_EXIT("vkCreateInstance failed.\n\nDo you have a compatible Vulkan "
@@ -2279,18 +2291,24 @@ static void demo_init_vk(struct demo *demo) {
                  "vkCreateInstance Failure");
     }
 
-    free(instance_layers);
-    free(instance_extensions);
-
     /* Make initial call to query gpu_count, then second call for gpu info*/
     err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, NULL);
     assert(!err && gpu_count > 0);
-    physical_devices = malloc(sizeof(VkPhysicalDevice) * gpu_count);
-    err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, physical_devices);
-    assert(!err);
-    /* For cube demo we just grab the first physical device */
-    demo->gpu = physical_devices[0];
-    free(physical_devices);
+
+    if (gpu_count > 0) {
+        VkPhysicalDevice *physical_devices = malloc(sizeof(VkPhysicalDevice) * gpu_count);
+        err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, physical_devices);
+        assert(!err);
+        /* For cube demo we just grab the first physical device */
+        demo->gpu = physical_devices[0];
+        free(physical_devices);
+    } else {
+        ERR_EXIT("vkEnumeratePhysicalDevices reported zero accessible devices.\n\n"
+                 "Do you have a compatible Vulkan installable client driver (ICD) "
+                 "installed?\nPlease look at the Getting Started guide for "
+                 "additional information.\n",
+                 "vkEnumeratePhysicalDevices Failure");
+    }
 
     /* Look for validation layers */
     validation_found = 0;
@@ -2300,49 +2318,62 @@ static void demo_init_vk(struct demo *demo) {
         vkEnumerateDeviceLayerProperties(demo->gpu, &device_layer_count, NULL);
     assert(!err);
 
-    device_layers = malloc(sizeof(VkLayerProperties) * device_layer_count);
-    err = vkEnumerateDeviceLayerProperties(demo->gpu, &device_layer_count,
-                                           device_layers);
-    assert(!err);
+    if (device_layer_count > 0) {
+        VkLayerProperties *device_layers =
+            malloc(sizeof(VkLayerProperties) * device_layer_count);
+        err = vkEnumerateDeviceLayerProperties(demo->gpu, &device_layer_count,
+                                               device_layers);
+        assert(!err);
 
-    if (demo->validate) {
-        validation_found = demo_check_layers(device_validation_layer_count,
-                                             demo->device_validation_layers,
-                                             device_layer_count, device_layers);
-        if (!validation_found) {
-            ERR_EXIT("vkEnumerateDeviceLayerProperties failed to find"
-                     "a required validation layer.\n\n"
-                     "Please look at the Getting Started guide for additional "
-                     "information.\n",
-                     "vkCreateDevice Failure");
+        if (demo->validate) {
+            validation_found = demo_check_layers(device_validation_layer_count,
+                                                 demo->device_validation_layers,
+                                                 device_layer_count,
+                                                 device_layers);
+            demo->enabled_layer_count = device_validation_layer_count;
         }
-        demo->enabled_layer_count = device_validation_layer_count;
+
+        free(device_layers);
     }
 
-    uint32_t device_extension_count = 0;
-    VkExtensionProperties *device_extensions = NULL;
-    err = vkEnumerateDeviceExtensionProperties(demo->gpu, NULL,
-                                               &device_extension_count, NULL);
-    assert(!err);
+    if (demo->validate && !validation_found) {
+        ERR_EXIT("vkEnumerateDeviceLayerProperties failed to find"
+                 "a required validation layer.\n\n"
+                 "Please look at the Getting Started guide for additional "
+                 "information.\n",
+                 "vkCreateDevice Failure");
+    }
 
+    /* Look for device extensions */
+    uint32_t device_extension_count = 0;
     VkBool32 swapchainExtFound = 0;
     demo->enabled_extension_count = 0;
     memset(extension_names, 0, sizeof(extension_names));
-    device_extensions =
-        malloc(sizeof(VkExtensionProperties) * device_extension_count);
-    err = vkEnumerateDeviceExtensionProperties(
-        demo->gpu, NULL, &device_extension_count, device_extensions);
+
+    err = vkEnumerateDeviceExtensionProperties(demo->gpu, NULL,
+                                               &device_extension_count, NULL);
     assert(!err);
 
-    for (uint32_t i = 0; i < device_extension_count; i++) {
-        if (!strcmp(VK_KHR_SWAPCHAIN_EXTENSION_NAME,
-                    device_extensions[i].extensionName)) {
-            swapchainExtFound = 1;
-            demo->extension_names[demo->enabled_extension_count++] =
-                VK_KHR_SWAPCHAIN_EXTENSION_NAME;
+    if (device_extension_count > 0) {
+        VkExtensionProperties *device_extensions =
+            malloc(sizeof(VkExtensionProperties) * device_extension_count);
+        err = vkEnumerateDeviceExtensionProperties(
+            demo->gpu, NULL, &device_extension_count, device_extensions);
+        assert(!err);
+
+        for (uint32_t i = 0; i < device_extension_count; i++) {
+            if (!strcmp(VK_KHR_SWAPCHAIN_EXTENSION_NAME,
+                        device_extensions[i].extensionName)) {
+                swapchainExtFound = 1;
+                demo->extension_names[demo->enabled_extension_count++] =
+                    VK_KHR_SWAPCHAIN_EXTENSION_NAME;
+            }
+            assert(demo->enabled_extension_count < 64);
         }
-        assert(demo->enabled_extension_count < 64);
+
+        free(device_extensions);
     }
+
     if (!swapchainExtFound) {
         ERR_EXIT("vkEnumerateDeviceExtensionProperties failed to find "
                  "the " VK_KHR_SWAPCHAIN_EXTENSION_NAME
@@ -2435,8 +2466,6 @@ static void demo_init_vk(struct demo *demo) {
     VkPhysicalDeviceFeatures physDevFeatures;
     vkGetPhysicalDeviceFeatures(demo->gpu, &physDevFeatures);
 
-    free(device_layers);
-
     GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfaceSupportKHR);
     GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfaceCapabilitiesKHR);
     GET_INSTANCE_PROC_ADDR(demo->inst, GetPhysicalDeviceSurfaceFormatsKHR);
index b7cc2e0..fa19b4e 100644 (file)
@@ -1691,6 +1691,7 @@ static VkBool32 demo_check_layers(uint32_t check_count, char **check_names,
         for (uint32_t j = 0; j < layer_count; j++) {
             if (!strcmp(check_names[i], layers[j].layerName)) {
                 found = 1;
+                break;
             }
         }
         if (!found) {
@@ -1727,10 +1728,6 @@ VKAPI_ATTR void VKAPI_CALL myfree(void *pUserData, void *pMemory) {
 
 static void demo_init_vk(struct demo *demo) {
     VkResult err;
-    VkExtensionProperties *instance_extensions;
-    VkPhysicalDevice *physical_devices;
-    VkLayerProperties *instance_layers;
-    VkLayerProperties *device_layers;
     uint32_t instance_extension_count = 0;
     uint32_t instance_layer_count = 0;
     uint32_t device_validation_layer_count = 0;
@@ -1751,68 +1748,82 @@ static void demo_init_vk(struct demo *demo) {
     err = vkEnumerateInstanceLayerProperties(&instance_layer_count, NULL);
     assert(!err);
 
-    instance_layers = malloc(sizeof(VkLayerProperties) * instance_layer_count);
-    err = vkEnumerateInstanceLayerProperties(&instance_layer_count,
-                                             instance_layers);
-    assert(!err);
+    if (instance_layer_count > 0) {
+        VkLayerProperties *instance_layers =
+            malloc(sizeof(VkLayerProperties) * instance_layer_count);
+        err = vkEnumerateInstanceLayerProperties(&instance_layer_count,
+                                                 instance_layers);
+        assert(!err);
 
-    if (demo->validate) {
-        validation_found = demo_check_layers(
-            ARRAY_SIZE(instance_validation_layers), instance_validation_layers,
-            instance_layer_count, instance_layers);
-        if (!validation_found) {
-            ERR_EXIT("vkEnumerateInstanceLayerProperties failed to find"
-                     "required validation layer.\n\n"
-                     "Please look at the Getting Started guide for additional "
-                     "information.\n",
-                     "vkCreateInstance Failure");
+        if (demo->validate) {
+            validation_found = demo_check_layers(
+                ARRAY_SIZE(instance_validation_layers),
+                instance_validation_layers, instance_layer_count,
+                instance_layers);
+            demo->enabled_layer_count = ARRAY_SIZE(instance_validation_layers);
         }
-        demo->enabled_layer_count = ARRAY_SIZE(instance_validation_layers);
+
+        free(instance_layers);
     }
 
-    err = vkEnumerateInstanceExtensionProperties(
-        NULL, &instance_extension_count, NULL);
-    assert(!err);
+    if (demo->validate && !validation_found) {
+        ERR_EXIT("vkEnumerateInstanceLayerProperties failed to find"
+                 "required validation layer.\n\n"
+                 "Please look at the Getting Started guide for additional "
+                 "information.\n",
+                 "vkCreateInstance Failure");
+    }
 
+    /* Look for instance extensions */
     VkBool32 surfaceExtFound = 0;
     VkBool32 platformSurfaceExtFound = 0;
     memset(demo->extension_names, 0, sizeof(demo->extension_names));
-    instance_extensions =
-        malloc(sizeof(VkExtensionProperties) * instance_extension_count);
+
     err = vkEnumerateInstanceExtensionProperties(
-        NULL, &instance_extension_count, instance_extensions);
+        NULL, &instance_extension_count, NULL);
     assert(!err);
-    for (uint32_t i = 0; i < instance_extension_count; i++) {
-        if (!strcmp(VK_KHR_SURFACE_EXTENSION_NAME,
-                    instance_extensions[i].extensionName)) {
-            surfaceExtFound = 1;
-            demo->extension_names[demo->enabled_extension_count++] =
-                VK_KHR_SURFACE_EXTENSION_NAME;
-        }
+
+    if (instance_extension_count > 0) {
+        VkExtensionProperties *instance_extensions =
+            malloc(sizeof(VkExtensionProperties) * instance_extension_count);
+        err = vkEnumerateInstanceExtensionProperties(
+            NULL, &instance_extension_count, instance_extensions);
+        assert(!err);
+        for (uint32_t i = 0; i < instance_extension_count; i++) {
+            if (!strcmp(VK_KHR_SURFACE_EXTENSION_NAME,
+                        instance_extensions[i].extensionName)) {
+                surfaceExtFound = 1;
+                demo->extension_names[demo->enabled_extension_count++] =
+                    VK_KHR_SURFACE_EXTENSION_NAME;
+            }
 #ifdef _WIN32
-        if (!strcmp(VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
-                    instance_extensions[i].extensionName)) {
-            platformSurfaceExtFound = 1;
-            demo->extension_names[demo->enabled_extension_count++] =
-                VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
-        }
+            if (!strcmp(VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
+                        instance_extensions[i].extensionName)) {
+                platformSurfaceExtFound = 1;
+                demo->extension_names[demo->enabled_extension_count++] =
+                    VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
+            }
 #else  // _WIN32
-        if (!strcmp(VK_KHR_XCB_SURFACE_EXTENSION_NAME,
-                    instance_extensions[i].extensionName)) {
-            platformSurfaceExtFound = 1;
-            demo->extension_names[demo->enabled_extension_count++] =
-                VK_KHR_XCB_SURFACE_EXTENSION_NAME;
-        }
-#endif // _WIN32
-        if (!strcmp(VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
-                    instance_extensions[i].extensionName)) {
-            if (demo->validate) {
+            if (!strcmp(VK_KHR_XCB_SURFACE_EXTENSION_NAME,
+                        instance_extensions[i].extensionName)) {
+                platformSurfaceExtFound = 1;
                 demo->extension_names[demo->enabled_extension_count++] =
-                    VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
+                    VK_KHR_XCB_SURFACE_EXTENSION_NAME;
+            }
+#endif // _WIN32
+            if (!strcmp(VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
+                        instance_extensions[i].extensionName)) {
+                if (demo->validate) {
+                    demo->extension_names[demo->enabled_extension_count++] =
+                        VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
+                }
             }
+            assert(demo->enabled_extension_count < 64);
         }
-        assert(demo->enabled_extension_count < 64);
+
+        free(instance_extensions);
     }
+
     if (!surfaceExtFound) {
         ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find "
                  "the " VK_KHR_SURFACE_EXTENSION_NAME
@@ -1883,18 +1894,26 @@ static void demo_init_vk(struct demo *demo) {
                  "vkCreateInstance Failure");
     }
 
-    free(instance_layers);
-    free(instance_extensions);
-
     /* Make initial call to query gpu_count, then second call for gpu info*/
     err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, NULL);
     assert(!err && gpu_count > 0);
-    physical_devices = malloc(sizeof(VkPhysicalDevice) * gpu_count);
-    err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, physical_devices);
-    assert(!err);
-    /* For tri demo we just grab the first physical device */
-    demo->gpu = physical_devices[0];
-    free(physical_devices);
+
+    if (gpu_count > 0) {
+        VkPhysicalDevice *physical_devices =
+            malloc(sizeof(VkPhysicalDevice) * gpu_count);
+        err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count,
+                                         physical_devices);
+        assert(!err);
+        /* For tri demo we just grab the first physical device */
+        demo->gpu = physical_devices[0];
+        free(physical_devices);
+    } else {
+        ERR_EXIT("vkEnumeratePhysicalDevices reported zero accessible devices."
+                 "\n\nDo you have a compatible Vulkan installable client"
+                 " driver (ICD) installed?\nPlease look at the Getting Started"
+                 " guide for additional information.\n",
+                 "vkEnumeratePhysicalDevices Failure");
+    }
 
     /* Look for validation layers */
     validation_found = 0;
@@ -1904,49 +1923,62 @@ static void demo_init_vk(struct demo *demo) {
         vkEnumerateDeviceLayerProperties(demo->gpu, &device_layer_count, NULL);
     assert(!err);
 
-    device_layers = malloc(sizeof(VkLayerProperties) * device_layer_count);
-    err = vkEnumerateDeviceLayerProperties(demo->gpu, &device_layer_count,
-                                           device_layers);
-    assert(!err);
+    if (device_layer_count > 0) {
+        VkLayerProperties *device_layers =
+            malloc(sizeof(VkLayerProperties) * device_layer_count);
+        err = vkEnumerateDeviceLayerProperties(demo->gpu, &device_layer_count,
+                                               device_layers);
+        assert(!err);
 
-    if (demo->validate) {
-        validation_found = demo_check_layers(device_validation_layer_count,
-                                             demo->device_validation_layers,
-                                             device_layer_count, device_layers);
-        if (!validation_found) {
-            ERR_EXIT("vkEnumerateDeviceLayerProperties failed to find "
-                     "a required validation layer.\n\n"
-                     "Please look at the Getting Started guide for additional "
-                     "information.\n",
-                     "vkCreateDevice Failure");
+        if (demo->validate) {
+            validation_found = demo_check_layers(device_validation_layer_count,
+                                                 demo->device_validation_layers,
+                                                 device_layer_count,
+                                                 device_layers);
+            demo->enabled_layer_count = device_validation_layer_count;
         }
-        demo->enabled_layer_count = device_validation_layer_count;
+
+        free(device_layers);
     }
 
-    uint32_t device_extension_count = 0;
-    VkExtensionProperties *device_extensions = NULL;
-    err = vkEnumerateDeviceExtensionProperties(demo->gpu, NULL,
-                                               &device_extension_count, NULL);
-    assert(!err);
+    if (demo->validate && !validation_found) {
+        ERR_EXIT("vkEnumerateDeviceLayerProperties failed to find "
+                 "a required validation layer.\n\n"
+                 "Please look at the Getting Started guide for additional "
+                 "information.\n",
+                 "vkCreateDevice Failure");
+    }
 
+    /* Loog for device extensions */
+    uint32_t device_extension_count = 0;
     VkBool32 swapchainExtFound = 0;
     demo->enabled_extension_count = 0;
     memset(demo->extension_names, 0, sizeof(demo->extension_names));
-    device_extensions =
-        malloc(sizeof(VkExtensionProperties) * device_extension_count);
-    err = vkEnumerateDeviceExtensionProperties(
-        demo->gpu, NULL, &device_extension_count, device_extensions);
+
+    err = vkEnumerateDeviceExtensionProperties(demo->gpu, NULL,
+                                               &device_extension_count, NULL);
     assert(!err);
 
-    for (uint32_t i = 0; i < device_extension_count; i++) {
-        if (!strcmp(VK_KHR_SWAPCHAIN_EXTENSION_NAME,
-                    device_extensions[i].extensionName)) {
-            swapchainExtFound = 1;
-            demo->extension_names[demo->enabled_extension_count++] =
-                VK_KHR_SWAPCHAIN_EXTENSION_NAME;
+    if (device_extension_count > 0) {
+        VkExtensionProperties *device_extensions =
+                malloc(sizeof(VkExtensionProperties) * device_extension_count);
+        err = vkEnumerateDeviceExtensionProperties(
+            demo->gpu, NULL, &device_extension_count, device_extensions);
+        assert(!err);
+
+        for (uint32_t i = 0; i < device_extension_count; i++) {
+            if (!strcmp(VK_KHR_SWAPCHAIN_EXTENSION_NAME,
+                        device_extensions[i].extensionName)) {
+                swapchainExtFound = 1;
+                demo->extension_names[demo->enabled_extension_count++] =
+                    VK_KHR_SWAPCHAIN_EXTENSION_NAME;
+            }
+            assert(demo->enabled_extension_count < 64);
         }
-        assert(demo->enabled_extension_count < 64);
+
+        free(device_extensions);
     }
+
     if (!swapchainExtFound) {
         ERR_EXIT("vkEnumerateDeviceExtensionProperties failed to find "
                  "the " VK_KHR_SWAPCHAIN_EXTENSION_NAME